diff --git a/llvm/test/ObjectYAML/MachO/DWARF-pubsections.yaml b/llvm/test/ObjectYAML/MachO/DWARF-pubsections.yaml --- a/llvm/test/ObjectYAML/MachO/DWARF-pubsections.yaml +++ b/llvm/test/ObjectYAML/MachO/DWARF-pubsections.yaml @@ -430,3 +430,62 @@ reserved2: 0x00000000 reserved3: 0x00000000 DWARF: + +## c) Test that obj2yaml is able to dump a __debug_pubnames section whose length field is greater than the section size. + +# RUN: yaml2obj --docnum=3 %s | obj2yaml | FileCheck %s --check-prefix=INVALID-LENGTH + +# INVALID-LENGTH: DWARF: +# INVALID-LENGTH-NEXT: debug_pubnames: +# INVALID-LENGTH-NEXT: Length: 0x00000000DEADBEEF +# INVALID-LENGTH-NEXT: Version: 2 +# INVALID-LENGTH-NEXT: UnitOffset: 0 +# INVALID-LENGTH-NEXT: UnitSize: 121 +# INVALID-LENGTH-NEXT: Entries: +# INVALID-LENGTH-NEXT: - DieOffset: 0x0000002A +# INVALID-LENGTH-NEXT: Name: main + +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x01000007 + cpusubtype: 0x00000003 + filetype: 0x0000000A + ncmds: 1 + sizeofcmds: 1888 + flags: 0x00000000 + reserved: 0x00000000 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 152 + segname: __DWARF + vmaddr: 0x00000000 + vmsize: 0x00000000 + fileoff: 0 + filesize: 0xffff + maxprot: 0 + initprot: 0 + nsects: 1 + flags: 0 + Sections: + - sectname: __debug_pubnames + segname: __DWARF + addr: 0x0000000000000000 + size: 24 + offset: 0x000000b8 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 +DWARF: + debug_pubnames: + Length: 0xdeadbeef + Version: 2 + UnitOffset: 0 + UnitSize: 121 + Entries: + - DieOffset: 0x0000002A + Name: main diff --git a/llvm/tools/obj2yaml/dwarf2yaml.cpp b/llvm/tools/obj2yaml/dwarf2yaml.cpp --- a/llvm/tools/obj2yaml/dwarf2yaml.cpp +++ b/llvm/tools/obj2yaml/dwarf2yaml.cpp @@ -10,6 +10,7 @@ #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h" #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/DebugInfo/DWARF/DWARFSection.h" @@ -118,32 +119,31 @@ return ErrorSuccess(); } -static DWARFYAML::PubSection dumpPubSection(const DWARFContext &DCtx, - const DWARFSection &Section, - bool IsGNUStyle) { +static Optional +dumpPubSection(const DWARFContext &DCtx, const DWARFSection &Section, + bool IsGNUStyle) { + DWARFYAML::PubSection Y; DWARFDataExtractor PubSectionData(DCtx.getDWARFObj(), Section, DCtx.isLittleEndian(), 0); - DWARFYAML::PubSection Y; - uint64_t Offset = 0; - uint64_t Length = PubSectionData.getU32(&Offset); - if (Length == dwarf::DW_LENGTH_DWARF64) { - Y.Format = dwarf::DWARF64; - Y.Length = PubSectionData.getU64(&Offset); - } else { - Y.Format = dwarf::DWARF32; - Y.Length = Length; - } - Y.Version = PubSectionData.getU16(&Offset); - Y.UnitOffset = PubSectionData.getU32(&Offset); - Y.UnitSize = PubSectionData.getU32(&Offset); - while (Offset < Y.Length) { - DWARFYAML::PubEntry NewEntry; - NewEntry.DieOffset = PubSectionData.getU32(&Offset); - if (IsGNUStyle) - NewEntry.Descriptor = PubSectionData.getU8(&Offset); - NewEntry.Name = PubSectionData.getCStr(&Offset); - Y.Entries.push_back(NewEntry); - } + DWARFDebugPubTable Table; + // We ignore any errors that don't prevent parsing the section, since we can + // still represent such sections. + Table.extract(PubSectionData, IsGNUStyle, + [](Error Err) { consumeError(std::move(Err)); }); + ArrayRef Sets = Table.getData(); + if (Sets.empty()) + return None; + + // FIXME: Currently, obj2yaml only supports dumping the first pubtable. + Y.Format = Sets[0].Format; + Y.Length = Sets[0].Length; + Y.Version = Sets[0].Version; + Y.UnitOffset = Sets[0].Offset; + Y.UnitSize = Sets[0].Size; + + for (const DWARFDebugPubTable::Entry &E : Sets[0].Entries) + Y.Entries.push_back( + DWARFYAML::PubEntry{E.SecOffset, E.Descriptor.toBits(), E.Name}); return Y; } @@ -151,23 +151,16 @@ void dumpDebugPubSections(DWARFContext &DCtx, DWARFYAML::Data &Y) { const DWARFObject &D = DCtx.getDWARFObj(); - const DWARFSection PubNames = D.getPubnamesSection(); - if (!PubNames.Data.empty()) - Y.PubNames = dumpPubSection(DCtx, PubNames, /*IsGNUStyle=*/false); - - const DWARFSection PubTypes = D.getPubtypesSection(); - if (!PubTypes.Data.empty()) - Y.PubTypes = dumpPubSection(DCtx, PubTypes, /*IsGNUStyle=*/false); - - const DWARFSection GNUPubNames = D.getGnuPubnamesSection(); - if (!GNUPubNames.Data.empty()) - // TODO: Test dumping .debug_gnu_pubnames section. - Y.GNUPubNames = dumpPubSection(DCtx, GNUPubNames, /*IsGNUStyle=*/true); - - const DWARFSection GNUPubTypes = D.getGnuPubtypesSection(); - if (!GNUPubTypes.Data.empty()) - // TODO: Test dumping .debug_gnu_pubtypes section. - Y.GNUPubTypes = dumpPubSection(DCtx, GNUPubTypes, /*IsGNUStyle=*/true); + Y.PubNames = + dumpPubSection(DCtx, D.getPubnamesSection(), /*IsGNUStyle=*/false); + Y.PubTypes = + dumpPubSection(DCtx, D.getPubtypesSection(), /*IsGNUStyle=*/false); + // TODO: Test dumping .debug_gnu_pubnames section. + Y.GNUPubNames = + dumpPubSection(DCtx, D.getGnuPubnamesSection(), /*IsGNUStyle=*/true); + // TODO: Test dumping .debug_gnu_pubtypes section. + Y.GNUPubTypes = + dumpPubSection(DCtx, D.getGnuPubtypesSection(), /*IsGNUStyle=*/true); } void dumpDebugInfo(DWARFContext &DCtx, DWARFYAML::Data &Y) {