X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FDebugInfo%2FDWARFContext.cpp;h=b725619d8e2528f16def360a984676717979a480;hb=27276437ae2169640633f9961620a8d0b19deb39;hp=baf2bb5b577289b656aa8d6b1017433ee53a26d3;hpb=eb0c179b5688177c1ab5f52a8c0338459e97606e;p=oota-llvm.git diff --git a/lib/DebugInfo/DWARFContext.cpp b/lib/DebugInfo/DWARFContext.cpp index baf2bb5b577..b725619d8e2 100644 --- a/lib/DebugInfo/DWARFContext.cpp +++ b/lib/DebugInfo/DWARFContext.cpp @@ -8,9 +8,9 @@ //===----------------------------------------------------------------------===// #include "DWARFContext.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/Support/Compression.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/Format.h" @@ -25,23 +25,81 @@ typedef DWARFDebugLine::LineTable DWARFLineTable; DWARFContext::~DWARFContext() { DeleteContainerPointers(CUs); + DeleteContainerPointers(TUs); DeleteContainerPointers(DWOCUs); } +static void dumpPubSection(raw_ostream &OS, StringRef Name, StringRef Data, + bool LittleEndian, bool GnuStyle) { + OS << "\n." << Name << " contents:\n"; + DataExtractor pubNames(Data, LittleEndian, 0); + uint32_t offset = 0; + while (pubNames.isValidOffset(offset)) { + OS << "length = " << format("0x%08x", pubNames.getU32(&offset)); + OS << " version = " << format("0x%04x", pubNames.getU16(&offset)); + OS << " unit_offset = " << format("0x%08x", pubNames.getU32(&offset)); + OS << " unit_size = " << format("0x%08x", pubNames.getU32(&offset)) << '\n'; + if (GnuStyle) + OS << "Offset Linkage Kind Name\n"; + else + OS << "Offset Name\n"; + + while (offset < Data.size()) { + uint32_t dieRef = pubNames.getU32(&offset); + if (dieRef == 0) + break; + OS << format("0x%8.8x ", dieRef); + if (GnuStyle) { + PubIndexEntryDescriptor desc(pubNames.getU8(&offset)); + OS << format("%-8s", dwarf::GDBIndexEntryLinkageString(desc.Linkage)) + << ' ' << format("%-8s", dwarf::GDBIndexEntryKindString(desc.Kind)) + << ' '; + } + OS << '\"' << pubNames.getCStr(&offset) << "\"\n"; + } + } +} + void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) { if (DumpType == DIDT_All || DumpType == DIDT_Abbrev) { OS << ".debug_abbrev contents:\n"; getDebugAbbrev()->dump(OS); } + if (DumpType == DIDT_All || DumpType == DIDT_AbbrevDwo) + if (const DWARFDebugAbbrev *D = getDebugAbbrevDWO()) { + OS << "\n.debug_abbrev.dwo contents:\n"; + D->dump(OS); + } + if (DumpType == DIDT_All || DumpType == DIDT_Info) { OS << "\n.debug_info contents:\n"; for (unsigned i = 0, e = getNumCompileUnits(); i != e; ++i) getCompileUnitAtIndex(i)->dump(OS); } + if ((DumpType == DIDT_All || DumpType == DIDT_InfoDwo) && + getNumDWOCompileUnits()) { + OS << "\n.debug_info.dwo contents:\n"; + for (unsigned i = 0, e = getNumDWOCompileUnits(); i != e; ++i) + getDWOCompileUnitAtIndex(i)->dump(OS); + } + + if ((DumpType == DIDT_All || DumpType == DIDT_Types) && getNumTypeUnits()) { + OS << "\n.debug_types contents:\n"; + for (unsigned i = 0, e = getNumTypeUnits(); i != e; ++i) + getTypeUnitAtIndex(i)->dump(OS); + } + + if (DumpType == DIDT_All || DumpType == DIDT_TypesDwo) + if (getNumDWOTypeUnits()) { + OS << "\n.debug_types.dwo contents:\n"; + for (unsigned i = 0, e = getNumDWOTypeUnits(); i != e; ++i) + getDWOTypeUnitAtIndex(i)->dump(OS); + } + if (DumpType == DIDT_All || DumpType == DIDT_Loc) { - OS << ".debug_loc contents:\n"; + OS << "\n.debug_loc contents:\n"; getDebugLoc()->dump(OS); } @@ -66,13 +124,13 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) { DWARFCompileUnit *cu = getCompileUnitAtIndex(i); savedAddressByteSize = cu->getAddressByteSize(); unsigned stmtOffset = - cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list, - -1U); + cu->getCompileUnitDIE()->getAttributeValueAsSectionOffset( + cu, DW_AT_stmt_list, -1U); if (stmtOffset != -1U) { - DataExtractor lineData(getLineSection(), isLittleEndian(), + DataExtractor lineData(getLineSection().Data, isLittleEndian(), savedAddressByteSize); DWARFDebugLine::DumpingState state(OS); - DWARFDebugLine::parseStatementTable(lineData, &lineRelocMap(), &stmtOffset, state); + DWARFDebugLine::parseStatementTable(lineData, &getLineSection().Relocs, &stmtOffset, state); } } } @@ -88,6 +146,18 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) { } } + if ((DumpType == DIDT_All || DumpType == DIDT_StrDwo) && + !getStringDWOSection().empty()) { + OS << "\n.debug_str.dwo contents:\n"; + DataExtractor strDWOData(getStringDWOSection(), isLittleEndian(), 0); + offset = 0; + uint32_t strDWOOffset = 0; + while (const char *s = strDWOData.getCStr(&offset)) { + OS << format("0x%8.8x: \"%s\"\n", strDWOOffset, s); + strDWOOffset = offset; + } + } + if (DumpType == DIDT_All || DumpType == DIDT_Ranges) { OS << "\n.debug_ranges contents:\n"; // In fact, different compile units may have different address byte @@ -102,62 +172,34 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) { rangeList.dump(OS); } - if (DumpType == DIDT_All || DumpType == DIDT_Pubnames) { - OS << "\n.debug_pubnames contents:\n"; - DataExtractor pubNames(getPubNamesSection(), isLittleEndian(), 0); - offset = 0; - OS << "Length: " << pubNames.getU32(&offset) << "\n"; - OS << "Version: " << pubNames.getU16(&offset) << "\n"; - OS << "Offset in .debug_info: " << pubNames.getU32(&offset) << "\n"; - OS << "Size: " << pubNames.getU32(&offset) << "\n"; - OS << "\n Offset Name\n"; - while (offset < getPubNamesSection().size()) { - uint32_t n = pubNames.getU32(&offset); - if (n == 0) - break; - OS << format("%8x ", n); - OS << pubNames.getCStr(&offset) << "\n"; - } - } + if (DumpType == DIDT_All || DumpType == DIDT_Pubnames) + dumpPubSection(OS, "debug_pubnames", getPubNamesSection(), + isLittleEndian(), false); - if (DumpType == DIDT_All || DumpType == DIDT_AbbrevDwo) { - const DWARFDebugAbbrev *D = getDebugAbbrevDWO(); - if (D) { - OS << "\n.debug_abbrev.dwo contents:\n"; - getDebugAbbrevDWO()->dump(OS); - } - } + if (DumpType == DIDT_All || DumpType == DIDT_Pubtypes) + dumpPubSection(OS, "debug_pubtypes", getPubTypesSection(), + isLittleEndian(), false); - if (DumpType == DIDT_All || DumpType == DIDT_InfoDwo) - if (getNumDWOCompileUnits()) { - OS << "\n.debug_info.dwo contents:\n"; - for (unsigned i = 0, e = getNumDWOCompileUnits(); i != e; ++i) - getDWOCompileUnitAtIndex(i)->dump(OS); - } + if (DumpType == DIDT_All || DumpType == DIDT_GnuPubnames) + dumpPubSection(OS, "debug_gnu_pubnames", getGnuPubNamesSection(), + isLittleEndian(), true /* GnuStyle */); - if (DumpType == DIDT_All || DumpType == DIDT_StrDwo) - if (!getStringDWOSection().empty()) { - OS << "\n.debug_str.dwo contents:\n"; - DataExtractor strDWOData(getStringDWOSection(), isLittleEndian(), 0); - offset = 0; - uint32_t strDWOOffset = 0; - while (const char *s = strDWOData.getCStr(&offset)) { - OS << format("0x%8.8x: \"%s\"\n", strDWOOffset, s); - strDWOOffset = offset; - } - } + if (DumpType == DIDT_All || DumpType == DIDT_GnuPubtypes) + dumpPubSection(OS, "debug_gnu_pubtypes", getGnuPubTypesSection(), + isLittleEndian(), true /* GnuStyle */); - if (DumpType == DIDT_All || DumpType == DIDT_StrOffsetsDwo) - if (!getStringOffsetDWOSection().empty()) { - OS << "\n.debug_str_offsets.dwo contents:\n"; - DataExtractor strOffsetExt(getStringOffsetDWOSection(), isLittleEndian(), 0); - offset = 0; - uint64_t size = getStringOffsetDWOSection().size(); - while (offset < size) { - OS << format("0x%8.8x: ", offset); - OS << format("%8.8x\n", strOffsetExt.getU32(&offset)); - } + if ((DumpType == DIDT_All || DumpType == DIDT_StrOffsetsDwo) && + !getStringOffsetDWOSection().empty()) { + OS << "\n.debug_str_offsets.dwo contents:\n"; + DataExtractor strOffsetExt(getStringOffsetDWOSection(), isLittleEndian(), + 0); + offset = 0; + uint64_t size = getStringOffsetDWOSection().size(); + while (offset < size) { + OS << format("0x%8.8x: ", offset); + OS << format("%8.8x\n", strOffsetExt.getU32(&offset)); } + } } const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() { @@ -185,8 +227,8 @@ const DWARFDebugLoc *DWARFContext::getDebugLoc() { if (Loc) return Loc.get(); - DataExtractor LocData(getLocSection(), isLittleEndian(), 0); - Loc.reset(new DWARFDebugLoc(locRelocMap())); + DataExtractor LocData(getLocSection().Data, isLittleEndian(), 0); + Loc.reset(new DWARFDebugLoc(getLocSection().Relocs)); // assume all compile units have the same address byte size if (getNumCompileUnits()) Loc->parse(LocData, getCompileUnitAtIndex(0)->getAddressByteSize()); @@ -197,13 +239,7 @@ const DWARFDebugAranges *DWARFContext::getDebugAranges() { if (Aranges) return Aranges.get(); - DataExtractor arangesData(getARangeSection(), isLittleEndian(), 0); - Aranges.reset(new DWARFDebugAranges()); - Aranges->extract(arangesData); - // Generate aranges from DIEs: even if .debug_aranges section is present, - // it may describe only a small subset of compilation units, so we need to - // manually build aranges for the rest of them. Aranges->generate(this); return Aranges.get(); } @@ -231,11 +267,11 @@ const DWARFDebugFrame *DWARFContext::getDebugFrame() { const DWARFLineTable * DWARFContext::getLineTableForCompileUnit(DWARFCompileUnit *cu) { if (!Line) - Line.reset(new DWARFDebugLine(&lineRelocMap())); + Line.reset(new DWARFDebugLine(&getLineSection().Relocs)); unsigned stmtOffset = - cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list, - -1U); + cu->getCompileUnitDIE()->getAttributeValueAsSectionOffset( + cu, DW_AT_stmt_list, -1U); if (stmtOffset == -1U) return 0; // No line table for this compile unit. @@ -244,43 +280,84 @@ DWARFContext::getLineTableForCompileUnit(DWARFCompileUnit *cu) { return lt; // We have to parse it first. - DataExtractor lineData(getLineSection(), isLittleEndian(), + DataExtractor lineData(getLineSection().Data, isLittleEndian(), cu->getAddressByteSize()); return Line->getOrParseLineTable(lineData, stmtOffset); } void DWARFContext::parseCompileUnits() { uint32_t offset = 0; - const DataExtractor &DIData = DataExtractor(getInfoSection(), + const DataExtractor &DIData = DataExtractor(getInfoSection().Data, isLittleEndian(), 0); while (DIData.isValidOffset(offset)) { OwningPtr CU(new DWARFCompileUnit( - getDebugAbbrev(), getInfoSection(), getAbbrevSection(), + getDebugAbbrev(), getInfoSection().Data, getAbbrevSection(), getRangeSection(), getStringSection(), StringRef(), getAddrSection(), - &infoRelocMap(), isLittleEndian())); + &getInfoSection().Relocs, isLittleEndian())); if (!CU->extract(DIData, &offset)) { break; } CUs.push_back(CU.take()); - offset = CUs.back()->getNextCompileUnitOffset(); + offset = CUs.back()->getNextUnitOffset(); + } +} + +void DWARFContext::parseTypeUnits() { + const TypeSectionMap &Sections = getTypesSections(); + for (TypeSectionMap::const_iterator I = Sections.begin(), E = Sections.end(); + I != E; ++I) { + uint32_t offset = 0; + const DataExtractor &DIData = + DataExtractor(I->second.Data, isLittleEndian(), 0); + while (DIData.isValidOffset(offset)) { + OwningPtr TU(new DWARFTypeUnit( + getDebugAbbrev(), I->second.Data, getAbbrevSection(), + getRangeSection(), getStringSection(), StringRef(), getAddrSection(), + &I->second.Relocs, isLittleEndian())); + if (!TU->extract(DIData, &offset)) + break; + TUs.push_back(TU.take()); + offset = TUs.back()->getNextUnitOffset(); + } } } void DWARFContext::parseDWOCompileUnits() { uint32_t offset = 0; - const DataExtractor &DIData = DataExtractor(getInfoDWOSection(), - isLittleEndian(), 0); + const DataExtractor &DIData = + DataExtractor(getInfoDWOSection().Data, isLittleEndian(), 0); while (DIData.isValidOffset(offset)) { OwningPtr DWOCU(new DWARFCompileUnit( - getDebugAbbrevDWO(), getInfoDWOSection(), getAbbrevDWOSection(), + getDebugAbbrevDWO(), getInfoDWOSection().Data, getAbbrevDWOSection(), getRangeDWOSection(), getStringDWOSection(), - getStringOffsetDWOSection(), getAddrSection(), &infoDWORelocMap(), - isLittleEndian())); + getStringOffsetDWOSection(), getAddrSection(), + &getInfoDWOSection().Relocs, isLittleEndian())); if (!DWOCU->extract(DIData, &offset)) { break; } DWOCUs.push_back(DWOCU.take()); - offset = DWOCUs.back()->getNextCompileUnitOffset(); + offset = DWOCUs.back()->getNextUnitOffset(); + } +} + +void DWARFContext::parseDWOTypeUnits() { + const TypeSectionMap &Sections = getTypesDWOSections(); + for (TypeSectionMap::const_iterator I = Sections.begin(), E = Sections.end(); + I != E; ++I) { + uint32_t offset = 0; + const DataExtractor &DIData = + DataExtractor(I->second.Data, isLittleEndian(), 0); + while (DIData.isValidOffset(offset)) { + OwningPtr TU(new DWARFTypeUnit( + getDebugAbbrevDWO(), I->second.Data, getAbbrevDWOSection(), + getRangeDWOSection(), getStringDWOSection(), + getStringOffsetDWOSection(), getAddrSection(), &I->second.Relocs, + isLittleEndian())); + if (!TU->extract(DIData, &offset)) + break; + DWOTUs.push_back(TU.take()); + offset = DWOTUs.back()->getNextUnitOffset(); + } } } @@ -379,7 +456,7 @@ DILineInfo DWARFContext::getLineInfoForAddress(uint64_t Address, CU->getInlinedChainForAddress(Address); if (InlinedChain.DIEs.size() > 0) { const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain.DIEs[0]; - if (const char *Name = TopFunctionDIE.getSubroutineName(InlinedChain.CU)) + if (const char *Name = TopFunctionDIE.getSubroutineName(InlinedChain.U)) FunctionName = Name; } } @@ -412,19 +489,16 @@ DILineInfoTable DWARFContext::getLineInfoForAddressRange(uint64_t Address, CU->getInlinedChainForAddress(Address); if (InlinedChain.DIEs.size() > 0) { const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain.DIEs[0]; - if (const char *Name = TopFunctionDIE.getSubroutineName(InlinedChain.CU)) + if (const char *Name = TopFunctionDIE.getSubroutineName(InlinedChain.U)) FunctionName = Name; } } - StringRef FuncNameRef = StringRef(FunctionName); - // If the Specifier says we don't need FileLineInfo, just // return the top-most function at the starting address. if (!Specifier.needs(DILineInfoSpecifier::FileLineInfo)) { - Lines.push_back(std::make_pair(Address, - DILineInfo(StringRef(""), - FuncNameRef, 0, 0))); + Lines.push_back( + std::make_pair(Address, DILineInfo("", FunctionName, 0, 0))); return Lines; } @@ -445,9 +519,8 @@ DILineInfoTable DWARFContext::getLineInfoForAddressRange(uint64_t Address, std::string FileName = ""; getFileNameForCompileUnit(CU, LineTable, Row.File, NeedsAbsoluteFilePath, FileName); - Lines.push_back(std::make_pair(Row.Address, - DILineInfo(StringRef(FileName), - FuncNameRef, Row.Line, Row.Column))); + Lines.push_back(std::make_pair( + Row.Address, DILineInfo(FileName, FunctionName, Row.Line, Row.Column))); } return Lines; @@ -475,7 +548,7 @@ DIInliningInfo DWARFContext::getInliningInfoForAddress(uint64_t Address, uint32_t Column = 0; // Get function name if necessary. if (Specifier.needs(DILineInfoSpecifier::FunctionName)) { - if (const char *Name = FunctionDIE.getSubroutineName(InlinedChain.CU)) + if (const char *Name = FunctionDIE.getSubroutineName(InlinedChain.U)) FunctionName = Name; } if (Specifier.needs(DILineInfoSpecifier::FileLineInfo)) { @@ -499,7 +572,7 @@ DIInliningInfo DWARFContext::getInliningInfoForAddress(uint64_t Address, } // Get call file/line/column of a current DIE. if (i + 1 < n) { - FunctionDIE.getCallerFrame(InlinedChain.CU, CallFile, CallLine, + FunctionDIE.getCallerFrame(InlinedChain.U, CallFile, CallLine, CallColumn); } } @@ -556,29 +629,39 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) : UncompressedSections.push_back(UncompressedSection.take()); } - StringRef *Section = StringSwitch(name) - .Case("debug_info", &InfoSection) - .Case("debug_abbrev", &AbbrevSection) - .Case("debug_loc", &LocSection) - .Case("debug_line", &LineSection) - .Case("debug_aranges", &ARangeSection) - .Case("debug_frame", &DebugFrameSection) - .Case("debug_str", &StringSection) - .Case("debug_ranges", &RangeSection) - .Case("debug_pubnames", &PubNamesSection) - .Case("debug_info.dwo", &InfoDWOSection) - .Case("debug_abbrev.dwo", &AbbrevDWOSection) - .Case("debug_str.dwo", &StringDWOSection) - .Case("debug_str_offsets.dwo", &StringOffsetDWOSection) - .Case("debug_addr", &AddrSection) - // Any more debug info sections go here. - .Default(0); + StringRef *Section = + StringSwitch(name) + .Case("debug_info", &InfoSection.Data) + .Case("debug_abbrev", &AbbrevSection) + .Case("debug_loc", &LocSection.Data) + .Case("debug_line", &LineSection.Data) + .Case("debug_aranges", &ARangeSection) + .Case("debug_frame", &DebugFrameSection) + .Case("debug_str", &StringSection) + .Case("debug_ranges", &RangeSection) + .Case("debug_pubnames", &PubNamesSection) + .Case("debug_pubtypes", &PubTypesSection) + .Case("debug_gnu_pubnames", &GnuPubNamesSection) + .Case("debug_gnu_pubtypes", &GnuPubTypesSection) + .Case("debug_info.dwo", &InfoDWOSection.Data) + .Case("debug_abbrev.dwo", &AbbrevDWOSection) + .Case("debug_str.dwo", &StringDWOSection) + .Case("debug_str_offsets.dwo", &StringOffsetDWOSection) + .Case("debug_addr", &AddrSection) + // Any more debug info sections go here. + .Default(0); if (Section) { *Section = data; if (name == "debug_ranges") { // FIXME: Use the other dwo range section when we emit it. RangeDWOSection = data; } + } else if (name == "debug_types") { + // Find debug_types data by section rather than name as there are + // multiple, comdat grouped, debug_types sections. + TypesSections[*i].Data = data; + } else if (name == "debug_types.dwo") { + TypesDWOSections[*i].Data = data; } section_iterator RelocatedSection = i->getRelocatedSection(); @@ -593,13 +676,21 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) : // TODO: Add support for relocations in other sections as needed. // Record relocations for the debug_info and debug_line sections. RelocAddrMap *Map = StringSwitch(RelSecName) - .Case("debug_info", &InfoRelocMap) - .Case("debug_loc", &LocRelocMap) - .Case("debug_info.dwo", &InfoDWORelocMap) - .Case("debug_line", &LineRelocMap) + .Case("debug_info", &InfoSection.Relocs) + .Case("debug_loc", &LocSection.Relocs) + .Case("debug_info.dwo", &InfoDWOSection.Relocs) + .Case("debug_line", &LineSection.Relocs) .Default(0); - if (!Map) - continue; + if (!Map) { + // Find debug_types relocs by section rather than name as there are + // multiple, comdat grouped, debug_types sections. + if (RelSecName == "debug_types") + Map = &TypesSections[*RelocatedSection].Relocs; + else if (RelSecName == "debug_types.dwo") + Map = &TypesDWOSections[*RelocatedSection].Relocs; + else + continue; + } if (i->begin_relocations() != i->end_relocations()) { uint64_t SectionSize;