summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/DebugInfo/DWARF/DWARFContext.cpp145
-rw-r--r--llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp8
-rw-r--r--llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp56
-rw-r--r--llvm/lib/MC/MCObjectFileInfo.cpp16
-rw-r--r--llvm/lib/Object/MachOObjectFile.cpp6
5 files changed, 196 insertions, 35 deletions
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
index 1be156d6ea9..a781aa1ca7d 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ b/llvm/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;
@@ -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)
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp b/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp
index 0963d7bfd71..8d23a9a438d 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp
@@ -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)) {
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
index c5add6a478b..eb138e28307 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
@@ -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.
}
diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp
index b685790910d..75aed850525 100644
--- a/llvm/lib/MC/MCObjectFileInfo.cpp
+++ b/llvm/lib/MC/MCObjectFileInfo.cpp
@@ -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 |
diff --git a/llvm/lib/Object/MachOObjectFile.cpp b/llvm/lib/Object/MachOObjectFile.cpp
index 084159a61f5..e8516369493 100644
--- a/llvm/lib/Object/MachOObjectFile.cpp
+++ b/llvm/lib/Object/MachOObjectFile.cpp
@@ -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);
+}
OpenPOWER on IntegriCloud