X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FDebugInfo%2FDWARFContext.cpp;h=9a2c7cc19629d412a7c416ff148cebe938decbcd;hb=04fab61b356ce7bc64374c4838fc770b824717d8;hp=08b7b9163776335fba4606a27e9b06a161859faf;hpb=c87722ce4beb2975e86d7225c9cba1f600c266e9;p=oota-llvm.git diff --git a/lib/DebugInfo/DWARFContext.cpp b/lib/DebugInfo/DWARFContext.cpp index 08b7b916377..9a2c7cc1962 100644 --- a/lib/DebugInfo/DWARFContext.cpp +++ b/lib/DebugInfo/DWARFContext.cpp @@ -9,6 +9,7 @@ #include "DWARFContext.h" #include "DWARFDebugArangeSet.h" +#include "DWARFAcceleratorTable.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" @@ -25,6 +26,8 @@ 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) { @@ -57,6 +60,18 @@ static void dumpPubSection(raw_ostream &OS, StringRef Name, StringRef Data, } } +static void dumpAccelSection(raw_ostream &OS, StringRef Name, + const DWARFSection& Section, StringRef StringSection, + bool LittleEndian) { + DataExtractor AccelSection(Section.Data, LittleEndian, 0); + DataExtractor StrData(StringSection, LittleEndian, 0); + OS << "\n." << Name << " contents:\n"; + DWARFAcceleratorTable Accel(AccelSection, StrData, Section.Relocs); + if (!Accel.extract()) + return; + Accel.dump(OS); +} + void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) { if (DumpType == DIDT_All || DumpType == DIDT_Abbrev) { OS << ".debug_abbrev contents:\n"; @@ -84,15 +99,17 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) { if ((DumpType == DIDT_All || DumpType == DIDT_Types) && getNumTypeUnits()) { OS << "\n.debug_types contents:\n"; - for (const auto &TU : type_units()) - TU->dump(OS); + for (const auto &TUS : type_unit_sections()) + for (const auto &TU : TUS) + TU->dump(OS); } if ((DumpType == DIDT_All || DumpType == DIDT_TypesDwo) && getNumDWOTypeUnits()) { OS << "\n.debug_types.dwo contents:\n"; - for (const auto &DWOTU : dwo_type_units()) - DWOTU->dump(OS); + for (const auto &DWOTUS : dwo_type_unit_sections()) + for (const auto &DWOTU : DWOTUS) + DWOTU->dump(OS); } if (DumpType == DIDT_All || DumpType == DIDT_Loc) { @@ -130,8 +147,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); } } } @@ -141,9 +159,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) { @@ -211,6 +231,22 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) { OS << format("%8.8x\n", strOffsetExt.getU32(&offset)); } } + + if (DumpType == DIDT_All || DumpType == DIDT_AppleNames) + dumpAccelSection(OS, "apple_names", getAppleNamesSection(), + getStringSection(), isLittleEndian()); + + if (DumpType == DIDT_All || DumpType == DIDT_AppleTypes) + dumpAccelSection(OS, "apple_types", getAppleTypesSection(), + getStringSection(), isLittleEndian()); + + if (DumpType == DIDT_All || DumpType == DIDT_AppleNamespaces) + dumpAccelSection(OS, "apple_namespaces", getAppleNamespacesSection(), + getStringSection(), isLittleEndian()); + + if (DumpType == DIDT_All || DumpType == DIDT_AppleObjC) + dumpAccelSection(OS, "apple_objc", getAppleObjCSection(), + getStringSection(), isLittleEndian()); } const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() { @@ -286,7 +322,7 @@ const DWARFDebugFrame *DWARFContext::getDebugFrame() { } const DWARFLineTable * -DWARFContext::getLineTableForCompileUnit(DWARFCompileUnit *cu) { +DWARFContext::getLineTableForUnit(DWARFUnit *cu) { if (!Line) Line.reset(new DWARFDebugLine(&getLineSection().Relocs)); @@ -307,110 +343,34 @@ DWARFContext::getLineTableForCompileUnit(DWARFCompileUnit *cu) { } void DWARFContext::parseCompileUnits() { - if (!CUs.empty()) - return; - uint32_t offset = 0; - const DataExtractor &DIData = DataExtractor(getInfoSection().Data, - isLittleEndian(), 0); - while (DIData.isValidOffset(offset)) { - std::unique_ptr CU(new DWARFCompileUnit( - getDebugAbbrev(), getInfoSection().Data, getRangeSection(), - getStringSection(), StringRef(), getAddrSection(), - &getInfoSection().Relocs, isLittleEndian())); - if (!CU->extract(DIData, &offset)) { - break; - } - CUs.push_back(std::move(CU)); - offset = CUs.back()->getNextUnitOffset(); - } + CUs.parse(*this, getInfoSection()); } void DWARFContext::parseTypeUnits() { if (!TUs.empty()) return; for (const auto &I : getTypesSections()) { - uint32_t offset = 0; - const DataExtractor &DIData = - DataExtractor(I.second.Data, isLittleEndian(), 0); - while (DIData.isValidOffset(offset)) { - std::unique_ptr 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)); - offset = TUs.back()->getNextUnitOffset(); - } + TUs.push_back(DWARFUnitSection()); + TUs.back().parse(*this, I.second); } } void DWARFContext::parseDWOCompileUnits() { - if (!DWOCUs.empty()) - return; - uint32_t offset = 0; - const DataExtractor &DIData = - DataExtractor(getInfoDWOSection().Data, isLittleEndian(), 0); - while (DIData.isValidOffset(offset)) { - std::unique_ptr DWOCU(new DWARFCompileUnit( - getDebugAbbrevDWO(), getInfoDWOSection().Data, getRangeDWOSection(), - getStringDWOSection(), getStringOffsetDWOSection(), getAddrSection(), - &getInfoDWOSection().Relocs, isLittleEndian())); - if (!DWOCU->extract(DIData, &offset)) { - break; - } - DWOCUs.push_back(std::move(DWOCU)); - offset = DWOCUs.back()->getNextUnitOffset(); - } + DWOCUs.parseDWO(*this, getInfoDWOSection()); } void DWARFContext::parseDWOTypeUnits() { if (!DWOTUs.empty()) return; for (const auto &I : getTypesDWOSections()) { - uint32_t offset = 0; - const DataExtractor &DIData = - DataExtractor(I.second.Data, isLittleEndian(), 0); - while (DIData.isValidOffset(offset)) { - std::unique_ptr TU(new DWARFTypeUnit( - getDebugAbbrevDWO(), I.second.Data, getRangeDWOSection(), - getStringDWOSection(), getStringOffsetDWOSection(), getAddrSection(), - &I.second.Relocs, isLittleEndian())); - if (!TU->extract(DIData, &offset)) - break; - DWOTUs.push_back(std::move(TU)); - offset = DWOTUs.back()->getNextUnitOffset(); - } + DWOTUs.push_back(DWARFUnitSection()); + DWOTUs.back().parseDWO(*this, I.second); } } -namespace { - struct OffsetComparator { - - bool operator()(const std::unique_ptr &LHS, - const std::unique_ptr &RHS) const { - return LHS->getOffset() < RHS->getOffset(); - } - bool operator()(const std::unique_ptr &LHS, - uint32_t RHS) const { - return LHS->getOffset() < RHS; - } - bool operator()(uint32_t LHS, - const std::unique_ptr &RHS) const { - return LHS < RHS->getOffset(); - } - }; -} - DWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint32_t Offset) { parseCompileUnits(); - - std::unique_ptr *CU = - std::lower_bound(CUs.begin(), CUs.end(), Offset, OffsetComparator()); - if (CU != CUs.end()) { - return CU->get(); - } - return nullptr; + return CUs.getUnitForOffset(Offset); } DWARFCompileUnit *DWARFContext::getCompileUnitForAddress(uint64_t Address) { @@ -420,50 +380,11 @@ DWARFCompileUnit *DWARFContext::getCompileUnitForAddress(uint64_t Address) { return getCompileUnitForOffset(CUOffset); } -static bool getFileNameForCompileUnit(DWARFCompileUnit *CU, - const DWARFLineTable *LineTable, - uint64_t FileIndex, - bool NeedsAbsoluteFilePath, - std::string &FileName) { - if (!CU || !LineTable || - !LineTable->getFileNameByIndex(FileIndex, NeedsAbsoluteFilePath, - FileName)) - return false; - if (NeedsAbsoluteFilePath && 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()) { - sys::path::append(AbsolutePath, CompilationDir); - } - sys::path::append(AbsolutePath, FileName); - FileName = AbsolutePath.str(); - } - return true; -} - -static bool getFileLineInfoForCompileUnit(DWARFCompileUnit *CU, - const DWARFLineTable *LineTable, - uint64_t Address, - bool NeedsAbsoluteFilePath, - 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); - if (RowIndex == -1U) - 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, - Result.FileName)) - return false; - 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. @@ -472,7 +393,8 @@ static bool getFunctionNameForAddress(DWARFCompileUnit *CU, uint64_t Address, if (InlinedChain.DIEs.size() == 0) return false; const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain.DIEs[0]; - if (const char *Name = TopFunctionDIE.getSubroutineName(InlinedChain.U)) { + if (const char *Name = + TopFunctionDIE.getSubroutineName(InlinedChain.U, Kind)) { FunctionName = Name; return true; } @@ -480,50 +402,42 @@ static bool getFunctionNameForAddress(DWARFCompileUnit *CU, uint64_t Address, } DILineInfo DWARFContext::getLineInfoForAddress(uint64_t Address, - DILineInfoSpecifier Specifier) { + DILineInfoSpecifier Spec) { 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); + getFunctionNameForAddress(CU, Address, Spec.FNKind, Result.FunctionName); + if (Spec.FLIKind != FileLineInfoKind::None) { + if (const DWARFLineTable *LineTable = getLineTableForUnit(CU)) + LineTable->getFileLineInfoForAddress(Address, CU->getCompilationDir(), + Spec.FLIKind, Result); } 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 = ""; - if (Specifier.needs(DILineInfoSpecifier::FunctionName)) { - getFunctionNameForAddress(CU, Address, FunctionName); - } + 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)) { + 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); + const DWARFLineTable *LineTable = getLineTableForUnit(CU); // Get the index of row we're looking for in the line table. std::vector RowVector; @@ -534,8 +448,8 @@ DILineInfoTable DWARFContext::getLineInfoForAddressRange(uint64_t Address, // 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); + LineTable->getFileNameByIndex(Row.File, CU->getCompilationDir(), + Spec.FLIKind, Result.FileName); Result.FunctionName = FunctionName; Result.Line = Row.Line; Result.Column = Row.Column; @@ -545,8 +459,9 @@ DILineInfoTable DWARFContext::getLineInfoForAddressRange(uint64_t Address, return Lines; } -DIInliningInfo DWARFContext::getInliningInfoForAddress(uint64_t Address, - DILineInfoSpecifier Specifier) { +DIInliningInfo +DWARFContext::getInliningInfoForAddress(uint64_t Address, + DILineInfoSpecifier Spec) { DIInliningInfo InliningInfo; DWARFCompileUnit *CU = getCompileUnitForAddress(Address); @@ -554,20 +469,18 @@ DIInliningInfo DWARFContext::getInliningInfoForAddress(uint64_t Address, 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)) { + if (Spec.FLIKind != FileLineInfoKind::None) { DILineInfo Frame; - LineTable = getLineTableForCompileUnit(CU); - if (getFileLineInfoForCompileUnit(CU, LineTable, Address, - NeedsAbsoluteFilePath, Frame)) { + LineTable = getLineTableForUnit(CU); + if (LineTable && + LineTable->getFileLineInfoForAddress(Address, CU->getCompilationDir(), + Spec.FLIKind, Frame)) InliningInfo.addFrame(Frame); - } } return InliningInfo; } @@ -577,23 +490,24 @@ DIInliningInfo DWARFContext::getInliningInfoForAddress(uint64_t Address, 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 (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); + LineTable = getLineTableForUnit(CU); // For the topmost routine, get file/line info from line table. - getFileLineInfoForCompileUnit(CU, LineTable, Address, - NeedsAbsoluteFilePath, Frame); + if (LineTable) + LineTable->getFileLineInfoForAddress(Address, CU->getCompilationDir(), + Spec.FLIKind, Frame); } else { // Otherwise, use call file, call line and call column from // previous DIE in inlined chain. - getFileNameForCompileUnit(CU, LineTable, CallFile, - NeedsAbsoluteFilePath, Frame.FileName); + if (LineTable) + LineTable->getFileNameByIndex(CallFile, CU->getCompilationDir(), + Spec.FLIKind, Frame.FileName); Frame.Line = CallLine; Frame.Column = CallColumn; } @@ -624,12 +538,19 @@ static bool consumeCompressedDebugSectionHeader(StringRef &data, return true; } -DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) - : IsLittleEndian(Obj->isLittleEndian()), - AddressSize(Obj->getBytesInAddress()) { - for (const SectionRef &Section : Obj->sections()) { +DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj) + : IsLittleEndian(Obj.isLittleEndian()), + AddressSize(Obj.getBytesInAddress()) { + for (const SectionRef &Section : Obj.sections()) { StringRef name; Section.getName(name); + // Skip BSS and Virtual sections, they aren't interesting. + bool IsBSS = Section.isBSS(); + if (IsBSS) + continue; + bool IsVirtual = Section.isVirtual(); + if (IsVirtual) + continue; StringRef data; Section.getContents(data); @@ -673,6 +594,11 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) .Case("debug_str.dwo", &StringDWOSection) .Case("debug_str_offsets.dwo", &StringOffsetDWOSection) .Case("debug_addr", &AddrSection) + .Case("apple_names", &AppleNamesSection.Data) + .Case("apple_types", &AppleTypesSection.Data) + .Case("apple_namespaces", &AppleNamespacesSection.Data) + .Case("apple_namespac", &AppleNamespacesSection.Data) + .Case("apple_objc", &AppleObjCSection.Data) // Any more debug info sections go here. .Default(nullptr); if (SectionData) { @@ -690,7 +616,7 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) } section_iterator RelocatedSection = Section.getRelocatedSection(); - if (RelocatedSection == Obj->section_end()) + if (RelocatedSection == Obj.section_end()) continue; StringRef RelSecName; @@ -705,6 +631,11 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) .Case("debug_loc", &LocSection.Relocs) .Case("debug_info.dwo", &InfoDWOSection.Relocs) .Case("debug_line", &LineSection.Relocs) + .Case("apple_names", &AppleNamesSection.Relocs) + .Case("apple_types", &AppleTypesSection.Relocs) + .Case("apple_namespaces", &AppleNamespacesSection.Relocs) + .Case("apple_namespac", &AppleNamespacesSection.Relocs) + .Case("apple_objc", &AppleObjCSection.Relocs) .Default(nullptr); if (!Map) { // Find debug_types relocs by section rather than name as there are @@ -718,26 +649,22 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) } if (Section.relocation_begin() != Section.relocation_end()) { - uint64_t SectionSize; - RelocatedSection->getSize(SectionSize); + uint64_t SectionSize = RelocatedSection->getSize(); for (const RelocationRef &Reloc : Section.relocations()) { uint64_t Address; Reloc.getOffset(Address); uint64_t Type; Reloc.getType(Type); uint64_t SymAddr = 0; - // ELF relocations may need the symbol address - if (Obj->isELF()) { - object::symbol_iterator Sym = Reloc.getSymbol(); + object::symbol_iterator Sym = Reloc.getSymbol(); + if (Sym != Obj.symbol_end()) Sym->getAddress(SymAddr); - } - object::RelocVisitor V(Obj->getFileFormatName()); - // The section address is always 0 for debug sections. - object::RelocToApply R(V.visit(Type, Reloc, 0, SymAddr)); + object::RelocVisitor V(Obj); + object::RelocToApply R(V.visit(Type, Reloc, SymAddr)); if (V.error()) { SmallString<32> Name; - error_code ec(Reloc.getTypeName(Name)); + std::error_code ec(Reloc.getTypeName(Name)); if (ec) { errs() << "Aaaaaa! Nameless relocation! Aaaaaa!\n"; }