Index: llvm/docs/CommandGuide/llvm-objdump.rst =================================================================== --- llvm/docs/CommandGuide/llvm-objdump.rst +++ llvm/docs/CommandGuide/llvm-objdump.rst @@ -172,6 +172,12 @@ When disassembling with the :option:`--source` option, prepend ``prefix`` to absolute paths. +.. option:: --prefix-strip= + + When disassembling with the :option:`--source` option, strip out ``level`` + initial directories from absolute paths. It has no effect without + :option:`--prefix`. + .. option:: --print-imm-hex Use hex format when printing immediate values in disassembly output. Index: llvm/docs/llvm-objdump.1 =================================================================== --- llvm/docs/llvm-objdump.1 +++ llvm/docs/llvm-objdump.1 @@ -109,6 +109,11 @@ When disassembling, add .Ar PREFIX to absolute paths. +.It Fl -prefix-strip Ns = Ns Ar LEVEL +When disassembling, strip out +.Ar LEVEL +initial directories from absolute paths. It has no effect without +.Fl -prefix Ns = Ns PREFIX . .It Fl -print-imm-hex Use hex format for immediate values. .It Fl -private-header Index: llvm/test/tools/llvm-objdump/X86/source-interleave-prefix.test =================================================================== --- llvm/test/tools/llvm-objdump/X86/source-interleave-prefix.test +++ llvm/test/tools/llvm-objdump/X86/source-interleave-prefix.test @@ -12,8 +12,8 @@ ; RUN: sed -e "s,SRC_COMPDIR,./Inputs,g" %p/Inputs/source-interleave.ll > %t-relative-path.ll ; RUN: llc -o %t-relative-path.o -filetype=obj -mtriple=x86_64-pc-linux %t-relative-path.ll ; RUN: llvm-objdump --prefix myprefix --source %t-relative-path.o 2>&1 | \ -; RUN: FileCheck %s --check-prefix=CHECK-BROKEN-PREFIX -DFILE=%t-relative-path.o -DPREFIX=. -; CHECK-BROKEN-PREFIX: warning: '[[FILE]]': failed to find source [[PREFIX]]/Inputs{{[/\\]}}source-interleave-x86_64.c +; RUN: FileCheck %s --check-prefix=CHECK-BROKEN-PREFIX -DFILE=%t-relative-path.o -DPREFIX=. -DCOMPDIR=/Inputs +; CHECK-BROKEN-PREFIX: warning: '[[FILE]]': failed to find source [[PREFIX]][[COMPDIR]]{{[/\\]}}source-interleave-x86_64.c ;; Test invalid source interleave fixed by adding the correct prefix. @@ -28,16 +28,47 @@ ; RUN: sed -e "s,SRC_COMPDIR,%/p/Inputs,g" %p/Inputs/source-interleave.ll > %t-correct-prefix.ll ; RUN: llc -o %t-correct-prefix.o -filetype=obj -mtriple=x86_64-pc-linux %t-correct-prefix.ll ; RUN: llvm-objdump --prefix myprefix --source %t-correct-prefix.o 2>&1 | \ -; RUN: FileCheck %s --check-prefix=CHECK-BROKEN-PREFIX -DFILE=%t-correct-prefix.o -DPREFIX=myprefix%/p +; RUN: FileCheck %s --check-prefix=CHECK-BROKEN-PREFIX -DFILE=%t-correct-prefix.o -DPREFIX=myprefix%/p -DCOMPDIR=/Inputs ;; Using only a prefix separator is the same as not using the `--prefix` option. ; RUN: llvm-objdump --prefix / --source %t-missing-prefix.o 2>&1 | \ -; RUN: FileCheck %s --check-prefix=CHECK-BROKEN-PREFIX -DFILE=%t-missing-prefix.o -DPREFIX='' +; RUN: FileCheck %s --check-prefix=CHECK-BROKEN-PREFIX -DFILE=%t-missing-prefix.o -DPREFIX='' -DCOMPDIR=/Inputs ;; All trailing separators on the prefix are discarded. ;; The prefix 'myprefix//' is converted to 'myprefix'. ; RUN: llvm-objdump --prefix myprefix// --source %t-missing-prefix.o 2>&1 | \ -; RUN: FileCheck %s --check-prefix=CHECK-BROKEN-PREFIX -DFILE=%t-missing-prefix.o -DPREFIX=myprefix +; RUN: FileCheck %s --check-prefix=CHECK-BROKEN-PREFIX -DFILE=%t-missing-prefix.o -DPREFIX=myprefix -DCOMPDIR=/Inputs +;; Test invalid source interleave fixed by adding the correct prefix and +;; stripping out an extra directory from the path. + +; RUN: sed -e "s,SRC_COMPDIR,/extra/Inputs,g" %p/Inputs/source-interleave.ll > %t-extra-path-prefix.ll +; RUN: llc -o %t-extra-path-prefix.o -filetype=obj -mtriple=x86_64-pc-linux %t-extra-path-prefix.ll +; RUN: llvm-objdump --prefix %p --prefix-strip 1 --source %t-extra-path-prefix.o 2>&1 | \ +; RUN: FileCheck %s --check-prefix=CHECK-MISSING-PREFIX-FIX + +;; Test do not skip extra separators. The --prefix-strip should take into +;; account each separator individually. Hence, to fix '/extra/Inputs' +;; --prefix-strip needs to be 1. To fix '//extra/Inputs' --prefix-strip +;; needs to be 2. + +; RUN: sed -e "s,SRC_COMPDIR,//extra/Inputs,g" %p/Inputs/source-interleave.ll > %t-extra-sep-path-prefix.ll +; RUN: llc -o %t-extra-sep-path-prefix.o -filetype=obj -mtriple=x86_64-pc-linux %t-extra-sep-path-prefix.ll +; RUN: llvm-objdump --prefix %p --prefix-strip 2 --source %t-extra-sep-path-prefix.o 2>&1 | \ +; RUN: FileCheck %s --check-prefix=CHECK-MISSING-PREFIX-FIX + +;; Test --prefix-strip value of 0. No effect. + +; RUN: llvm-objdump --prefix %p --prefix-strip 0 --source %t-missing-prefix.o 2>&1 | \ +; RUN: FileCheck %s --check-prefix=CHECK-MISSING-PREFIX-FIX + +;; Test --prefix-strip value equal to the number of directory components. + +; RUN: llvm-objdump --prefix %p --prefix-strip 1 --source %t-missing-prefix.o 2>&1 | \ +; RUN: FileCheck %s --check-prefix=CHECK-BROKEN-PREFIX -DFILE=%t-missing-prefix.o -DPREFIX=%p -DCOMPDIR='' + +;; Test --prefix-strip value greater than the number of components. +; RUN: llvm-objdump --prefix %p --prefix-strip 2 --source %t-missing-prefix.o 2>&1 | \ +; RUN: FileCheck %s --check-prefix=CHECK-BROKEN-PREFIX -DFILE=%t-missing-prefix.o -DPREFIX=%p -DCOMPDIR='' Index: llvm/tools/llvm-objdump/llvm-objdump.h =================================================================== --- llvm/tools/llvm-objdump/llvm-objdump.h +++ llvm/tools/llvm-objdump/llvm-objdump.h @@ -42,6 +42,7 @@ extern cl::opt NoShowRawInsn; extern cl::opt NoLeadingAddr; extern cl::opt Prefix; +extern cl::opt PrefixStrip; extern cl::opt PrintImmHex; extern cl::opt PrivateHeaders; extern cl::opt Relocations; Index: llvm/tools/llvm-objdump/llvm-objdump.cpp =================================================================== --- llvm/tools/llvm-objdump/llvm-objdump.cpp +++ llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -358,6 +358,12 @@ cl::desc("Add prefix to absolute paths"), cl::cat(ObjdumpCat)); +cl::opt + objdump::PrefixStrip("prefix-strip", + cl::desc("Strip out initial directories from absolute " + "paths. It has no effect without --prefix"), + cl::init(0), cl::cat(ObjdumpCat)); + enum DebugVarsFormat { DVDisabled, DVUnicode, @@ -1031,6 +1037,26 @@ } if (!Prefix.empty() && sys::path::is_absolute_gnu(LineInfo.FileName)) { + // FileName has at least one character since is_absolute_gnu is false for + // an empty string. + assert(!LineInfo.FileName.empty()); + if (PrefixStrip > 0) { + uint32_t Level = 0; + const char *FileName = LineInfo.FileName.c_str(); + + // Path.h iterator skips extra separators. Therefore it cannot be used + // here to keep compatibility with GNU Objdump. + for (const char *S = FileName + 1; *S != '\0' && Level < PrefixStrip; + ++S) { + if (sys::path::is_separator(*S)) { + FileName = S; + ++Level; + } + } + + LineInfo.FileName = std::string(FileName); + } + SmallString<128> FilePath; sys::path::append(FilePath, Prefix, LineInfo.FileName);