Index: include/llvm/DebugInfo/DWARF/DWARFContext.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFContext.h +++ include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -200,6 +200,13 @@ DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; DILineInfoTable getLineInfoForAddressRange(uint64_t Address, uint64_t Size, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; + /// Gets the inline stack of \p Address by calling \p Inserter on all levels + /// of the inline stack. + void getInliningInfoForAddress( + uint64_t Address, DILineInfoSpecifier Spec, + std::function + Inserter); DIInliningInfo getInliningInfoForAddress(uint64_t Address, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; Index: include/llvm/DebugInfo/DWARF/DWARFDebugLine.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFDebugLine.h +++ include/llvm/DebugInfo/DWARF/DWARFDebugLine.h @@ -180,6 +180,12 @@ struct LineTable { LineTable(); + // Returns the file path string with the given \p CompDir, \p IncludeDir + // and \p FileName, for the given \p Kind. + static std::string getFilePath(const char *CompDir, const char *IncludeDir, + const char *FileName, + DILineInfoSpecifier::FileLineInfoKind Kind); + // Represents an invalid row const uint32_t UnknownRowIndex = UINT32_MAX; @@ -200,12 +206,24 @@ bool hasFileAtIndex(uint64_t FileIndex) const; + // Extracts \p IncludeDir and \p FileName by its index in filename table + // in prologue. Returns true on success. + bool getFileNameByIndex(uint64_t FileIndex, const char *&IncludeDir, + const char *&FileName) const; + // Extracts filename by its index in filename table in prologue. // Returns true on success. bool getFileNameByIndex(uint64_t FileIndex, const char *CompDir, DILineInfoSpecifier::FileLineInfoKind Kind, std::string &Result) const; + // Fills the \p IncludeDir, \p FileName, \p Line, \p Column and + // \p Discriminator with the given \p Address. Returns true on success. + bool getFileLineInfoForAddress(uint64_t Address, const char *&IncludeDir, + const char *&FileName, uint32_t &Line, + uint32_t &Column, + uint32_t &Discriminator) const; + // Fills the Result argument with the file and line information // corresponding to Address. Returns true on success. bool getFileLineInfoForAddress(uint64_t Address, const char *CompDir, Index: lib/DebugInfo/DWARF/DWARFContext.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFContext.cpp +++ lib/DebugInfo/DWARF/DWARFContext.cpp @@ -553,41 +553,47 @@ return Lines; } -DIInliningInfo -DWARFContext::getInliningInfoForAddress(uint64_t Address, - DILineInfoSpecifier Spec) { - DIInliningInfo InliningInfo; - +void DWARFContext::getInliningInfoForAddress( + uint64_t Address, DILineInfoSpecifier Spec, + std::function + Inserter) { DWARFCompileUnit *CU = getCompileUnitForAddress(Address); if (!CU) - return InliningInfo; + return; const DWARFLineTable *LineTable = nullptr; SmallVector InlinedChain; CU->getInlinedChainForAddress(Address, InlinedChain); if (InlinedChain.size() == 0) { + if (Spec.FLIKind == FileLineInfoKind::None) + return; // If there is no DIE for address (e.g. it is in unavailable .dwo file), // try to at least get file/line info from symbol table. - if (Spec.FLIKind != FileLineInfoKind::None) { - DILineInfo Frame; - LineTable = getLineTableForUnit(CU); - if (LineTable && - LineTable->getFileLineInfoForAddress(Address, CU->getCompilationDir(), - Spec.FLIKind, Frame)) - InliningInfo.addFrame(Frame); - } - return InliningInfo; + const char *FileName = nullptr; + const char *IncludeDir = nullptr; + uint32_t Line = 0; + uint32_t Column = 0; + uint32_t Discriminator = 0; + LineTable = getLineTableForUnit(CU); + if (LineTable && + LineTable->getFileLineInfoForAddress(Address, IncludeDir, FileName, + Line, Column, Discriminator)) + Inserter(nullptr, CU->getCompilationDir(), IncludeDir, FileName, 0, Line, + Column, Discriminator); + return; } uint32_t CallFile = 0, CallLine = 0, CallColumn = 0, CallDiscriminator = 0; for (uint32_t i = 0, n = InlinedChain.size(); i != n; i++) { DWARFDie &FunctionDIE = InlinedChain[i]; - DILineInfo Frame; - // Get function name if necessary. - if (const char *Name = FunctionDIE.getSubroutineName(Spec.FNKind)) - Frame.FunctionName = Name; - if (auto DeclLineResult = FunctionDIE.getDeclLine()) - Frame.StartLine = DeclLineResult; + const char *FunctionName = FunctionDIE.getSubroutineName(Spec.FNKind); + const char *FileName = nullptr; + const char *IncludeDir = nullptr; + uint32_t StartLine = FunctionDIE.getDeclLine(); + uint32_t Line = 0; + uint32_t Column = 0; + uint32_t Discriminator = 0; if (Spec.FLIKind != FileLineInfoKind::None) { if (i == 0) { // For the topmost frame, initialize the line table of this @@ -595,17 +601,16 @@ LineTable = getLineTableForUnit(CU); // For the topmost routine, get file/line info from line table. if (LineTable) - LineTable->getFileLineInfoForAddress(Address, CU->getCompilationDir(), - Spec.FLIKind, Frame); + LineTable->getFileLineInfoForAddress(Address, IncludeDir, FileName, + Line, Column, Discriminator); } else { // Otherwise, use call file, call line and call column from // previous DIE in inlined chain. if (LineTable) - LineTable->getFileNameByIndex(CallFile, CU->getCompilationDir(), - Spec.FLIKind, Frame.FileName); - Frame.Line = CallLine; - Frame.Column = CallColumn; - Frame.Discriminator = CallDiscriminator; + LineTable->getFileNameByIndex(CallFile, IncludeDir, FileName); + Line = CallLine; + Column = CallColumn; + Discriminator = CallDiscriminator; } // Get call file/line/column of a current DIE. if (i + 1 < n) { @@ -613,8 +618,33 @@ CallDiscriminator); } } - InliningInfo.addFrame(Frame); + Inserter(FunctionName, CU->getCompilationDir(), IncludeDir, FileName, + StartLine, Line, Column, Discriminator); } +} + +DIInliningInfo +DWARFContext::getInliningInfoForAddress(uint64_t Address, + DILineInfoSpecifier Spec) { + DIInliningInfo InliningInfo; + + getInliningInfoForAddress( + Address, Spec, + [&](const char *FunctionName, const char *CompDir, const char *IncludeDir, + const char *FileName, uint32_t StartLine, uint32_t Line, + uint32_t Column, uint32_t Discriminator) { + DILineInfo Frame; + if (FileName) + Frame.FileName = DWARFLineTable::getFilePath( + CompDir, IncludeDir, FileName, Spec.FLIKind); + if (FunctionName) + Frame.FunctionName = FunctionName; + Frame.Line = Line; + Frame.Column = Column; + Frame.StartLine = StartLine; + Frame.Discriminator = Discriminator; + InliningInfo.addFrame(Frame); + }); return InliningInfo; } Index: lib/DebugInfo/DWARF/DWARFDebugLine.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFDebugLine.cpp +++ lib/DebugInfo/DWARF/DWARFDebugLine.cpp @@ -638,55 +638,80 @@ return FileIndex != 0 && FileIndex <= Prologue.FileNames.size(); } -bool -DWARFDebugLine::LineTable::getFileNameByIndex(uint64_t FileIndex, - const char *CompDir, - FileLineInfoKind Kind, - std::string &Result) const { - if (Kind == FileLineInfoKind::None || !hasFileAtIndex(FileIndex)) - return false; - const FileNameEntry &Entry = Prologue.FileNames[FileIndex - 1]; - const char *FileName = Entry.Name; +std::string DWARFDebugLine::LineTable::getFilePath(const char *CompDir, + const char *IncludeDir, + const char *FileName, + FileLineInfoKind Kind) { + if (FileName == nullptr) + return ""; if (Kind != FileLineInfoKind::AbsoluteFilePath || sys::path::is_absolute(FileName)) { - Result = FileName; - return true; + return FileName; } SmallString<16> FilePath; - uint64_t IncludeDirIndex = Entry.DirIdx; - const char *IncludeDir = ""; - // Be defensive about the contents of Entry. - if (IncludeDirIndex > 0 && - IncludeDirIndex <= Prologue.IncludeDirectories.size()) - IncludeDir = Prologue.IncludeDirectories[IncludeDirIndex - 1]; // We may still need to append compilation directory of compile unit. // We know that FileName is not absolute, the only way to have an // absolute path at this point would be if IncludeDir is absolute. - if (CompDir && Kind == FileLineInfoKind::AbsoluteFilePath && - sys::path::is_relative(IncludeDir)) + if (CompDir && sys::path::is_relative(IncludeDir)) sys::path::append(FilePath, CompDir); // sys::path::append skips empty strings. sys::path::append(FilePath, IncludeDir, FileName); - Result = FilePath.str(); + return FilePath.str(); +} + +bool DWARFDebugLine::LineTable::getFileNameByIndex( + uint64_t FileIndex, const char *&IncludeDir, const char *&FileName) const { + if (!hasFileAtIndex(FileIndex)) + return false; + const FileNameEntry &Entry = Prologue.FileNames[FileIndex - 1]; + FileName = Entry.Name; + if (Entry.DirIdx > 0 && Entry.DirIdx <= Prologue.IncludeDirectories.size()) + IncludeDir = Prologue.IncludeDirectories[Entry.DirIdx - 1]; + else + IncludeDir = ""; + return true; +} + +bool DWARFDebugLine::LineTable::getFileNameByIndex(uint64_t FileIndex, + const char *CompDir, + FileLineInfoKind Kind, + std::string &Result) const { + if (Kind == FileLineInfoKind::None) + return false; + const char *FileName = nullptr; + const char *IncludeDir = nullptr; + if (!getFileNameByIndex(FileIndex, IncludeDir, FileName)) + return false; + Result = getFilePath(CompDir, IncludeDir, FileName, Kind); return true; } bool DWARFDebugLine::LineTable::getFileLineInfoForAddress( - uint64_t Address, const char *CompDir, FileLineInfoKind Kind, - DILineInfo &Result) const { + uint64_t Address, const char *&IncludeDir, const char *&FileName, + uint32_t &Line, uint32_t &Column, uint32_t &Discriminator) const { // Get the index of row we're looking for in the line table. uint32_t RowIndex = lookupAddress(Address); if (RowIndex == -1U) return false; // Take file number and line/column from the row. const auto &Row = Rows[RowIndex]; - if (!getFileNameByIndex(Row.File, CompDir, Kind, Result.FileName)) + Line = Row.Line; + Column = Row.Column; + Discriminator = Row.Discriminator; + return getFileNameByIndex(Row.File, IncludeDir, FileName); +} + +bool DWARFDebugLine::LineTable::getFileLineInfoForAddress( + uint64_t Address, const char *CompDir, FileLineInfoKind Kind, + DILineInfo &Result) const { + const char *FileName = nullptr; + const char *IncludeDir = nullptr; + if (!getFileLineInfoForAddress(Address, IncludeDir, FileName, Result.Line, + Result.Column, Result.Discriminator)) return false; - Result.Line = Row.Line; - Result.Column = Row.Column; - Result.Discriminator = Row.Discriminator; + Result.FileName = getFilePath(CompDir, IncludeDir, FileName, Kind); return true; }