mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-26 07:24:25 +00:00
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
This commit is contained in:
@ -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() { }
|
||||
|
Reference in New Issue
Block a user