This change allows to use llvm-symbolizer binary in
signal handler to provide a better stacktrace. Instead of printing
raw addresses and optional symbol names, stack trace will now contain
file/line information (if binary has debug info). See example outputs below.
This is an RFC patch. IMO it can already be applied now with minor changes
(add a check that dl_iterate_phdr and <link.h> are available on given platform).
However, I see the following areas for improvement:
- Thanks to powerful LLVMSupport, printSymbolizedStackTrace() is short and
mostly portable code (the only Linux-specific part is dl_iterate_phdr). We can
make this function generally available by putting it to Support headers. By doing
this we'll also be able to unit-test both this function and llvm-symbolizer tool
(to some extent).
- Currently llvm-symbolizer input/output format is hardcoded in the tool
implementation *and* in printSymbolizedStackTrace(). We can instead move the
description of this format to Support headers/library: move DILineInfo (format-neutral
container for representing file/line information) and DIInliningInfo to Support
and provide methods to serialize/deserialize it. These methods can then be used
in both tools/llvm-symbolizer and printSymbolizedStackTraces() and unit-tested
appropriately.
Let me know what you think about this patch (in case I'm doing something stupid),
and what pieces of 1)-2) I should work on before landing this (or I can procced
with this patch and work on that parts later).
- before:
0 clang 0x00000000021f260f llvm::sys::PrintStackTrace(_IO_FILE*) + 38
1 clang 0x00000000021f288c
2 clang 0x00000000021f14ea
3 libpthread.so.0 0x00002b753e753cb0
4 libc.so.6 0x00002b753f3ca0d5 gsignal + 53
5 libc.so.6 0x00002b753f3cd83b abort + 379
6 libc.so.6 0x00002b753f3c2d9e
7 libc.so.6 0x00002b753f3c2e42
8 clang 0x0000000002891db7 clang::CodeGen::CodeGenFunction::EmitFunctionEpilog(clang::CodeGen::CGFunctionInfo const&, bool, clang::SourceLocation) + 2163
9 clang 0x00000000027844de clang::CodeGen::CodeGenFunction::FinishFunction(clang::SourceLocation) + 518
10 clang 0x0000000002787a72 clang::CodeGen::CodeGenFunction::GenerateCode(clang::GlobalDecl, llvm::Function*, clang::CodeGen::CGFunctionInfo const&) + 2304
11 clang 0x000000000279b63a clang::CodeGen::CodeGenModule::EmitGlobalFunctionDefinition(clang::GlobalDecl, llvm::GlobalValue*) + 1134
12 clang 0x00000000027989c9 clang::CodeGen::CodeGenModule::EmitGlobalDefinition(clang::GlobalDecl, llvm::GlobalValue*) + 487
13 clang 0x0000000002798299 clang::CodeGen::CodeGenModule::EmitGlobal(clang::GlobalDecl) + 801
14 clang 0x000000000279eace clang::CodeGen::CodeGenModule::EmitTopLevelDecl(clang::Decl*) + 292
15 clang 0x000000000271acf5
16 clang 0x0000000002704c8e
17 clang 0x00000000030dd545 clang::ParseAST(clang::Sema&, bool, bool) + 550
18 clang 0x00000000023da536 clang::ASTFrontendAction::ExecuteAction() + 322
19 clang 0x000000000270749c clang::CodeGenAction::ExecuteAction() + 1306
20 clang 0x00000000023d9fed clang::FrontendAction::Execute() + 139
21 clang 0x00000000023a3c1c clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) + 770
22 clang 0x00000000024e8117 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) + 1102
23 clang 0x000000000113f53f cc1_main(llvm::ArrayRef<char const*>, char const*, void*) + 689
24 clang 0x000000000113840d
25 clang 0x0000000001138994 main + 979
26 libc.so.6 0x00002b753f3b576d __libc_start_main + 237
27 clang 0x0000000001135609
<...>
- after:
#0 0x21f260f llvm::sys::PrintStackTrace(_IO_FILE*) llvm/lib/Support/Unix/Signals.inc:399:0
#1 0x21f28aa PrintStackTraceSignalHandler(void*) llvm/lib/Support/Unix/Signals.inc:457:0
#2 0x21f14ea SignalHandler(int) llvm/lib/Support/Unix/Signals.inc:196:0
#3 0x2b3c83ca6cb0 restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0xfcb0)
#4 0x2b3c8491d0d5 gsignal /build/buildd/eglibc-2.15/signal/../nptl/sysdeps/unix/sysv/linux/raise.c:64:0
#5 0x2b3c8492083b abort /build/buildd/eglibc-2.15/stdlib/abort.c:93:0
#6 0x2b3c84915d9e assert_fail_base /build/buildd/eglibc-2.15/assert/assert.c:55:0
#7 0x2b3c84915e42 (/lib/x86_64-linux-gnu/libc.so.6+0x2ee42)
#8 0x2891dd7 clang::CodeGen::CodeGenFunction::EmitFunctionEpilog(clang::CodeGen::CGFunctionInfo const&, bool, clang::SourceLocation) llvm/tools/clang/lib/CodeGen/CGCall.cpp:2219:0
#9 0x27844fe clang::CodeGen::CodeGenFunction::FinishFunction(clang::SourceLocation) llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp:261:0
#10 0x2787a92 clang::CodeGen::CodeGenFunction::GenerateCode(clang::GlobalDecl, llvm::Function*, clang::CodeGen::CGFunctionInfo const&) llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp:910:0
#11 0x279b65a clang::CodeGen::CodeGenModule::EmitGlobalFunctionDefinition(clang::GlobalDecl, llvm::GlobalValue*) llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp:2292:0
#12 0x27989e9 clang::CodeGen::CodeGenModule::EmitGlobalDefinition(clang::GlobalDecl, llvm::GlobalValue*) llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp:1433:0
#13 0x27982b9 clang::CodeGen::CodeGenModule::EmitGlobal(clang::GlobalDecl) llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp:1293:0
#14 0x279eaee clang::CodeGen::CodeGenModule::EmitTopLevelDecl(clang::Decl*) llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp:3034:0
#15 0x271ad15 (anonymous namespace)::CodeGeneratorImpl::HandleTopLevelDecl(clang::DeclGroupRef) llvm/tools/clang/lib/CodeGen/ModuleBuilder.cpp:113:0
#16 0x2704cae clang::BackendConsumer::HandleTopLevelDecl(clang::DeclGroupRef) llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp:106:0
#17 0x30dd565 clang::ParseAST(clang::Sema&, bool, bool) llvm/tools/clang/lib/Parse/ParseAST.cpp:143:0
#18 0x23da556 clang::ASTFrontendAction::ExecuteAction() llvm/tools/clang/lib/Frontend/FrontendAction.cpp:523:0
#19 0x27074bc clang::CodeGenAction::ExecuteAction() llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp:718:0
#20 0x23da00d clang::FrontendAction::Execute() llvm/tools/clang/lib/Frontend/FrontendAction.cpp:427:0
#21 0x23a3c3c clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) llvm/tools/clang/lib/Frontend/CompilerInstance.cpp:812:0
#22 0x24e8137 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp:222:0
#23 0x113f53f cc1_main(llvm::ArrayRef<char const*>, char const*, void*) llvm/tools/clang/tools/driver/cc1_main.cpp:110:0
#24 0x113840d ExecuteCC1Tool(llvm::ArrayRef<char const*>, llvm::StringRef) llvm/tools/clang/tools/driver/driver.cpp:368:0
#25 0x1138994 main llvm/tools/clang/tools/driver/driver.cpp:411:0
#26 0x2b3c8490876d __libc_start_main /build/buildd/eglibc-2.15/csu/libc-start.c:258:0
#27 0x1135609 _start (llvm_cmake_debug/bin/clang-3.6+0x1135609)
<...>
This builds on FreeBSD (with the linux removed again) after your ElfW(Phdr)->auto *phdr change