diff options
author | Stephen Hines <srhines@google.com> | 2014-05-29 02:49:00 -0700 |
---|---|---|
committer | Stephen Hines <srhines@google.com> | 2014-05-29 02:49:00 -0700 |
commit | dce4a407a24b04eebc6a376f8e62b41aaa7b071f (patch) | |
tree | dcebc53f2b182f145a2e659393bf9a0472cedf23 /lib/DebugInfo | |
parent | 220b921aed042f9e520c26cffd8282a94c66c3d5 (diff) | |
download | external_llvm-dce4a407a24b04eebc6a376f8e62b41aaa7b071f.zip external_llvm-dce4a407a24b04eebc6a376f8e62b41aaa7b071f.tar.gz external_llvm-dce4a407a24b04eebc6a376f8e62b41aaa7b071f.tar.bz2 |
Update LLVM for 3.5 rebase (r209712).
Change-Id: I149556c940fb7dc92d075273c87ff584f400941f
Diffstat (limited to 'lib/DebugInfo')
-rw-r--r-- | lib/DebugInfo/DWARFCompileUnit.h | 6 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFContext.cpp | 246 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFContext.h | 2 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFDebugAbbrev.cpp | 112 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFDebugAbbrev.h | 50 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFDebugArangeSet.h | 1 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFDebugAranges.cpp | 36 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFDebugAranges.h | 17 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFDebugFrame.cpp | 72 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFDebugFrame.h | 6 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFDebugInfoEntry.cpp | 95 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFDebugInfoEntry.h | 57 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFDebugLine.cpp | 348 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFDebugLine.h | 109 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFDebugRangeList.cpp | 15 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFDebugRangeList.h | 15 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFFormValue.cpp | 10 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFTypeUnit.h | 10 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFUnit.cpp | 145 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFUnit.h | 24 | ||||
-rw-r--r-- | lib/DebugInfo/module.modulemap | 1 |
21 files changed, 673 insertions, 704 deletions
diff --git a/lib/DebugInfo/DWARFCompileUnit.h b/lib/DebugInfo/DWARFCompileUnit.h index d1853d8..2ed188e 100644 --- a/lib/DebugInfo/DWARFCompileUnit.h +++ b/lib/DebugInfo/DWARFCompileUnit.h @@ -16,10 +16,10 @@ namespace llvm { class DWARFCompileUnit : public DWARFUnit { public: - DWARFCompileUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef AS, - StringRef RS, StringRef SS, StringRef SOS, StringRef AOS, + DWARFCompileUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef RS, + StringRef SS, StringRef SOS, StringRef AOS, const RelocAddrMap *M, bool LE) - : DWARFUnit(DA, IS, AS, RS, SS, SOS, AOS, M, LE) {} + : DWARFUnit(DA, IS, RS, SS, SOS, AOS, M, LE) {} void dump(raw_ostream &OS); // VTable anchor. ~DWARFCompileUnit() override; diff --git a/lib/DebugInfo/DWARFContext.cpp b/lib/DebugInfo/DWARFContext.cpp index 60c5f6a..e52e8af 100644 --- a/lib/DebugInfo/DWARFContext.cpp +++ b/lib/DebugInfo/DWARFContext.cpp @@ -8,6 +8,8 @@ //===----------------------------------------------------------------------===// #include "DWARFContext.h" +#include "DWARFDebugArangeSet.h" + #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/Compression.h" @@ -20,7 +22,11 @@ using namespace llvm; using namespace dwarf; using namespace object; +#define DEBUG_TYPE "dwarf" + typedef DWARFDebugLine::LineTable DWARFLineTable; +typedef DILineInfoSpecifier::FileLineInfoKind FileLineInfoKind; +typedef DILineInfoSpecifier::FunctionNameKind FunctionNameKind; static void dumpPubSection(raw_ostream &OS, StringRef Name, StringRef Data, bool LittleEndian, bool GnuStyle) { @@ -126,8 +132,9 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) { if (stmtOffset != -1U) { DataExtractor lineData(getLineSection().Data, isLittleEndian(), savedAddressByteSize); - DWARFDebugLine::DumpingState state(OS); - DWARFDebugLine::parseStatementTable(lineData, &getLineSection().Relocs, &stmtOffset, state); + DWARFDebugLine::LineTable LineTable; + LineTable.parse(lineData, &getLineSection().Relocs, &stmtOffset); + LineTable.dump(OS); } } } @@ -137,9 +144,11 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) { unsigned stmtOffset = 0; DataExtractor lineData(getLineDWOSection().Data, isLittleEndian(), savedAddressByteSize); - DWARFDebugLine::DumpingState state(OS); - while (DWARFDebugLine::parsePrologue(lineData, &stmtOffset, &state.Prologue)) - state.finalize(); + DWARFDebugLine::LineTable LineTable; + while (LineTable.Prologue.parse(lineData, &stmtOffset)) { + LineTable.dump(OS); + LineTable.clear(); + } } if (DumpType == DIDT_All || DumpType == DIDT_Str) { @@ -216,7 +225,7 @@ const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() { DataExtractor abbrData(getAbbrevSection(), isLittleEndian(), 0); Abbrev.reset(new DWARFDebugAbbrev()); - Abbrev->parse(abbrData); + Abbrev->extract(abbrData); return Abbrev.get(); } @@ -226,7 +235,7 @@ const DWARFDebugAbbrev *DWARFContext::getDebugAbbrevDWO() { DataExtractor abbrData(getAbbrevDWOSection(), isLittleEndian(), 0); AbbrevDWO.reset(new DWARFDebugAbbrev()); - AbbrevDWO->parse(abbrData); + AbbrevDWO->extract(abbrData); return AbbrevDWO.get(); } @@ -290,7 +299,7 @@ DWARFContext::getLineTableForCompileUnit(DWARFCompileUnit *cu) { cu->getCompileUnitDIE()->getAttributeValueAsSectionOffset( cu, DW_AT_stmt_list, -1U); if (stmtOffset == -1U) - return 0; // No line table for this compile unit. + return nullptr; // No line table for this compile unit. // See if the line table is cached. if (const DWARFLineTable *lt = Line->getLineTable(stmtOffset)) @@ -310,8 +319,8 @@ void DWARFContext::parseCompileUnits() { isLittleEndian(), 0); while (DIData.isValidOffset(offset)) { std::unique_ptr<DWARFCompileUnit> CU(new DWARFCompileUnit( - getDebugAbbrev(), getInfoSection().Data, getAbbrevSection(), - getRangeSection(), getStringSection(), StringRef(), getAddrSection(), + getDebugAbbrev(), getInfoSection().Data, getRangeSection(), + getStringSection(), StringRef(), getAddrSection(), &getInfoSection().Relocs, isLittleEndian())); if (!CU->extract(DIData, &offset)) { break; @@ -329,10 +338,10 @@ void DWARFContext::parseTypeUnits() { const DataExtractor &DIData = DataExtractor(I.second.Data, isLittleEndian(), 0); while (DIData.isValidOffset(offset)) { - std::unique_ptr<DWARFTypeUnit> TU(new DWARFTypeUnit( - getDebugAbbrev(), I.second.Data, getAbbrevSection(), - getRangeSection(), getStringSection(), StringRef(), getAddrSection(), - &I.second.Relocs, isLittleEndian())); + std::unique_ptr<DWARFTypeUnit> TU( + new DWARFTypeUnit(getDebugAbbrev(), I.second.Data, getRangeSection(), + getStringSection(), StringRef(), getAddrSection(), + &I.second.Relocs, isLittleEndian())); if (!TU->extract(DIData, &offset)) break; TUs.push_back(std::move(TU)); @@ -349,9 +358,8 @@ void DWARFContext::parseDWOCompileUnits() { DataExtractor(getInfoDWOSection().Data, isLittleEndian(), 0); while (DIData.isValidOffset(offset)) { std::unique_ptr<DWARFCompileUnit> DWOCU(new DWARFCompileUnit( - getDebugAbbrevDWO(), getInfoDWOSection().Data, getAbbrevDWOSection(), - getRangeDWOSection(), getStringDWOSection(), - getStringOffsetDWOSection(), getAddrSection(), + getDebugAbbrevDWO(), getInfoDWOSection().Data, getRangeDWOSection(), + getStringDWOSection(), getStringOffsetDWOSection(), getAddrSection(), &getInfoDWOSection().Relocs, isLittleEndian())); if (!DWOCU->extract(DIData, &offset)) { break; @@ -370,10 +378,9 @@ void DWARFContext::parseDWOTypeUnits() { DataExtractor(I.second.Data, isLittleEndian(), 0); while (DIData.isValidOffset(offset)) { std::unique_ptr<DWARFTypeUnit> TU(new DWARFTypeUnit( - getDebugAbbrevDWO(), I.second.Data, getAbbrevDWOSection(), - getRangeDWOSection(), getStringDWOSection(), - getStringOffsetDWOSection(), getAddrSection(), &I.second.Relocs, - isLittleEndian())); + getDebugAbbrevDWO(), I.second.Data, getRangeDWOSection(), + getStringDWOSection(), getStringOffsetDWOSection(), getAddrSection(), + &I.second.Relocs, isLittleEndian())); if (!TU->extract(DIData, &offset)) break; DWOTUs.push_back(std::move(TU)); @@ -408,7 +415,7 @@ DWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint32_t Offset) { if (CU != CUs.end()) { return CU->get(); } - return 0; + return nullptr; } DWARFCompileUnit *DWARFContext::getCompileUnitForAddress(uint64_t Address) { @@ -420,15 +427,13 @@ DWARFCompileUnit *DWARFContext::getCompileUnitForAddress(uint64_t Address) { static bool getFileNameForCompileUnit(DWARFCompileUnit *CU, const DWARFLineTable *LineTable, - uint64_t FileIndex, - bool NeedsAbsoluteFilePath, + uint64_t FileIndex, FileLineInfoKind Kind, std::string &FileName) { - if (CU == 0 || - LineTable == 0 || - !LineTable->getFileNameByIndex(FileIndex, NeedsAbsoluteFilePath, - FileName)) + if (!CU || !LineTable || Kind == FileLineInfoKind::None || + !LineTable->getFileNameByIndex(FileIndex, Kind, FileName)) return false; - if (NeedsAbsoluteFilePath && sys::path::is_relative(FileName)) { + if (Kind == FileLineInfoKind::AbsoluteFilePath && + sys::path::is_relative(FileName)) { // We may still need to append compilation directory of compile unit. SmallString<16> AbsolutePath; if (const char *CompilationDir = CU->getCompilationDir()) { @@ -443,10 +448,9 @@ static bool getFileNameForCompileUnit(DWARFCompileUnit *CU, static bool getFileLineInfoForCompileUnit(DWARFCompileUnit *CU, const DWARFLineTable *LineTable, uint64_t Address, - bool NeedsAbsoluteFilePath, - std::string &FileName, - uint32_t &Line, uint32_t &Column) { - if (CU == 0 || LineTable == 0) + FileLineInfoKind Kind, + DILineInfo &Result) { + if (!CU || !LineTable) return false; // Get the index of row we're looking for in the line table. uint32_t RowIndex = LineTable->lookupAddress(Address); @@ -454,80 +458,71 @@ static bool getFileLineInfoForCompileUnit(DWARFCompileUnit *CU, return false; // Take file number and line/column from the row. const DWARFDebugLine::Row &Row = LineTable->Rows[RowIndex]; - if (!getFileNameForCompileUnit(CU, LineTable, Row.File, - NeedsAbsoluteFilePath, FileName)) + if (!getFileNameForCompileUnit(CU, LineTable, Row.File, Kind, + Result.FileName)) return false; - Line = Row.Line; - Column = Row.Column; + Result.Line = Row.Line; + Result.Column = Row.Column; return true; } +static bool getFunctionNameForAddress(DWARFCompileUnit *CU, uint64_t Address, + FunctionNameKind Kind, + std::string &FunctionName) { + if (Kind == FunctionNameKind::None) + return false; + // 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 DWARFDebugInfoEntryInlinedChain &InlinedChain = + CU->getInlinedChainForAddress(Address); + if (InlinedChain.DIEs.size() == 0) + return false; + const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain.DIEs[0]; + if (const char *Name = + TopFunctionDIE.getSubroutineName(InlinedChain.U, Kind)) { + FunctionName = Name; + return true; + } + return false; +} + DILineInfo DWARFContext::getLineInfoForAddress(uint64_t Address, - DILineInfoSpecifier Specifier) { + DILineInfoSpecifier Spec) { + DILineInfo Result; + 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 DWARFDebugInfoEntryInlinedChain &InlinedChain = - CU->getInlinedChainForAddress(Address); - if (InlinedChain.DIEs.size() > 0) { - const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain.DIEs[0]; - if (const char *Name = TopFunctionDIE.getSubroutineName(InlinedChain.U)) - FunctionName = Name; - } - } - if (Specifier.needs(DILineInfoSpecifier::FileLineInfo)) { + return Result; + getFunctionNameForAddress(CU, Address, Spec.FNKind, Result.FunctionName); + if (Spec.FLIKind != FileLineInfoKind::None) { const DWARFLineTable *LineTable = getLineTableForCompileUnit(CU); - const bool NeedsAbsoluteFilePath = - Specifier.needs(DILineInfoSpecifier::AbsoluteFilePath); - getFileLineInfoForCompileUnit(CU, LineTable, Address, - NeedsAbsoluteFilePath, - FileName, Line, Column); + getFileLineInfoForCompileUnit(CU, LineTable, Address, Spec.FLIKind, Result); } - return DILineInfo(StringRef(FileName), StringRef(FunctionName), - Line, Column); + return Result; } -DILineInfoTable DWARFContext::getLineInfoForAddressRange(uint64_t Address, - uint64_t Size, - DILineInfoSpecifier Specifier) { +DILineInfoTable +DWARFContext::getLineInfoForAddressRange(uint64_t Address, uint64_t Size, + DILineInfoSpecifier Spec) { 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 DWARFDebugInfoEntryInlinedChain &InlinedChain = - CU->getInlinedChainForAddress(Address); - if (InlinedChain.DIEs.size() > 0) { - const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain.DIEs[0]; - if (const char *Name = TopFunctionDIE.getSubroutineName(InlinedChain.U)) - FunctionName = Name; - } - } + getFunctionNameForAddress(CU, Address, Spec.FNKind, 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("<invalid>", FunctionName, 0, 0))); + if (Spec.FLIKind == FileLineInfoKind::None) { + 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; @@ -537,59 +532,67 @@ DILineInfoTable DWARFContext::getLineInfoForAddressRange(uint64_t Address, for (uint32_t RowIndex : RowVector) { // 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(FileName, FunctionName, Row.Line, Row.Column))); + DILineInfo Result; + getFileNameForCompileUnit(CU, LineTable, Row.File, Spec.FLIKind, + Result.FileName); + Result.FunctionName = FunctionName; + Result.Line = Row.Line; + Result.Column = Row.Column; + Lines.push_back(std::make_pair(Row.Address, Result)); } return Lines; } -DIInliningInfo DWARFContext::getInliningInfoForAddress(uint64_t Address, - DILineInfoSpecifier Specifier) { +DIInliningInfo +DWARFContext::getInliningInfoForAddress(uint64_t Address, + DILineInfoSpecifier Spec) { + DIInliningInfo InliningInfo; + DWARFCompileUnit *CU = getCompileUnitForAddress(Address); if (!CU) - return DIInliningInfo(); + return InliningInfo; + const DWARFLineTable *LineTable = nullptr; const DWARFDebugInfoEntryInlinedChain &InlinedChain = CU->getInlinedChainForAddress(Address); - if (InlinedChain.DIEs.size() == 0) - return DIInliningInfo(); + 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 (Spec.FLIKind != FileLineInfoKind::None) { + DILineInfo Frame; + LineTable = getLineTableForCompileUnit(CU); + if (getFileLineInfoForCompileUnit(CU, LineTable, Address, Spec.FLIKind, + Frame)) { + InliningInfo.addFrame(Frame); + } + } + return InliningInfo; + } - 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; + DILineInfo Frame; // 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 (const char *Name = + FunctionDIE.getSubroutineName(InlinedChain.U, Spec.FNKind)) + Frame.FunctionName = Name; + if (Spec.FLIKind != FileLineInfoKind::None) { 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); + getFileLineInfoForCompileUnit(CU, LineTable, Address, Spec.FLIKind, + Frame); } 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; + getFileNameForCompileUnit(CU, LineTable, CallFile, Spec.FLIKind, + Frame.FileName); + Frame.Line = CallLine; + Frame.Column = CallColumn; } // Get call file/line/column of a current DIE. if (i + 1 < n) { @@ -597,8 +600,6 @@ DIInliningInfo DWARFContext::getInliningInfoForAddress(uint64_t Address, CallColumn); } } - DILineInfo Frame(StringRef(FileName), StringRef(FunctionName), - Line, Column); InliningInfo.addFrame(Frame); } return InliningInfo; @@ -637,14 +638,15 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) if (!zlib::isAvailable() || !consumeCompressedDebugSectionHeader(data, OriginalSize)) continue; - std::unique_ptr<MemoryBuffer> UncompressedSection; - if (zlib::uncompress(data, UncompressedSection, OriginalSize) != - zlib::StatusOK) + UncompressedSections.resize(UncompressedSections.size() + 1); + if (zlib::uncompress(data, UncompressedSections.back(), OriginalSize) != + zlib::StatusOK) { + UncompressedSections.pop_back(); continue; + } // Make data point to uncompressed section contents and save its contents. name = name.substr(1); - data = UncompressedSection->getBuffer(); - UncompressedSections.push_back(std::move(UncompressedSection)); + data = UncompressedSections.back(); } StringRef *SectionData = @@ -669,7 +671,7 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) .Case("debug_str_offsets.dwo", &StringOffsetDWOSection) .Case("debug_addr", &AddrSection) // Any more debug info sections go here. - .Default(0); + .Default(nullptr); if (SectionData) { *SectionData = data; if (name == "debug_ranges") { @@ -700,7 +702,7 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) .Case("debug_loc", &LocSection.Relocs) .Case("debug_info.dwo", &InfoDWOSection.Relocs) .Case("debug_line", &LineSection.Relocs) - .Default(0); + .Default(nullptr); if (!Map) { // Find debug_types relocs by section rather than name as there are // multiple, comdat grouped, debug_types sections. diff --git a/lib/DebugInfo/DWARFContext.h b/lib/DebugInfo/DWARFContext.h index ad6841a..6d1ae92 100644 --- a/lib/DebugInfo/DWARFContext.h +++ b/lib/DebugInfo/DWARFContext.h @@ -242,7 +242,7 @@ class DWARFContextInMemory : public DWARFContext { StringRef RangeDWOSection; StringRef AddrSection; - SmallVector<std::unique_ptr<MemoryBuffer>, 4> UncompressedSections; + SmallVector<SmallString<32>, 4> UncompressedSections; public: DWARFContextInMemory(object::ObjectFile *); diff --git a/lib/DebugInfo/DWARFDebugAbbrev.cpp b/lib/DebugInfo/DWARFDebugAbbrev.cpp index fd5f5e9..8426bf9 100644 --- a/lib/DebugInfo/DWARFDebugAbbrev.cpp +++ b/lib/DebugInfo/DWARFDebugAbbrev.cpp @@ -12,24 +12,36 @@ #include "llvm/Support/raw_ostream.h" using namespace llvm; -bool DWARFAbbreviationDeclarationSet::extract(DataExtractor data, - uint32_t* offset_ptr) { - const uint32_t beginOffset = *offset_ptr; - Offset = beginOffset; +DWARFAbbreviationDeclarationSet::DWARFAbbreviationDeclarationSet() { clear(); - DWARFAbbreviationDeclaration abbrevDeclaration; - uint32_t prevAbbrAode = 0; - while (abbrevDeclaration.extract(data, offset_ptr)) { - Decls.push_back(abbrevDeclaration); - if (IdxOffset == 0) { - IdxOffset = abbrevDeclaration.getCode(); +} + +void DWARFAbbreviationDeclarationSet::clear() { + Offset = 0; + FirstAbbrCode = 0; + Decls.clear(); +} + +bool DWARFAbbreviationDeclarationSet::extract(DataExtractor Data, + uint32_t *OffsetPtr) { + clear(); + const uint32_t BeginOffset = *OffsetPtr; + Offset = BeginOffset; + DWARFAbbreviationDeclaration AbbrDecl; + uint32_t PrevAbbrCode = 0; + while (AbbrDecl.extract(Data, OffsetPtr)) { + Decls.push_back(AbbrDecl); + if (FirstAbbrCode == 0) { + FirstAbbrCode = AbbrDecl.getCode(); } else { - if (prevAbbrAode + 1 != abbrevDeclaration.getCode()) - IdxOffset = UINT32_MAX;// Out of order indexes, we can't do O(1) lookups + if (PrevAbbrCode + 1 != AbbrDecl.getCode()) { + // Codes are not consecutive, can't do O(1) lookups. + FirstAbbrCode = UINT32_MAX; + } } - prevAbbrAode = abbrevDeclaration.getCode(); + PrevAbbrCode = AbbrDecl.getCode(); } - return beginOffset != *offset_ptr; + return BeginOffset != *OffsetPtr; } void DWARFAbbreviationDeclarationSet::dump(raw_ostream &OS) const { @@ -37,67 +49,67 @@ void DWARFAbbreviationDeclarationSet::dump(raw_ostream &OS) const { Decl.dump(OS); } -const DWARFAbbreviationDeclaration* -DWARFAbbreviationDeclarationSet::getAbbreviationDeclaration(uint32_t abbrCode) - const { - if (IdxOffset == UINT32_MAX) { +const DWARFAbbreviationDeclaration * +DWARFAbbreviationDeclarationSet::getAbbreviationDeclaration( + uint32_t AbbrCode) const { + if (FirstAbbrCode == UINT32_MAX) { for (const auto &Decl : Decls) { - if (Decl.getCode() == abbrCode) + if (Decl.getCode() == AbbrCode) return &Decl; } - } else { - uint32_t idx = abbrCode - IdxOffset; - if (idx < Decls.size()) - return &Decls[idx]; + return nullptr; } - return NULL; + if (AbbrCode < FirstAbbrCode || AbbrCode >= FirstAbbrCode + Decls.size()) + return nullptr; + return &Decls[AbbrCode - FirstAbbrCode]; } -DWARFDebugAbbrev::DWARFDebugAbbrev() : - AbbrevCollMap(), - PrevAbbrOffsetPos(AbbrevCollMap.end()) {} - +DWARFDebugAbbrev::DWARFDebugAbbrev() { + clear(); +} -void DWARFDebugAbbrev::parse(DataExtractor data) { - uint32_t offset = 0; +void DWARFDebugAbbrev::clear() { + AbbrDeclSets.clear(); + PrevAbbrOffsetPos = AbbrDeclSets.end(); +} - while (data.isValidOffset(offset)) { - uint32_t initial_cu_offset = offset; - DWARFAbbreviationDeclarationSet abbrevDeclSet; +void DWARFDebugAbbrev::extract(DataExtractor Data) { + clear(); - if (abbrevDeclSet.extract(data, &offset)) - AbbrevCollMap[initial_cu_offset] = abbrevDeclSet; - else + uint32_t Offset = 0; + DWARFAbbreviationDeclarationSet AbbrDecls; + while (Data.isValidOffset(Offset)) { + uint32_t CUAbbrOffset = Offset; + if (!AbbrDecls.extract(Data, &Offset)) break; + AbbrDeclSets[CUAbbrOffset] = AbbrDecls; } - PrevAbbrOffsetPos = AbbrevCollMap.end(); } void DWARFDebugAbbrev::dump(raw_ostream &OS) const { - if (AbbrevCollMap.empty()) { + if (AbbrDeclSets.empty()) { OS << "< EMPTY >\n"; return; } - for (const auto &I : AbbrevCollMap) { + for (const auto &I : AbbrDeclSets) { OS << format("Abbrev table for offset: 0x%8.8" PRIx64 "\n", I.first); I.second.dump(OS); } } const DWARFAbbreviationDeclarationSet* -DWARFDebugAbbrev::getAbbreviationDeclarationSet(uint64_t cu_abbr_offset) const { - DWARFAbbreviationDeclarationCollMapConstIter end = AbbrevCollMap.end(); - DWARFAbbreviationDeclarationCollMapConstIter pos; - if (PrevAbbrOffsetPos != end && - PrevAbbrOffsetPos->first == cu_abbr_offset) { +DWARFDebugAbbrev::getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const { + const auto End = AbbrDeclSets.end(); + if (PrevAbbrOffsetPos != End && PrevAbbrOffsetPos->first == CUAbbrOffset) { return &(PrevAbbrOffsetPos->second); - } else { - pos = AbbrevCollMap.find(cu_abbr_offset); - PrevAbbrOffsetPos = pos; } - if (pos != AbbrevCollMap.end()) - return &(pos->second); - return NULL; + const auto Pos = AbbrDeclSets.find(CUAbbrOffset); + if (Pos != End) { + PrevAbbrOffsetPos = Pos; + return &(Pos->second); + } + + return nullptr; } diff --git a/lib/DebugInfo/DWARFDebugAbbrev.h b/lib/DebugInfo/DWARFDebugAbbrev.h index c7c0436..3a9adba 100644 --- a/lib/DebugInfo/DWARFDebugAbbrev.h +++ b/lib/DebugInfo/DWARFDebugAbbrev.h @@ -17,55 +17,45 @@ namespace llvm { -typedef std::vector<DWARFAbbreviationDeclaration> - DWARFAbbreviationDeclarationColl; -typedef DWARFAbbreviationDeclarationColl::iterator - DWARFAbbreviationDeclarationCollIter; -typedef DWARFAbbreviationDeclarationColl::const_iterator - DWARFAbbreviationDeclarationCollConstIter; - class DWARFAbbreviationDeclarationSet { uint32_t Offset; - uint32_t IdxOffset; + /// Code of the first abbreviation, if all abbreviations in the set have + /// consecutive codes. UINT32_MAX otherwise. + uint32_t FirstAbbrCode; std::vector<DWARFAbbreviationDeclaration> Decls; - public: - DWARFAbbreviationDeclarationSet() - : Offset(0), IdxOffset(0) {} - DWARFAbbreviationDeclarationSet(uint32_t offset, uint32_t idxOffset) - : Offset(offset), IdxOffset(idxOffset) {} +public: + DWARFAbbreviationDeclarationSet(); - void clear() { - IdxOffset = 0; - Decls.clear(); - } uint32_t getOffset() const { return Offset; } void dump(raw_ostream &OS) const; - bool extract(DataExtractor data, uint32_t* offset_ptr); + bool extract(DataExtractor Data, uint32_t *OffsetPtr); const DWARFAbbreviationDeclaration * - getAbbreviationDeclaration(uint32_t abbrCode) const; + getAbbreviationDeclaration(uint32_t AbbrCode) const; + +private: + void clear(); }; class DWARFDebugAbbrev { -public: typedef std::map<uint64_t, DWARFAbbreviationDeclarationSet> - DWARFAbbreviationDeclarationCollMap; - typedef DWARFAbbreviationDeclarationCollMap::iterator - DWARFAbbreviationDeclarationCollMapIter; - typedef DWARFAbbreviationDeclarationCollMap::const_iterator - DWARFAbbreviationDeclarationCollMapConstIter; + DWARFAbbreviationDeclarationSetMap; -private: - DWARFAbbreviationDeclarationCollMap AbbrevCollMap; - mutable DWARFAbbreviationDeclarationCollMapConstIter PrevAbbrOffsetPos; + DWARFAbbreviationDeclarationSetMap AbbrDeclSets; + mutable DWARFAbbreviationDeclarationSetMap::const_iterator PrevAbbrOffsetPos; public: DWARFDebugAbbrev(); + const DWARFAbbreviationDeclarationSet * - getAbbreviationDeclarationSet(uint64_t cu_abbr_offset) const; + getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const; + void dump(raw_ostream &OS) const; - void parse(DataExtractor data); + void extract(DataExtractor Data); + +private: + void clear(); }; } diff --git a/lib/DebugInfo/DWARFDebugArangeSet.h b/lib/DebugInfo/DWARFDebugArangeSet.h index c18b3c5..d6c2d8b 100644 --- a/lib/DebugInfo/DWARFDebugArangeSet.h +++ b/lib/DebugInfo/DWARFDebugArangeSet.h @@ -63,7 +63,6 @@ public: return desc_iterator_range(ArangeDescriptors.begin(), ArangeDescriptors.end()); } - uint32_t getNumDescriptors() const { return ArangeDescriptors.size(); } }; } diff --git a/lib/DebugInfo/DWARFDebugAranges.cpp b/lib/DebugInfo/DWARFDebugAranges.cpp index dfab788..2524adc 100644 --- a/lib/DebugInfo/DWARFDebugAranges.cpp +++ b/lib/DebugInfo/DWARFDebugAranges.cpp @@ -10,6 +10,7 @@ #include "DWARFDebugAranges.h" #include "DWARFCompileUnit.h" #include "DWARFContext.h" +#include "DWARFDebugArangeSet.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> @@ -20,23 +21,11 @@ void DWARFDebugAranges::extract(DataExtractor DebugArangesData) { if (!DebugArangesData.isValidOffset(0)) return; uint32_t Offset = 0; - typedef std::vector<DWARFDebugArangeSet> RangeSetColl; - RangeSetColl Sets; DWARFDebugArangeSet Set; - uint32_t TotalRanges = 0; while (Set.extract(DebugArangesData, &Offset)) { - Sets.push_back(Set); - TotalRanges += Set.getNumDescriptors(); - } - if (TotalRanges == 0) - return; - - Aranges.reserve(TotalRanges); - for (const auto &I : Sets) { - uint32_t CUOffset = I.getCompileUnitDIEOffset(); - - for (const auto &Desc : I.descriptors()) { + uint32_t CUOffset = Set.getCompileUnitDIEOffset(); + for (const auto &Desc : Set.descriptors()) { uint64_t LowPC = Desc.Address; uint64_t HighPC = Desc.getEndAddress(); appendRange(CUOffset, LowPC, HighPC); @@ -58,13 +47,23 @@ void DWARFDebugAranges::generate(DWARFContext *CTX) { // manually build aranges for the rest of them. for (const auto &CU : CTX->compile_units()) { uint32_t CUOffset = CU->getOffset(); - if (ParsedCUOffsets.insert(CUOffset).second) - CU->buildAddressRangeTable(this, true, CUOffset); + if (ParsedCUOffsets.insert(CUOffset).second) { + DWARFAddressRangesVector CURanges; + CU->collectAddressRanges(CURanges); + for (const auto &R : CURanges) { + appendRange(CUOffset, R.first, R.second); + } + } } sortAndMinimize(); } +void DWARFDebugAranges::clear() { + Aranges.clear(); + ParsedCUOffsets.clear(); +} + void DWARFDebugAranges::appendRange(uint32_t CUOffset, uint64_t LowPC, uint64_t HighPC) { if (!Aranges.empty()) { @@ -101,11 +100,6 @@ void DWARFDebugAranges::sortAndMinimize() { ++minimal_size; } - // If the sizes are the same, then no consecutive aranges can be - // combined, we are done. - if (minimal_size == orig_arange_size) - return; - // Else, make a new RangeColl that _only_ contains what we need. RangeColl minimal_aranges; minimal_aranges.resize(minimal_size); diff --git a/lib/DebugInfo/DWARFDebugAranges.h b/lib/DebugInfo/DWARFDebugAranges.h index 35ad8e5..de96d7f 100644 --- a/lib/DebugInfo/DWARFDebugAranges.h +++ b/lib/DebugInfo/DWARFDebugAranges.h @@ -10,9 +10,9 @@ #ifndef LLVM_DEBUGINFO_DWARFDEBUGARANGES_H #define LLVM_DEBUGINFO_DWARFDEBUGARANGES_H -#include "DWARFDebugArangeSet.h" #include "llvm/ADT/DenseSet.h" -#include <list> +#include "llvm/Support/DataExtractor.h" +#include <vector> namespace llvm { @@ -20,20 +20,15 @@ class DWARFContext; class DWARFDebugAranges { public: - void clear() { - Aranges.clear(); - ParsedCUOffsets.clear(); - } - void generate(DWARFContext *CTX); - - // Use appendRange multiple times and then call sortAndMinimize. - void appendRange(uint32_t CUOffset, uint64_t LowPC, uint64_t HighPC); - uint32_t findAddress(uint64_t Address) const; private: + void clear(); void extract(DataExtractor DebugArangesData); + + // Use appendRange multiple times and then call sortAndMinimize. + void appendRange(uint32_t CUOffset, uint64_t LowPC, uint64_t HighPC); void sortAndMinimize(); struct Range { diff --git a/lib/DebugInfo/DWARFDebugFrame.cpp b/lib/DebugInfo/DWARFDebugFrame.cpp index 5bf7b07..a33548e 100644 --- a/lib/DebugInfo/DWARFDebugFrame.cpp +++ b/lib/DebugInfo/DWARFDebugFrame.cpp @@ -26,8 +26,8 @@ using namespace dwarf; class llvm::FrameEntry { public: enum FrameKind {FK_CIE, FK_FDE}; - FrameEntry(FrameKind K, DataExtractor D, uint64_t Offset, uint64_t Length) - : Kind(K), Data(D), Offset(Offset), Length(Length) {} + FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length) + : Kind(K), Offset(Offset), Length(Length) {} virtual ~FrameEntry() { } @@ -35,11 +35,12 @@ public: FrameKind getKind() const { return Kind; } virtual uint64_t getOffset() const { return Offset; } - /// \brief Parse and store a sequence of CFI instructions from our data - /// stream, starting at *Offset and ending at EndOffset. If everything + /// \brief Parse and store a sequence of CFI instructions from Data, + /// starting at *Offset and ending at EndOffset. If everything /// goes well, *Offset should be equal to EndOffset when this method /// returns. Otherwise, an error occurred. - virtual void parseInstructions(uint32_t *Offset, uint32_t EndOffset); + virtual void parseInstructions(DataExtractor Data, uint32_t *Offset, + uint32_t EndOffset); /// \brief Dump the entry header to the given output stream. virtual void dumpHeader(raw_ostream &OS) const = 0; @@ -50,10 +51,6 @@ public: protected: const FrameKind Kind; - /// \brief The data stream holding the section from which the entry was - /// parsed. - DataExtractor Data; - /// \brief Offset of this entry in the section. uint64_t Offset; @@ -97,8 +94,8 @@ protected: const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0; const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f; - -void FrameEntry::parseInstructions(uint32_t *Offset, uint32_t EndOffset) { +void FrameEntry::parseInstructions(DataExtractor Data, uint32_t *Offset, + uint32_t EndOffset) { while (*Offset < EndOffset) { uint8_t Opcode = Data.getU8(Offset); // Some instructions have a primary opcode encoded in the top bits. @@ -201,13 +198,13 @@ class CIE : public FrameEntry { public: // CIEs (and FDEs) are simply container classes, so the only sensible way to // create them is by providing the full parsed contents in the constructor. - CIE(DataExtractor D, uint64_t Offset, uint64_t Length, uint8_t Version, + CIE(uint64_t Offset, uint64_t Length, uint8_t Version, SmallString<8> Augmentation, uint64_t CodeAlignmentFactor, int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister) - : FrameEntry(FK_CIE, D, Offset, Length), Version(Version), - Augmentation(Augmentation), CodeAlignmentFactor(CodeAlignmentFactor), - DataAlignmentFactor(DataAlignmentFactor), - ReturnAddressRegister(ReturnAddressRegister) {} + : FrameEntry(FK_CIE, Offset, Length), Version(Version), + Augmentation(Augmentation), CodeAlignmentFactor(CodeAlignmentFactor), + DataAlignmentFactor(DataAlignmentFactor), + ReturnAddressRegister(ReturnAddressRegister) {} ~CIE() { } @@ -229,7 +226,7 @@ public: static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_CIE; - } + } private: /// The following fields are defined in section 6.4.1 of the DWARF standard v3 @@ -247,11 +244,11 @@ public: // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with // an offset to the CIE (provided by parsing the FDE header). The CIE itself // is obtained lazily once it's actually required. - FDE(DataExtractor D, uint64_t Offset, uint64_t Length, - int64_t LinkedCIEOffset, uint64_t InitialLocation, uint64_t AddressRange) - : FrameEntry(FK_FDE, D, Offset, Length), LinkedCIEOffset(LinkedCIEOffset), - InitialLocation(InitialLocation), AddressRange(AddressRange), - LinkedCIE(NULL) {} + FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset, + uint64_t InitialLocation, uint64_t AddressRange) + : FrameEntry(FK_FDE, Offset, Length), LinkedCIEOffset(LinkedCIEOffset), + InitialLocation(InitialLocation), AddressRange(AddressRange), + LinkedCIE(nullptr) {} ~FDE() { } @@ -270,9 +267,9 @@ public: static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_FDE; - } -private: + } +private: /// The following fields are defined in section 6.4.1 of the DWARF standard v3 uint64_t LinkedCIEOffset; uint64_t InitialLocation; @@ -285,14 +282,9 @@ private: DWARFDebugFrame::DWARFDebugFrame() { } - DWARFDebugFrame::~DWARFDebugFrame() { - for (const auto &Entry : Entries) { - delete Entry; - } } - static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data, uint32_t Offset, int Length) { errs() << "DUMP: "; @@ -334,7 +326,6 @@ void DWARFDebugFrame::parse(DataExtractor Data) { Id = Data.getUnsigned(&Offset, IsDWARF64 ? 8 : 4); bool IsCIE = ((IsDWARF64 && Id == DW64_CIE_ID) || Id == DW_CIE_ID); - FrameEntry *Entry = 0; if (IsCIE) { // Note: this is specifically DWARFv3 CIE header structure. It was // changed in DWARFv4. We currently don't support reading DWARFv4 @@ -346,30 +337,25 @@ void DWARFDebugFrame::parse(DataExtractor Data) { int64_t DataAlignmentFactor = Data.getSLEB128(&Offset); uint64_t ReturnAddressRegister = Data.getULEB128(&Offset); - Entry = new CIE(Data, StartOffset, Length, Version, - StringRef(Augmentation), CodeAlignmentFactor, - DataAlignmentFactor, ReturnAddressRegister); + Entries.emplace_back(new CIE(StartOffset, Length, Version, + StringRef(Augmentation), CodeAlignmentFactor, + DataAlignmentFactor, ReturnAddressRegister)); } else { // FDE uint64_t CIEPointer = Id; uint64_t InitialLocation = Data.getAddress(&Offset); uint64_t AddressRange = Data.getAddress(&Offset); - Entry = new FDE(Data, StartOffset, Length, CIEPointer, - InitialLocation, AddressRange); + Entries.emplace_back(new FDE(StartOffset, Length, CIEPointer, + InitialLocation, AddressRange)); } - assert(Entry && "Expected Entry to be populated with CIE or FDE"); - Entry->parseInstructions(&Offset, EndStructureOffset); + Entries.back()->parseInstructions(Data, &Offset, EndStructureOffset); - if (Offset == EndStructureOffset) { - // Entry instrucitons parsed successfully. - Entries.push_back(Entry); - } else { + if (Offset != EndStructureOffset) { std::string Str; raw_string_ostream OS(Str); - OS << format("Parsing entry instructions at %lx failed", - Entry->getOffset()); + OS << format("Parsing entry instructions at %lx failed", StartOffset); report_fatal_error(Str); } } diff --git a/lib/DebugInfo/DWARFDebugFrame.h b/lib/DebugInfo/DWARFDebugFrame.h index 7683849..bd4ef45 100644 --- a/lib/DebugInfo/DWARFDebugFrame.h +++ b/lib/DebugInfo/DWARFDebugFrame.h @@ -12,14 +12,13 @@ #include "llvm/Support/DataExtractor.h" #include "llvm/Support/raw_ostream.h" +#include <memory> #include <vector> - namespace llvm { class FrameEntry; - /// \brief A parsed .debug_frame section /// class DWARFDebugFrame { @@ -35,8 +34,7 @@ public: void parse(DataExtractor Data); private: - typedef std::vector<FrameEntry *> EntryVector; - EntryVector Entries; + std::vector<std::unique_ptr<FrameEntry>> Entries; }; diff --git a/lib/DebugInfo/DWARFDebugInfoEntry.cpp b/lib/DebugInfo/DWARFDebugInfoEntry.cpp index bde25ec..b811ed7 100644 --- a/lib/DebugInfo/DWARFDebugInfoEntry.cpp +++ b/lib/DebugInfo/DWARFDebugInfoEntry.cpp @@ -18,6 +18,7 @@ #include "llvm/Support/raw_ostream.h" using namespace llvm; using namespace dwarf; +typedef DILineInfoSpecifier::FunctionNameKind FunctionNameKind; void DWARFDebugInfoEntryMinimal::dump(raw_ostream &OS, const DWARFUnit *u, unsigned recurseDepth, @@ -99,11 +100,11 @@ bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFUnit *U, uint64_t AbbrCode = DebugInfoData.getULEB128(OffsetPtr); if (0 == AbbrCode) { // NULL debug tag entry. - AbbrevDecl = NULL; + AbbrevDecl = nullptr; return true; } AbbrevDecl = U->getAbbreviations()->getAbbreviationDeclaration(AbbrCode); - if (0 == AbbrevDecl) { + if (nullptr == AbbrevDecl) { // Restore the original offset. *OffsetPtr = Offset; return false; @@ -226,54 +227,66 @@ bool DWARFDebugInfoEntryMinimal::getLowAndHighPC(const DWARFUnit *U, return (HighPC != -1ULL); } -void DWARFDebugInfoEntryMinimal::buildAddressRangeTable( - const DWARFUnit *U, DWARFDebugAranges *DebugAranges, - uint32_t UOffsetInAranges) const { - if (AbbrevDecl) { - if (isSubprogramDIE()) { - uint64_t LowPC, HighPC; - if (getLowAndHighPC(U, LowPC, HighPC)) - DebugAranges->appendRange(UOffsetInAranges, LowPC, HighPC); - // FIXME: try to append ranges from .debug_ranges section. - } - - const DWARFDebugInfoEntryMinimal *Child = getFirstChild(); - while (Child) { - Child->buildAddressRangeTable(U, DebugAranges, UOffsetInAranges); - Child = Child->getSibling(); - } - } -} - -bool DWARFDebugInfoEntryMinimal::addressRangeContainsAddress( - const DWARFUnit *U, const uint64_t Address) const { +DWARFAddressRangesVector +DWARFDebugInfoEntryMinimal::getAddressRanges(const DWARFUnit *U) const { if (isNULL()) - return false; + return DWARFAddressRangesVector(); + // Single range specified by low/high PC. uint64_t LowPC, HighPC; - if (getLowAndHighPC(U, LowPC, HighPC)) - return (LowPC <= Address && Address <= HighPC); - // Try to get address ranges from .debug_ranges section. + if (getLowAndHighPC(U, LowPC, HighPC)) { + return DWARFAddressRangesVector(1, std::make_pair(LowPC, HighPC)); + } + // Multiple ranges from .debug_ranges section. uint32_t RangesOffset = getAttributeValueAsSectionOffset(U, DW_AT_ranges, -1U); if (RangesOffset != -1U) { DWARFDebugRangeList RangeList; if (U->extractRangeList(RangesOffset, RangeList)) - return RangeList.containsAddress(U->getBaseAddress(), Address); + return RangeList.getAbsoluteRanges(U->getBaseAddress()); + } + return DWARFAddressRangesVector(); +} + +void DWARFDebugInfoEntryMinimal::collectChildrenAddressRanges( + const DWARFUnit *U, DWARFAddressRangesVector& Ranges) const { + if (isNULL()) + return; + if (isSubprogramDIE()) { + const auto &DIERanges = getAddressRanges(U); + Ranges.insert(Ranges.end(), DIERanges.begin(), DIERanges.end()); + } + + const DWARFDebugInfoEntryMinimal *Child = getFirstChild(); + while (Child) { + Child->collectChildrenAddressRanges(U, Ranges); + Child = Child->getSibling(); + } +} + +bool DWARFDebugInfoEntryMinimal::addressRangeContainsAddress( + const DWARFUnit *U, const uint64_t Address) const { + for (const auto& R : getAddressRanges(U)) { + if (R.first <= Address && Address < R.second) + return true; } return false; } const char * -DWARFDebugInfoEntryMinimal::getSubroutineName(const DWARFUnit *U) const { - if (!isSubroutineDIE()) - return 0; - // Try to get mangled name if possible. - if (const char *name = - getAttributeValueAsString(U, DW_AT_MIPS_linkage_name, 0)) - return name; - if (const char *name = getAttributeValueAsString(U, DW_AT_linkage_name, 0)) - return name; - if (const char *name = getAttributeValueAsString(U, DW_AT_name, 0)) +DWARFDebugInfoEntryMinimal::getSubroutineName(const DWARFUnit *U, + FunctionNameKind Kind) const { + if (!isSubroutineDIE() || Kind == FunctionNameKind::None) + return nullptr; + // Try to get mangled name only if it was asked for. + if (Kind == FunctionNameKind::LinkageName) { + if (const char *name = + getAttributeValueAsString(U, DW_AT_MIPS_linkage_name, nullptr)) + return name; + if (const char *name = + getAttributeValueAsString(U, DW_AT_linkage_name, nullptr)) + return name; + } + if (const char *name = getAttributeValueAsString(U, DW_AT_name, nullptr)) return name; // Try to get name from specification DIE. uint32_t spec_ref = @@ -281,7 +294,7 @@ DWARFDebugInfoEntryMinimal::getSubroutineName(const DWARFUnit *U) const { if (spec_ref != -1U) { DWARFDebugInfoEntryMinimal spec_die; if (spec_die.extractFast(U, &spec_ref)) { - if (const char *name = spec_die.getSubroutineName(U)) + if (const char *name = spec_die.getSubroutineName(U, Kind)) return name; } } @@ -291,11 +304,11 @@ DWARFDebugInfoEntryMinimal::getSubroutineName(const DWARFUnit *U) const { if (abs_origin_ref != -1U) { DWARFDebugInfoEntryMinimal abs_origin_die; if (abs_origin_die.extractFast(U, &abs_origin_ref)) { - if (const char *name = abs_origin_die.getSubroutineName(U)) + if (const char *name = abs_origin_die.getSubroutineName(U, Kind)) return name; } } - return 0; + return nullptr; } void DWARFDebugInfoEntryMinimal::getCallerFrame(const DWARFUnit *U, diff --git a/lib/DebugInfo/DWARFDebugInfoEntry.h b/lib/DebugInfo/DWARFDebugInfoEntry.h index f30e531..916e1ed 100644 --- a/lib/DebugInfo/DWARFDebugInfoEntry.h +++ b/lib/DebugInfo/DWARFDebugInfoEntry.h @@ -11,7 +11,9 @@ #define LLVM_DEBUGINFO_DWARFDEBUGINFOENTRY_H #include "DWARFAbbreviationDeclaration.h" +#include "DWARFDebugRangeList.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/DIContext.h" #include "llvm/Support/DataTypes.h" namespace llvm { @@ -28,17 +30,13 @@ class DWARFDebugInfoEntryMinimal { /// Offset within the .debug_info of the start of this entry. uint32_t Offset; - /// How many to subtract from "this" to get the parent. - /// If zero this die has no parent. - uint32_t ParentIdx; - /// How many to add to "this" to get the sibling. uint32_t SiblingIdx; const DWARFAbbreviationDeclaration *AbbrevDecl; public: DWARFDebugInfoEntryMinimal() - : Offset(0), ParentIdx(0), SiblingIdx(0), AbbrevDecl(0) {} + : Offset(0), SiblingIdx(0), AbbrevDecl(nullptr) {} void dump(raw_ostream &OS, const DWARFUnit *u, unsigned recurseDepth, unsigned indent = 0) const; @@ -51,7 +49,7 @@ public: bool extractFast(const DWARFUnit *U, uint32_t *OffsetPtr); uint32_t getTag() const { return AbbrevDecl ? AbbrevDecl->getTag() : 0; } - bool isNULL() const { return AbbrevDecl == 0; } + bool isNULL() const { return AbbrevDecl == nullptr; } /// Returns true if DIE represents a subprogram (not inlined). bool isSubprogramDIE() const; @@ -63,45 +61,23 @@ public: bool hasChildren() const { return !isNULL() && AbbrevDecl->hasChildren(); } // We know we are kept in a vector of contiguous entries, so we know - // our parent will be some index behind "this". - DWARFDebugInfoEntryMinimal *getParent() { - return ParentIdx > 0 ? this - ParentIdx : 0; - } - const DWARFDebugInfoEntryMinimal *getParent() const { - return ParentIdx > 0 ? this - ParentIdx : 0; - } - // We know we are kept in a vector of contiguous entries, so we know // our sibling will be some index after "this". - DWARFDebugInfoEntryMinimal *getSibling() { - return SiblingIdx > 0 ? this + SiblingIdx : 0; - } const DWARFDebugInfoEntryMinimal *getSibling() const { - return SiblingIdx > 0 ? this + SiblingIdx : 0; + return SiblingIdx > 0 ? this + SiblingIdx : nullptr; } + // We know we are kept in a vector of contiguous entries, so we know // we don't need to store our child pointer, if we have a child it will // be the next entry in the list... - DWARFDebugInfoEntryMinimal *getFirstChild() { - return hasChildren() ? this + 1 : 0; - } const DWARFDebugInfoEntryMinimal *getFirstChild() const { - return hasChildren() ? this + 1 : 0; + return hasChildren() ? this + 1 : nullptr; } - void setParent(DWARFDebugInfoEntryMinimal *parent) { - if (parent) { - // We know we are kept in a vector of contiguous entries, so we know - // our parent will be some index behind "this". - ParentIdx = this - parent; - } else - ParentIdx = 0; - } - void setSibling(DWARFDebugInfoEntryMinimal *sibling) { - if (sibling) { + void setSibling(const DWARFDebugInfoEntryMinimal *Sibling) { + if (Sibling) { // We know we are kept in a vector of contiguous entries, so we know // our sibling will be some index after "this". - SiblingIdx = sibling - this; - sibling->setParent(getParent()); + SiblingIdx = Sibling - this; } else SiblingIdx = 0; } @@ -135,9 +111,10 @@ public: bool getLowAndHighPC(const DWARFUnit *U, uint64_t &LowPC, uint64_t &HighPC) const; - void buildAddressRangeTable(const DWARFUnit *U, - DWARFDebugAranges *DebugAranges, - uint32_t CUOffsetInAranges) const; + DWARFAddressRangesVector getAddressRanges(const DWARFUnit *U) const; + + void collectChildrenAddressRanges(const DWARFUnit *U, + DWARFAddressRangesVector &Ranges) const; bool addressRangeContainsAddress(const DWARFUnit *U, const uint64_t Address) const; @@ -146,7 +123,9 @@ public: /// returns its mangled name (or short name, if mangled is missing). /// This name may be fetched from specification or abstract origin /// for this subprogram. Returns null if no name is found. - const char *getSubroutineName(const DWARFUnit *U) const; + const char * + getSubroutineName(const DWARFUnit *U, + DILineInfoSpecifier::FunctionNameKind Kind) 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). @@ -166,7 +145,7 @@ public: /// (except the last DIE) in this chain is contained in address /// range for next DIE in the chain. struct DWARFDebugInfoEntryInlinedChain { - DWARFDebugInfoEntryInlinedChain() : U(0) {} + DWARFDebugInfoEntryInlinedChain() : U(nullptr) {} SmallVector<DWARFDebugInfoEntryMinimal, 4> DIEs; const DWARFUnit *U; }; diff --git a/lib/DebugInfo/DWARFDebugLine.cpp b/lib/DebugInfo/DWARFDebugLine.cpp index 43d9764..ce87635 100644 --- a/lib/DebugInfo/DWARFDebugLine.cpp +++ b/lib/DebugInfo/DWARFDebugLine.cpp @@ -15,6 +15,20 @@ #include <algorithm> using namespace llvm; using namespace dwarf; +typedef DILineInfoSpecifier::FileLineInfoKind FileLineInfoKind; + +DWARFDebugLine::Prologue::Prologue() { + clear(); +} + +void DWARFDebugLine::Prologue::clear() { + TotalLength = Version = PrologueLength = 0; + MinInstLength = MaxOpsPerInst = DefaultIsStmt = LineBase = LineRange = 0; + OpcodeBase = 0; + StandardOpcodeLengths.clear(); + IncludeDirectories.clear(); + FileNames.clear(); +} void DWARFDebugLine::Prologue::dump(raw_ostream &OS) const { OS << "Line table prologue:\n" @@ -51,6 +65,67 @@ void DWARFDebugLine::Prologue::dump(raw_ostream &OS) const { } } +bool DWARFDebugLine::Prologue::parse(DataExtractor debug_line_data, + uint32_t *offset_ptr) { + const uint32_t prologue_offset = *offset_ptr; + + clear(); + TotalLength = debug_line_data.getU32(offset_ptr); + Version = debug_line_data.getU16(offset_ptr); + if (Version < 2) + return false; + + PrologueLength = debug_line_data.getU32(offset_ptr); + const uint32_t end_prologue_offset = PrologueLength + *offset_ptr; + MinInstLength = debug_line_data.getU8(offset_ptr); + if (Version >= 4) + MaxOpsPerInst = debug_line_data.getU8(offset_ptr); + DefaultIsStmt = debug_line_data.getU8(offset_ptr); + LineBase = debug_line_data.getU8(offset_ptr); + LineRange = debug_line_data.getU8(offset_ptr); + OpcodeBase = debug_line_data.getU8(offset_ptr); + + StandardOpcodeLengths.reserve(OpcodeBase - 1); + for (uint32_t i = 1; i < OpcodeBase; ++i) { + uint8_t op_len = debug_line_data.getU8(offset_ptr); + StandardOpcodeLengths.push_back(op_len); + } + + while (*offset_ptr < end_prologue_offset) { + const char *s = debug_line_data.getCStr(offset_ptr); + if (s && s[0]) + IncludeDirectories.push_back(s); + else + break; + } + + while (*offset_ptr < end_prologue_offset) { + const char *name = debug_line_data.getCStr(offset_ptr); + if (name && name[0]) { + FileNameEntry fileEntry; + fileEntry.Name = name; + fileEntry.DirIdx = debug_line_data.getULEB128(offset_ptr); + fileEntry.ModTime = debug_line_data.getULEB128(offset_ptr); + fileEntry.Length = debug_line_data.getULEB128(offset_ptr); + FileNames.push_back(fileEntry); + } else { + break; + } + } + + if (*offset_ptr != end_prologue_offset) { + fprintf(stderr, "warning: parsing line table prologue at 0x%8.8x should" + " have ended at 0x%8.8x but it ended at 0x%8.8x\n", + prologue_offset, end_prologue_offset, *offset_ptr); + return false; + } + return true; +} + +DWARFDebugLine::Row::Row(bool default_is_stmt) { + reset(default_is_stmt); +} + void DWARFDebugLine::Row::postAppend() { BasicBlock = false; PrologueEnd = false; @@ -82,6 +157,22 @@ void DWARFDebugLine::Row::dump(raw_ostream &OS) const { << '\n'; } +DWARFDebugLine::Sequence::Sequence() { + reset(); +} + +void DWARFDebugLine::Sequence::reset() { + LowPC = 0; + HighPC = 0; + FirstRowIndex = 0; + LastRowIndex = 0; + Empty = true; +} + +DWARFDebugLine::LineTable::LineTable() { + clear(); +} + void DWARFDebugLine::LineTable::dump(raw_ostream &OS) const { Prologue.dump(OS); OS << '\n'; @@ -96,50 +187,40 @@ void DWARFDebugLine::LineTable::dump(raw_ostream &OS) const { } } -DWARFDebugLine::State::~State() {} - -void DWARFDebugLine::State::appendRowToMatrix(uint32_t offset) { - if (Sequence::Empty) { - // Record the beginning of instruction sequence. - Sequence::Empty = false; - Sequence::LowPC = Address; - Sequence::FirstRowIndex = row; - } - ++row; // Increase the row number. - LineTable::appendRow(*this); - if (EndSequence) { - // Record the end of instruction sequence. - Sequence::HighPC = Address; - Sequence::LastRowIndex = row; - if (Sequence::isValid()) - LineTable::appendSequence(*this); - Sequence::reset(); - } - Row::postAppend(); +void DWARFDebugLine::LineTable::clear() { + Prologue.clear(); + Rows.clear(); + Sequences.clear(); } -void DWARFDebugLine::State::finalize() { - row = DoneParsingLineTable; - if (!Sequence::Empty) { - fprintf(stderr, "warning: last sequence in debug line table is not" - "terminated!\n"); - } - // Sort all sequences so that address lookup will work faster. - if (!Sequences.empty()) { - std::sort(Sequences.begin(), Sequences.end(), Sequence::orderByLowPC); - // Note: actually, instruction address ranges of sequences should not - // overlap (in shared objects and executables). If they do, the address - // lookup would still work, though, but result would be ambiguous. - // We don't report warning in this case. For example, - // sometimes .so compiled from multiple object files contains a few - // rudimentary sequences for address ranges [0x0, 0xsomething). - } +DWARFDebugLine::ParsingState::ParsingState(struct LineTable *LT) + : LineTable(LT), RowNumber(0) { + resetRowAndSequence(); } -DWARFDebugLine::DumpingState::~DumpingState() {} +void DWARFDebugLine::ParsingState::resetRowAndSequence() { + Row.reset(LineTable->Prologue.DefaultIsStmt); + Sequence.reset(); +} -void DWARFDebugLine::DumpingState::finalize() { - LineTable::dump(OS); +void DWARFDebugLine::ParsingState::appendRowToMatrix(uint32_t offset) { + if (Sequence.Empty) { + // Record the beginning of instruction sequence. + Sequence.Empty = false; + Sequence.LowPC = Row.Address; + Sequence.FirstRowIndex = RowNumber; + } + ++RowNumber; + LineTable->appendRow(Row); + if (Row.EndSequence) { + // Record the end of instruction sequence. + Sequence.HighPC = Row.Address; + Sequence.LastRowIndex = RowNumber; + if (Sequence.isValid()) + LineTable->appendSequence(Sequence); + Sequence.reset(); + } + Row.postAppend(); } const DWARFDebugLine::LineTable * @@ -147,7 +228,7 @@ DWARFDebugLine::getLineTable(uint32_t offset) const { LineTableConstIter pos = LineTableMap.find(offset); if (pos != LineTableMap.end()) return &pos->second; - return 0; + return nullptr; } const DWARFDebugLine::LineTable * @@ -155,91 +236,31 @@ DWARFDebugLine::getOrParseLineTable(DataExtractor debug_line_data, uint32_t offset) { std::pair<LineTableIter, bool> pos = LineTableMap.insert(LineTableMapTy::value_type(offset, LineTable())); + LineTable *LT = &pos.first->second; if (pos.second) { - // Parse and cache the line table for at this offset. - State state; - if (!parseStatementTable(debug_line_data, RelocMap, &offset, state)) - return 0; - pos.first->second = state; + if (!LT->parse(debug_line_data, RelocMap, &offset)) + return nullptr; } - return &pos.first->second; + return LT; } -bool -DWARFDebugLine::parsePrologue(DataExtractor debug_line_data, - uint32_t *offset_ptr, Prologue *prologue) { - const uint32_t prologue_offset = *offset_ptr; - - prologue->clear(); - prologue->TotalLength = debug_line_data.getU32(offset_ptr); - prologue->Version = debug_line_data.getU16(offset_ptr); - if (prologue->Version < 2) - return false; - - prologue->PrologueLength = debug_line_data.getU32(offset_ptr); - const uint32_t end_prologue_offset = prologue->PrologueLength + *offset_ptr; - prologue->MinInstLength = debug_line_data.getU8(offset_ptr); - if (prologue->Version >= 4) - prologue->MaxOpsPerInst = debug_line_data.getU8(offset_ptr); - prologue->DefaultIsStmt = debug_line_data.getU8(offset_ptr); - prologue->LineBase = debug_line_data.getU8(offset_ptr); - prologue->LineRange = debug_line_data.getU8(offset_ptr); - prologue->OpcodeBase = debug_line_data.getU8(offset_ptr); - - prologue->StandardOpcodeLengths.reserve(prologue->OpcodeBase-1); - for (uint32_t i = 1; i < prologue->OpcodeBase; ++i) { - uint8_t op_len = debug_line_data.getU8(offset_ptr); - prologue->StandardOpcodeLengths.push_back(op_len); - } - - while (*offset_ptr < end_prologue_offset) { - const char *s = debug_line_data.getCStr(offset_ptr); - if (s && s[0]) - prologue->IncludeDirectories.push_back(s); - else - break; - } - - while (*offset_ptr < end_prologue_offset) { - const char *name = debug_line_data.getCStr(offset_ptr); - if (name && name[0]) { - FileNameEntry fileEntry; - fileEntry.Name = name; - fileEntry.DirIdx = debug_line_data.getULEB128(offset_ptr); - fileEntry.ModTime = debug_line_data.getULEB128(offset_ptr); - fileEntry.Length = debug_line_data.getULEB128(offset_ptr); - prologue->FileNames.push_back(fileEntry); - } else { - break; - } - } - - if (*offset_ptr != end_prologue_offset) { - fprintf(stderr, "warning: parsing line table prologue at 0x%8.8x should" - " have ended at 0x%8.8x but it ended at 0x%8.8x\n", - prologue_offset, end_prologue_offset, *offset_ptr); - return false; - } - return true; -} - -bool DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data, - const RelocAddrMap *RMap, - uint32_t *offset_ptr, State &state) { +bool DWARFDebugLine::LineTable::parse(DataExtractor debug_line_data, + const RelocAddrMap *RMap, + uint32_t *offset_ptr) { const uint32_t debug_line_offset = *offset_ptr; - Prologue *prologue = &state.Prologue; + clear(); - if (!parsePrologue(debug_line_data, offset_ptr, prologue)) { + if (!Prologue.parse(debug_line_data, offset_ptr)) { // Restore our offset and return false to indicate failure! *offset_ptr = debug_line_offset; return false; } - const uint32_t end_offset = debug_line_offset + prologue->TotalLength + - sizeof(prologue->TotalLength); + const uint32_t end_offset = debug_line_offset + Prologue.TotalLength + + sizeof(Prologue.TotalLength); - state.reset(); + ParsingState State(this); while (*offset_ptr < end_offset) { uint8_t opcode = debug_line_data.getU8(offset_ptr); @@ -261,9 +282,9 @@ bool DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data, // with a DW_LNE_end_sequence instruction which creates a row whose // address is that of the byte after the last target machine instruction // of the sequence. - state.EndSequence = true; - state.appendRowToMatrix(*offset_ptr); - state.reset(); + State.Row.EndSequence = true; + State.appendRowToMatrix(*offset_ptr); + State.resetRowAndSequence(); break; case DW_LNE_set_address: @@ -278,9 +299,10 @@ bool DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data, RelocAddrMap::const_iterator AI = RMap->find(*offset_ptr); if (AI != RMap->end()) { const std::pair<uint8_t, int64_t> &R = AI->second; - state.Address = debug_line_data.getAddress(offset_ptr) + R.second; + State.Row.Address = + debug_line_data.getAddress(offset_ptr) + R.second; } else - state.Address = debug_line_data.getAddress(offset_ptr); + State.Row.Address = debug_line_data.getAddress(offset_ptr); } break; @@ -311,12 +333,12 @@ bool DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data, fileEntry.DirIdx = debug_line_data.getULEB128(offset_ptr); fileEntry.ModTime = debug_line_data.getULEB128(offset_ptr); fileEntry.Length = debug_line_data.getULEB128(offset_ptr); - prologue->FileNames.push_back(fileEntry); + Prologue.FileNames.push_back(fileEntry); } break; case DW_LNE_set_discriminator: - state.Discriminator = debug_line_data.getULEB128(offset_ptr); + State.Row.Discriminator = debug_line_data.getULEB128(offset_ptr); break; default: @@ -325,52 +347,52 @@ bool DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data, (*offset_ptr) += arg_size; break; } - } else if (opcode < prologue->OpcodeBase) { + } else if (opcode < Prologue.OpcodeBase) { switch (opcode) { // Standard Opcodes case DW_LNS_copy: // Takes no arguments. Append a row to the matrix using the // current values of the state-machine registers. Then set // the basic_block register to false. - state.appendRowToMatrix(*offset_ptr); + State.appendRowToMatrix(*offset_ptr); break; case DW_LNS_advance_pc: // Takes a single unsigned LEB128 operand, multiplies it by the // min_inst_length field of the prologue, and adds the // result to the address register of the state machine. - state.Address += debug_line_data.getULEB128(offset_ptr) * - prologue->MinInstLength; + State.Row.Address += + debug_line_data.getULEB128(offset_ptr) * Prologue.MinInstLength; break; case DW_LNS_advance_line: // Takes a single signed LEB128 operand and adds that value to // the line register of the state machine. - state.Line += debug_line_data.getSLEB128(offset_ptr); + State.Row.Line += debug_line_data.getSLEB128(offset_ptr); break; case DW_LNS_set_file: // Takes a single unsigned LEB128 operand and stores it in the file // register of the state machine. - state.File = debug_line_data.getULEB128(offset_ptr); + State.Row.File = debug_line_data.getULEB128(offset_ptr); break; case DW_LNS_set_column: // Takes a single unsigned LEB128 operand and stores it in the // column register of the state machine. - state.Column = debug_line_data.getULEB128(offset_ptr); + State.Row.Column = debug_line_data.getULEB128(offset_ptr); break; case DW_LNS_negate_stmt: // Takes no arguments. Set the is_stmt register of the state // machine to the logical negation of its current value. - state.IsStmt = !state.IsStmt; + State.Row.IsStmt = !State.Row.IsStmt; break; case DW_LNS_set_basic_block: // Takes no arguments. Set the basic_block register of the // state machine to true - state.BasicBlock = true; + State.Row.BasicBlock = true; break; case DW_LNS_const_add_pc: @@ -386,10 +408,10 @@ bool DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data, // than twice that range will it need to use both DW_LNS_advance_pc // and a special opcode, requiring three or more bytes. { - uint8_t adjust_opcode = 255 - prologue->OpcodeBase; - uint64_t addr_offset = (adjust_opcode / prologue->LineRange) * - prologue->MinInstLength; - state.Address += addr_offset; + uint8_t adjust_opcode = 255 - Prologue.OpcodeBase; + uint64_t addr_offset = + (adjust_opcode / Prologue.LineRange) * Prologue.MinInstLength; + State.Row.Address += addr_offset; } break; @@ -403,25 +425,25 @@ bool DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data, // judge when the computation of a special opcode overflows and // requires the use of DW_LNS_advance_pc. Such assemblers, however, // can use DW_LNS_fixed_advance_pc instead, sacrificing compression. - state.Address += debug_line_data.getU16(offset_ptr); + State.Row.Address += debug_line_data.getU16(offset_ptr); break; case DW_LNS_set_prologue_end: // Takes no arguments. Set the prologue_end register of the // state machine to true - state.PrologueEnd = true; + State.Row.PrologueEnd = true; break; case DW_LNS_set_epilogue_begin: // Takes no arguments. Set the basic_block register of the // state machine to true - state.EpilogueBegin = true; + State.Row.EpilogueBegin = true; break; case DW_LNS_set_isa: // Takes a single unsigned LEB128 operand and stores it in the // column register of the state machine. - state.Isa = debug_line_data.getULEB128(offset_ptr); + State.Row.Isa = debug_line_data.getULEB128(offset_ptr); break; default: @@ -429,9 +451,9 @@ bool DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data, // of such opcodes because they are specified in the prologue // as a multiple of LEB128 operands for each opcode. { - assert(opcode - 1U < prologue->StandardOpcodeLengths.size()); - uint8_t opcode_length = prologue->StandardOpcodeLengths[opcode - 1]; - for (uint8_t i=0; i<opcode_length; ++i) + assert(opcode - 1U < Prologue.StandardOpcodeLengths.size()); + uint8_t opcode_length = Prologue.StandardOpcodeLengths[opcode - 1]; + for (uint8_t i = 0; i < opcode_length; ++i) debug_line_data.getULEB128(offset_ptr); } break; @@ -470,24 +492,37 @@ bool DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data, // // line increment = line_base + (adjusted opcode % line_range) - uint8_t adjust_opcode = opcode - prologue->OpcodeBase; - uint64_t addr_offset = (adjust_opcode / prologue->LineRange) * - prologue->MinInstLength; - int32_t line_offset = prologue->LineBase + - (adjust_opcode % prologue->LineRange); - state.Line += line_offset; - state.Address += addr_offset; - state.appendRowToMatrix(*offset_ptr); + uint8_t adjust_opcode = opcode - Prologue.OpcodeBase; + uint64_t addr_offset = + (adjust_opcode / Prologue.LineRange) * Prologue.MinInstLength; + int32_t line_offset = + Prologue.LineBase + (adjust_opcode % Prologue.LineRange); + State.Row.Line += line_offset; + State.Row.Address += addr_offset; + State.appendRowToMatrix(*offset_ptr); } } - state.finalize(); + if (!State.Sequence.Empty) { + fprintf(stderr, "warning: last sequence in debug line table is not" + "terminated!\n"); + } + + // Sort all sequences so that address lookup will work faster. + if (!Sequences.empty()) { + std::sort(Sequences.begin(), Sequences.end(), Sequence::orderByLowPC); + // Note: actually, instruction address ranges of sequences should not + // overlap (in shared objects and executables). If they do, the address + // lookup would still work, though, but result would be ambiguous. + // We don't report warning in this case. For example, + // sometimes .so compiled from multiple object files contains a few + // rudimentary sequences for address ranges [0x0, 0xsomething). + } return end_offset; } -uint32_t -DWARFDebugLine::LineTable::lookupAddress(uint64_t address) const { +uint32_t DWARFDebugLine::LineTable::lookupAddress(uint64_t address) const { uint32_t unknown_index = UINT32_MAX; if (Sequences.empty()) return unknown_index; @@ -532,10 +567,8 @@ DWARFDebugLine::LineTable::lookupAddress(uint64_t address) const { return index; } -bool -DWARFDebugLine::LineTable::lookupAddressRange(uint64_t address, - uint64_t size, - std::vector<uint32_t>& result) const { +bool DWARFDebugLine::LineTable::lookupAddressRange( + uint64_t address, uint64_t size, std::vector<uint32_t> &result) const { if (Sequences.empty()) return false; uint64_t end_addr = address + size; @@ -611,13 +644,14 @@ DWARFDebugLine::LineTable::lookupAddressRange(uint64_t address, bool DWARFDebugLine::LineTable::getFileNameByIndex(uint64_t FileIndex, - bool NeedsAbsoluteFilePath, + FileLineInfoKind Kind, std::string &Result) const { - if (FileIndex == 0 || FileIndex > Prologue.FileNames.size()) + if (FileIndex == 0 || FileIndex > Prologue.FileNames.size() || + Kind == FileLineInfoKind::None) return false; const FileNameEntry &Entry = Prologue.FileNames[FileIndex - 1]; const char *FileName = Entry.Name; - if (!NeedsAbsoluteFilePath || + if (Kind != FileLineInfoKind::AbsoluteFilePath || sys::path::is_absolute(FileName)) { Result = FileName; return true; diff --git a/lib/DebugInfo/DWARFDebugLine.h b/lib/DebugInfo/DWARFDebugLine.h index a336f49..c7b7ec2 100644 --- a/lib/DebugInfo/DWARFDebugLine.h +++ b/lib/DebugInfo/DWARFDebugLine.h @@ -11,6 +11,7 @@ #define LLVM_DEBUGINFO_DWARFDEBUGLINE_H #include "DWARFRelocMap.h" +#include "llvm/DebugInfo/DIContext.h" #include "llvm/Support/DataExtractor.h" #include <map> #include <string> @@ -24,7 +25,7 @@ class DWARFDebugLine { public: DWARFDebugLine(const RelocAddrMap* LineInfoRelocMap) : RelocMap(LineInfoRelocMap) {} struct FileNameEntry { - FileNameEntry() : Name(0), DirIdx(0), ModTime(0), Length(0) {} + FileNameEntry() : Name(nullptr), DirIdx(0), ModTime(0), Length(0) {} const char *Name; uint64_t DirIdx; @@ -33,10 +34,7 @@ public: }; struct Prologue { - Prologue() - : TotalLength(0), Version(0), PrologueLength(0), MinInstLength(0), - MaxOpsPerInst(0), DefaultIsStmt(0), LineBase(0), LineRange(0), - OpcodeBase(0) {} + Prologue(); // The size in bytes of the statement information for this compilation unit // (not including the total_length field itself). @@ -77,19 +75,16 @@ public: int32_t getMaxLineIncrementForSpecialOpcode() const { return LineBase + (int8_t)LineRange - 1; } + + void clear(); void dump(raw_ostream &OS) const; - void clear() { - TotalLength = Version = PrologueLength = 0; - MinInstLength = LineBase = LineRange = OpcodeBase = 0; - StandardOpcodeLengths.clear(); - IncludeDirectories.clear(); - FileNames.clear(); - } + bool parse(DataExtractor debug_line_data, uint32_t *offset_ptr); }; // Standard .debug_line state machine structure. struct Row { - Row(bool default_is_stmt = false) { reset(default_is_stmt); } + explicit Row(bool default_is_stmt = false); + /// Called after a row is appended to the matrix. void postAppend(); void reset(bool default_is_stmt); @@ -151,14 +146,9 @@ public: unsigned LastRowIndex; bool Empty; - Sequence() { reset(); } - void reset() { - LowPC = 0; - HighPC = 0; - FirstRowIndex = 0; - LastRowIndex = 0; - Empty = true; - } + Sequence(); + void reset(); + static bool orderByLowPC(const Sequence& LHS, const Sequence& RHS) { return LHS.LowPC < RHS.LowPC; } @@ -171,31 +161,34 @@ public: }; struct LineTable { - void appendRow(const DWARFDebugLine::Row &state) { Rows.push_back(state); } - void appendSequence(const DWARFDebugLine::Sequence &sequence) { - Sequences.push_back(sequence); + LineTable(); + + void appendRow(const DWARFDebugLine::Row &R) { + Rows.push_back(R); } - void clear() { - Prologue.clear(); - Rows.clear(); - Sequences.clear(); + void appendSequence(const DWARFDebugLine::Sequence &S) { + Sequences.push_back(S); } // Returns the index of the row with file/line info for a given address, // or -1 if there is no such row. uint32_t lookupAddress(uint64_t address) const; - bool lookupAddressRange(uint64_t address, - uint64_t size, - std::vector<uint32_t>& result) const; + bool lookupAddressRange(uint64_t address, uint64_t size, + std::vector<uint32_t> &result) const; // Extracts filename by its index in filename table in prologue. // Returns true on success. bool getFileNameByIndex(uint64_t FileIndex, - bool NeedsAbsoluteFilePath, + DILineInfoSpecifier::FileLineInfoKind Kind, std::string &Result) const; void dump(raw_ostream &OS) const; + void clear(); + + /// Parse prologue and all rows. + bool parse(DataExtractor debug_line_data, const RelocAddrMap *RMap, + uint32_t *offset_ptr); struct Prologue Prologue; typedef std::vector<Row> RowVector; @@ -206,48 +199,26 @@ public: SequenceVector Sequences; }; - struct State : public Row, public Sequence, public LineTable { - // Special row codes. - enum { - StartParsingLineTable = 0, - DoneParsingLineTable = -1 - }; - - State() : row(StartParsingLineTable) {} - virtual ~State(); - - virtual void appendRowToMatrix(uint32_t offset); - virtual void finalize(); - virtual void reset() { - Row::reset(Prologue.DefaultIsStmt); - Sequence::reset(); - } - - // The row number that starts at zero for the prologue, and increases for - // each row added to the matrix. - unsigned row; - }; - - struct DumpingState : public State { - DumpingState(raw_ostream &OS) : OS(OS) {} - virtual ~DumpingState(); - void finalize() override; - private: - raw_ostream &OS; - }; - - static bool parsePrologue(DataExtractor debug_line_data, uint32_t *offset_ptr, - Prologue *prologue); - /// Parse a single line table (prologue and all rows). - static bool parseStatementTable(DataExtractor debug_line_data, - const RelocAddrMap *RMap, - uint32_t *offset_ptr, State &state); - const LineTable *getLineTable(uint32_t offset) const; const LineTable *getOrParseLineTable(DataExtractor debug_line_data, uint32_t offset); private: + struct ParsingState { + ParsingState(struct LineTable *LT); + + void resetRowAndSequence(); + void appendRowToMatrix(uint32_t offset); + + // Line table we're currently parsing. + struct LineTable *LineTable; + // The row number that starts at zero for the prologue, and increases for + // each row added to the matrix. + unsigned RowNumber; + struct Row Row; + struct Sequence Sequence; + }; + typedef std::map<uint32_t, LineTable> LineTableMapTy; typedef LineTableMapTy::iterator LineTableIter; typedef LineTableMapTy::const_iterator LineTableConstIter; diff --git a/lib/DebugInfo/DWARFDebugRangeList.cpp b/lib/DebugInfo/DWARFDebugRangeList.cpp index aa2a2be..07b23b3 100644 --- a/lib/DebugInfo/DWARFDebugRangeList.cpp +++ b/lib/DebugInfo/DWARFDebugRangeList.cpp @@ -54,13 +54,16 @@ void DWARFDebugRangeList::dump(raw_ostream &OS) const { OS << format("%08x <End of list>\n", Offset); } -bool DWARFDebugRangeList::containsAddress(uint64_t BaseAddress, - uint64_t Address) const { +DWARFAddressRangesVector +DWARFDebugRangeList::getAbsoluteRanges(uint64_t BaseAddress) const { + DWARFAddressRangesVector Res; for (const RangeListEntry &RLE : Entries) { - if (RLE.isBaseAddressSelectionEntry(AddressSize)) + if (RLE.isBaseAddressSelectionEntry(AddressSize)) { BaseAddress = RLE.EndAddress; - else if (RLE.containsAddress(BaseAddress, Address)) - return true; + } else { + Res.push_back(std::make_pair(BaseAddress + RLE.StartAddress, + BaseAddress + RLE.EndAddress)); + } } - return false; + return Res; } diff --git a/lib/DebugInfo/DWARFDebugRangeList.h b/lib/DebugInfo/DWARFDebugRangeList.h index 4e34a91..587b550 100644 --- a/lib/DebugInfo/DWARFDebugRangeList.h +++ b/lib/DebugInfo/DWARFDebugRangeList.h @@ -17,6 +17,9 @@ namespace llvm { class raw_ostream; +/// DWARFAddressRangesVector - represents a set of absolute address ranges. +typedef std::vector<std::pair<uint64_t, uint64_t>> DWARFAddressRangesVector; + class DWARFDebugRangeList { public: struct RangeListEntry { @@ -50,10 +53,6 @@ public: else return StartAddress == -1ULL; } - bool containsAddress(uint64_t BaseAddress, uint64_t Address) const { - return (BaseAddress + StartAddress <= Address) && - (Address < BaseAddress + EndAddress); - } }; private: @@ -67,10 +66,10 @@ public: void clear(); void dump(raw_ostream &OS) const; bool extract(DataExtractor data, uint32_t *offset_ptr); - /// containsAddress - Returns true if range list contains the given - /// address. Has to be passed base address of the compile unit that - /// references this range list. - bool containsAddress(uint64_t BaseAddress, uint64_t Address) const; + /// getAbsoluteRanges - Returns absolute address ranges defined by this range + /// list. Has to be passed base address of the compile unit referencing this + /// range list. + DWARFAddressRangesVector getAbsoluteRanges(uint64_t BaseAddress) const; }; } // namespace llvm diff --git a/lib/DebugInfo/DWARFFormValue.cpp b/lib/DebugInfo/DWARFFormValue.cpp index da71fb3..8d0f966 100644 --- a/lib/DebugInfo/DWARFFormValue.cpp +++ b/lib/DebugInfo/DWARFFormValue.cpp @@ -131,7 +131,7 @@ bool DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr, const DWARFUnit *cu) { bool indirect = false; bool is_block = false; - Value.data = NULL; + Value.data = nullptr; // Read the value for the form into value and follow and DW_FORM_indirect // instances we run into do { @@ -241,7 +241,7 @@ bool DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr, if (is_block) { StringRef str = data.getData().substr(*offset_ptr, Value.uval); - Value.data = NULL; + Value.data = nullptr; if (!str.empty()) { Value.data = reinterpret_cast<const uint8_t *>(str.data()); *offset_ptr += Value.uval; @@ -488,7 +488,7 @@ Optional<const char *> DWARFFormValue::getAsCString(const DWARFUnit *U) const { return None; if (Form == DW_FORM_string) return Value.cstr; - if (U == 0) + if (!U) return None; uint32_t Offset = Value.uval; if (Form == DW_FORM_GNU_str_index) { @@ -509,7 +509,7 @@ Optional<uint64_t> DWARFFormValue::getAsAddress(const DWARFUnit *U) const { if (Form == DW_FORM_GNU_addr_index) { uint32_t Index = Value.uval; uint64_t Result; - if (U == 0 || !U->getAddrOffsetSectionItem(Index, Result)) + if (!U || !U->getAddrOffsetSectionItem(Index, Result)) return None; return Result; } @@ -525,7 +525,7 @@ Optional<uint64_t> DWARFFormValue::getAsReference(const DWARFUnit *U) const { case DW_FORM_ref4: case DW_FORM_ref8: case DW_FORM_ref_udata: - if (U == 0) + if (!U) return None; return Value.uval + U->getOffset(); case DW_FORM_ref_addr: diff --git a/lib/DebugInfo/DWARFTypeUnit.h b/lib/DebugInfo/DWARFTypeUnit.h index 05e13ff..cf773b8 100644 --- a/lib/DebugInfo/DWARFTypeUnit.h +++ b/lib/DebugInfo/DWARFTypeUnit.h @@ -19,11 +19,13 @@ private: uint64_t TypeHash; uint32_t TypeOffset; public: - DWARFTypeUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef AS, - StringRef RS, StringRef SS, StringRef SOS, StringRef AOS, + DWARFTypeUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef RS, + StringRef SS, StringRef SOS, StringRef AOS, const RelocAddrMap *M, bool LE) - : DWARFUnit(DA, IS, AS, RS, SS, SOS, AOS, M, LE) {} - uint32_t getSize() const override { return DWARFUnit::getSize() + 12; } + : DWARFUnit(DA, IS, RS, SS, SOS, AOS, M, LE) {} + uint32_t getHeaderSize() const override { + return DWARFUnit::getHeaderSize() + 12; + } void dump(raw_ostream &OS); protected: bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) override; diff --git a/lib/DebugInfo/DWARFUnit.cpp b/lib/DebugInfo/DWARFUnit.cpp index 316c208..f5f5072 100644 --- a/lib/DebugInfo/DWARFUnit.cpp +++ b/lib/DebugInfo/DWARFUnit.cpp @@ -17,12 +17,12 @@ using namespace llvm; using namespace dwarf; -DWARFUnit::DWARFUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef AS, - StringRef RS, StringRef SS, StringRef SOS, StringRef AOS, +DWARFUnit::DWARFUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef RS, + StringRef SS, StringRef SOS, StringRef AOS, const RelocAddrMap *M, bool LE) - : Abbrev(DA), InfoSection(IS), AbbrevSection(AS), RangeSection(RS), - StringSection(SS), StringOffsetSection(SOS), AddrOffsetSection(AOS), - RelocMap(M), isLittleEndian(LE) { + : Abbrev(DA), InfoSection(IS), RangeSection(RS), StringSection(SS), + StringOffsetSection(SOS), AddrOffsetSection(AOS), RelocMap(M), + isLittleEndian(LE) { clear(); } @@ -54,18 +54,20 @@ bool DWARFUnit::getStringOffsetSectionItem(uint32_t Index, bool DWARFUnit::extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) { Length = debug_info.getU32(offset_ptr); Version = debug_info.getU16(offset_ptr); - uint64_t abbrOffset = debug_info.getU32(offset_ptr); + uint64_t AbbrOffset = debug_info.getU32(offset_ptr); AddrSize = debug_info.getU8(offset_ptr); - bool lengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1); - bool versionOK = DWARFContext::isSupportedVersion(Version); - bool abbrOffsetOK = AbbrevSection.size() > abbrOffset; - bool addrSizeOK = AddrSize == 4 || AddrSize == 8; + bool LengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1); + bool VersionOK = DWARFContext::isSupportedVersion(Version); + bool AddrSizeOK = AddrSize == 4 || AddrSize == 8; - if (!lengthOK || !versionOK || !addrSizeOK || !abbrOffsetOK) + if (!LengthOK || !VersionOK || !AddrSizeOK) + return false; + + Abbrevs = Abbrev->getAbbreviationDeclarationSet(AbbrOffset); + if (Abbrevs == nullptr) return false; - Abbrevs = Abbrev->getAbbreviationDeclarationSet(abbrOffset); return true; } @@ -98,7 +100,7 @@ void DWARFUnit::clear() { Offset = 0; Length = 0; Version = 0; - Abbrevs = 0; + Abbrevs = nullptr; AddrSize = 0; BaseAddr = 0; RangeSectionBase = 0; @@ -110,8 +112,8 @@ void DWARFUnit::clear() { const char *DWARFUnit::getCompilationDir() { extractDIEsIfNeeded(true); if (DieArray.empty()) - return 0; - return DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, 0); + return nullptr; + return DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, nullptr); } uint64_t DWARFUnit::getDWOId() { @@ -124,38 +126,32 @@ uint64_t DWARFUnit::getDWOId() { } void DWARFUnit::setDIERelations() { - if (DieArray.empty()) + if (DieArray.size() <= 1) return; - DWARFDebugInfoEntryMinimal *die_array_begin = &DieArray.front(); - DWARFDebugInfoEntryMinimal *die_array_end = &DieArray.back(); - DWARFDebugInfoEntryMinimal *curr_die; - // We purposely are skipping the last element in the array in the loop below - // so that we can always have a valid next item - for (curr_die = die_array_begin; curr_die < die_array_end; ++curr_die) { - // Since our loop doesn't include the last element, we can always - // safely access the next die in the array. - DWARFDebugInfoEntryMinimal *next_die = curr_die + 1; - - const DWARFAbbreviationDeclaration *curr_die_abbrev = - curr_die->getAbbreviationDeclarationPtr(); - - if (curr_die_abbrev) { - // Normal DIE - if (curr_die_abbrev->hasChildren()) - next_die->setParent(curr_die); - else - curr_die->setSibling(next_die); + + std::vector<DWARFDebugInfoEntryMinimal *> ParentChain; + DWARFDebugInfoEntryMinimal *SiblingChain = nullptr; + for (auto &DIE : DieArray) { + if (SiblingChain) { + SiblingChain->setSibling(&DIE); + } + if (const DWARFAbbreviationDeclaration *AbbrDecl = + DIE.getAbbreviationDeclarationPtr()) { + // Normal DIE. + if (AbbrDecl->hasChildren()) { + ParentChain.push_back(&DIE); + SiblingChain = nullptr; + } else { + SiblingChain = &DIE; + } } else { - // NULL DIE that terminates a sibling chain - DWARFDebugInfoEntryMinimal *parent = curr_die->getParent(); - if (parent) - parent->setSibling(next_die); + // NULL entry terminates the sibling chain. + SiblingChain = ParentChain.back(); + ParentChain.pop_back(); } } - - // Since we skipped the last element, we need to fix it up! - if (die_array_begin < die_array_end) - curr_die->setParent(die_array_begin); + assert(SiblingChain == nullptr || SiblingChain == &DieArray[0]); + assert(ParentChain.empty()); } void DWARFUnit::extractDIEsToVector( @@ -166,13 +162,13 @@ void DWARFUnit::extractDIEsToVector( // Set the offset to that of the first DIE and calculate the start of the // next compilation unit header. - uint32_t Offset = getFirstDIEOffset(); + uint32_t DIEOffset = Offset + getHeaderSize(); uint32_t NextCUOffset = getNextUnitOffset(); DWARFDebugInfoEntryMinimal DIE; uint32_t Depth = 0; bool IsCUDie = true; - while (Offset < NextCUOffset && DIE.extractFast(this, &Offset)) { + while (DIEOffset < NextCUOffset && DIE.extractFast(this, &DIEOffset)) { if (IsCUDie) { if (AppendCUDie) Dies.push_back(DIE); @@ -187,9 +183,8 @@ void DWARFUnit::extractDIEsToVector( Dies.push_back(DIE); } - const DWARFAbbreviationDeclaration *AbbrDecl = - DIE.getAbbreviationDeclarationPtr(); - if (AbbrDecl) { + if (const DWARFAbbreviationDeclaration *AbbrDecl = + DIE.getAbbreviationDeclarationPtr()) { // Normal DIE if (AbbrDecl->hasChildren()) ++Depth; @@ -205,9 +200,9 @@ void DWARFUnit::extractDIEsToVector( // Give a little bit of info if we encounter corrupt DWARF (our offset // should always terminate at or before the start of the next compilation // unit header). - if (Offset > NextCUOffset) + if (DIEOffset > NextCUOffset) fprintf(stderr, "warning: DWARF compile unit extends beyond its " - "bounds cu 0x%8.8x at 0x%8.8x'\n", getOffset(), Offset); + "bounds cu 0x%8.8x at 0x%8.8x'\n", getOffset(), DIEOffset); } size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) { @@ -241,25 +236,25 @@ size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) { DWARFUnit::DWOHolder::DWOHolder(object::ObjectFile *DWOFile) : DWOFile(DWOFile), DWOContext(cast<DWARFContext>(DIContext::getDWARFContext(DWOFile))), - DWOU(0) { + DWOU(nullptr) { if (DWOContext->getNumDWOCompileUnits() > 0) DWOU = DWOContext->getDWOCompileUnitAtIndex(0); } bool DWARFUnit::parseDWO() { - if (DWO.get() != 0) + if (DWO.get()) return false; extractDIEsIfNeeded(true); if (DieArray.empty()) return false; const char *DWOFileName = - DieArray[0].getAttributeValueAsString(this, DW_AT_GNU_dwo_name, 0); - if (DWOFileName == 0) + DieArray[0].getAttributeValueAsString(this, DW_AT_GNU_dwo_name, nullptr); + if (!DWOFileName) return false; const char *CompilationDir = - DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, 0); + DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, nullptr); SmallString<16> AbsolutePath; - if (sys::path::is_relative(DWOFileName) && CompilationDir != 0) { + if (sys::path::is_relative(DWOFileName) && CompilationDir != nullptr) { sys::path::append(AbsolutePath, CompilationDir); } sys::path::append(AbsolutePath, DWOFileName); @@ -271,7 +266,7 @@ bool DWARFUnit::parseDWO() { DWO.reset(new DWOHolder(DWOFile.get())); DWARFUnit *DWOCU = DWO->getUnit(); // Verify that compile unit in .dwo file is valid. - if (DWOCU == 0 || DWOCU->getDWOId() != getDWOId()) { + if (!DWOCU || DWOCU->getDWOId() != getDWOId()) { DWO.reset(); return false; } @@ -298,33 +293,33 @@ void DWARFUnit::clearDIEs(bool KeepCUDie) { } } -void -DWARFUnit::buildAddressRangeTable(DWARFDebugAranges *debug_aranges, - bool clear_dies_if_already_not_parsed, - uint32_t CUOffsetInAranges) { +void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) { + // First, check if CU DIE describes address ranges for the unit. + const auto &CUDIERanges = getCompileUnitDIE()->getAddressRanges(this); + if (!CUDIERanges.empty()) { + CURanges.insert(CURanges.end(), CUDIERanges.begin(), CUDIERanges.end()); + return; + } + // This function is usually called if there in no .debug_aranges section // in order to produce a compile unit level set of address ranges that // is accurate. If the DIEs weren't parsed, then we don't want all dies for // all compile units to stay loaded when they weren't needed. So we can end // up parsing the DWARF and then throwing them all away to keep memory usage // down. - const bool clear_dies = extractDIEsIfNeeded(false) > 1 && - clear_dies_if_already_not_parsed; - DieArray[0].buildAddressRangeTable(this, debug_aranges, CUOffsetInAranges); + const bool ClearDIEs = extractDIEsIfNeeded(false) > 1; + DieArray[0].collectChildrenAddressRanges(this, CURanges); + + // Collect address ranges from DIEs in .dwo if necessary. bool DWOCreated = parseDWO(); - if (DWO.get()) { - // If there is a .dwo file for this compile unit, then skeleton CU DIE - // doesn't have children, and we should instead build address range table - // from DIEs in the .debug_info.dwo section of .dwo file. - DWO->getUnit()->buildAddressRangeTable( - debug_aranges, clear_dies_if_already_not_parsed, CUOffsetInAranges); - } - if (DWOCreated && clear_dies_if_already_not_parsed) + if (DWO.get()) + DWO->getUnit()->collectAddressRanges(CURanges); + if (DWOCreated) DWO.reset(); // Keep memory down by clearing DIEs if this generate function // caused them to be parsed. - if (clear_dies) + if (ClearDIEs) clearDIEs(true); } @@ -337,14 +332,14 @@ DWARFUnit::getSubprogramForAddress(uint64_t Address) { return &DIE; } } - return 0; + return nullptr; } DWARFDebugInfoEntryInlinedChain DWARFUnit::getInlinedChainForAddress(uint64_t Address) { // First, find a subprogram that contains the given address (the root // of inlined chain). - const DWARFUnit *ChainCU = 0; + const DWARFUnit *ChainCU = nullptr; const DWARFDebugInfoEntryMinimal *SubprogramDIE = getSubprogramForAddress(Address); if (SubprogramDIE) { diff --git a/lib/DebugInfo/DWARFUnit.h b/lib/DebugInfo/DWARFUnit.h index 5b4cf09..471da36 100644 --- a/lib/DebugInfo/DWARFUnit.h +++ b/lib/DebugInfo/DWARFUnit.h @@ -29,7 +29,6 @@ class raw_ostream; class DWARFUnit { const DWARFDebugAbbrev *Abbrev; StringRef InfoSection; - StringRef AbbrevSection; StringRef RangeSection; uint32_t RangeSectionBase; StringRef StringSection; @@ -60,12 +59,13 @@ class DWARFUnit { protected: virtual bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr); + /// Size in bytes of the unit header. + virtual uint32_t getHeaderSize() const { return 11; } public: - - DWARFUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef AS, - StringRef RS, StringRef SS, StringRef SOS, StringRef AOS, - const RelocAddrMap *M, bool LE); + DWARFUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef RS, + StringRef SS, StringRef SOS, StringRef AOS, const RelocAddrMap *M, + bool LE); virtual ~DWARFUnit(); @@ -102,12 +102,7 @@ public: DWARFDebugRangeList &RangeList) const; void clear(); uint32_t getOffset() const { return Offset; } - /// Size in bytes of the compile unit header. - virtual uint32_t getSize() const { return 11; } - uint32_t getFirstDIEOffset() const { return Offset + getSize(); } uint32_t getNextUnitOffset() const { return Offset + Length + 4; } - /// Size in bytes of the .debug_info data associated with this compile unit. - size_t getDebugInfoSize() const { return Length + 4 - getSize(); } uint32_t getLength() const { return Length; } uint16_t getVersion() const { return Version; } const DWARFAbbreviationDeclarationSet *getAbbreviations() const { @@ -123,15 +118,13 @@ public: const DWARFDebugInfoEntryMinimal * getCompileUnitDIE(bool extract_cu_die_only = true) { extractDIEsIfNeeded(extract_cu_die_only); - return DieArray.empty() ? NULL : &DieArray[0]; + return DieArray.empty() ? nullptr : &DieArray[0]; } const char *getCompilationDir(); uint64_t getDWOId(); - void buildAddressRangeTable(DWARFDebugAranges *debug_aranges, - bool clear_dies_if_already_not_parsed, - uint32_t CUOffsetInAranges); + void collectAddressRanges(DWARFAddressRangesVector &CURanges); /// getInlinedChainForAddress - fetches inlined chain for a given address. /// Returns empty chain if there is no subprogram containing address. The @@ -139,6 +132,9 @@ public: DWARFDebugInfoEntryInlinedChain getInlinedChainForAddress(uint64_t Address); private: + /// Size in bytes of the .debug_info data associated with this compile unit. + size_t getDebugInfoSize() const { return Length + 4 - getHeaderSize(); } + /// extractDIEsIfNeeded - Parses a compile unit and indexes its DIEs if it /// hasn't already been done. Returns the number of DIEs parsed at this call. size_t extractDIEsIfNeeded(bool CUDieOnly); diff --git a/lib/DebugInfo/module.modulemap b/lib/DebugInfo/module.modulemap new file mode 100644 index 0000000..1fe5ab1 --- /dev/null +++ b/lib/DebugInfo/module.modulemap @@ -0,0 +1 @@ +module DebugInfo { requires cplusplus umbrella "." module * { export * } } |