DILineInfo DWARFContext::getLineInfoForAddress(uint64_t Address, DILineInfoSpecifier Specifier) { DWARFCompileUnit *CU = getCompileUnitForAddress(Address); if (!CU) return DILineInfo(); std::string FileName = "<invalid>"; std::string FunctionName = "<invalid>"; uint32_t Line = 0; uint32_t Column = 0; if (Specifier.needs(DILineInfoSpecifier::FunctionName)) { // 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 DWARFLineTable *LineTable = getLineTableForCompileUnit(CU); const bool NeedsAbsoluteFilePath = Specifier.needs(DILineInfoSpecifier::AbsoluteFilePath); getFileLineInfoForCompileUnit(CU, LineTable, Address, NeedsAbsoluteFilePath, FileName, Line, Column); } return DILineInfo(StringRef(FileName), StringRef(FunctionName), Line, Column); }
DILineInfo DWARFContext::getLineInfoForAddress(uint64_t address, DILineInfoSpecifier specifier) { // First, get the offset of the compile unit. uint32_t cuOffset = getDebugAranges()->findAddress(address); // Retrieve the compile unit. DWARFCompileUnit *cu = getCompileUnitForOffset(cuOffset); if (!cu) return DILineInfo(); SmallString<16> fileName("<invalid>"); SmallString<16> functionName("<invalid>"); uint32_t line = 0; uint32_t column = 0; if (specifier.needs(DILineInfoSpecifier::FunctionName)) { const DWARFDebugInfoEntryMinimal *function_die = cu->getFunctionDIEForAddress(address); if (function_die) { if (const char *name = function_die->getSubprogramName(cu)) functionName = name; } } if (specifier.needs(DILineInfoSpecifier::FileLineInfo)) { // Get the line table for this compile unit. const DWARFDebugLine::LineTable *lineTable = getLineTableForCompileUnit(cu); if (lineTable) { // Get the index of the row we're looking for in the line table. uint32_t rowIndex = lineTable->lookupAddress(address); if (rowIndex != -1U) { const DWARFDebugLine::Row &row = lineTable->Rows[rowIndex]; // Take file/line info from the line table. const DWARFDebugLine::FileNameEntry &fileNameEntry = lineTable->Prologue.FileNames[row.File - 1]; fileName = fileNameEntry.Name; if (specifier.needs(DILineInfoSpecifier::AbsoluteFilePath) && sys::path::is_relative(fileName.str())) { // Append include directory of file (if it is present in line table) // and compilation directory of compile unit to make path absolute. const char *includeDir = 0; if (uint64_t includeDirIndex = fileNameEntry.DirIdx) { includeDir = lineTable->Prologue .IncludeDirectories[includeDirIndex - 1]; } SmallString<16> absFileName; if (includeDir == 0 || sys::path::is_relative(includeDir)) { if (const char *compilationDir = cu->getCompilationDir()) sys::path::append(absFileName, compilationDir); } if (includeDir) { sys::path::append(absFileName, includeDir); } sys::path::append(absFileName, fileName.str()); fileName = absFileName; } line = row.Line; column = row.Column; } } } return DILineInfo(fileName, functionName, line, column); }
DILineInfoTable DWARFContext::getLineInfoForAddressRange(uint64_t Address, uint64_t Size, DILineInfoSpecifier Specifier) { DILineInfoTable Lines; DWARFCompileUnit *CU = getCompileUnitForAddress(Address); if (!CU) return Lines; std::string FunctionName = "<invalid>"; if (Specifier.needs(DILineInfoSpecifier::FunctionName)) { // 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; } } StringRef FuncNameRef = StringRef(FunctionName); // If the Specifier says we don't need FileLineInfo, just // return the top-most function at the starting address. if (!Specifier.needs(DILineInfoSpecifier::FileLineInfo)) { Lines.push_back(std::make_pair(Address, DILineInfo(StringRef("<invalid>"), FuncNameRef, 0, 0))); return Lines; } const DWARFLineTable *LineTable = getLineTableForCompileUnit(CU); const bool NeedsAbsoluteFilePath = Specifier.needs(DILineInfoSpecifier::AbsoluteFilePath); // Get the index of row we're looking for in the line table. std::vector<uint32_t> RowVector; if (!LineTable->lookupAddressRange(Address, Size, RowVector)) return Lines; uint32_t NumRows = RowVector.size(); for (uint32_t i = 0; i < NumRows; ++i) { uint32_t RowIndex = RowVector[i]; // Take file number and line/column from the row. const DWARFDebugLine::Row &Row = LineTable->Rows[RowIndex]; std::string FileName = "<invalid>"; getFileNameForCompileUnit(CU, LineTable, Row.File, NeedsAbsoluteFilePath, FileName); Lines.push_back(std::make_pair(Row.Address, DILineInfo(StringRef(FileName), FuncNameRef, Row.Line, Row.Column))); } return Lines; }
DIInliningInfo DWARFContext::getInliningInfoForAddress(uint64_t Address, DILineInfoSpecifier Specifier) { DWARFCompileUnit *CU = getCompileUnitForAddress(Address); if (!CU) return DIInliningInfo(); const DWARFDebugInfoEntryInlinedChain &InlinedChain = CU->getInlinedChainForAddress(Address); if (InlinedChain.DIEs.size() == 0) return DIInliningInfo(); DIInliningInfo InliningInfo; uint32_t CallFile = 0, CallLine = 0, CallColumn = 0; const DWARFLineTable *LineTable = 0; for (uint32_t i = 0, n = InlinedChain.DIEs.size(); i != n; i++) { const DWARFDebugInfoEntryMinimal &FunctionDIE = InlinedChain.DIEs[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(InlinedChain.U)) 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(InlinedChain.U, CallFile, CallLine, CallColumn); } } DILineInfo Frame(StringRef(FileName), StringRef(FunctionName), Line, Column); InliningInfo.addFrame(Frame); } return InliningInfo; }
DILineInfoTable DWARFContext::getLineInfoForAddressRange(uint64_t Address, uint64_t Size, DILineInfoSpecifier Specifier) { DILineInfoTable Lines; DWARFCompileUnit *CU = getCompileUnitForAddress(Address); if (!CU) return Lines; std::string FunctionName = "<invalid>"; if (Specifier.needs(DILineInfoSpecifier::FunctionName)) { getFunctionNameForAddress(CU, Address, FunctionName); } // If the Specifier says we don't need FileLineInfo, just // return the top-most function at the starting address. if (!Specifier.needs(DILineInfoSpecifier::FileLineInfo)) { DILineInfo Result; Result.FunctionName = FunctionName; Lines.push_back(std::make_pair(Address, Result)); return Lines; } const DWARFLineTable *LineTable = getLineTableForCompileUnit(CU); const bool NeedsAbsoluteFilePath = Specifier.needs(DILineInfoSpecifier::AbsoluteFilePath); // Get the index of row we're looking for in the line table. std::vector<uint32_t> RowVector; if (!LineTable->lookupAddressRange(Address, Size, RowVector)) return Lines; for (uint32_t RowIndex : RowVector) { // Take file number and line/column from the row. const DWARFDebugLine::Row &Row = LineTable->Rows[RowIndex]; DILineInfo Result; getFileNameForCompileUnit(CU, LineTable, Row.File, NeedsAbsoluteFilePath, Result.FileName); Result.FunctionName = FunctionName; Result.Line = Row.Line; Result.Column = Row.Column; Lines.push_back(std::make_pair(Row.Address, Result)); } return Lines; }
DILineInfo DWARFContext::getLineInfoForAddress(uint64_t Address, DILineInfoSpecifier Specifier) { DILineInfo Result; DWARFCompileUnit *CU = getCompileUnitForAddress(Address); if (!CU) return Result; if (Specifier.needs(DILineInfoSpecifier::FunctionName)) { getFunctionNameForAddress(CU, Address, Result.FunctionName); } if (Specifier.needs(DILineInfoSpecifier::FileLineInfo)) { const DWARFLineTable *LineTable = getLineTableForCompileUnit(CU); const bool NeedsAbsoluteFilePath = Specifier.needs(DILineInfoSpecifier::AbsoluteFilePath); getFileLineInfoForCompileUnit(CU, LineTable, Address, NeedsAbsoluteFilePath, Result); } return Result; }
DILineInfo DWARFContext::getLineInfoForAddress(uint64_t address, DILineInfoSpecifier specifier) { // First, get the offset of the compile unit. uint32_t cuOffset = getDebugAranges()->findAddress(address); // Retrieve the compile unit. DWARFCompileUnit *cu = getCompileUnitForOffset(cuOffset); if (!cu) return DILineInfo(); const char *fileName = "<invalid>"; const char *functionName = "<invalid>"; uint32_t line = 0; uint32_t column = 0; if (specifier.needs(DILineInfoSpecifier::FunctionName)) { const DWARFDebugInfoEntryMinimal *function_die = cu->getFunctionDIEForAddress(address); if (function_die) functionName = function_die->getSubprogramName(cu); } if (specifier.needs(DILineInfoSpecifier::FileLineInfo)) { // Get the line table for this compile unit. const DWARFDebugLine::LineTable *lineTable = getLineTableForCompileUnit(cu); if (lineTable) { // Get the index of the row we're looking for in the line table. uint64_t hiPC = cu->getCompileUnitDIE()->getAttributeValueAsUnsigned( cu, DW_AT_high_pc, -1ULL); uint32_t rowIndex = lineTable->lookupAddress(address, hiPC); if (rowIndex != -1U) { const DWARFDebugLine::Row &row = lineTable->Rows[rowIndex]; // Take file/line info from the line table. fileName = lineTable->Prologue.FileNames[row.File - 1].Name.c_str(); line = row.Line; column = row.Column; } } } return DILineInfo(fileName, functionName, line, column); }
DIInliningInfo DWARFContext::getInliningInfoForAddress(uint64_t Address, DILineInfoSpecifier Specifier) { DIInliningInfo InliningInfo; DWARFCompileUnit *CU = getCompileUnitForAddress(Address); if (!CU) return InliningInfo; const DWARFLineTable *LineTable = nullptr; const bool NeedsAbsoluteFilePath = Specifier.needs(DILineInfoSpecifier::AbsoluteFilePath); const DWARFDebugInfoEntryInlinedChain &InlinedChain = CU->getInlinedChainForAddress(Address); if (InlinedChain.DIEs.size() == 0) { // 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 (Specifier.needs(DILineInfoSpecifier::FileLineInfo)) { DILineInfo Frame; LineTable = getLineTableForCompileUnit(CU); if (getFileLineInfoForCompileUnit(CU, LineTable, Address, NeedsAbsoluteFilePath, Frame)) { InliningInfo.addFrame(Frame); } } return InliningInfo; } uint32_t CallFile = 0, CallLine = 0, CallColumn = 0; for (uint32_t i = 0, n = InlinedChain.DIEs.size(); i != n; i++) { const DWARFDebugInfoEntryMinimal &FunctionDIE = InlinedChain.DIEs[i]; DILineInfo Frame; // Get function name if necessary. if (Specifier.needs(DILineInfoSpecifier::FunctionName)) { if (const char *Name = FunctionDIE.getSubroutineName(InlinedChain.U)) Frame.FunctionName = Name; } if (Specifier.needs(DILineInfoSpecifier::FileLineInfo)) { 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, Frame); } else { // Otherwise, use call file, call line and call column from // previous DIE in inlined chain. getFileNameForCompileUnit(CU, LineTable, CallFile, NeedsAbsoluteFilePath, Frame.FileName); Frame.Line = CallLine; Frame.Column = CallColumn; } // Get call file/line/column of a current DIE. if (i + 1 < n) { FunctionDIE.getCallerFrame(InlinedChain.U, CallFile, CallLine, CallColumn); } } InliningInfo.addFrame(Frame); } return InliningInfo; }