summaryrefslogtreecommitdiff
path: root/lib/DebugInfo/DWARF/DWARFContext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/DebugInfo/DWARF/DWARFContext.cpp')
-rw-r--r--lib/DebugInfo/DWARF/DWARFContext.cpp149
1 files changed, 135 insertions, 14 deletions
diff --git a/lib/DebugInfo/DWARF/DWARFContext.cpp b/lib/DebugInfo/DWARF/DWARFContext.cpp
index 1be156d6ea9b..42ab48808f9a 100644
--- a/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ b/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -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;
@@ -104,14 +221,14 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpOptions DumpOpts){
if (DumpType == DIDT_All || DumpType == DIDT_Info) {
OS << "\n.debug_info contents:\n";
for (const auto &CU : compile_units())
- CU->dump(OS);
+ CU->dump(OS, DumpOpts);
}
if ((DumpType == DIDT_All || DumpType == DIDT_InfoDwo) &&
getNumDWOCompileUnits()) {
OS << "\n.debug_info.dwo contents:\n";
for (const auto &DWOCU : dwo_compile_units())
- DWOCU->dump(OS);
+ DWOCU->dump(OS, DumpOpts);
}
if ((DumpType == DIDT_All || DumpType == DIDT_Types) && getNumTypeUnits()) {
@@ -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)