diff options
author | Alexey Samsonov <samsonov@google.com> | 2012-09-04 08:12:33 +0000 |
---|---|---|
committer | Alexey Samsonov <samsonov@google.com> | 2012-09-04 08:12:33 +0000 |
commit | 5eae90d727c64ca5b4b43b110521b38dcd9f0de6 (patch) | |
tree | b932b5a23ada1047a06817c055c1e97a469f39a9 /lib/DebugInfo/DWARFContext.cpp | |
parent | 2d5c28da0d14883cd0cd6fcf38d7e28040b634c0 (diff) | |
download | external_llvm-5eae90d727c64ca5b4b43b110521b38dcd9f0de6.zip external_llvm-5eae90d727c64ca5b4b43b110521b38dcd9f0de6.tar.gz external_llvm-5eae90d727c64ca5b4b43b110521b38dcd9f0de6.tar.bz2 |
Add support for fetching inlining context (stack of source code locations)
by instruction address from DWARF.
Add --inlining flag to llvm-dwarfdump to demonstrate and test this functionality,
so that "llvm-dwarfdump --inlining --address=0x..." now works much like
"addr2line -i 0x...", provided that the binary has debug info
(Clang's -gline-tables-only *is* enough).
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163128 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/DebugInfo/DWARFContext.cpp')
-rw-r--r-- | lib/DebugInfo/DWARFContext.cpp | 87 |
1 files changed, 73 insertions, 14 deletions
diff --git a/lib/DebugInfo/DWARFContext.cpp b/lib/DebugInfo/DWARFContext.cpp index 3f9edd3..241f55e 100644 --- a/lib/DebugInfo/DWARFContext.cpp +++ b/lib/DebugInfo/DWARFContext.cpp @@ -183,15 +183,11 @@ static bool getFileNameForCompileUnit( return true; } -bool -DWARFContext::getFileLineInfoForCompileUnit(DWARFCompileUnit *CU, - uint64_t Address, - bool NeedsAbsoluteFilePath, - std::string &FileName, - uint32_t &Line, uint32_t &Column) { - // Get the line table for this compile unit. - const DWARFDebugLine::LineTable *LineTable = getLineTableForCompileUnit(CU); - if (!LineTable) +static bool getFileLineInfoForCompileUnit( + DWARFCompileUnit *CU, const DWARFDebugLine::LineTable *LineTable, + uint64_t Address, bool NeedsAbsoluteFilePath, std::string &FileName, + uint32_t &Line, uint32_t &Column) { + if (CU == 0 || LineTable == 0) return false; // Get the index of row we're looking for in the line table. uint32_t RowIndex = LineTable->lookupAddress(Address); @@ -217,21 +213,84 @@ DILineInfo DWARFContext::getLineInfoForAddress(uint64_t Address, uint32_t Line = 0; uint32_t Column = 0; if (Specifier.needs(DILineInfoSpecifier::FunctionName)) { - const DWARFDebugInfoEntryMinimal *FunctionDIE = - CU->getFunctionDIEForAddress(Address); - if (FunctionDIE) { - if (const char *Name = FunctionDIE->getSubprogramName(CU)) + // The address may correspond to instruction in some inlined function, + // so we have to build the chain of inlined functions and take the + // name of the topmost function in it. + const DWARFDebugInfoEntryMinimal::InlinedChain &InlinedChain = + CU->getInlinedChainForAddress(Address); + if (InlinedChain.size() > 0) { + const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain[0]; + if (const char *Name = TopFunctionDIE.getSubroutineName(CU)) FunctionName = Name; } } if (Specifier.needs(DILineInfoSpecifier::FileLineInfo)) { + const DWARFDebugLine::LineTable *LineTable = + getLineTableForCompileUnit(CU); const bool NeedsAbsoluteFilePath = Specifier.needs(DILineInfoSpecifier::AbsoluteFilePath); - getFileLineInfoForCompileUnit(CU, Address, NeedsAbsoluteFilePath, + getFileLineInfoForCompileUnit(CU, LineTable, Address, + NeedsAbsoluteFilePath, FileName, Line, Column); } return DILineInfo(StringRef(FileName), StringRef(FunctionName), Line, Column); } +DIInliningInfo DWARFContext::getInliningInfoForAddress(uint64_t Address, + DILineInfoSpecifier Specifier) { + DWARFCompileUnit *CU = getCompileUnitForAddress(Address); + if (!CU) + return DIInliningInfo(); + + const DWARFDebugInfoEntryMinimal::InlinedChain &InlinedChain = + CU->getInlinedChainForAddress(Address); + if (InlinedChain.size() == 0) + return DIInliningInfo(); + + DIInliningInfo InliningInfo; + uint32_t CallFile = 0, CallLine = 0, CallColumn = 0; + const DWARFDebugLine::LineTable *LineTable = 0; + for (uint32_t i = 0, n = InlinedChain.size(); i != n; i++) { + const DWARFDebugInfoEntryMinimal &FunctionDIE = InlinedChain[i]; + std::string FileName = "<invalid>"; + std::string FunctionName = "<invalid>"; + uint32_t Line = 0; + uint32_t Column = 0; + // Get function name if necessary. + if (Specifier.needs(DILineInfoSpecifier::FunctionName)) { + if (const char *Name = FunctionDIE.getSubroutineName(CU)) + FunctionName = Name; + } + if (Specifier.needs(DILineInfoSpecifier::FileLineInfo)) { + const bool NeedsAbsoluteFilePath = + Specifier.needs(DILineInfoSpecifier::AbsoluteFilePath); + if (i == 0) { + // For the topmost frame, initialize the line table of this + // compile unit and fetch file/line info from it. + LineTable = getLineTableForCompileUnit(CU); + // For the topmost routine, get file/line info from line table. + getFileLineInfoForCompileUnit(CU, LineTable, Address, + NeedsAbsoluteFilePath, + FileName, Line, Column); + } else { + // Otherwise, use call file, call line and call column from + // previous DIE in inlined chain. + getFileNameForCompileUnit(CU, LineTable, CallFile, + NeedsAbsoluteFilePath, FileName); + Line = CallLine; + Column = CallColumn; + } + // Get call file/line/column of a current DIE. + if (i + 1 < n) { + FunctionDIE.getCallerFrame(CU, CallFile, CallLine, CallColumn); + } + } + DILineInfo Frame(StringRef(FileName), StringRef(FunctionName), + Line, Column); + InliningInfo.addFrame(Frame); + } + return InliningInfo; +} + void DWARFContextInMemory::anchor() { } |