Index: include/llvm/DebugInfo/Symbolize/DIPrinter.h =================================================================== --- include/llvm/DebugInfo/Symbolize/DIPrinter.h +++ include/llvm/DebugInfo/Symbolize/DIPrinter.h @@ -30,17 +30,22 @@ int PrintSourceContext; bool Verbose; bool Basenames; + bool OutputStyleGNU; void print(const DILineInfo &Info, bool Inlined); void printContext(const std::string &FileName, int64_t Line); public: + enum class OutputStyle { LLVM, GNU }; + DIPrinter(raw_ostream &OS, bool PrintFunctionNames = true, bool PrintPretty = false, int PrintSourceContext = 0, - bool Verbose = false, bool Basenames = false) + bool Verbose = false, bool Basenames = false, + OutputStyle Style = OutputStyle::LLVM) : OS(OS), PrintFunctionNames(PrintFunctionNames), PrintPretty(PrintPretty), PrintSourceContext(PrintSourceContext), - Verbose(Verbose), Basenames(Basenames) {} + Verbose(Verbose), Basenames(Basenames), + OutputStyleGNU(Style == OutputStyle::GNU) {} DIPrinter &operator<<(const DILineInfo &Info); DIPrinter &operator<<(const DIInliningInfo &Info); Index: include/llvm/DebugInfo/Symbolize/SymbolizableModule.h =================================================================== --- include/llvm/DebugInfo/Symbolize/SymbolizableModule.h +++ include/llvm/DebugInfo/Symbolize/SymbolizableModule.h @@ -24,9 +24,10 @@ public: virtual ~SymbolizableModule() = default; - virtual DILineInfo symbolizeCode(object::SectionedAddress ModuleOffset, - FunctionNameKind FNKind, - bool UseSymbolTable) const = 0; + virtual DILineInfo + symbolizeCode(object::SectionedAddress ModuleOffset, FunctionNameKind FNKind, + bool UseSymbolTable, + bool UseSymbolTableForInlinedFunctions) const = 0; virtual DIInliningInfo symbolizeInlinedCode(object::SectionedAddress ModuleOffset, FunctionNameKind FNKind, bool UseSymbolTable) const = 0; Index: include/llvm/DebugInfo/Symbolize/Symbolize.h =================================================================== --- include/llvm/DebugInfo/Symbolize/Symbolize.h +++ include/llvm/DebugInfo/Symbolize/Symbolize.h @@ -37,6 +37,10 @@ struct Options { FunctionNameKind PrintFunctions; bool UseSymbolTable : 1; + // Allow LLVMSymbolizer::symbolizeCode to replace the name of an inlined + // function with the name from the symbol table, which corresponds to + // the topmost caller function in the inlining chain. + bool UseSymbolTableForInlinedFunctions : 1; bool Demangle : 1; bool RelativeAddresses : 1; std::string DefaultArch; @@ -46,11 +50,14 @@ Options(FunctionNameKind PrintFunctions = FunctionNameKind::LinkageName, bool UseSymbolTable = true, bool Demangle = true, bool RelativeAddresses = false, std::string DefaultArch = "", - std::string FallbackDebugPath = "") + std::string FallbackDebugPath = "", + bool UseSymbolTableForInlinedFunctions = true) : PrintFunctions(PrintFunctions), UseSymbolTable(UseSymbolTable), Demangle(Demangle), RelativeAddresses(RelativeAddresses), DefaultArch(std::move(DefaultArch)), - FallbackDebugPath(std::move(FallbackDebugPath)) {} + FallbackDebugPath(std::move(FallbackDebugPath)), + UseSymbolTableForInlinedFunctions(UseSymbolTableForInlinedFunctions) { + } }; LLVMSymbolizer(const Options &Opts = Options()) : Opts(Opts) {} Index: lib/DebugInfo/Symbolize/DIPrinter.cpp =================================================================== --- lib/DebugInfo/Symbolize/DIPrinter.cpp +++ lib/DebugInfo/Symbolize/DIPrinter.cpp @@ -81,7 +81,10 @@ else if (Basenames) Filename = llvm::sys::path::filename(Filename); if (!Verbose) { - OS << Filename << ":" << Info.Line << ":" << Info.Column << "\n"; + OS << Filename << ":" << Info.Line; + if (!OutputStyleGNU) + OS << ":" << Info.Column; + OS << "\n"; printContext(Filename, Info.Line); return; } Index: lib/DebugInfo/Symbolize/SymbolizableObjectFile.h =================================================================== --- lib/DebugInfo/Symbolize/SymbolizableObjectFile.h +++ lib/DebugInfo/Symbolize/SymbolizableObjectFile.h @@ -33,9 +33,10 @@ static ErrorOr> create(object::ObjectFile *Obj, std::unique_ptr DICtx); - DILineInfo symbolizeCode(object::SectionedAddress ModuleOffset, - FunctionNameKind FNKind, - bool UseSymbolTable) const override; + DILineInfo + symbolizeCode(object::SectionedAddress ModuleOffset, FunctionNameKind FNKind, + bool UseSymbolTable, + bool UseSymbolTableForInlinedFunctions) const override; DIInliningInfo symbolizeInlinedCode(object::SectionedAddress ModuleOffset, FunctionNameKind FNKind, bool UseSymbolTable) const override; Index: lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp =================================================================== --- lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp +++ lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp @@ -222,10 +222,14 @@ isa(DebugInfoContext.get()); } -DILineInfo -SymbolizableObjectFile::symbolizeCode(object::SectionedAddress ModuleOffset, - FunctionNameKind FNKind, - bool UseSymbolTable) const { +DILineInfo SymbolizableObjectFile::symbolizeCode( + object::SectionedAddress ModuleOffset, FunctionNameKind FNKind, + bool UseSymbolTable, bool UseSymbolTableForInlinedFunctions) const { + if (!UseSymbolTableForInlinedFunctions && + shouldOverrideWithSymbolTable(FNKind, UseSymbolTable)) + return symbolizeInlinedCode(ModuleOffset, FNKind, UseSymbolTable) + .getFrame(0); + DILineInfo LineInfo; if (ModuleOffset.SectionIndex == object::SectionedAddress::UndefSection) Index: lib/DebugInfo/Symbolize/Symbolize.cpp =================================================================== --- lib/DebugInfo/Symbolize/Symbolize.cpp +++ lib/DebugInfo/Symbolize/Symbolize.cpp @@ -70,8 +70,9 @@ if (Opts.RelativeAddresses) ModuleOffset.Address += Info->getModulePreferredBase(); - DILineInfo LineInfo = Info->symbolizeCode(ModuleOffset, Opts.PrintFunctions, - Opts.UseSymbolTable); + DILineInfo LineInfo = Info->symbolizeCode( + ModuleOffset, Opts.PrintFunctions, Opts.UseSymbolTable, + Opts.UseSymbolTableForInlinedFunctions); if (Opts.Demangle) LineInfo.FunctionName = DemangleName(LineInfo.FunctionName, Info); return LineInfo; Index: test/CMakeLists.txt =================================================================== --- test/CMakeLists.txt +++ test/CMakeLists.txt @@ -45,6 +45,7 @@ llc lli lli-child-target + llvm-addr2line llvm-ar llvm-as llvm-bcanalyzer Index: test/tools/llvm-symbolizer/addr2line.test =================================================================== --- /dev/null +++ test/tools/llvm-symbolizer/addr2line.test @@ -0,0 +1,20 @@ +# Should print the function name with '-f'. +# Should print an inlined function name even with '-i=0' (the default) +RUN: llvm-addr2line -fe %p/Inputs/addr.exe < %p/Inputs/addr.inp \ +RUN: | FileCheck %s --check-prefix=FUNCNAME +FUNCNAME: inctwo + +# Should not print function name by default. +RUN: llvm-addr2line -e %p/Inputs/addr.exe < %p/Inputs/addr.inp \ +RUN: | FileCheck %s --check-prefix=NOFUNCNAME +NOFUNCNAME-NOT: inctwo + +# Should not print column number. +RUN: llvm-addr2line -e %p/Inputs/addr.exe < %p/Inputs/addr.inp \ +RUN: | FileCheck %s --check-prefix=NOCOLUMN +NOCOLUMN: {{^}}/tmp{{\\|/}}x.c:3{{$}} + +# Should not print inlined frames by default +RUN: llvm-addr2line -f -p -e %p/Inputs/addr.exe < %p/Inputs/addr.inp \ +RUN: | FileCheck %s --check-prefix=NOINLINING +NOINLINING-NOT: (inlined by) \ No newline at end of file Index: test/tools/llvm-symbolizer/demangle.s =================================================================== --- test/tools/llvm-symbolizer/demangle.s +++ test/tools/llvm-symbolizer/demangle.s @@ -25,5 +25,11 @@ # RUN: llvm-symbolizer --no-demangle -C --obj %t.o 0 \ # RUN: | FileCheck %s --check-prefix=DEMANGLED_FUNCTION_NAME +# Check that for llvm-addr2line the default is not to demangle. +# RUN: llvm-addr2line -fe %t.o 0 \ +# RUN: | FileCheck %s --check-prefix=MANGLED_FUNCTION_NAME +# RUN: llvm-addr2line -fCe %t.o 0 \ +# RUN: | FileCheck %s --check-prefix=DEMANGLED_FUNCTION_NAME + # MANGLED_FUNCTION_NAME: _Z1cv # DEMANGLED_FUNCTION_NAME: c() Index: tools/llvm-symbolizer/CMakeLists.txt =================================================================== --- tools/llvm-symbolizer/CMakeLists.txt +++ tools/llvm-symbolizer/CMakeLists.txt @@ -16,6 +16,8 @@ llvm-symbolizer.cpp ) +add_llvm_tool_symlink(llvm-addr2line llvm-symbolizer) + if(LLVM_INSTALL_BINUTILS_SYMLINKS) add_llvm_tool_symlink(addr2line llvm-symbolizer) endif() Index: tools/llvm-symbolizer/llvm-symbolizer.cpp =================================================================== --- tools/llvm-symbolizer/llvm-symbolizer.cpp +++ tools/llvm-symbolizer/llvm-symbolizer.cpp @@ -43,7 +43,7 @@ clEnumValN(FunctionNameKind::ShortName, "short", "print short function name"), clEnumValN(FunctionNameKind::LinkageName, "linkage", - "print function linkage name (default)"), + "print function linkage name"), // Sentinel value for unspecified value. clEnumValN(FunctionNameKind::LinkageName, "", ""))); static cl::alias ClPrintFunctionsShort("f", cl::desc("Alias for -functions"), @@ -94,10 +94,9 @@ static cl::alias ClBinaryNameAliasExe("exe", cl::desc("Alias for -obj"), cl::NotHidden, cl::aliasopt(ClBinaryName)); -static cl::alias -ClBinaryNameAliasE("e", cl::desc("Alias for -obj"), - cl::NotHidden, cl::aliasopt(ClBinaryName)); - +static cl::alias ClBinaryNameAliasE("e", cl::desc("Alias for -obj"), + cl::Grouping, cl::NotHidden, + cl::aliasopt(ClBinaryName)); static cl::opt ClDwpName("dwp", cl::init(""), @@ -147,6 +146,14 @@ ClFallbackDebugPath("fallback-debug-path", cl::init(""), cl::desc("Fallback path for debug binaries.")); +static cl::opt + ClOutputStyle("output-style", cl::init(DIPrinter::OutputStyle::LLVM), + cl::desc("Specify print style"), cl::Hidden, + cl::values(clEnumValN(DIPrinter::OutputStyle::LLVM, "LLVM", + "LLVM default style"), + clEnumValN(DIPrinter::OutputStyle::GNU, "GNU", + "GNU addr2line style"))); + template static bool error(Expected &ResOrErr) { if (ResOrErr) @@ -233,8 +240,18 @@ int main(int argc, char **argv) { InitLLVM X(argc, argv); + bool IsAddr2Line = sys::path::stem(argv[0]).contains("addr2line"); + + if (IsAddr2Line) { + ClDemangle.setInitialValue(false); + ClPrintFunctions.setInitialValue(FunctionNameKind::None); + ClPrintInlining.setInitialValue(false); + ClOutputStyle.setInitialValue(DIPrinter::OutputStyle::GNU); + } + llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded); - cl::ParseCommandLineOptions(argc, argv, "llvm-symbolizer\n"); + cl::ParseCommandLineOptions( + argc, argv, IsAddr2Line ? "llvm-addr2line\n" : "llvm-symbolizer\n"); // If both --demangle and --no-demangle are specified then pick the last one. if (ClNoDemangle.getPosition() > ClDemangle.getPosition()) @@ -242,7 +259,7 @@ LLVMSymbolizer::Options Opts(ClPrintFunctions, ClUseSymbolTable, ClDemangle, ClUseRelativeAddress, ClDefaultArch, - ClFallbackDebugPath); + ClFallbackDebugPath, !IsAddr2Line); for (const auto &hint : ClDsymHint) { if (sys::path::extension(hint) == ".dSYM") { @@ -256,7 +273,7 @@ DIPrinter Printer(outs(), ClPrintFunctions != FunctionNameKind::None, ClPrettyPrint, ClPrintSourceContextLines, ClVerbose, - ClBasenames); + ClBasenames, ClOutputStyle); if (ClInputAddresses.empty()) { const int kMaxInputStringLength = 1024;