Index: include/llvm/DebugInfo/DIContext.h =================================================================== --- include/llvm/DebugInfo/DIContext.h +++ include/llvm/DebugInfo/DIContext.h @@ -34,24 +34,28 @@ std::string FunctionName; uint32_t Line; uint32_t Column; + uint32_t StartLine; // DWARF-specific. uint32_t Discriminator; DILineInfo() : FileName(""), FunctionName(""), 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); } }; Index: lib/DebugInfo/DWARF/DWARFContext.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFContext.cpp +++ lib/DebugInfo/DWARF/DWARFContext.cpp @@ -439,23 +439,54 @@ return getCompileUnitForOffset(CUOffset); } -static bool getFunctionNameForAddress(DWARFCompileUnit *CU, uint64_t Address, - FunctionNameKind Kind, - std::string &FunctionName) { - if (Kind == FunctionNameKind::None) - return false; +static uint32_t getStartLineFromDie(const DWARFDie &DIE, uint32_t FailValue) { + uint32_t StartLine = + DIE.getAttributeValueAsUnsignedConstant(DW_AT_decl_line, FailValue); + if (StartLine == FailValue) { + // If it was not found, try to get it from specification DIE. + DWARFDie SpecDIE = + DIE.getAttributeValueAsReferencedDie(DW_AT_specification); + if (SpecDIE) { + StartLine = SpecDIE.getAttributeValueAsUnsignedConstant(DW_AT_decl_line, + FailValue); + } + } + if (StartLine == FailValue) { + // If it was not found, try to get it from abstract origin DIE. + DWARFDie AbsDIE = + DIE.getAttributeValueAsReferencedDie(DW_AT_abstract_origin); + if (AbsDIE) + StartLine = AbsDIE.getAttributeValueAsUnsignedConstant(DW_AT_decl_line, + FailValue); + } + return StartLine; +} + +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 &InlinedChain + // name of the topmost function in it. SmallVector 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 = DIE.getSubroutineName(Kind); + if (Kind != FunctionNameKind::None && Name) { FunctionName = Name; - return true; + FoundResult = true; } - return false; + StartLine = getStartLineFromDie(DIE, -1U); + if (StartLine != -1U) + FoundResult = true; + + return FoundResult; } DILineInfo DWARFContext::getLineInfoForAddress(uint64_t Address, @@ -465,7 +496,9 @@ 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 +516,16 @@ return Lines; std::string FunctionName = ""; - 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 +546,7 @@ 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 +586,7 @@ // Get function name if necessary. if (const char *Name = FunctionDIE.getSubroutineName(Spec.FNKind)) Frame.FunctionName = Name; + Frame.StartLine = getStartLineFromDie(FunctionDIE, -1U); if (Spec.FLIKind != FileLineInfoKind::None) { if (i == 0) { // For the topmost frame, initialize the line table of this