[llvm-symbolizer] Print file/line for a PC even if there is no DIE describing it.

This is important for symbolizing executables with debug info in
unavailable .dwo files. Even if all DIE entries are missing, we can
still symbolize an address: function name can be fetched from symbol table,
and file/line info can be fetched from line table.

llvm-svn: 206665
This commit is contained in:
Alexey Samsonov 2014-04-18 22:22:44 +00:00
parent ec8c975214
commit 5c39fdfb7b
4 changed files with 42 additions and 9 deletions

View File

@ -545,18 +545,32 @@ DILineInfoTable DWARFContext::getLineInfoForAddressRange(uint64_t Address,
DIInliningInfo DWARFContext::getInliningInfoForAddress(uint64_t Address, DIInliningInfo DWARFContext::getInliningInfoForAddress(uint64_t Address,
DILineInfoSpecifier Specifier) { DILineInfoSpecifier Specifier) {
DIInliningInfo InliningInfo;
DWARFCompileUnit *CU = getCompileUnitForAddress(Address); DWARFCompileUnit *CU = getCompileUnitForAddress(Address);
if (!CU) if (!CU)
return DIInliningInfo(); return InliningInfo;
const DWARFLineTable *LineTable = nullptr;
const bool NeedsAbsoluteFilePath =
Specifier.needs(DILineInfoSpecifier::AbsoluteFilePath);
const DWARFDebugInfoEntryInlinedChain &InlinedChain = const DWARFDebugInfoEntryInlinedChain &InlinedChain =
CU->getInlinedChainForAddress(Address); CU->getInlinedChainForAddress(Address);
if (InlinedChain.DIEs.size() == 0) if (InlinedChain.DIEs.size() == 0) {
return DIInliningInfo(); // If there is no DIE for address (e.g. it is in unavailable .dwo file),
// try to at least get file/line info from symbol table.
if (Specifier.needs(DILineInfoSpecifier::FileLineInfo)) {
DILineInfo Frame;
LineTable = getLineTableForCompileUnit(CU);
if (getFileLineInfoForCompileUnit(CU, LineTable, Address,
NeedsAbsoluteFilePath, Frame)) {
InliningInfo.addFrame(Frame);
}
}
return InliningInfo;
}
DIInliningInfo InliningInfo;
uint32_t CallFile = 0, CallLine = 0, CallColumn = 0; uint32_t CallFile = 0, CallLine = 0, CallColumn = 0;
const DWARFLineTable *LineTable = nullptr;
for (uint32_t i = 0, n = InlinedChain.DIEs.size(); i != n; i++) { for (uint32_t i = 0, n = InlinedChain.DIEs.size(); i != n; i++) {
const DWARFDebugInfoEntryMinimal &FunctionDIE = InlinedChain.DIEs[i]; const DWARFDebugInfoEntryMinimal &FunctionDIE = InlinedChain.DIEs[i];
DILineInfo Frame; DILineInfo Frame;
@ -566,16 +580,13 @@ DIInliningInfo DWARFContext::getInliningInfoForAddress(uint64_t Address,
Frame.FunctionName = Name; Frame.FunctionName = Name;
} }
if (Specifier.needs(DILineInfoSpecifier::FileLineInfo)) { if (Specifier.needs(DILineInfoSpecifier::FileLineInfo)) {
const bool NeedsAbsoluteFilePath =
Specifier.needs(DILineInfoSpecifier::AbsoluteFilePath);
if (i == 0) { if (i == 0) {
// For the topmost frame, initialize the line table of this // For the topmost frame, initialize the line table of this
// compile unit and fetch file/line info from it. // compile unit and fetch file/line info from it.
LineTable = getLineTableForCompileUnit(CU); LineTable = getLineTableForCompileUnit(CU);
// For the topmost routine, get file/line info from line table. // For the topmost routine, get file/line info from line table.
getFileLineInfoForCompileUnit(CU, LineTable, Address, getFileLineInfoForCompileUnit(CU, LineTable, Address,
NeedsAbsoluteFilePath, NeedsAbsoluteFilePath, Frame);
Frame);
} else { } else {
// Otherwise, use call file, call line and call column from // Otherwise, use call file, call line and call column from
// previous DIE in inlined chain. // previous DIE in inlined chain.

Binary file not shown.

View File

@ -0,0 +1,18 @@
int f(int a, int b) {
return a + b;
}
int g(int a) {
return a + 1;
}
int main() {
return f(2, g(2));
}
// Built with Clang 3.5.0:
// $ mkdir -p /tmp/dbginfo
// $ cp llvm-symbolizer-dwo-test.cc /tmp/dbginfo
// $ cd /tmp/dbginfo
// $ clang -gsplit-dwarf llvm-symbolizer-dwo-test.cc

View File

@ -8,6 +8,7 @@ RUN: echo "\"%p/Inputs/dwarfdump-test3.elf-x86-64 space\" 0x633" >> %t.input
RUN: echo "%p/Inputs/macho-universal 0x1f84" >> %t.input RUN: echo "%p/Inputs/macho-universal 0x1f84" >> %t.input
RUN: echo "%p/Inputs/macho-universal:i386 0x1f67" >> %t.input RUN: echo "%p/Inputs/macho-universal:i386 0x1f67" >> %t.input
RUN: echo "%p/Inputs/macho-universal:x86_64 0x100000f05" >> %t.input RUN: echo "%p/Inputs/macho-universal:x86_64 0x100000f05" >> %t.input
RUN: echo "%p/Inputs/llvm-symbolizer-dwo-test 0x400514" >> %t.input
RUN: llvm-symbolizer --functions --inlining --demangle=false \ RUN: llvm-symbolizer --functions --inlining --demangle=false \
RUN: --default-arch=i386 < %t.input | FileCheck %s RUN: --default-arch=i386 < %t.input | FileCheck %s
@ -48,6 +49,9 @@ CHECK: main
CHECK: _Z3inci CHECK: _Z3inci
CHECK: _Z3inci CHECK: _Z3inci
CHECK: main
CHECK-NEXT: llvm-symbolizer-dwo-test.cc:11
RUN: echo "unexisting-file 0x1234" > %t.input2 RUN: echo "unexisting-file 0x1234" > %t.input2
RUN: llvm-symbolizer < %t.input2 RUN: llvm-symbolizer < %t.input2