mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-04 01:26:41 +00:00
Get function start line number from DWARF info
DWARF info contains info about the line number at which a function starts (DW_AT_decl_line). This patch creates a function to look up the start line number for a function, and returns it in DILineInfo when looking up debug info for a particular address. Patch by Simon Que! Reviewed By: dblaikie Differential Revision: https://reviews.llvm.org/D27962 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@294231 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
919fdbb92a
commit
4ee57e2bef
@ -34,24 +34,28 @@ struct DILineInfo {
|
||||
std::string FunctionName;
|
||||
uint32_t Line;
|
||||
uint32_t Column;
|
||||
uint32_t StartLine;
|
||||
|
||||
// DWARF-specific.
|
||||
uint32_t Discriminator;
|
||||
|
||||
DILineInfo()
|
||||
: FileName("<invalid>"), FunctionName("<invalid>"), Line(0), Column(0),
|
||||
Discriminator(0) {}
|
||||
StartLine(0), Discriminator(0) {}
|
||||
|
||||
bool operator==(const DILineInfo &RHS) const {
|
||||
return Line == RHS.Line && Column == RHS.Column &&
|
||||
FileName == RHS.FileName && FunctionName == RHS.FunctionName;
|
||||
FileName == RHS.FileName && FunctionName == RHS.FunctionName &&
|
||||
StartLine == RHS.StartLine && Discriminator == RHS.Discriminator;
|
||||
}
|
||||
bool operator!=(const DILineInfo &RHS) const {
|
||||
return !(*this == RHS);
|
||||
}
|
||||
bool operator<(const DILineInfo &RHS) const {
|
||||
return std::tie(FileName, FunctionName, Line, Column) <
|
||||
std::tie(RHS.FileName, RHS.FunctionName, RHS.Line, RHS.Column);
|
||||
return std::tie(FileName, FunctionName, Line, Column, StartLine,
|
||||
Discriminator) <
|
||||
std::tie(RHS.FileName, RHS.FunctionName, RHS.Line, RHS.Column,
|
||||
RHS.StartLine, RHS.Discriminator);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -233,6 +233,12 @@ public:
|
||||
/// references if necessary. Returns null if no name is found.
|
||||
const char *getName(DINameKind Kind) const;
|
||||
|
||||
/// Returns the declaration line (start line) for a DIE, assuming it specifies
|
||||
/// a subprogram. This may be fetched from specification or abstract origin
|
||||
/// for this subprogram by resolving DW_AT_sepcification or
|
||||
/// DW_AT_abstract_origin references if necessary.
|
||||
uint64_t getDeclLine() const;
|
||||
|
||||
/// Retrieves values of DW_AT_call_file, DW_AT_call_line and DW_AT_call_column
|
||||
/// from DIE (or zeroes if they are missing). This function looks for
|
||||
/// DW_AT_call attributes in this DIE only, it will not resolve the attribute
|
||||
|
@ -439,23 +439,32 @@ DWARFCompileUnit *DWARFContext::getCompileUnitForAddress(uint64_t Address) {
|
||||
return getCompileUnitForOffset(CUOffset);
|
||||
}
|
||||
|
||||
static bool getFunctionNameForAddress(DWARFCompileUnit *CU, uint64_t Address,
|
||||
FunctionNameKind Kind,
|
||||
std::string &FunctionName) {
|
||||
if (Kind == FunctionNameKind::None)
|
||||
return false;
|
||||
static bool getFunctionNameAndStartLineForAddress(DWARFCompileUnit *CU,
|
||||
uint64_t Address,
|
||||
FunctionNameKind Kind,
|
||||
std::string &FunctionName,
|
||||
uint32_t &StartLine) {
|
||||
// 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.SmallVectorImpl<DWARFDie> &InlinedChain
|
||||
// name of the topmost function in it.
|
||||
SmallVector<DWARFDie, 4> InlinedChain;
|
||||
CU->getInlinedChainForAddress(Address, InlinedChain);
|
||||
if (InlinedChain.size() == 0)
|
||||
if (InlinedChain.empty())
|
||||
return false;
|
||||
if (const char *Name = InlinedChain[0].getSubroutineName(Kind)) {
|
||||
|
||||
const DWARFDie &DIE = InlinedChain[0];
|
||||
bool FoundResult = false;
|
||||
const char *Name = nullptr;
|
||||
if (Kind != FunctionNameKind::None && (Name = DIE.getSubroutineName(Kind))) {
|
||||
FunctionName = Name;
|
||||
return true;
|
||||
FoundResult = true;
|
||||
}
|
||||
return false;
|
||||
if (auto DeclLineResult = DIE.getDeclLine()) {
|
||||
StartLine = DeclLineResult;
|
||||
FoundResult = true;
|
||||
}
|
||||
|
||||
return FoundResult;
|
||||
}
|
||||
|
||||
DILineInfo DWARFContext::getLineInfoForAddress(uint64_t Address,
|
||||
@ -465,7 +474,9 @@ DILineInfo DWARFContext::getLineInfoForAddress(uint64_t Address,
|
||||
DWARFCompileUnit *CU = getCompileUnitForAddress(Address);
|
||||
if (!CU)
|
||||
return Result;
|
||||
getFunctionNameForAddress(CU, Address, Spec.FNKind, Result.FunctionName);
|
||||
getFunctionNameAndStartLineForAddress(CU, Address, Spec.FNKind,
|
||||
Result.FunctionName,
|
||||
Result.StartLine);
|
||||
if (Spec.FLIKind != FileLineInfoKind::None) {
|
||||
if (const DWARFLineTable *LineTable = getLineTableForUnit(CU))
|
||||
LineTable->getFileLineInfoForAddress(Address, CU->getCompilationDir(),
|
||||
@ -483,13 +494,16 @@ DWARFContext::getLineInfoForAddressRange(uint64_t Address, uint64_t Size,
|
||||
return Lines;
|
||||
|
||||
std::string FunctionName = "<invalid>";
|
||||
getFunctionNameForAddress(CU, Address, Spec.FNKind, FunctionName);
|
||||
uint32_t StartLine = 0;
|
||||
getFunctionNameAndStartLineForAddress(CU, Address, Spec.FNKind, FunctionName,
|
||||
StartLine);
|
||||
|
||||
// If the Specifier says we don't need FileLineInfo, just
|
||||
// return the top-most function at the starting address.
|
||||
if (Spec.FLIKind == FileLineInfoKind::None) {
|
||||
DILineInfo Result;
|
||||
Result.FunctionName = FunctionName;
|
||||
Result.StartLine = StartLine;
|
||||
Lines.push_back(std::make_pair(Address, Result));
|
||||
return Lines;
|
||||
}
|
||||
@ -510,6 +524,7 @@ DWARFContext::getLineInfoForAddressRange(uint64_t Address, uint64_t Size,
|
||||
Result.FunctionName = FunctionName;
|
||||
Result.Line = Row.Line;
|
||||
Result.Column = Row.Column;
|
||||
Result.StartLine = StartLine;
|
||||
Lines.push_back(std::make_pair(Row.Address, Result));
|
||||
}
|
||||
|
||||
@ -549,6 +564,8 @@ DWARFContext::getInliningInfoForAddress(uint64_t Address,
|
||||
// Get function name if necessary.
|
||||
if (const char *Name = FunctionDIE.getSubroutineName(Spec.FNKind))
|
||||
Frame.FunctionName = Name;
|
||||
if (auto DeclLineResult = FunctionDIE.getDeclLine())
|
||||
Frame.StartLine = DeclLineResult;
|
||||
if (Spec.FLIKind != FileLineInfoKind::None) {
|
||||
if (i == 0) {
|
||||
// For the topmost frame, initialize the line table of this
|
||||
|
@ -291,6 +291,10 @@ DWARFDie::getName(DINameKind Kind) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint64_t DWARFDie::getDeclLine() const {
|
||||
return toUnsigned(findRecursively(DW_AT_decl_line), 0);
|
||||
}
|
||||
|
||||
void DWARFDie::getCallerFrame(uint32_t &CallFile, uint32_t &CallLine,
|
||||
uint32_t &CallColumn) const {
|
||||
CallFile = toUnsigned(find(DW_AT_call_file), 0);
|
||||
|
@ -84,6 +84,8 @@ void DIPrinter::print(const DILineInfo &Info, bool Inlined) {
|
||||
return;
|
||||
}
|
||||
OS << " Filename: " << Filename << "\n";
|
||||
if (Info.StartLine)
|
||||
OS << "Function start line: " << Info.StartLine << "\n";
|
||||
OS << " Line: " << Info.Line << "\n";
|
||||
OS << " Column: " << Info.Column << "\n";
|
||||
if (Info.Discriminator)
|
||||
|
@ -15,6 +15,7 @@ RUN: llvm-symbolizer -verbose -print-address -obj=%p/Inputs/discrim < %p/Inputs/
|
||||
#CHECK: 0x4004f2
|
||||
#CHECK-NEXT: main
|
||||
#CHECK-NEXT: Filename: /tmp{{[\\/]}}discrim.c
|
||||
#CHECK-NEXT: Function start line: 4
|
||||
#CHECK-NEXT: Line: 6
|
||||
#CHECK-NEXT: Column: 7
|
||||
#CHECK-NOT: Discriminator: 0
|
||||
@ -22,6 +23,7 @@ RUN: llvm-symbolizer -verbose -print-address -obj=%p/Inputs/discrim < %p/Inputs/
|
||||
#CHECK: 0x400509
|
||||
#CHECK-NEXT: main
|
||||
#CHECK-NEXT: Filename: /tmp{{[\\/]}}discrim.c
|
||||
#CHECK-NEXT: Function start line: 4
|
||||
#CHECK-NEXT: Line: 7
|
||||
#CHECK-NEXT: Column: 3
|
||||
#CHECK-NEXT: Discriminator: 1
|
||||
@ -29,6 +31,7 @@ RUN: llvm-symbolizer -verbose -print-address -obj=%p/Inputs/discrim < %p/Inputs/
|
||||
#CHECK: 0x40050d
|
||||
#CHECK-NEXT: main
|
||||
#CHECK-NEXT: Filename: /tmp{{[\\/]}}discrim.c
|
||||
#CHECK-NEXT: Function start line: 4
|
||||
#CHECK-NEXT: Line: 7
|
||||
#CHECK-NEXT: Column: 3
|
||||
#CHECK-NEXT: Discriminator: 2
|
||||
|
Loading…
x
Reference in New Issue
Block a user