[DWARF] Adding support for the DWARF v5 string offsets table (consumer/reader part only).

Reviewers: dblaikie, aprantl

Differential Revision: https://reviews.llvm.org/D32779

llvm-svn: 304759
This commit is contained in:
Wolfgang Pieb 2017-06-06 01:22:34 +00:00
parent 7bda195812
commit 77d3e938f8
30 changed files with 1351 additions and 50 deletions

View File

@ -135,6 +135,7 @@ enum DIDumpType {
DIDT_GnuPubnames,
DIDT_GnuPubtypes,
DIDT_Str,
DIDT_StrOffsets,
DIDT_StrDwo,
DIDT_StrOffsetsDwo,
DIDT_AppleNames,

View File

@ -19,8 +19,8 @@ class DWARFCompileUnit : public DWARFUnit {
public:
DWARFCompileUnit(DWARFContext &Context, const DWARFSection &Section,
const DWARFDebugAbbrev *DA, const DWARFSection *RS,
StringRef SS, StringRef SOS, const DWARFSection *AOS,
StringRef LS, bool LE, bool IsDWO,
StringRef SS, const DWARFSection &SOS,
const DWARFSection *AOS, StringRef LS, bool LE, bool IsDWO,
const DWARFUnitSectionBase &UnitSection,
const DWARFUnitIndex::Entry *Entry)
: DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LS, LE, IsDWO,

View File

@ -72,6 +72,9 @@ class DWARFContext : public DIContext {
std::unique_ptr<DWARFDebugAbbrev> AbbrevDWO;
std::unique_ptr<DWARFDebugLocDWO> LocDWO;
/// The maximum DWARF version of all units.
unsigned MaxVersion;
struct DWOFile {
object::OwningBinary<object::ObjectFile> File;
std::unique_ptr<DWARFContext> Context;
@ -97,7 +100,7 @@ class DWARFContext : public DIContext {
void parseDWOTypeUnits();
public:
DWARFContext() : DIContext(CK_DWARF) {}
DWARFContext() : DIContext(CK_DWARF), MaxVersion(0) {}
DWARFContext(DWARFContext &) = delete;
DWARFContext &operator=(DWARFContext &) = delete;
@ -178,6 +181,13 @@ public:
/// Get a DIE given an exact offset.
DWARFDie getDIEForOffset(uint32_t Offset);
unsigned getMaxVersion() const { return MaxVersion; }
void setMaxVersionIfGreater(unsigned Version) {
if (Version > MaxVersion)
MaxVersion = Version;
}
const DWARFUnitIndex &getCUIndex();
DWARFGdbIndex &getGdbIndex();
const DWARFUnitIndex &getTUIndex();
@ -237,6 +247,11 @@ public:
virtual StringRef getGnuPubNamesSection() = 0;
virtual StringRef getGnuPubTypesSection() = 0;
/// DWARF v5
/// @{
virtual const DWARFSection &getStringOffsetSection() = 0;
/// @}
// Sections for DWARF5 split dwarf proposal.
virtual const DWARFSection &getInfoDWOSection() = 0;
virtual const TypeSectionMap &getTypesDWOSections() = 0;
@ -244,7 +259,7 @@ public:
virtual const DWARFSection &getLineDWOSection() = 0;
virtual const DWARFSection &getLocDWOSection() = 0;
virtual StringRef getStringDWOSection() = 0;
virtual StringRef getStringOffsetDWOSection() = 0;
virtual const DWARFSection &getStringOffsetDWOSection() = 0;
virtual const DWARFSection &getRangeDWOSection() = 0;
virtual const DWARFSection &getAddrSection() = 0;
virtual const DWARFSection& getAppleNamesSection() = 0;
@ -295,6 +310,11 @@ class DWARFContextInMemory : public DWARFContext {
StringRef GnuPubNamesSection;
StringRef GnuPubTypesSection;
/// DWARF v5
/// @{
DWARFSection StringOffsetSection;
/// @}
// Sections for DWARF5 split dwarf proposal.
DWARFSection InfoDWOSection;
TypeSectionMap TypesDWOSections;
@ -302,7 +322,7 @@ class DWARFContextInMemory : public DWARFContext {
DWARFSection LineDWOSection;
DWARFSection LocDWOSection;
StringRef StringDWOSection;
StringRef StringOffsetDWOSection;
DWARFSection StringOffsetDWOSection;
DWARFSection RangeDWOSection;
DWARFSection AddrSection;
DWARFSection AppleNamesSection;
@ -353,6 +373,11 @@ public:
const DWARFSection& getAppleNamespacesSection() override { return AppleNamespacesSection; }
const DWARFSection& getAppleObjCSection() override { return AppleObjCSection; }
// DWARF v5
const DWARFSection &getStringOffsetSection() override {
return StringOffsetSection;
}
// Sections for DWARF5 split dwarf proposal.
const DWARFSection &getInfoDWOSection() override { return InfoDWOSection; }
@ -365,7 +390,7 @@ public:
const DWARFSection &getLocDWOSection() override { return LocDWOSection; }
StringRef getStringDWOSection() override { return StringDWOSection; }
StringRef getStringOffsetDWOSection() override {
const DWARFSection &getStringOffsetDWOSection() override {
return StringOffsetDWOSection;
}

View File

@ -31,7 +31,7 @@ private:
public:
DWARFTypeUnit(DWARFContext &Context, const DWARFSection &Section,
const DWARFDebugAbbrev *DA, const DWARFSection *RS,
StringRef SS, StringRef SOS, const DWARFSection *AOS,
StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS,
StringRef LS, bool LE, bool IsDWO,
const DWARFUnitSectionBase &UnitSection,
const DWARFUnitIndex::Entry *Entry)

View File

@ -57,8 +57,9 @@ protected:
virtual void parseImpl(DWARFContext &Context, const DWARFSection &Section,
const DWARFDebugAbbrev *DA, const DWARFSection *RS,
StringRef SS, StringRef SOS, const DWARFSection *AOS,
StringRef LS, bool isLittleEndian, bool isDWO) = 0;
StringRef SS, const DWARFSection &SOS,
const DWARFSection *AOS, StringRef LS,
bool isLittleEndian, bool isDWO) = 0;
};
const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context,
@ -89,7 +90,7 @@ public:
private:
void parseImpl(DWARFContext &Context, const DWARFSection &Section,
const DWARFDebugAbbrev *DA, const DWARFSection *RS,
StringRef SS, StringRef SOS, const DWARFSection *AOS,
StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS,
StringRef LS, bool LE, bool IsDWO) override {
if (Parsed)
return;
@ -119,7 +120,8 @@ class DWARFUnit {
uint32_t RangeSectionBase;
StringRef LineSection;
StringRef StringSection;
StringRef StringOffsetSection;
const DWARFSection &StringOffsetSection;
uint64_t StringOffsetSectionBase = 0;
const DWARFSection *AddrOffsetSection;
uint32_t AddrOffsetSectionBase;
bool isLittleEndian;
@ -162,8 +164,8 @@ protected:
public:
DWARFUnit(DWARFContext &Context, const DWARFSection &Section,
const DWARFDebugAbbrev *DA, const DWARFSection *RS, StringRef SS,
StringRef SOS, const DWARFSection *AOS, StringRef LS, bool LE,
bool IsDWO, const DWARFUnitSectionBase &UnitSection,
const DWARFSection &SOS, const DWARFSection *AOS, StringRef LS,
bool LE, bool IsDWO, const DWARFUnitSectionBase &UnitSection,
const DWARFUnitIndex::Entry *IndexEntry = nullptr);
virtual ~DWARFUnit();
@ -172,7 +174,9 @@ public:
StringRef getLineSection() const { return LineSection; }
StringRef getStringSection() const { return StringSection; }
StringRef getStringOffsetSection() const { return StringOffsetSection; }
const DWARFSection &getStringOffsetSection() const {
return StringOffsetSection;
}
void setAddrOffsetSection(const DWARFSection *AOS, uint32_t Base) {
AddrOffsetSection = AOS;
@ -189,7 +193,8 @@ public:
bool getAddrOffsetSectionItem(uint32_t Index, uint64_t &Result) const;
// FIXME: Result should be uint64_t in DWARF64.
bool getStringOffsetSectionItem(uint32_t Index, uint32_t &Result) const;
bool getStringOffsetSectionItem(uint32_t Index, uint64_t &Result) const;
uint64_t getStringOffsetSectionRelocation(uint32_t Index) const;
DataExtractor getDebugInfoExtractor() const {
return DataExtractor(InfoSection.Data, isLittleEndian, AddrSize);
@ -200,6 +205,9 @@ public:
}
const RelocAddrMap *getRelocMap() const { return &InfoSection.Relocs; }
const RelocAddrMap &getStringOffsetsRelocMap() const {
return StringOffsetSection.Relocs;
}
bool extract(DataExtractor debug_info, uint32_t* offset_ptr);

View File

@ -109,6 +109,9 @@ protected:
MCSection *DwarfLineDWOSection;
MCSection *DwarfLocDWOSection;
MCSection *DwarfStrOffDWOSection;
/// The DWARF v5 string offset and address table sections.
MCSection *DwarfStrOffSection;
MCSection *DwarfAddrSection;
// These are for Fission DWP files.
@ -260,6 +263,7 @@ public:
MCSection *getDwarfLineDWOSection() const { return DwarfLineDWOSection; }
MCSection *getDwarfLocDWOSection() const { return DwarfLocDWOSection; }
MCSection *getDwarfStrOffDWOSection() const { return DwarfStrOffDWOSection; }
MCSection *getDwarfStrOffSection() const { return DwarfStrOffSection; }
MCSection *getDwarfAddrSection() const { return DwarfAddrSection; }
MCSection *getDwarfCUIndexSection() const { return DwarfCUIndexSection; }
MCSection *getDwarfTUIndexSection() const { return DwarfTUIndexSection; }

View File

@ -550,6 +550,8 @@ public:
bool isRelocatableObject() const override;
StringRef mapDebugSectionName(StringRef Name) const override;
bool hasPageZeroSegment() const { return HasPageZeroSegment; }
static bool classof(const Binary *v) {

View File

@ -292,6 +292,9 @@ public:
return std::error_code();
}
/// Maps a debug section name to a standard DWARF section name.
virtual StringRef mapDebugSectionName(StringRef Name) const { return Name; }
/// True if this is a relocatable object (.o/.obj).
virtual bool isRelocatableObject() const = 0;

View File

@ -84,6 +84,123 @@ static void dumpAccelSection(raw_ostream &OS, StringRef Name,
Accel.dump(OS);
}
static void
dumpDWARFv5StringOffsetsSection(raw_ostream &OS, StringRef SectionName,
const DWARFSection &StringOffsetsSection,
StringRef StringSection, bool LittleEndian) {
DataExtractor StrOffsetExt(StringOffsetsSection.Data, LittleEndian, 0);
uint32_t Offset = 0;
uint64_t SectionSize = StringOffsetsSection.Data.size();
while (Offset < SectionSize) {
unsigned Version = 0;
DwarfFormat Format = DWARF32;
unsigned EntrySize = 4;
// Perform validation and extract the segment size from the header.
if (!StrOffsetExt.isValidOffsetForDataOfSize(Offset, 4)) {
OS << "error: invalid contribution to string offsets table in section ."
<< SectionName << ".\n";
return;
}
uint32_t ContributionStart = Offset;
uint64_t ContributionSize = StrOffsetExt.getU32(&Offset);
// A contribution size of 0xffffffff indicates DWARF64, with the actual size
// in the following 8 bytes. Otherwise, the DWARF standard mandates that
// the contribution size must be at most 0xfffffff0.
if (ContributionSize == 0xffffffff) {
if (!StrOffsetExt.isValidOffsetForDataOfSize(Offset, 8)) {
OS << "error: invalid contribution to string offsets table in section ."
<< SectionName << ".\n";
return;
}
Format = DWARF64;
EntrySize = 8;
ContributionSize = StrOffsetExt.getU64(&Offset);
} else if (ContributionSize > 0xfffffff0) {
OS << "error: invalid contribution to string offsets table in section ."
<< SectionName << ".\n";
return;
}
// We must ensure that we don't read a partial record at the end, so we
// validate for a multiple of EntrySize. Also, we're expecting a version
// number and padding, which adds an additional 4 bytes.
uint64_t ValidationSize =
4 + ((ContributionSize + EntrySize - 1) & (-(uint64_t)EntrySize));
if (!StrOffsetExt.isValidOffsetForDataOfSize(Offset, ValidationSize)) {
OS << "error: contribution to string offsets table in section ."
<< SectionName << " has invalid length.\n";
return;
}
Version = StrOffsetExt.getU16(&Offset);
Offset += 2;
OS << format("0x%8.8x: ", ContributionStart);
OS << "Contribution size = " << ContributionSize
<< ", Version = " << Version << "\n";
uint32_t ContributionBase = Offset;
DataExtractor StrData(StringSection, LittleEndian, 0);
while (Offset - ContributionBase < ContributionSize) {
OS << format("0x%8.8x: ", Offset);
// FIXME: We can only extract strings in DWARF32 format at the moment.
uint64_t StringOffset = getRelocatedValue(
StrOffsetExt, EntrySize, &Offset, &StringOffsetsSection.Relocs);
if (Format == DWARF32) {
OS << format("%8.8x ", StringOffset);
uint32_t StringOffset32 = (uint32_t)StringOffset;
const char *S = StrData.getCStr(&StringOffset32);
if (S)
OS << format("\"%s\"", S);
} else
OS << format("%16.16x ", StringOffset);
OS << "\n";
}
}
}
// Dump a DWARF string offsets section. This may be a DWARF v5 formatted
// string offsets section, where each compile or type unit contributes a
// number of entries (string offsets), with each contribution preceded by
// a header containing size and version number. Alternatively, it may be a
// monolithic series of string offsets, as generated by the pre-DWARF v5
// implementation of split DWARF.
static void dumpStringOffsetsSection(raw_ostream &OS, StringRef SectionName,
const DWARFSection &StringOffsetsSection,
StringRef StringSection, bool LittleEndian,
unsigned MaxVersion) {
if (StringOffsetsSection.Data.empty())
return;
OS << "\n." << SectionName << " contents:\n";
// If we have at least one (compile or type) unit with DWARF v5 or greater,
// we assume that the section is formatted like a DWARF v5 string offsets
// section.
if (MaxVersion >= 5)
dumpDWARFv5StringOffsetsSection(OS, SectionName, StringOffsetsSection,
StringSection, LittleEndian);
else {
DataExtractor strOffsetExt(StringOffsetsSection.Data, LittleEndian, 0);
uint32_t offset = 0;
uint64_t size = StringOffsetsSection.Data.size();
// Ensure that size is a multiple of the size of an entry.
if (size & ((uint64_t)(sizeof(uint32_t) - 1))) {
OS << "error: size of ." << SectionName << " is not a multiple of "
<< sizeof(uint32_t) << ".\n";
size &= -(uint64_t)sizeof(uint32_t);
}
DataExtractor StrData(StringSection, LittleEndian, 0);
while (offset < size) {
OS << format("0x%8.8x: ", offset);
uint32_t StringOffset = strOffsetExt.getU32(&offset);
OS << format("%8.8x ", StringOffset);
const char *S = StrData.getCStr(&StringOffset);
if (S)
OS << format("\"%s\"", S);
OS << "\n";
}
}
}
void DWARFContext::dump(raw_ostream &OS, DIDumpOptions DumpOpts){
DIDumpType DumpType = DumpOpts.DumpType;
@ -258,17 +375,15 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpOptions DumpOpts){
true /* GnuStyle */)
.dump("debug_gnu_pubtypes", OS);
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));
}
if (DumpType == DIDT_All || DumpType == DIDT_StrOffsets)
dumpStringOffsetsSection(OS, "debug_str_offsets", getStringOffsetSection(),
getStringSection(), isLittleEndian(),
getMaxVersion());
if (DumpType == DIDT_All || DumpType == DIDT_StrOffsetsDwo) {
dumpStringOffsetsSection(OS, "debug_str_offsets.dwo",
getStringOffsetDWOSection(), getStringDWOSection(),
isLittleEndian(), getMaxVersion());
}
if ((DumpType == DIDT_All || DumpType == DIDT_GdbIndex) &&
@ -1109,6 +1224,10 @@ DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
TypesDWOSections[Section].Data = data;
}
// Map platform specific debug section names to DWARF standard section
// names.
name = Obj.mapDebugSectionName(name);
if (RelocatedSection == Obj.section_end())
continue;
@ -1141,6 +1260,7 @@ DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
.Case("debug_loc", &LocSection.Relocs)
.Case("debug_info.dwo", &InfoDWOSection.Relocs)
.Case("debug_line", &LineSection.Relocs)
.Case("debug_str_offsets", &StringOffsetSection.Relocs)
.Case("debug_ranges", &RangeSection.Relocs)
.Case("debug_addr", &AddrSection.Relocs)
.Case("apple_names", &AppleNamesSection.Relocs)
@ -1211,6 +1331,7 @@ StringRef *DWARFContextInMemory::MapSectionToMember(StringRef Name) {
.Case("debug_frame", &DebugFrameSection)
.Case("eh_frame", &EHFrameSection)
.Case("debug_str", &StringSection)
.Case("debug_str_offsets", &StringOffsetSection.Data)
.Case("debug_ranges", &RangeSection.Data)
.Case("debug_macinfo", &MacinfoSection)
.Case("debug_pubnames", &PubNamesSection)
@ -1222,7 +1343,7 @@ StringRef *DWARFContextInMemory::MapSectionToMember(StringRef Name) {
.Case("debug_loc.dwo", &LocDWOSection.Data)
.Case("debug_line.dwo", &LineDWOSection.Data)
.Case("debug_str.dwo", &StringDWOSection)
.Case("debug_str_offsets.dwo", &StringOffsetDWOSection)
.Case("debug_str_offsets.dwo", &StringOffsetDWOSection.Data)
.Case("debug_addr", &AddrSection.Data)
.Case("apple_names", &AppleNamesSection.Data)
.Case("apple_types", &AppleTypesSection.Data)

View File

@ -301,6 +301,7 @@ bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const {
return (FC == FC_Address);
case DW_FORM_GNU_str_index:
case DW_FORM_GNU_strp_alt:
case DW_FORM_strx:
return (FC == FC_String);
case DW_FORM_implicit_const:
return (FC == FC_Constant);
@ -415,6 +416,7 @@ bool DWARFFormValue::extractValue(const DataExtractor &Data,
break;
case DW_FORM_GNU_addr_index:
case DW_FORM_GNU_str_index:
case DW_FORM_strx:
Value.uval = Data.getULEB128(OffsetPtr);
break;
default:
@ -542,6 +544,7 @@ void DWARFFormValue::dump(raw_ostream &OS) const {
OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)UValue);
dumpString(OS);
break;
case DW_FORM_strx:
case DW_FORM_GNU_str_index:
OS << format(" indexed (%8.8x) string = ", (uint32_t)UValue);
dumpString(OS);
@ -620,10 +623,11 @@ Optional<const char *> DWARFFormValue::getAsCString() const {
if (Form == DW_FORM_GNU_strp_alt || U == nullptr)
return None;
uint32_t Offset = Value.uval;
if (Form == DW_FORM_GNU_str_index) {
uint32_t StrOffset;
if (Form == DW_FORM_GNU_str_index || Form == DW_FORM_strx) {
uint64_t StrOffset;
if (!U->getStringOffsetSectionItem(Offset, StrOffset))
return None;
StrOffset += U->getStringOffsetSectionRelocation(Offset);
Offset = StrOffset;
}
if (const char *Str = U->getStringExtractor().getCStr(&Offset)) {

View File

@ -33,8 +33,9 @@ using namespace dwarf;
void DWARFUnitSectionBase::parse(DWARFContext &C, const DWARFSection &Section) {
parseImpl(C, Section, C.getDebugAbbrev(), &C.getRangeSection(),
C.getStringSection(), StringRef(), &C.getAddrSection(),
C.getLineSection().Data, C.isLittleEndian(), false);
C.getStringSection(), C.getStringOffsetSection(),
&C.getAddrSection(), C.getLineSection().Data, C.isLittleEndian(),
false);
}
void DWARFUnitSectionBase::parseDWO(DWARFContext &C,
@ -48,19 +49,14 @@ void DWARFUnitSectionBase::parseDWO(DWARFContext &C,
DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section,
const DWARFDebugAbbrev *DA, const DWARFSection *RS,
StringRef SS, StringRef SOS, const DWARFSection *AOS,
StringRef LS, bool LE, bool IsDWO,
StringRef SS, const DWARFSection &SOS,
const DWARFSection *AOS, StringRef LS, bool LE, bool IsDWO,
const DWARFUnitSectionBase &UnitSection,
const DWARFUnitIndex::Entry *IndexEntry)
: Context(DC), InfoSection(Section), Abbrev(DA), RangeSection(RS),
LineSection(LS), StringSection(SS), StringOffsetSection([&]() {
if (IndexEntry)
if (const auto *C = IndexEntry->getOffset(DW_SECT_STR_OFFSETS))
return SOS.slice(C->Offset, C->Offset + C->Length);
return SOS;
}()),
AddrOffsetSection(AOS), isLittleEndian(LE), isDWO(IsDWO),
UnitSection(UnitSection), IndexEntry(IndexEntry) {
LineSection(LS), StringSection(SS), StringOffsetSection(SOS),
StringOffsetSectionBase(0), AddrOffsetSection(AOS), isLittleEndian(LE),
isDWO(IsDWO), UnitSection(UnitSection), IndexEntry(IndexEntry) {
clear();
}
@ -77,17 +73,25 @@ bool DWARFUnit::getAddrOffsetSectionItem(uint32_t Index,
}
bool DWARFUnit::getStringOffsetSectionItem(uint32_t Index,
uint32_t &Result) const {
// FIXME: string offset section entries are 8-byte for DWARF64.
const uint32_t ItemSize = 4;
uint32_t Offset = Index * ItemSize;
if (StringOffsetSection.size() < Offset + ItemSize)
uint64_t &Result) const {
unsigned ItemSize = getFormat() == DWARF64 ? 8 : 4;
uint32_t Offset = StringOffsetSectionBase + Index * ItemSize;
if (StringOffsetSection.Data.size() < Offset + ItemSize)
return false;
DataExtractor DA(StringOffsetSection, isLittleEndian, 0);
Result = DA.getU32(&Offset);
DataExtractor DA(StringOffsetSection.Data, isLittleEndian, 0);
Result = ItemSize == 4 ? DA.getU32(&Offset) : DA.getU64(&Offset);
return true;
}
uint64_t DWARFUnit::getStringOffsetSectionRelocation(uint32_t Index) const {
unsigned ItemSize = getFormat() == DWARF64 ? 8 : 4;
uint64_t ByteOffset = StringOffsetSectionBase + Index * ItemSize;
RelocAddrMap::const_iterator AI = getStringOffsetsRelocMap().find(ByteOffset);
if (AI != getStringOffsetsRelocMap().end())
return AI->second.Value;
return 0;
}
bool DWARFUnit::extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) {
Length = debug_info.getU32(offset_ptr);
Version = debug_info.getU16(offset_ptr);
@ -119,6 +123,9 @@ bool DWARFUnit::extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) {
if (!LengthOK || !VersionOK || !AddrSizeOK)
return false;
// Keep track of the highest DWARF version we encounter across all units.
Context.setMaxVersionIfGreater(Version);
Abbrevs = Abbrev->getAbbreviationDeclarationSet(AbbrOffset);
return Abbrevs != nullptr;
}
@ -242,6 +249,17 @@ size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) {
setBaseAddress(*BaseAddr);
AddrOffsetSectionBase = toSectionOffset(UnitDie.find(DW_AT_GNU_addr_base), 0);
RangeSectionBase = toSectionOffset(UnitDie.find(DW_AT_rnglists_base), 0);
// In general, we derive the offset of the unit's contibution to the
// debug_str_offsets{.dwo} section from the unit DIE's
// DW_AT_str_offsets_base attribute. In dwp files we add to it the offset
// we get from the index table.
StringOffsetSectionBase =
toSectionOffset(UnitDie.find(DW_AT_str_offsets_base), 0);
if (IndexEntry)
if (const auto *C = IndexEntry->getOffset(DW_SECT_STR_OFFSETS))
StringOffsetSectionBase += C->Offset;
// Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for
// skeleton CU DIE, so that DWARF users not aware of it are not broken.
}

View File

@ -241,6 +241,9 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(const Triple &T) {
DwarfStrSection =
Ctx->getMachOSection("__DWARF", "__debug_str", MachO::S_ATTR_DEBUG,
SectionKind::getMetadata(), "info_string");
DwarfStrOffSection =
Ctx->getMachOSection("__DWARF", "__debug_str_offs", MachO::S_ATTR_DEBUG,
SectionKind::getMetadata(), "section_str_off");
DwarfLocSection =
Ctx->getMachOSection("__DWARF", "__debug_loc", MachO::S_ATTR_DEBUG,
SectionKind::getMetadata(), "section_debug_loc");
@ -557,6 +560,11 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T) {
DwarfAccelTypesSection =
Ctx->getELFSection(".apple_types", ELF::SHT_PROGBITS, 0);
// String Offset and Address Sections
DwarfStrOffSection =
Ctx->getELFSection(".debug_str_offsets", DebugSecType, 0);
DwarfAddrSection = Ctx->getELFSection(".debug_addr", DebugSecType, 0);
// Fission Sections
DwarfInfoDWOSection =
Ctx->getELFSection(".debug_info.dwo", DebugSecType, 0);
@ -573,7 +581,6 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T) {
Ctx->getELFSection(".debug_loc.dwo", DebugSecType, 0);
DwarfStrOffDWOSection =
Ctx->getELFSection(".debug_str_offsets.dwo", DebugSecType, 0);
DwarfAddrSection = Ctx->getELFSection(".debug_addr", DebugSecType, 0);
// DWP Sections
DwarfCUIndexSection =
@ -695,6 +702,11 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {
COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
COFF::IMAGE_SCN_MEM_READ,
SectionKind::getMetadata(), "info_string");
DwarfStrOffSection = Ctx->getCOFFSection(
".debug_str_offsets",
COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
COFF::IMAGE_SCN_MEM_READ,
SectionKind::getMetadata(), "section_str_off");
DwarfLocSection = Ctx->getCOFFSection(
".debug_loc",
COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
@ -749,7 +761,7 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {
".debug_str_offsets.dwo",
COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
COFF::IMAGE_SCN_MEM_READ,
SectionKind::getMetadata());
SectionKind::getMetadata(), "section_str_off_dwo");
DwarfAddrSection = Ctx->getCOFFSection(
".debug_addr",
COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |

View File

@ -4314,3 +4314,9 @@ ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer,
return make_error<GenericBinaryError>("Unrecognized MachO magic number",
object_error::invalid_file_type);
}
StringRef MachOObjectFile::mapDebugSectionName(StringRef Name) const {
return StringSwitch<StringRef>(Name)
.Case("debug_str_offs", "debug_str_offsets")
.Default(Name);
}

View File

@ -0,0 +1,277 @@
# Test object to verify that dwarfdump handles dwp files with DWARF v5 string
# offset tables. We have 2 CUs and 2 TUs, where it is assumed that
# CU1 and TU1 came from one object file, CU2 and TU2 from a second object
# file.
#
# To generate the test object:
# llvm-mc -triple x86_64-unknown-linux dwarfdump-str-offsets-dwp.s -filetype=obj \
# -o dwarfdump-str_offsets-dwp.x86_64.o
.section .debug_str.dwo,"MS",@progbits,1
str_producer:
.asciz "Handmade DWARF producer"
str_CU1:
.asciz "Compile_Unit_1"
str_CU1_dir:
.asciz "/home/test/CU1"
str_CU2:
.asciz "Compile_Unit_2"
str_CU2_dir:
.asciz "/home/test/CU2"
str_TU1:
.asciz "Type_Unit_1"
str_TU1_type:
.asciz "MyStruct_1"
str_TU2:
.asciz "Type_Unit_2"
str_TU2_type:
.asciz "MyStruct_2"
.section .debug_str_offsets.dwo,"",@progbits
# Object files 1's portion of the .debug_str_offsets.dwo section.
.debug_str_offsets_object_file1:
# CU1's contribution (from object file 1)
.debug_str_offsets_start_CU1:
.long .debug_str_offsets_end_CU1-.debug_str_offsets_base_CU1
.short 5 # DWARF version
.short 0 # Padding
.debug_str_offsets_base_CU1:
.long str_producer-.debug_str.dwo
.long str_CU1-.debug_str.dwo
.long str_CU1_dir-.debug_str.dwo
.debug_str_offsets_end_CU1:
# TU1's contribution (from object file 1)
.debug_str_offsets_start_TU1:
.long .debug_str_offsets_end_TU1-.debug_str_offsets_base_TU1
.short 5 # DWARF version
.short 0 # Padding
.debug_str_offsets_base_TU1:
.long str_TU1-.debug_str.dwo
.long str_TU1_type-.debug_str.dwo
.debug_str_offsets_end_TU1:
# Object files 2's portion of the .debug_str_offsets.dwo section.
.debug_str_offsets_object_file2:
# CU2's contribution (from object file 2)
.debug_str_offsets_start_CU2:
.long .debug_str_offsets_end_CU2-.debug_str_offsets_base_CU2
.short 5 # DWARF version
.short 0 # Padding
.debug_str_offsets_base_CU2:
.long str_producer-.debug_str.dwo
.long str_CU2-.debug_str.dwo
.long str_CU2_dir-.debug_str.dwo
.debug_str_offsets_end_CU2:
# TU2's contribution (from object file 2)
.debug_str_offsets_start_TU2:
.long .debug_str_offsets_end_TU2-.debug_str_offsets_base_TU2
.short 5 # DWARF version
.short 0 # Padding
.debug_str_offsets_base_TU2:
.long str_TU2-.debug_str.dwo
.long str_TU2_type-.debug_str.dwo
.debug_str_offsets_end_TU2:
# Abbrevs are shared for all compile and type units
.section .debug_abbrev.dwo,"",@progbits
.byte 0x01 # Abbrev code
.byte 0x11 # DW_TAG_compile_unit
.byte 0x00 # DW_CHILDREN_no
.byte 0x25 # DW_AT_producer
.byte 0x1a # DW_FORM_strx
.byte 0x03 # DW_AT_name
.byte 0x1a # DW_FORM_strx
.byte 0x72 # DW_AT_str_offsets_base
.byte 0x17 # DW_FORM_sec_offset
.byte 0x03 # DW_AT_name
.byte 0x1a # DW_FORM_strx
.byte 0x00 # EOM(1)
.byte 0x00 # EOM(2)
.byte 0x02 # Abbrev code
.byte 0x41 # DW_TAG_type_unit
.byte 0x01 # DW_CHILDREN_yes
.byte 0x03 # DW_AT_name
.byte 0x1a # DW_FORM_strx
.byte 0x72 # DW_AT_str_offsets_base
.byte 0x17 # DW_FORM_sec_offset
.byte 0x00 # EOM(1)
.byte 0x00 # EOM(2)
.byte 0x03 # Abbrev code
.byte 0x13 # DW_TAG_structure_type
.byte 0x00 # DW_CHILDREN_no (no members)
.byte 0x03 # DW_AT_name
.byte 0x1a # DW_FORM_strx
.byte 0x00 # EOM(1)
.byte 0x00 # EOM(2)
.byte 0x00 # EOM(3)
abbrev_end:
.section .debug_info.dwo,"",@progbits
# DWARF v5 CU header.
CU1_5_start:
.long CU1_5_end-CU1_5_version # Length of Unit
CU1_5_version:
.short 5 # DWARF version number
.byte 1 # DWARF Unit Type
.byte 8 # Address Size (in bytes)
.long .debug_abbrev.dwo # Offset Into Abbrev. Section
# The compile-unit DIE, which has a DW_AT_producer, DW_AT_name,
# DW_AT_str_offsets and DW_AT_compdir.
.byte 1 # Abbreviation code
.byte 0 # The index of the producer string
.byte 1 # The index of the CU name string
# The DW_AT_str_offsets_base attribute for CU1 contains the offset of CU1's
# contribution relative to the start of object file 1's portion of the
# .debug_str_offsets section.
.long .debug_str_offsets_base_CU1-.debug_str_offsets_object_file1
.byte 2 # The index of the comp dir string
.byte 0 # NULL
CU1_5_end:
CU2_5_start:
.long CU2_5_end-CU2_5_version # Length of Unit
CU2_5_version:
.short 5 # DWARF version number
.byte 1 # DWARF Unit Type
.byte 8 # Address Size (in bytes)
.long .debug_abbrev.dwo # Offset Into Abbrev. Section
# The compile-unit DIE, which has a DW_AT_producer, DW_AT_name,
# DW_AT_str_offsets and DW_AT_compdir.
.byte 1 # Abbreviation code
.byte 0 # The index of the producer string
.byte 1 # The index of the CU name string
# The DW_AT_str_offsets_base attribute for CU2 contains the offset of CU2's
# contribution relative to the start of object file 2's portion of the
# .debug_str_offsets section.
.long .debug_str_offsets_base_CU2-.debug_str_offsets_object_file2
.byte 2 # The index of the comp dir string
.byte 0 # NULL
CU2_5_end:
.section .debug_types.dwo,"",@progbits
# DWARF v5 Type unit header.
TU1_5_start:
.long TU1_5_end-TU1_5_version # Length of Unit
TU1_5_version:
.short 5 # DWARF version number
.byte 2 # DWARF Unit Type
.byte 8 # Address Size (in bytes)
.long .debug_abbrev.dwo # Offset Into Abbrev. Section
.quad 0x0011223344556677 # Type Signature
.long TU1_5_type-TU1_5_start # Type offset
# The type-unit DIE, which has a name.
.byte 2 # Abbreviation code
.byte 0 # Index of the unit type name string
# The DW_AT_str_offsets_base attribute for TU1 contains the offset of TU1's
# contribution relative to the start of object file 1's portion of the
# .debug_str_offsets section.
.long .debug_str_offsets_base_TU1-.debug_str_offsets_object_file1
# The type DIE, which has a name.
TU1_5_type:
.byte 3 # Abbreviation code
.byte 1 # Index of the type name string
.byte 0 # NULL
.byte 0 # NULL
TU1_5_end:
TU2_5_start:
.long TU2_5_end-TU2_5_version # Length of Unit
TU2_5_version:
.short 5 # DWARF version number
.byte 2 # DWARF Unit Type
.byte 8 # Address Size (in bytes)
.long .debug_abbrev.dwo # Offset Into Abbrev. Section
.quad 0x00aabbccddeeff99 # Type Signature
.long TU2_5_type-TU2_5_start # Type offset
# The type-unit DIE, which has a name.
.byte 2 # Abbreviation code
.byte 0 # Index of the unit type name string
# The DW_AT_str_offsets_base attribute for TU2 contains the offset of TU2's
# contribution relative to the start of object file 2's portion of the
# .debug_str_offsets section.
.long .debug_str_offsets_base_TU2-.debug_str_offsets_object_file2
# The type DIE, which has a name.
TU2_5_type:
.byte 3 # Abbreviation code
.byte 1 # Index of the type name string
.byte 0 # NULL
.byte 0 # NULL
TU2_5_end:
.section .debug_cu_index,"",@progbits
# The index header
.long 2 # Version
.long 3 # Columns of contribution matrix
.long 2 # number of units
.long 2 # number of hash buckets in table
# The signatures for both CUs.
.quad 0xddeeaaddbbaabbee # signature 1
.quad 0xff00ffeeffaaff00 # signature 2
# The indexes for both CUs.
.long 1 # index 1
.long 2 # index 2
# The sections to which both CUs contribute.
.long 1 # DW_SECT_INFO
.long 3 # DW_SECT_ABBREV
.long 6 # DW_SECT_STR_OFFSETS
# The starting offsets of both CU's contributions to info,
# abbrev and string offsets table.
.long CU1_5_start-.debug_info.dwo
.long 0
.long .debug_str_offsets_object_file1-.debug_str_offsets.dwo
.long CU2_5_start-.debug_info.dwo
.long 0
.long .debug_str_offsets_object_file2-.debug_str_offsets.dwo
# The lengths of both CU's contributions to info, abbrev and
# string offsets table.
.long CU1_5_end-CU1_5_start
.long abbrev_end-.debug_abbrev.dwo
.long .debug_str_offsets_end_CU1-.debug_str_offsets_start_CU1
.long CU2_5_end-CU2_5_start
.long abbrev_end-.debug_abbrev.dwo
.long .debug_str_offsets_end_CU2-.debug_str_offsets_start_CU2
.section .debug_tu_index,"",@progbits
# The index header
.long 2 # Version
.long 3 # Columns of contribution matrix
.long 2 # number of units
.long 2 # number of hash buckets in table
# The signatures for both TUs.
.quad 0xeeaaddbbaabbeedd # signature 1
.quad 0x00ffeeffaaff00ff # signature 2
# The indexes for both TUs.
.long 1 # index 1
.long 2 # index 2
# The sections to which both TUs contribute.
.long 2 # DW_SECT_TYPES
.long 3 # DW_SECT_ABBREV
.long 6 # DW_SECT_STR_OFFSETS
# The starting offsets of both TU's contributions to info,
# abbrev and string offsets table.
.long TU1_5_start-.debug_types.dwo
.long 0
.long .debug_str_offsets_object_file1-.debug_str_offsets.dwo
.long TU2_5_start-.debug_types.dwo
.long 0
.long .debug_str_offsets_object_file2-.debug_str_offsets.dwo
# The lengths of both TU's contributions to info, abbrev and
# string offsets table.
.long TU1_5_end-TU1_5_start
.long abbrev_end-.debug_abbrev.dwo
.long .debug_str_offsets_end_TU1-.debug_str_offsets_start_TU1
.long TU2_5_end-TU2_5_start
.long abbrev_end-.debug_abbrev.dwo
.long .debug_str_offsets_end_TU2-.debug_str_offsets_start_TU2

View File

@ -0,0 +1,34 @@
# Test object to verify that llvm-dwarfdump handles an invalid string offsets
# table.
#
# To generate the test object:
# llvm-mc -triple x86_64-unknown-linux dwarfdump-str-offsets-invalid-1.s -filetype=obj \
# -o dwarfdump-str-offsets-invalid-1.x86_64.o
#
# A rudimentary abbrev section.
.section .debug_abbrev,"",@progbits
.byte 0x01 # Abbrev code
.byte 0x11 # DW_TAG_compile_unit
.byte 0x00 # DW_CHILDREN_no
.byte 0x00 # EOM(1)
.byte 0x00 # EOM(2)
.byte 0x00 # EOM(3)
# A rudimentary compile unit to convince dwarfdump that we are dealing with a
# DWARF v5 string offsets table.
.section .debug_info,"",@progbits
# DWARF v5 CU header.
.long CU1_5_end-CU1_5_version # Length of Unit
CU1_5_version:
.short 5 # DWARF version number
.byte 1 # DWARF Unit Type
.byte 8 # Address Size (in bytes)
.long .debug_abbrev # Offset Into Abbrev. Section
# A compile-unit DIE, which has no attributes.
.byte 1 # Abbreviation code
CU1_5_end:
.section .debug_str_offsets,"",@progbits
# A degenerate section, not enough for a single contribution size.
.byte 2

View File

@ -0,0 +1,36 @@
# Test object to verify that llvm-dwarfdump handles an invalid string offsets
# table.
#
# To generate the test object:
# llvm-mc -triple x86_64-unknown-linux dwarfdump-str-offsets-invalid-2.s -filetype=obj \
# -o dwarfdump-str-offsets-invalid-2.x86_64.o
# A rudimentary abbrev section.
.section .debug_abbrev,"",@progbits
.byte 0x01 # Abbrev code
.byte 0x11 # DW_TAG_compile_unit
.byte 0x00 # DW_CHILDREN_no
.byte 0x00 # EOM(1)
.byte 0x00 # EOM(2)
.byte 0x00 # EOM(3)
# A rudimentary compile unit to convince dwarfdump that we are dealing with a
# DWARF v5 string offsets table.
.section .debug_info,"",@progbits
# DWARF v5 CU header.
.long CU1_5_end-CU1_5_version # Length of Unit
CU1_5_version:
.short 5 # DWARF version number
.byte 1 # DWARF Unit Type
.byte 8 # Address Size (in bytes)
.long .debug_abbrev # Offset Into Abbrev. Section
# A compile-unit DIE, which has no attributes.
.byte 1 # Abbreviation code
CU1_5_end:
.section .debug_str_offsets,"",@progbits
# A degenerate section with fewer bytes than required for a DWARF64 size.
.long 0xffffffff
.long 0
.short 4

View File

@ -0,0 +1,88 @@
# Test object to verify that llvm-dwarfdump handles an invalid string offsets
# table.
#
# To generate the test object:
# llvm-mc -triple x86_64-unknown-linux dwarfdump-str-offsets-invalid-3.s -filetype=obj \
# -o dwarfdump-str-offsets-invalid-3.x86_64.o
.section .debug_str,"MS",@progbits,1
str_producer:
.asciz "Handmade DWARF producer"
str_CU1:
.asciz "Compile_Unit_1"
str_CU1_dir:
.asciz "/home/test/CU1"
str_CU2:
.asciz "Compile_Unit_2"
str_CU2_dir:
.asciz "/home/test/CU2"
str_TU:
.asciz "Type_Unit"
str_TU_type:
.asciz "MyStruct"
.section .debug_str.dwo,"MS",@progbits,1
dwo_str_CU_5_producer:
.asciz "Handmade split DWARF producer"
dwo_str_CU_5_name:
.asciz "V5_split_compile_unit"
dwo_str_CU_5_comp_dir:
.asciz "/home/test/splitCU"
dwo_str_TU_5:
.asciz "V5_split_type_unit"
dwo_str_TU_5_type:
.asciz "V5_split_Mystruct"
# A rudimentary abbrev section.
.section .debug_abbrev,"",@progbits
.byte 0x01 # Abbrev code
.byte 0x11 # DW_TAG_compile_unit
.byte 0x00 # DW_CHILDREN_no
.byte 0x00 # EOM(1)
.byte 0x00 # EOM(2)
.byte 0x00 # EOM(3)
# A rudimentary compile unit to convince dwarfdump that we are dealing with a
# DWARF v5 string offsets table.
.section .debug_info,"",@progbits
# DWARF v5 CU header.
.long CU1_5_end-CU1_5_version # Length of Unit
CU1_5_version:
.short 5 # DWARF version number
.byte 1 # DWARF Unit Type
.byte 8 # Address Size (in bytes)
.long .debug_abbrev # Offset Into Abbrev. Section
# A compile-unit DIE, which has no attributes.
.byte 1 # Abbreviation code
CU1_5_end:
.section .debug_str_offsets,"",@progbits
# CU1's contribution
# Invalid length
.long 0xfffffffe
.long .debug_str_offsets_segment0_end-.debug_str_offsets_base0
.short 5 # DWARF version
.short 0 # Padding
.debug_str_offsets_base0:
.long str_producer
.long str_CU1
.long str_CU1_dir
.debug_str_offsets_segment0_end:
# CU2's contribution
.long .debug_str_offsets_segment1_end-.debug_str_offsets_base1
.short 5 # DWARF version
.short 0 # Padding
.debug_str_offsets_base1:
.long str_producer
.long str_CU2
.long str_CU2_dir
.debug_str_offsets_segment1_end:
# The TU's contribution
.long .debug_str_offsets_segment2_end-.debug_str_offsets_base2
.short 5 # DWARF version
.short 0 # Padding
.debug_str_offsets_base2:
.long str_TU
.long str_TU_type
.debug_str_offsets_segment2_end:

View File

@ -0,0 +1,50 @@
# Test object to verify that llvm-dwarfdump handles an invalid string offsets
# table.
#
# To generate the test object:
# llvm-mc -triple x86_64-unknown-linux dwarfdump-str-offsets-invalid-4.s -filetype=obj \
# -o dwarfdump-str-offsets-invalid-4.x86_64.o
.section .debug_str,"MS",@progbits,1
str_producer:
.asciz "Handmade DWARF producer"
str_CU1:
.asciz "Compile_Unit_1"
# A rudimentary abbrev section.
.section .debug_abbrev,"",@progbits
.byte 0x01 # Abbrev code
.byte 0x11 # DW_TAG_compile_unit
.byte 0x00 # DW_CHILDREN_no
.byte 0x00 # EOM(1)
.byte 0x00 # EOM(2)
.byte 0x00 # EOM(3)
# A rudimentary compile unit to convince dwarfdump that we are dealing with a
# DWARF v5 string offsets table.
.section .debug_info,"",@progbits
# DWARF v5 CU header.
.long CU1_5_end-CU1_5_version # Length of Unit
CU1_5_version:
.short 5 # DWARF version number
.byte 1 # DWARF Unit Type
.byte 8 # Address Size (in bytes)
.long .debug_abbrev # Offset Into Abbrev. Section
# A compile-unit DIE, which has no attributes.
.byte 1 # Abbreviation code
CU1_5_end:
# Every unit contributes to the string_offsets table.
.section .debug_str_offsets,"",@progbits
# CU1's contribution
# The length is not a multiple of 4. Check that we don't read off the
# end.
.long .debug_str_offsets_segment0_end-.debug_str_offsets_base0
.short 5 # DWARF version
.short 0 # Padding
.debug_str_offsets_base0:
.long str_producer
.long str_CU1
.byte 0
.debug_str_offsets_segment0_end:

View File

@ -0,0 +1,10 @@
# Test object to verify that llvm-dwarfdump handles a degenerate string offsets
# section.
#
# To generate the test object:
# llvm-mc -triple x86_64-unknown-linux dwarfdump-str-offsets-invalid-5.s -filetype=obj \
# -o dwarfdump-str-offsets-invalid-5.x86_64.o
# Every unit contributes to the string_offsets table.
.section .debug_str_offsets,"",@progbits
# A degenerate section, not enough for a single entry.
.byte 2

View File

@ -0,0 +1,500 @@
# Test object to verify dwarfdump handles v5 string offset tables.
# We have 2 v5 CUs, a v5 TU, and a split v5 CU and TU.
#
# To generate the test object:
# llvm-mc -triple x86_64-unknown-linux dwarfdump-str-offsets.s -filetype=obj \
# -o dwarfdump-str-offsets.x86_64.o
.section .debug_str,"MS",@progbits,1
str_producer:
.asciz "Handmade DWARF producer"
str_CU1:
.asciz "Compile_Unit_1"
str_CU1_dir:
.asciz "/home/test/CU1"
str_CU2:
.asciz "Compile_Unit_2"
str_CU2_dir:
.asciz "/home/test/CU2"
str_TU:
.asciz "Type_Unit"
str_TU_type:
.asciz "MyStruct"
# Every unit contributes to the string_offsets table.
.section .debug_str_offsets,"",@progbits
# CU1's contribution
.long .debug_str_offsets_segment0_end-.debug_str_offsets_base0
.short 5 # DWARF version
.short 0 # Padding
.debug_str_offsets_base0:
.long str_producer
.long str_CU1
.long str_CU1_dir
.debug_str_offsets_segment0_end:
# CU2's contribution
.long .debug_str_offsets_segment1_end-.debug_str_offsets_base1
.short 5 # DWARF version
.short 0 # Padding
.debug_str_offsets_base1:
.long str_producer
.long str_CU2
.long str_CU2_dir
.debug_str_offsets_segment1_end:
# The TU's contribution
.long .debug_str_offsets_segment2_end-.debug_str_offsets_base2
.short 5 # DWARF version
.short 0 # Padding
.debug_str_offsets_base2:
.long str_TU
.long str_TU_type
.debug_str_offsets_segment2_end:
.section .debug_str.dwo,"MS",@progbits,1
dwo_str_CU_5_producer:
.asciz "Handmade split DWARF producer"
dwo_str_CU_5_name:
.asciz "V5_split_compile_unit"
dwo_str_CU_5_comp_dir:
.asciz "/home/test/splitCU"
dwo_str_TU_5:
.asciz "V5_split_type_unit"
dwo_str_TU_5_type:
.asciz "V5_split_Mystruct"
.section .debug_str_offsets.dwo,"",@progbits
# The split CU's contribution
.long .debug_dwo_str_offsets_segment0_end-.debug_dwo_str_offsets_base0
.short 5 # DWARF version
.short 0 # Padding
.debug_dwo_str_offsets_base0:
.long dwo_str_CU_5_producer-.debug_str.dwo
.long dwo_str_CU_5_name-.debug_str.dwo
.long dwo_str_CU_5_comp_dir-.debug_str.dwo
.debug_dwo_str_offsets_segment0_end:
# The split TU's contribution
.long .debug_dwo_str_offsets_segment1_end-.debug_dwo_str_offsets_base1
.short 5 # DWARF version
.short 0 # Padding
.debug_dwo_str_offsets_base1:
.long dwo_str_TU_5-.debug_str.dwo
.long dwo_str_TU_5_type-.debug_str.dwo
.debug_dwo_str_offsets_segment1_end:
# All CUs/TUs use the same abbrev section for simplicity.
.section .debug_abbrev,"",@progbits
.byte 0x01 # Abbrev code
.byte 0x11 # DW_TAG_compile_unit
.byte 0x00 # DW_CHILDREN_no
.byte 0x25 # DW_AT_producer
.byte 0x1a # DW_FORM_strx
.byte 0x03 # DW_AT_name
.byte 0x1a # DW_FORM_strx
.byte 0x72 # DW_AT_str_offsets_base
.byte 0x17 # DW_FORM_sec_offset
.byte 0x1b # DW_AT_comp_dir
.byte 0x1a # DW_FORM_strx
.byte 0x00 # EOM(1)
.byte 0x00 # EOM(2)
.byte 0x02 # Abbrev code
.byte 0x41 # DW_TAG_type_unit
.byte 0x01 # DW_CHILDREN_yes
.byte 0x03 # DW_AT_name
.byte 0x1a # DW_FORM_strx
.byte 0x72 # DW_AT_str_offsets_base
.byte 0x17 # DW_FORM_sec_offset
.byte 0x00 # EOM(1)
.byte 0x00 # EOM(2)
.byte 0x03 # Abbrev code
.byte 0x13 # DW_TAG_structure_type
.byte 0x00 # DW_CHILDREN_no (no members)
.byte 0x03 # DW_AT_name
.byte 0x1a # DW_FORM_strx
.byte 0x00 # EOM(1)
.byte 0x00 # EOM(2)
.byte 0x00 # EOM(3)
# And a .dwo copy for the .dwo sections.
.section .debug_abbrev.dwo,"",@progbits
.byte 0x01 # Abbrev code
.byte 0x11 # DW_TAG_compile_unit
.byte 0x00 # DW_CHILDREN_no
.byte 0x25 # DW_AT_producer
.byte 0x1a # DW_FORM_strx
.byte 0x03 # DW_AT_name
.byte 0x1a # DW_FORM_strx
.byte 0x72 # DW_AT_str_offsets_base
.byte 0x17 # DW_FORM_sec_offset
.byte 0x1b # DW_AT_comp_dir
.byte 0x1a # DW_FORM_strx
.byte 0x00 # EOM(1)
.byte 0x00 # EOM(2)
.byte 0x02 # Abbrev code
.byte 0x41 # DW_TAG_type_unit
.byte 0x01 # DW_CHILDREN_yes
.byte 0x03 # DW_AT_name
.byte 0x1a # DW_FORM_strx
.byte 0x72 # DW_AT_str_offsets_base
.byte 0x17 # DW_FORM_sec_offset
.byte 0x00 # EOM(1)
.byte 0x00 # EOM(2)
.byte 0x03 # Abbrev code
.byte 0x13 # DW_TAG_structure_type
.byte 0x00 # DW_CHILDREN_no (no members)
.byte 0x03 # DW_AT_name
.byte 0x1a # DW_FORM_strx
.byte 0x00 # EOM(1)
.byte 0x00 # EOM(2)
.byte 0x00 # EOM(3)
.section .debug_info,"",@progbits
# DWARF v5 CU header.
.long CU1_5_end-CU1_5_version # Length of Unit
CU1_5_version:
.short 5 # DWARF version number
.byte 1 # DWARF Unit Type
.byte 8 # Address Size (in bytes)
.long .debug_abbrev # Offset Into Abbrev. Section
# The compile-unit DIE, which has a DW_AT_producer, DW_AT_name,
# DW_AT_str_offsets and DW_AT_compdir.
.byte 1 # Abbreviation code
.byte 0 # The index of the producer string
.byte 1 # The index of the CU name string
.long .debug_str_offsets_base0
.byte 2 # The index of the comp dir string
.byte 0 # NULL
CU1_5_end:
# DWARF v5 CU header
.long CU2_5_end-CU2_5_version # Length of Unit
CU2_5_version:
.short 5 # DWARF version number
.byte 1 # DWARF Unit Type
.byte 8 # Address Size (in bytes)
.long .debug_abbrev # Offset Into Abbrev. Section
# The compile-unit DIE, which has a DW_AT_producer, DW_AT_name,
# DW_AT_str_offsets and DW_AT_compdir.
.byte 1 # Abbreviation code
.byte 0 # The index of the producer string
.byte 1 # The index of the CU name string
.long .debug_str_offsets_base1
.byte 2 # The index of the comp dir string
.byte 0 # NULL
CU2_5_end:
.section .debug_types,"",@progbits
# DWARF v5 Type unit header.
TU_5_start:
.long TU_5_end-TU_5_version # Length of Unit
TU_5_version:
.short 5 # DWARF version number
.byte 2 # DWARF Unit Type
.byte 8 # Address Size (in bytes)
.long .debug_abbrev # Offset Into Abbrev. Section
.quad 0x0011223344556677 # Type Signature
.long TU_5_type-TU_5_start # Type offset
# The type-unit DIE, which has a name.
.byte 2 # Abbreviation code
.byte 0 # Index of the unit type name string
.long .debug_str_offsets_base2 # offset into the str_offsets section
# The type DIE, which has a name.
TU_5_type:
.byte 3 # Abbreviation code
.byte 1 # Index of the type name string
.byte 0 # NULL
.byte 0 # NULL
TU_5_end:
.section .debug_info.dwo,"",@progbits
# DWARF v5 split CU header.
.long CU_split_5_end-CU_split_5_version # Length of Unit
CU_split_5_version:
.short 5 # DWARF version number
.byte 1 # DWARF Unit Type
.byte 8 # Address Size (in bytes)
.long .debug_abbrev.dwo # Offset Into Abbrev Section
# The compile-unit DIE, which has a DW_AT_producer, DW_AT_name,
# DW_AT_str_offsets and DW_AT_compdir.
.byte 1 # Abbreviation code
.byte 0 # The index of the producer string
.byte 1 # The index of the CU name string
.long .debug_dwo_str_offsets_base0-.debug_str_offsets.dwo
.byte 2 # The index of the comp dir string
.byte 0 # NULL
CU_split_5_end:
.section .debug_types.dwo,"",@progbits
# DWARF v5 split type unit header.
TU_split_5_start:
.long TU_split_5_end-TU_split_5_version # Length of Unit
TU_split_5_version:
.short 5 # DWARF version number
.byte 6 # DWARF Unit Type
.byte 8 # Address Size (in bytes)
.long .debug_abbrev.dwo # Offset Into Abbrev Section
.quad 0x8899aabbccddeeff # Type Signature
.long TU_split_5_type-TU_split_5_start # Type offset
# The type-unit DIE, which has a name.
.byte 2 # Abbreviation code
.byte 0 # The index of the type unit name string
.long .debug_dwo_str_offsets_base1-.debug_str_offsets.dwo
# The type DIE, which has a name.
TU_split_5_type:
.byte 3 # Abbreviation code
.byte 1 # The index of the type name string
.byte 0 # NULL
.byte 0 # NULL
TU_split_5_end:
# Test object to verify dwarfdump handles v5 string offset tables.
# We have 2 v5 CUs, a v5 TU, and a split v5 CU and TU.
#
# To generate the test object:
# llvm-mc -triple x86_64-unknown-linux dwarfdump-str-offsets.s -filetype=obj \
# -o dwarfdump-str-offsets.elf-x86-64
.section .debug_str,"MS",@progbits,1
str_producer:
.asciz "Handmade DWARF producer"
str_CU1:
.asciz "Compile_Unit_1"
str_CU1_dir:
.asciz "/home/test/CU1"
str_CU2:
.asciz "Compile_Unit_2"
str_CU2_dir:
.asciz "/home/test/CU2"
str_TU:
.asciz "Type_Unit"
str_TU_type:
.asciz "MyStruct"
# Every unit contributes to the string_offsets table.
.section .debug_str_offsets,"",@progbits
# CU1's contribution
.long .debug_str_offsets_segment0_end-.debug_str_offsets_base0
.short 5 # DWARF version
.short 0 # Padding
.debug_str_offsets_base0:
.long str_producer
.long str_CU1
.long str_CU1_dir
.debug_str_offsets_segment0_end:
# CU2's contribution
.long .debug_str_offsets_segment1_end-.debug_str_offsets_base1
.short 5 # DWARF version
.short 0 # Padding
.debug_str_offsets_base1:
.long str_producer
.long str_CU2
.long str_CU2_dir
.debug_str_offsets_segment1_end:
# The TU's contribution
.long .debug_str_offsets_segment2_end-.debug_str_offsets_base2
.short 5 # DWARF version
.short 0 # Padding
.debug_str_offsets_base2:
.long str_TU
.long str_TU_type
.debug_str_offsets_segment2_end:
.section .debug_str.dwo,"MS",@progbits,1
dwo_str_CU_5_producer:
.asciz "Handmade split DWARF producer"
dwo_str_CU_5_name:
.asciz "V5_split_compile_unit"
dwo_str_CU_5_comp_dir:
.asciz "/home/test/splitCU"
dwo_str_TU_5:
.asciz "V5_split_type_unit"
dwo_str_TU_5_type:
.asciz "V5_split_Mystruct"
.section .debug_str_offsets.dwo,"",@progbits
# The split CU's contribution
.long .debug_dwo_str_offsets_segment0_end-.debug_dwo_str_offsets_base0
.short 5 # DWARF version
.short 0 # Padding
.debug_dwo_str_offsets_base0:
.long dwo_str_CU_5_producer-.debug_str.dwo
.long dwo_str_CU_5_name-.debug_str.dwo
.long dwo_str_CU_5_comp_dir-.debug_str.dwo
.debug_dwo_str_offsets_segment0_end:
# The split TU's contribution
.long .debug_dwo_str_offsets_segment1_end-.debug_dwo_str_offsets_base1
.short 5 # DWARF version
.short 0 # Padding
.debug_dwo_str_offsets_base1:
.long dwo_str_TU_5-.debug_str.dwo
.long dwo_str_TU_5_type-.debug_str.dwo
.debug_dwo_str_offsets_segment1_end:
# All CUs/TUs use the same abbrev section for simplicity.
.section .debug_abbrev,"",@progbits
.byte 0x01 # Abbrev code
.byte 0x11 # DW_TAG_compile_unit
.byte 0x00 # DW_CHILDREN_no
.byte 0x25 # DW_AT_producer
.byte 0x1a # DW_FORM_strx
.byte 0x03 # DW_AT_name
.byte 0x1a # DW_FORM_strx
.byte 0x72 # DW_AT_str_offsets_base
.byte 0x17 # DW_FORM_sec_offset
.byte 0x1b # DW_AT_comp_dir
.byte 0x1a # DW_FORM_strx
.byte 0x00 # EOM(1)
.byte 0x00 # EOM(2)
.byte 0x02 # Abbrev code
.byte 0x41 # DW_TAG_type_unit
.byte 0x01 # DW_CHILDREN_yes
.byte 0x03 # DW_AT_name
.byte 0x1a # DW_FORM_strx
.byte 0x72 # DW_AT_str_offsets_base
.byte 0x17 # DW_FORM_sec_offset
.byte 0x00 # EOM(1)
.byte 0x00 # EOM(2)
.byte 0x03 # Abbrev code
.byte 0x13 # DW_TAG_structure_type
.byte 0x00 # DW_CHILDREN_no (no members)
.byte 0x03 # DW_AT_name
.byte 0x1a # DW_FORM_strx
.byte 0x00 # EOM(1)
.byte 0x00 # EOM(2)
.byte 0x00 # EOM(3)
# And a .dwo copy for the .dwo sections.
.section .debug_abbrev.dwo,"",@progbits
.byte 0x01 # Abbrev code
.byte 0x11 # DW_TAG_compile_unit
.byte 0x00 # DW_CHILDREN_no
.byte 0x25 # DW_AT_producer
.byte 0x1a # DW_FORM_strx
.byte 0x03 # DW_AT_name
.byte 0x1a # DW_FORM_strx
.byte 0x72 # DW_AT_str_offsets_base
.byte 0x17 # DW_FORM_sec_offset
.byte 0x1b # DW_AT_comp_dir
.byte 0x1a # DW_FORM_strx
.byte 0x00 # EOM(1)
.byte 0x00 # EOM(2)
.byte 0x02 # Abbrev code
.byte 0x41 # DW_TAG_type_unit
.byte 0x01 # DW_CHILDREN_yes
.byte 0x03 # DW_AT_name
.byte 0x1a # DW_FORM_strx
.byte 0x72 # DW_AT_str_offsets_base
.byte 0x17 # DW_FORM_sec_offset
.byte 0x00 # EOM(1)
.byte 0x00 # EOM(2)
.byte 0x03 # Abbrev code
.byte 0x13 # DW_TAG_structure_type
.byte 0x00 # DW_CHILDREN_no (no members)
.byte 0x03 # DW_AT_name
.byte 0x1a # DW_FORM_strx
.byte 0x00 # EOM(1)
.byte 0x00 # EOM(2)
.byte 0x00 # EOM(3)
.section .debug_info,"",@progbits
# DWARF v5 CU header.
.long CU1_5_end-CU1_5_version # Length of Unit
CU1_5_version:
.short 5 # DWARF version number
.byte 1 # DWARF Unit Type
.byte 8 # Address Size (in bytes)
.long .debug_abbrev # Offset Into Abbrev. Section
# The compile-unit DIE, which has a DW_AT_producer, DW_AT_name,
# DW_AT_str_offsets and DW_AT_compdir.
.byte 1 # Abbreviation code
.byte 0 # The index of the producer string
.byte 1 # The index of the CU name string
.long .debug_str_offsets_base0
.byte 2 # The index of the comp dir string
.byte 0 # NULL
CU1_5_end:
# DWARF v5 CU header
.long CU2_5_end-CU2_5_version # Length of Unit
CU2_5_version:
.short 5 # DWARF version number
.byte 1 # DWARF Unit Type
.byte 8 # Address Size (in bytes)
.long .debug_abbrev # Offset Into Abbrev. Section
# The compile-unit DIE, which has a DW_AT_producer, DW_AT_name,
# DW_AT_str_offsets and DW_AT_compdir.
.byte 1 # Abbreviation code
.byte 0 # The index of the producer string
.byte 1 # The index of the CU name string
.long .debug_str_offsets_base1
.byte 2 # The index of the comp dir string
.byte 0 # NULL
CU2_5_end:
.section .debug_types,"",@progbits
# DWARF v5 Type unit header.
TU_5_start:
.long TU_5_end-TU_5_version # Length of Unit
TU_5_version:
.short 5 # DWARF version number
.byte 2 # DWARF Unit Type
.byte 8 # Address Size (in bytes)
.long .debug_abbrev # Offset Into Abbrev. Section
.quad 0x0011223344556677 # Type Signature
.long TU_5_type-TU_5_start # Type offset
# The type-unit DIE, which has a name.
.byte 2 # Abbreviation code
.byte 0 # Index of the unit type name string
.long .debug_str_offsets_base2 # offset into the str_offsets section
# The type DIE, which has a name.
TU_5_type:
.byte 3 # Abbreviation code
.byte 1 # Index of the type name string
.byte 0 # NULL
.byte 0 # NULL
TU_5_end:
.section .debug_info.dwo,"",@progbits
# DWARF v5 split CU header.
.long CU_split_5_end-CU_split_5_version # Length of Unit
CU_split_5_version:
.short 5 # DWARF version number
.byte 1 # DWARF Unit Type
.byte 8 # Address Size (in bytes)
.long .debug_abbrev.dwo # Offset Into Abbrev Section
# The compile-unit DIE, which has a DW_AT_producer, DW_AT_name,
# DW_AT_str_offsets and DW_AT_compdir.
.byte 1 # Abbreviation code
.byte 0 # The index of the producer string
.byte 1 # The index of the CU name string
.long .debug_dwo_str_offsets_base0-.debug_str_offsets.dwo
.byte 2 # The index of the comp dir string
.byte 0 # NULL
CU_split_5_end:
.section .debug_types.dwo,"",@progbits
# DWARF v5 split type unit header.
TU_split_5_start:
.long TU_split_5_end-TU_split_5_version # Length of Unit
TU_split_5_version:
.short 5 # DWARF version number
.byte 6 # DWARF Unit Type
.byte 8 # Address Size (in bytes)
.long .debug_abbrev.dwo # Offset Into Abbrev Section
.quad 0x8899aabbccddeeff # Type Signature
.long TU_split_5_type-TU_split_5_start # Type offset
# The type-unit DIE, which has a name.
.byte 2 # Abbreviation code
.byte 0 # The index of the type unit name string
.long .debug_dwo_str_offsets_base1-.debug_str_offsets.dwo
# The type DIE, which has a name.
TU_split_5_type:
.byte 3 # Abbreviation code
.byte 1 # The index of the type name string
.byte 0 # NULL
.byte 0 # NULL
TU_split_5_end:

View File

@ -0,0 +1,24 @@
; Verify that llvm-dwarfdump handles invalid string offset tables.
RUN: llvm-dwarfdump %p/Inputs/dwarfdump-str-offsets-invalid-1.x86_64.o | \
RUN: FileCheck --check-prefix=INVALIDCONTRIB %s
RUN: llvm-dwarfdump %p/Inputs/dwarfdump-str-offsets-invalid-2.x86_64.o | \
RUN: FileCheck --check-prefix=INVALIDCONTRIB %s
RUN: llvm-dwarfdump %p/Inputs/dwarfdump-str-offsets-invalid-3.x86_64.o | \
RUN: FileCheck --check-prefix=INVALIDCONTRIB %s
RUN: llvm-dwarfdump %p/Inputs/dwarfdump-str-offsets-invalid-4.x86_64.o | \
RUN: FileCheck --check-prefix=INVALIDLENGTH %s
RUN: llvm-dwarfdump %p/Inputs/dwarfdump-str-offsets-invalid-5.x86_64.o | \
RUN: FileCheck --check-prefix=INVALIDSECTIONLENGTH %s
INVALIDCONTRIB: .debug_str_offsets contents:
INVALIDCONTRIB-NOT: contents:
INVALIDCONTRIB: error: invalid contribution to string offsets table in section .debug_str_offsets.
INVALIDLENGTH: .debug_str_offsets contents:
INVALIDLENGTH-NOT: contents:
INVALIDLENGTH: error: contribution to string offsets table in section .debug_str_offsets has invalid length.
INVALIDSECTIONLENGTH: .debug_str_offsets contents:
INVALIDSECTIONLENGTH-NOT: contents:
INVALIDSECTIONLENGTH: error: size of .debug_str_offsets is not a multiple of 4.

View File

@ -0,0 +1,76 @@
RUN: llvm-dwarfdump %p/Inputs/dwarfdump-str-offsets.x86_64.o | FileCheck %s
; We are using a hand-constructed object file and are interest in the correct
; diplay of the DW_str_offsetsbase attribute, the correct display of strings
; and the dump of the .debug_str_offsets[.dwo] table.
;
; Abbreviation for DW_AT_str_offsets_base
CHECK: .debug_abbrev contents:
CHECK-NOT: contents:
CHECK: DW_TAG_compile_unit
CHECK-NOT: DW_TAG
CHECK: DW_AT_str_offsets_base DW_FORM_sec_offset
; Verify that strings are displayed correctly as indexed strings
CHECK: .debug_info contents:
CHECK-NOT: contents:
CHECK: DW_TAG_compile_unit
CHECK-NEXT: DW_AT_producer [DW_FORM_strx] ( indexed (00000000) string = "Handmade DWARF producer")
CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000001) string = "Compile_Unit_1")
CHECK-NEXT: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x00000008)
CHECK-NEXT: DW_AT_comp_dir [DW_FORM_strx] ( indexed (00000002) string = "/home/test/CU1")
; Second compile unit (b.cpp)
CHECK: DW_TAG_compile_unit
CHECK-NEXT: DW_AT_producer [DW_FORM_strx] ( indexed (00000000) string = "Handmade DWARF producer")
CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000001) string = "Compile_Unit_2")
CHECK-NEXT: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x0000001c)
CHECK-NEXT: DW_AT_comp_dir [DW_FORM_strx] ( indexed (00000002) string = "/home/test/CU2")
; The split CU
CHECK: .debug_info.dwo contents:
CHECK-NOT: contents:
CHECK: DW_TAG_compile_unit
CHECK-NEXT: DW_AT_producer [DW_FORM_strx] ( indexed (00000000) string = "Handmade split DWARF producer")
CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000001) string = "V5_split_compile_unit")
CHECK-NEXT: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x00000008)
CHECK-NEXT: DW_AT_comp_dir [DW_FORM_strx] ( indexed (00000002) string = "/home/test/splitCU")
; The type unit
CHECK: .debug_types contents:
CHECK: DW_TAG_type_unit
CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000000) string = "Type_Unit")
CHECK-NEXT: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x00000030)
CHECK: DW_TAG_structure_type
CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000001) string = "MyStruct")
; The split type unit
CHECK: .debug_types.dwo contents:
CHECK: DW_TAG_type_unit
CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000000) string = "V5_split_type_unit")
CHECK-NEXT: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x0000001c)
CHECK: DW_TAG_structure_type
CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000001) string = "V5_split_Mystruct")
; The .debug_str_offsets section
CHECK: .debug_str_offsets contents:
CHECK-NEXT: 0x00000000: Contribution size = 12, Version = 5
CHECK-NEXT: 0x00000008: 00000000 "Handmade DWARF producer"
CHECK-NEXT: 0x0000000c: 00000018 "Compile_Unit_1"
CHECK-NEXT: 0x00000010: 00000027 "/home/test/CU1"
CHECK-NEXT: 0x00000014: Contribution size = 12, Version = 5
CHECK-NEXT: 0x0000001c: 00000000 "Handmade DWARF producer"
CHECK-NEXT: 0x00000020: 00000036 "Compile_Unit_2"
CHECK-NEXT: 0x00000024: 00000045 "/home/test/CU2"
CHECK-NEXT: 0x00000028: Contribution size = 8, Version = 5
CHECK-NEXT: 0x00000030: 00000054 "Type_Unit"
CHECK-NEXT: 0x00000034: 0000005e "MyStruct"
CHECK: .debug_str_offsets.dwo contents:
CHECK-NEXT: 0x00000000: Contribution size = 12, Version = 5
CHECK-NEXT: 0x00000008: 00000000 "Handmade split DWARF producer"
CHECK-NEXT: 0x0000000c: 0000001e "V5_split_compile_unit"
CHECK-NEXT: 0x00000010: 00000034 "/home/test/splitCU"
CHECK-NEXT: 0x00000014: Contribution size = 8, Version = 5
CHECK-NEXT: 0x0000001c: 00000047 "V5_split_type_unit"
CHECK-NEXT: 0x00000020: 0000005a "V5_split_Mystruct"

View File

@ -67,6 +67,7 @@ static cl::opt<DIDumpType> DumpType(
clEnumValN(DIDT_GnuPubnames, "gnu_pubnames", ".debug_gnu_pubnames"),
clEnumValN(DIDT_GnuPubtypes, "gnu_pubtypes", ".debug_gnu_pubtypes"),
clEnumValN(DIDT_Str, "str", ".debug_str"),
clEnumValN(DIDT_StrOffsets, "str_offsets", ".debug_str_offsets"),
clEnumValN(DIDT_StrDwo, "str.dwo", ".debug_str.dwo"),
clEnumValN(DIDT_StrOffsetsDwo, "str_offsets.dwo",
".debug_str_offsets.dwo"),

View File

@ -203,6 +203,7 @@ void dumpDebugInfo(DWARFContextInMemory &DCtx, DWARFYAML::Data &Y) {
case dwarf::DW_FORM_line_strp:
case dwarf::DW_FORM_strp_sup:
case dwarf::DW_FORM_GNU_str_index:
case dwarf::DW_FORM_strx:
if (auto Val = FormValue.getValue().getAsCStringOffset())
NewValue.Value = Val.getValue();
break;