summaryrefslogtreecommitdiffstats
path: root/lib/DebugInfo/DWARFContext.cpp
diff options
context:
space:
mode:
authorAlexey Samsonov <samsonov@google.com>2012-09-04 08:12:33 +0000
committerAlexey Samsonov <samsonov@google.com>2012-09-04 08:12:33 +0000
commit5eae90d727c64ca5b4b43b110521b38dcd9f0de6 (patch)
treeb932b5a23ada1047a06817c055c1e97a469f39a9 /lib/DebugInfo/DWARFContext.cpp
parent2d5c28da0d14883cd0cd6fcf38d7e28040b634c0 (diff)
downloadexternal_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.cpp87
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() { }