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/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: test/tools/llvm-symbolizer/help.test =================================================================== --- /dev/null +++ test/tools/llvm-symbolizer/help.test @@ -0,0 +1,8 @@ +RUN: llvm-symbolizer -help | FileCheck %s --check-prefix=SYMBOLIZER +RUN: llvm-addr2line -help | FileCheck %s --check-prefix=ADDR2LINE + +SYMBOLIZER: OVERVIEW: llvm-symbolizer +SYMBOLIZER: USAGE: llvm-symbolizer{{(.exe)?}} [options] ... + +ADDR2LINE: OVERVIEW: llvm-addr2line +ADDR2LINE: USAGE: llvm-addr2line{{(.exe)?}} [options] ... Index: test/tools/llvm-symbolizer/output-style.test =================================================================== --- test/tools/llvm-symbolizer/output-style.test +++ test/tools/llvm-symbolizer/output-style.test @@ -7,5 +7,14 @@ RUN: llvm-symbolizer --output-style=LLVM -e %p/Inputs/addr.exe 0x40054d \ RUN: | FileCheck %s --check-prefix=LLVM +RUN: llvm-addr2line -e %p/Inputs/addr.exe 0x40054d \ +RUN: | FileCheck %s --check-prefix=GNU + +RUN: llvm-addr2line --output-style=GNU -e %p/Inputs/addr.exe 0x40054d \ +RUN: | FileCheck %s --check-prefix=GNU + +RUN: llvm-addr2line --output-style=LLVM -e %p/Inputs/addr.exe 0x40054d \ +RUN: | FileCheck %s --check-prefix=LLVM + LLVM: {{^}}/tmp{{\\|/}}x.c:3:3{{$}} GNU: {{^}}/tmp{{\\|/}}x.c:3{{$}} Index: test/tools/llvm-symbolizer/sym.test =================================================================== --- test/tools/llvm-symbolizer/sym.test +++ test/tools/llvm-symbolizer/sym.test @@ -29,6 +29,19 @@ RUN: echo "0x1" > %t.input RUN: llvm-symbolizer -obj=%p/Inputs/zero < %t.input | FileCheck -check-prefix="ZERO" %s +RUN: llvm-addr2line -obj=%p/Inputs/addr.exe < %p/Inputs/addr.inp | FileCheck -check-prefix=A2L %s +RUN: llvm-addr2line -a -obj=%p/Inputs/addr.exe < %p/Inputs/addr.inp | FileCheck -check-prefixes=A2L,A2L_A %s +RUN: llvm-addr2line -f -obj=%p/Inputs/addr.exe < %p/Inputs/addr.inp | FileCheck -check-prefixes=A2L,A2L_F %s +RUN: llvm-addr2line -i -obj=%p/Inputs/addr.exe < %p/Inputs/addr.inp | FileCheck -check-prefixes=A2L,A2L_I %s +RUN: llvm-addr2line -fi -obj=%p/Inputs/addr.exe < %p/Inputs/addr.inp | FileCheck -check-prefixes=A2L,A2L_F,A2L_I,A2L_FI %s + +RUN: llvm-addr2line -pa -obj=%p/Inputs/addr.exe < %p/Inputs/addr.inp | FileCheck -check-prefixes=A2LP,A2LP_A %s +RUN: llvm-addr2line -pf -obj=%p/Inputs/addr.exe < %p/Inputs/addr.inp | FileCheck -check-prefixes=A2LP,A2LP_F %s +RUN: llvm-addr2line -paf -obj=%p/Inputs/addr.exe < %p/Inputs/addr.inp | FileCheck -check-prefixes=A2LP,A2LP_AF %s +RUN: llvm-addr2line -pai -obj=%p/Inputs/addr.exe < %p/Inputs/addr.inp | FileCheck -check-prefixes=A2LP,A2LP_A,A2LP_I %s +RUN: llvm-addr2line -pfi -obj=%p/Inputs/addr.exe < %p/Inputs/addr.inp | FileCheck -check-prefixes=A2LP,A2LP_F,A2LP_FI %s +RUN: llvm-addr2line -pafi -obj=%p/Inputs/addr.exe < %p/Inputs/addr.inp | FileCheck -check-prefixes=A2LP,A2LP_AF,A2LP_FI %s + #CHECK: some text #CHECK: 0x40054d #CHECK: main @@ -43,3 +56,23 @@ # #ZERO: ?? #ZERO: ??:0:0 +# +#A2L: some text +#A2L_A-NEXT: 0x40054d +#A2L_F-NEXT: inctwo +#A2L-NEXT: {{[/\]+}}tmp{{[/\]+}}x.c:3 +#A2L_FI-NEXT: inc +#A2L_I-NEXT: {{[/\]+}}tmp{{[/\]+}}x.c:7 +#A2L_FI-NEXT: main +#A2L_I-NEXT: {{[/\]+}}tmp{{[/\]+}}x.c:14 +#A2L-NEXT: some text2 + +#A2LP: some text +#A2LP_A-NEXT: 0x40054d: {{[/\]+}}tmp{{[/\]+}}x.c:3 +#A2LP_F-NEXT: inctwo at {{[/\]+}}tmp{{[/\]+}}x.c:3 +#A2LP_AF-NEXT: 0x40054d: inctwo at {{[/\]+}}tmp{{[/\]+}}x.c:3 +#A2LP_I-NEXT: {{[/\]+}}tmp{{[/\]+}}x.c:7 +#A2LP_I-NEXT: {{[/\]+}}tmp{{[/\]+}}x.c:14 +#A2LP_FI-NEXT: (inlined by) inc at {{[/\]+}}tmp{{[/\]+}}x.c:7 +#A2LP_FI-NEXT: (inlined by) main at {{[/\]+}}tmp{{[/\]+}}x.c:14 +#A2LP-NEXT: some text2 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"), @@ -202,7 +202,7 @@ } static void symbolizeInput(StringRef InputString, LLVMSymbolizer &Symbolizer, - DIPrinter &Printer) { + DIPrinter &Printer, bool IsAddr2Line) { bool IsData = false; std::string ModuleName; uint64_t Offset = 0; @@ -227,21 +227,43 @@ ModuleName, {Offset, object::SectionedAddress::UndefSection}, ClDwpName); Printer << (error(ResOrErr) ? DIInliningInfo() : ResOrErr.get()); + } else if (IsAddr2Line) { + // With ClPrintFunctions == FunctionNameKind::LinkageName (default) + // and ClUseSymbolTable == true (also default), Symbolizer.symbolizeCode() + // may override the name of an inlined function with the name of the topmost + // caller function in the inlining chain. This contradicts the existing + // behavior of addr2line. Symbolizer.symbolizeInlinedCode() overrides only + // the topmost function, which suites our needs better. + auto ResOrErr = Symbolizer.symbolizeInlinedCode( + ModuleName, {Offset, object::SectionedAddress::UndefSection}, + ClDwpName); + Printer << (error(ResOrErr) ? DILineInfo() : ResOrErr.get().getFrame(0)); } else { auto ResOrErr = Symbolizer.symbolizeCode( ModuleName, {Offset, object::SectionedAddress::UndefSection}, ClDwpName); Printer << (error(ResOrErr) ? DILineInfo() : ResOrErr.get()); } - outs() << "\n"; + if (!IsAddr2Line) + outs() << "\n"; outs().flush(); } 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()) @@ -270,10 +292,10 @@ char InputString[kMaxInputStringLength]; while (fgets(InputString, sizeof(InputString), stdin)) - symbolizeInput(InputString, Symbolizer, Printer); + symbolizeInput(InputString, Symbolizer, Printer, IsAddr2Line); } else { for (StringRef Address : ClInputAddresses) - symbolizeInput(Address, Symbolizer, Printer); + symbolizeInput(Address, Symbolizer, Printer, IsAddr2Line); } return 0;