Index: llvm/docs/CommandGuide/llvm-objdump.rst =================================================================== --- llvm/docs/CommandGuide/llvm-objdump.rst +++ llvm/docs/CommandGuide/llvm-objdump.rst @@ -167,6 +167,10 @@ When disassembling, do not print the raw bytes of each instruction. +.. option:: --prefix= + + When disassembling with the :option:`--source` option, prepend ``prefix`` to absolute paths. + .. 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 @@ -105,6 +105,10 @@ Print no leading headers. .It Fl -no-show-raw-insn When disassembling instructions, do not print the instruction bytes. +.It Fl -prefix Ns = Ns Ar PREFIX +When disassembling, add +.Ar PREFIX +to absolute paths. .It Fl -print-imm-hex Use hex format for immediate values. .It Fl -private-header Index: llvm/test/tools/llvm-objdump/X86/source-interleave-absolute-paths.test =================================================================== --- /dev/null +++ llvm/test/tools/llvm-objdump/X86/source-interleave-absolute-paths.test @@ -0,0 +1,34 @@ +;; Test --prefix option. + +; RUN: sed -e "s,SRC_COMPDIR,/Inputs,g" %p/Inputs/source-interleave.ll > %t.ll +; RUN: llc -o %t.o -filetype=obj -mtriple=x86_64-pc-linux %t.ll + +; RUN: sed -e "s,SRC_COMPDIR,%/p/Inputs,g" %p/Inputs/source-interleave.ll > %t2.ll +; RUN: llc -o %t2.o -filetype=obj -mtriple=x86_64-pc-linux %t2.ll + +; RUN: sed -e "s,SRC_COMPDIR,,g" %p/Inputs/source-interleave.ll | sed -e "s,filename: \"source-interleave-x86_64.c\",filename: \"\",g"> %t3.ll +; RUN: llc -o %t3.o -filetype=obj -mtriple=x86_64-pc-linux %t3.ll + +;; Test invalid source interleave fixed by adding the correct prefix. + +; RUN: llvm-objdump --prefix %p --source %t.o 2>&1 | FileCheck %s --check-prefix CHECK-MISS-PREFIX-FIX +; CHECK-MISS-PREFIX-FIX: ; int foo() { + +;; Test valid source interleave being broken by adding a wrong prefix. + +; RUN: llvm-objdump --prefix myprefix --source %t2.o 2>&1 | FileCheck %s --check-prefix CHECK-BROKEN-PREFIX -DFILE=%t2.o -DROOT=%/p +; CHECK-BROKEN-PREFIX: warning: '[[FILE]]': failed to find source myprefix[[ROOT]]/Inputs/source-interleave-x86_64.c + +;; Test that trailing separators (i.e. '/') are removed from the prefix argument. +;; The prefix '/' is the same as not using the `--prefix` option. + +; RUN: llvm-objdump --prefix / --source %t2.o 2>&1 | FileCheck %s --check-prefix CHECK-MISS-PREFIX-FIX + +;; The prefix 'myprefix///' is converted to 'myprefix'. + +; RUN: llvm-objdump --prefix myprefix/// --source %t.o 2>&1 | FileCheck %s --check-prefix CHECK-TRAILING -DFILE=%t.o +; CHECK-TRAILING: warning: '[[FILE]]': failed to find source myprefix/Inputs/source-interleave-x86_64.c + +;; Test malformed input +; RUN: llvm-objdump --prefix myprefix --source %t3.o 2>&1 | FileCheck %s --check-prefix CHECK-MALFORMED -DFILE=%t3.o -DROOT=%/p +; CHECK-MALFORMED: warning: '[[FILE]]': failed to parse debug information for [[FILE]] Index: llvm/tools/llvm-objdump/llvm-objdump.h =================================================================== --- llvm/tools/llvm-objdump/llvm-objdump.h +++ llvm/tools/llvm-objdump/llvm-objdump.h @@ -48,6 +48,7 @@ extern cl::opt SymbolTable; extern cl::opt TripleName; extern cl::opt UnwindInfo; +extern cl::opt Prefix; extern StringSet<> FoundSectionSet; Index: llvm/tools/llvm-objdump/llvm-objdump.cpp =================================================================== --- llvm/tools/llvm-objdump/llvm-objdump.cpp +++ llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -353,6 +353,10 @@ cl::cat(ObjdumpCat)); static cl::alias WideShort("w", cl::Grouping, cl::aliasopt(Wide)); +cl::opt objdump::Prefix("prefix", + cl::desc("Add prefix to absolute paths"), + cl::cat(ObjdumpCat)); + enum DebugVarsFormat { DVDisabled, DVUnicode, @@ -417,6 +421,30 @@ /*IncrementIndex=*/true}; } +/// GNU tools is_absolute() equivalent. +/// +/// LLVM is_absolute() matches C++17 behavior that essentially says that the +/// path must be unambiguous (i.e. that there must be a drive letter for +/// Windows). However GNU tools treat a path as absolute with or without +/// the drive letter. +static bool objdumpIsAbsolute(const Twine &Path) { + if (Triple(sys::getProcessTriple()).isOSWindows()) { + SmallString<128> PathStorage; + StringRef P = Path.toStringRef(PathStorage); + + // Handle '/' and '\\' + if (!P.empty() && + sys::path::is_separator(P.front(), sys::path::Style::windows)) + return true; + + // Handle drive pattern (i.e "c:"). + if (P.size() >= 2 && (P[0] && P[1] == ':')) + return true; + } + + return sys::path::is_absolute(Path); +} + SectionFilter objdump::ToolSectionFilter(object::ObjectFile const &O, uint64_t *Idx) { // Start at UINT64_MAX so that the first index returned after an increment is @@ -1031,6 +1059,15 @@ } } + if (!Prefix.empty()) { + if (objdumpIsAbsolute(LineInfo.FileName)) { + SmallString<128> FilePath; + sys::path::append(FilePath, Prefix, LineInfo.FileName); + + LineInfo.FileName = std::string(FilePath); + } + } + if (PrintLines) printLines(OS, LineInfo, Delimiter, LVP); if (PrintSource) @@ -2969,6 +3006,15 @@ if (InputFilenames.empty()) InputFilenames.push_back("a.out"); + // The --prefix option removes the trailing separators from the given prefix. + if (!Prefix.empty()) { + bool IsOsWindows = Triple(sys::getProcessTriple()).isOSWindows(); + while (sys::path::is_separator(Prefix.back(), + IsOsWindows ? sys::path::Style::windows + : sys::path::Style::native)) + Prefix.pop_back(); + } + if (AllHeaders) ArchiveHeaders = FileHeaders = PrivateHeaders = Relocations = SectionHeaders = SymbolTable = true;