[obj2yaml] Refactor the .debug_pub* sections dumper.

It's good to reuse the DWARF parser in lib/DebugInfo so that we don't
need to maintain a separate parser in client side (obj2yaml). Besides,
A test case is added whose length field is a very huge value which makes
obj2yaml stuck when parsing the section.

Reviewed By: jhenderson

Differential Revision: https://reviews.llvm.org/D86192
This commit is contained in:
Xing GUO 2020-08-19 21:13:46 +08:00
parent 682842361d
commit 6ada6c96e0
2 changed files with 93 additions and 41 deletions

View File

@ -430,3 +430,62 @@ LoadCommands:
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

View File

@ -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 @@ Error dumpDebugRanges(DWARFContext &DCtx, DWARFYAML::Data &Y) {
return ErrorSuccess();
}
static DWARFYAML::PubSection dumpPubSection(const DWARFContext &DCtx,
const DWARFSection &Section,
static Optional<DWARFYAML::PubSection>
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<DWARFDebugPubTable::Set> 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 @@ static DWARFYAML::PubSection dumpPubSection(const DWARFContext &DCtx,
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())
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, GNUPubNames, /*IsGNUStyle=*/true);
const DWARFSection GNUPubTypes = D.getGnuPubtypesSection();
if (!GNUPubTypes.Data.empty())
Y.GNUPubNames =
dumpPubSection(DCtx, D.getGnuPubnamesSection(), /*IsGNUStyle=*/true);
// TODO: Test dumping .debug_gnu_pubtypes section.
Y.GNUPubTypes = dumpPubSection(DCtx, GNUPubTypes, /*IsGNUStyle=*/true);
Y.GNUPubTypes =
dumpPubSection(DCtx, D.getGnuPubtypesSection(), /*IsGNUStyle=*/true);
}
void dumpDebugInfo(DWARFContext &DCtx, DWARFYAML::Data &Y) {