From 804ff7f2933f2b0845da12c84c439a2e3d8b4e69 Mon Sep 17 00:00:00 2001 From: Vinicius Tinti Date: Fri, 31 Jul 2020 22:45:05 -0300 Subject: [PATCH] [llvm-objdump] Implement --prefix-strip option The option `--prefix-strip` is only used when `--prefix` is not empty. It removes N initial directories from absolute paths before adding the prefix. This matches GNU's objdump behavior. Reviewed By: jhenderson Differential Revision: https://reviews.llvm.org/D96679 --- llvm/docs/CommandGuide/llvm-objdump.rst | 6 ++ llvm/docs/llvm-objdump.1 | 5 ++ .../X86/source-interleave-prefix.test | 58 +++++++++++++++++-- llvm/tools/llvm-objdump/llvm-objdump.cpp | 27 +++++++++ llvm/tools/llvm-objdump/llvm-objdump.h | 1 + 5 files changed, 92 insertions(+), 5 deletions(-) diff --git a/llvm/docs/CommandGuide/llvm-objdump.rst b/llvm/docs/CommandGuide/llvm-objdump.rst index e92654b654ea..49edbcd91b07 100644 --- a/llvm/docs/CommandGuide/llvm-objdump.rst +++ b/llvm/docs/CommandGuide/llvm-objdump.rst @@ -172,6 +172,12 @@ OPTIONS 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. This option has no effect without + :option:`--prefix`. + .. option:: --print-imm-hex Use hex format when printing immediate values in disassembly output. diff --git a/llvm/docs/llvm-objdump.1 b/llvm/docs/llvm-objdump.1 index 1cf557dc8b64..4e9dbaea8704 100644 --- a/llvm/docs/llvm-objdump.1 +++ b/llvm/docs/llvm-objdump.1 @@ -109,6 +109,11 @@ When disassembling instructions, do not print the instruction bytes. 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. This option has no effect without +.Fl -prefix Ns = Ns PREFIX . .It Fl -print-imm-hex Use hex format for immediate values. .It Fl -private-header diff --git a/llvm/test/tools/llvm-objdump/X86/source-interleave-prefix.test b/llvm/test/tools/llvm-objdump/X86/source-interleave-prefix.test index f82d403437b4..c2fc95ed4f02 100644 --- a/llvm/test/tools/llvm-objdump/X86/source-interleave-prefix.test +++ b/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,64 @@ ; 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. +;; SRC_COMPDIR is set to '/Inputs' before and after --prefix-strip 0. + +; 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. +;; SRC_COMPDIR is set to '/Inputs' before --prefix-strip 1. +;; SRC_COMPDIR becomes '' after --prefix-strip 1. + +; RUN: llvm-objdump --prefix %p/Inputs --prefix-strip 1 --source %t-missing-prefix.o 2>&1 | \ +; RUN: FileCheck %s --check-prefix=CHECK-MISSING-PREFIX-FIX + +;; Test --prefix-strip value greater than the number of components. +;; SRC_COMPDIR is set to '/Inputs' before --prefix-strip 2. +;; SRC_COMPDIR becomes '' after --prefix-strip 2. + +; RUN: llvm-objdump --prefix %p/Inputs --prefix-strip 2 --source %t-missing-prefix.o 2>&1 | \ +; RUN: FileCheck %s --check-prefix=CHECK-MISSING-PREFIX-FIX + +;; Test negative value --prefix-strip. Reports an error. + +; RUN: not llvm-objdump --prefix %p --prefix-strip '-1' --source %t-missing-prefix.o 2>&1 | \ +; RUN: FileCheck %s --check-prefix=CHECK-INVALID-PREFIX-STRIP -DOPTION='-1' +; CHECK-INVALID-PREFIX-STRIP: llvm-objdump{{.*}}: for the --prefix-strip option: '[[OPTION]]' value invalid for uint argument! + +;; Test text value --prefix-strip. Reports an error. + +; RUN: not llvm-objdump --prefix %p --prefix-strip foo --source %t-missing-prefix.o 2>&1 | \ +; RUN: FileCheck %s --check-prefix=CHECK-INVALID-PREFIX-STRIP -DOPTION='foo' diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp index 6fccaa694afa..13d60f721add 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -358,6 +358,12 @@ cl::opt objdump::Prefix("prefix", 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. No effect without --prefix"), + cl::init(0), cl::cat(ObjdumpCat)); + enum DebugVarsFormat { DVDisabled, DVUnicode, @@ -1031,6 +1037,27 @@ void SourcePrinter::printSourceLine(formatted_raw_ostream &OS, } 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; + auto StrippedNameStart = LineInfo.FileName.begin(); + + // Path.h iterator skips extra separators. Therefore it cannot be used + // here to keep compatibility with GNU Objdump. + for (auto Pos = StrippedNameStart + 1, End = LineInfo.FileName.end(); + Pos != End && Level < PrefixStrip; ++Pos) { + if (sys::path::is_separator(*Pos)) { + StrippedNameStart = Pos; + ++Level; + } + } + + LineInfo.FileName = + std::string(StrippedNameStart, LineInfo.FileName.end()); + } + SmallString<128> FilePath; sys::path::append(FilePath, Prefix, LineInfo.FileName); diff --git a/llvm/tools/llvm-objdump/llvm-objdump.h b/llvm/tools/llvm-objdump/llvm-objdump.h index d15bc059b450..884702d11f85 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.h +++ b/llvm/tools/llvm-objdump/llvm-objdump.h @@ -42,6 +42,7 @@ extern cl::opt MCPU; 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;