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);
}
};
/// 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
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,
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(),
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;
}
Result.FunctionName = FunctionName;
Result.Line = Row.Line;
Result.Column = Row.Column;
+ Result.StartLine = StartLine;
Lines.push_back(std::make_pair(Row.Address, Result));
}
// 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