diff --git a/llvm/include/llvm/ObjectYAML/DWARFYAML.h b/llvm/include/llvm/ObjectYAML/DWARFYAML.h --- a/llvm/include/llvm/ObjectYAML/DWARFYAML.h +++ b/llvm/include/llvm/ObjectYAML/DWARFYAML.h @@ -113,7 +113,7 @@ Optional AddrSize; llvm::dwarf::UnitType Type; // Added in DWARF 5 Optional AbbrevTableID; - yaml::Hex64 AbbrOffset; + Optional AbbrOffset; std::vector Entries; }; @@ -231,10 +231,17 @@ bool isEmpty() const; SetVector getNonEmptySectionNames() const; - Expected getAbbrevTableIndexByID(uint64_t ID) const; + + struct AbbrevTableInfo { + uint64_t Index; + uint64_t Offset; + }; + Expected getAbbrevTableInfoByID(uint64_t ID) const; + StringRef getAbbrevTableContentByIndex(uint64_t Index) const; private: - mutable std::unordered_map AbbrevTableID2Index; + mutable std::unordered_map AbbrevTableInfoMap; + mutable std::unordered_map AbbrevTableContents; }; } // end namespace DWARFYAML diff --git a/llvm/lib/ObjectYAML/DWARFEmitter.cpp b/llvm/lib/ObjectYAML/DWARFEmitter.cpp --- a/llvm/lib/ObjectYAML/DWARFEmitter.cpp +++ b/llvm/lib/ObjectYAML/DWARFEmitter.cpp @@ -94,28 +94,45 @@ return Error::success(); } -Error DWARFYAML::emitDebugAbbrev(raw_ostream &OS, const DWARFYAML::Data &DI) { - for (const DWARFYAML::AbbrevTable &AbbrevTable : DI.DebugAbbrev) { - uint64_t AbbrevCode = 0; - for (const DWARFYAML::Abbrev &AbbrevDecl : AbbrevTable.Table) { - AbbrevCode = - AbbrevDecl.Code ? (uint64_t)*AbbrevDecl.Code : AbbrevCode + 1; - encodeULEB128(AbbrevCode, OS); - encodeULEB128(AbbrevDecl.Tag, OS); - OS.write(AbbrevDecl.Children); - for (auto Attr : AbbrevDecl.Attributes) { - encodeULEB128(Attr.Attribute, OS); - encodeULEB128(Attr.Form, OS); - if (Attr.Form == dwarf::DW_FORM_implicit_const) - encodeSLEB128(Attr.Value, OS); - } - encodeULEB128(0, OS); - encodeULEB128(0, OS); +StringRef DWARFYAML::Data::getAbbrevTableContentByIndex(uint64_t Index) const { + assert(Index < DebugAbbrev.size() && + "Index should be less than the size of DebugAbbrev array"); + auto It = AbbrevTableContents.find(Index); + if (It != AbbrevTableContents.cend()) + return It->second; + + std::string AbbrevTableBuffer; + raw_string_ostream OS(AbbrevTableBuffer); + + uint64_t AbbrevCode = 0; + for (const DWARFYAML::Abbrev &AbbrevDecl : DebugAbbrev[Index].Table) { + AbbrevCode = AbbrevDecl.Code ? (uint64_t)*AbbrevDecl.Code : AbbrevCode + 1; + encodeULEB128(AbbrevCode, OS); + encodeULEB128(AbbrevDecl.Tag, OS); + OS.write(AbbrevDecl.Children); + for (auto Attr : AbbrevDecl.Attributes) { + encodeULEB128(Attr.Attribute, OS); + encodeULEB128(Attr.Form, OS); + if (Attr.Form == dwarf::DW_FORM_implicit_const) + encodeSLEB128(Attr.Value, OS); } + encodeULEB128(0, OS); + encodeULEB128(0, OS); + } + + // The abbreviations for a given compilation unit end with an entry + // consisting of a 0 byte for the abbreviation code. + OS.write_zeros(1); + + AbbrevTableContents.insert({Index, AbbrevTableBuffer}); + + return AbbrevTableContents[Index]; +} - // The abbreviations for a given compilation unit end with an entry - // consisting of a 0 byte for the abbreviation code. - OS.write_zeros(1); +Error DWARFYAML::emitDebugAbbrev(raw_ostream &OS, const DWARFYAML::Data &DI) { + for (uint64_t I = 0; I < DI.DebugAbbrev.size(); ++I) { + StringRef AbbrevTableContent = DI.getAbbrevTableContentByIndex(I); + OS.write(AbbrevTableContent.data(), AbbrevTableContent.size()); } return Error::success(); @@ -257,16 +274,16 @@ if (AbbrCode == 0 || Entry.Values.empty()) return OS.tell() - EntryBegin; - Expected AbbrevTableIndexOrErr = - DI.getAbbrevTableIndexByID(AbbrevTableID); - if (!AbbrevTableIndexOrErr) + Expected AbbrevTableInfoOrErr = + DI.getAbbrevTableInfoByID(AbbrevTableID); + if (!AbbrevTableInfoOrErr) return createStringError(errc::invalid_argument, - toString(AbbrevTableIndexOrErr.takeError()) + + toString(AbbrevTableInfoOrErr.takeError()) + " for compilation unit with index " + utostr(CUIndex)); ArrayRef AbbrevDecls( - DI.DebugAbbrev[*AbbrevTableIndexOrErr].Table); + DI.DebugAbbrev[AbbrevTableInfoOrErr->Index].Table); if (AbbrCode > AbbrevDecls.size()) return createStringError( @@ -425,12 +442,28 @@ writeInitialLength(Unit.Format, Length, OS, DI.IsLittleEndian); writeInteger((uint16_t)Unit.Version, OS, DI.IsLittleEndian); + + uint64_t AbbrevTableOffset = 0; + if (Unit.AbbrOffset) { + AbbrevTableOffset = *Unit.AbbrOffset; + } else { + if (Expected AbbrevTableInfoOrErr = + DI.getAbbrevTableInfoByID(AbbrevTableID)) { + AbbrevTableOffset = AbbrevTableInfoOrErr->Offset; + } else { + // The current compilation unit may not have DIEs and it will not be + // able to find the associated abbrev table. We consume the error and + // assign 0 to the debug_abbrev_offset in such circumstances. + consumeError(AbbrevTableInfoOrErr.takeError()); + } + } + if (Unit.Version >= 5) { writeInteger((uint8_t)Unit.Type, OS, DI.IsLittleEndian); writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian); - writeDWARFOffset(Unit.AbbrOffset, Unit.Format, OS, DI.IsLittleEndian); + writeDWARFOffset(AbbrevTableOffset, Unit.Format, OS, DI.IsLittleEndian); } else { - writeDWARFOffset(Unit.AbbrOffset, Unit.Format, OS, DI.IsLittleEndian); + writeDWARFOffset(AbbrevTableOffset, Unit.Format, OS, DI.IsLittleEndian); writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian); } diff --git a/llvm/lib/ObjectYAML/DWARFYAML.cpp b/llvm/lib/ObjectYAML/DWARFYAML.cpp --- a/llvm/lib/ObjectYAML/DWARFYAML.cpp +++ b/llvm/lib/ObjectYAML/DWARFYAML.cpp @@ -55,25 +55,31 @@ return SecNames; } -Expected DWARFYAML::Data::getAbbrevTableIndexByID(uint64_t ID) const { - if (AbbrevTableID2Index.empty()) { +Expected +DWARFYAML::Data::getAbbrevTableInfoByID(uint64_t ID) const { + if (AbbrevTableInfoMap.empty()) { + uint64_t AbbrevTableOffset = 0; for (auto &AbbrevTable : enumerate(DebugAbbrev)) { // If the abbrev table's ID isn't specified, we use the index as its ID. uint64_t AbbrevTableID = AbbrevTable.value().ID.getValueOr(AbbrevTable.index()); - auto It = - AbbrevTableID2Index.insert({AbbrevTableID, AbbrevTable.index()}); + auto It = AbbrevTableInfoMap.insert( + {AbbrevTableID, AbbrevTableInfo{/*Index=*/AbbrevTable.index(), + /*Offset=*/AbbrevTableOffset}}); if (!It.second) return createStringError( errc::invalid_argument, "the ID (%" PRIu64 ") of abbrev table with index %zu has been used " "by abbrev table with index %" PRIu64, - AbbrevTableID, AbbrevTable.index(), It.first->second); + AbbrevTableID, AbbrevTable.index(), It.first->second.Index); + + AbbrevTableOffset += + getAbbrevTableContentByIndex(AbbrevTable.index()).size(); } } - auto It = AbbrevTableID2Index.find(ID); - if (It == AbbrevTableID2Index.end()) + auto It = AbbrevTableInfoMap.find(ID); + if (It == AbbrevTableInfoMap.end()) return createStringError(errc::invalid_argument, "cannot find abbrev table whose ID is %" PRIu64, ID); @@ -182,7 +188,7 @@ if (Unit.Version >= 5) IO.mapRequired("UnitType", Unit.Type); IO.mapOptional("AbbrevTableID", Unit.AbbrevTableID); - IO.mapRequired("AbbrOffset", Unit.AbbrOffset); + IO.mapOptional("AbbrOffset", Unit.AbbrOffset); IO.mapOptional("AddrSize", Unit.AddrSize); IO.mapOptional("Entries", Unit.Entries); } diff --git a/llvm/test/tools/yaml2obj/ELF/DWARF/debug-info.yaml b/llvm/test/tools/yaml2obj/ELF/DWARF/debug-info.yaml --- a/llvm/test/tools/yaml2obj/ELF/DWARF/debug-info.yaml +++ b/llvm/test/tools/yaml2obj/ELF/DWARF/debug-info.yaml @@ -902,7 +902,8 @@ - Value: 0x1234 ## o) Test that yaml2obj is able to generate compilation units according to the -## associated abbrev table that is referenced by the 'AbbrevTableID'. +## associated abbrev table that is referenced by the 'AbbrevTableID' and infer +## the value of the debug_abbrev_offset field. # RUN: yaml2obj --docnum=17 %s -o %t17.o # RUN: llvm-readelf --hex-dump=.debug_info %t17.o | FileCheck %s --check-prefix=MULTI-TABLES @@ -972,29 +973,54 @@ debug_info: - Version: 4 AbbrevTableID: 2 - AbbrOffset: 8 Entries: - AbbrCode: 1 Values: - Value: 0x1234 - Version: 4 AbbrevTableID: 2 - AbbrOffset: 8 Entries: - AbbrCode: 1 Values: - Value: 0x4321 - Version: 4 AbbrevTableID: 0 - AbbrOffset: 0 Entries: - AbbrCode: 1 Values: - Value: 0x5678 - Version: 4 AbbrevTableID: 1 - AbbrOffset: 16 Entries: - AbbrCode: 1 Values: - Value: 0x8765 + +## p) Test that when the debug_abbrev_offset field isn't specified and there is no associated +## abbrev table, yaml2obj will assign 0 to the debug_abbrev_offset field. + +# RUN: yaml2obj --docnum=18 %s -o %t18.o +# RUN: llvm-readelf --hex-dump=.debug_info %t18.o | FileCheck %s --check-prefix=ZERO-OFFSET + +# ZERO-OFFSET: Hex dump of section '.debug_info': +# ZERO-OFFSET-NEXT: 0x00000000 07000000 04000000 000008 ........... +## ^------- unit_length (4-byte) +## ^--- version (2-byte) +## ^-------- debug_abbrev_offset (4-byte) +## ^- address_size (1-byte) + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC +DWARF: + debug_info: + - Version: 4 + AbbrevTableID: [[ABBREVID=]] + +## q) Test that when we assign an invalid 'AbbrevTableID' that doesn't point to an abbrev table, +## yaml2obj will assign 0 to the debug_abbrev_offset field. + +# RUN: yaml2obj --docnum=18 -DABBREVID=2 %s -o %t18.o +# RUN: llvm-readelf --hex-dump=.debug_info %t18.o | FileCheck %s --check-prefix=ZERO-OFFSET diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp --- a/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp +++ b/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp @@ -1369,7 +1369,6 @@ " Children: DW_CHILDREN_yes\n" "debug_info:\n" " - Version: 4\n" - " AbbrOffset: 0\n" " AddrSize: 8\n" " Entries:\n" " - AbbrCode: 0x00000001\n" @@ -1903,7 +1902,6 @@ debug_info: - Length: 22 Version: 4 - AbbrOffset: 0 AddrSize: 8 Entries: - AbbrCode: 0x00000001 @@ -1952,7 +1950,6 @@ debug_info: - Length: 22 Version: 4 - AbbrOffset: 0 AddrSize: 8 Entries: - AbbrCode: 0x00000001 @@ -1993,7 +1990,6 @@ debug_info: - Length: 16 Version: 4 - AbbrOffset: 0 AddrSize: 8 Entries: - AbbrCode: 0x00000001 @@ -2032,7 +2028,6 @@ - Length: 17 Version: 5 UnitType: DW_UT_compile - AbbrOffset: 0 AddrSize: 8 Entries: - AbbrCode: 0x00000001 @@ -2069,7 +2064,6 @@ debug_info: - Length: 16 Version: 4 - AbbrOffset: 0 AddrSize: 8 Entries: - AbbrCode: 0x00000001 @@ -2104,7 +2098,6 @@ debug_info: - Length: 12 Version: 4 - AbbrOffset: 0 AddrSize: 8 Entries: - AbbrCode: 0x00000001 @@ -2146,7 +2139,6 @@ debug_info: - Length: 22 Version: 4 - AbbrOffset: 0 AddrSize: 8 Entries: - AbbrCode: 0x00000001 @@ -2188,7 +2180,6 @@ debug_info: - Length: 16 Version: 4 - AbbrOffset: 0 AddrSize: 8 Entries: - AbbrCode: 0x00000001 @@ -2255,7 +2246,6 @@ debug_info: - Length: 16 Version: 4 - AbbrOffset: 0 AddrSize: 8 Entries: - AbbrCode: 0x00000001 @@ -2324,7 +2314,6 @@ debug_info: - Length: 16 Version: 4 - AbbrOffset: 0 AddrSize: 8 Entries: - AbbrCode: 0x00000001 @@ -2394,7 +2383,6 @@ debug_info: - Length: 16 Version: 4 - AbbrOffset: 0 AddrSize: 8 Entries: - AbbrCode: 0x00000001 @@ -2469,7 +2457,6 @@ debug_info: - Length: 16 Version: 4 - AbbrOffset: 0 AddrSize: 8 Entries: - AbbrCode: 0x00000001 @@ -2479,7 +2466,6 @@ - Length: 16 Version: 4 AbbrevTableID: 0 - AbbrOffset: 0 AddrSize: 8 Entries: - AbbrCode: 0x00000001 @@ -2594,7 +2580,6 @@ debug_info: - Length: 46 Version: 4 - AbbrOffset: 0 AddrSize: 8 Entries: - AbbrCode: 0x00000001 @@ -2654,7 +2639,6 @@ debug_info: - Length: 52 Version: 4 - AbbrOffset: 0 AddrSize: 8 Entries: - AbbrCode: 0x00000001 @@ -2712,7 +2696,6 @@ debug_info: - Length: 55 Version: 4 - AbbrOffset: 0 AddrSize: 8 Entries: - AbbrCode: 0x00000001 @@ -2779,7 +2762,6 @@ debug_info: - Length: 85 Version: 4 - AbbrOffset: 0 AddrSize: 8 Entries: - AbbrCode: 0x00000001 @@ -2841,7 +2823,6 @@ debug_info: - Length: 34 Version: 4 - AbbrOffset: 0 AddrSize: 8 Entries: - AbbrCode: 0x00000001 @@ -2898,7 +2879,6 @@ debug_info: - Length: 71 Version: 4 - AbbrOffset: 0 AddrSize: 8 Entries: - AbbrCode: 0x00000001 @@ -2961,7 +2941,6 @@ debug_info: - Length: 73 Version: 4 - AbbrOffset: 0 AddrSize: 8 Entries: - AbbrCode: 0x00000001