[DWARFLinker][DWARFv5] Add support for .debug_rnglists.
This patch adds support of DWARFv5 .debug_rnglists table.
As DWARFLinker resolves relocations, it is able to always
use DW_FORM_addr instead of DW_FORM_addrx. DW_FORM_addrx
helps to minimize number of relocations, it is also used for
split DWARF. Both of these cases are not relevant for the
DWARFLinker. Thus, this patch converts all DW_FORM_addrx
forms into the DW_FORM_addr. And, as the result, it converts
range lists of DW_FORM_rnglistx form into the DW_FORM_sec_offset.
For the --update case all DW_FORM_addrx, DW_FORM_rnglistx
are preserved as is.
Reviewed By: aprantl
Differential Revision: https://reviews.llvm.org/D143903
GitOrigin-RevId: 1a50207f4ea575da2a3e861369227ce9f1d885e7
diff --git a/lib/DWARFLinker/DWARFStreamer.cpp b/lib/DWARFLinker/DWARFStreamer.cpp
index a34c407..3af7cde 100644
--- a/lib/DWARFLinker/DWARFStreamer.cpp
+++ b/lib/DWARFLinker/DWARFStreamer.cpp
@@ -108,6 +108,7 @@
Asm->setDwarfUsesRelocationsAcrossSections(false);
RangesSectionSize = 0;
+ RngListsSectionSize = 0;
LocSectionSize = 0;
LineSectionSize = 0;
FrameSectionSize = 0;
@@ -202,6 +203,9 @@
.Case("debug_frame", MC->getObjectFileInfo()->getDwarfFrameSection())
.Case("debug_aranges",
MC->getObjectFileInfo()->getDwarfARangesSection())
+ .Case("debug_addr", MC->getObjectFileInfo()->getDwarfAddrSection())
+ .Case("debug_rnglists",
+ MC->getObjectFileInfo()->getDwarfRnglistsSection())
.Default(nullptr);
if (Section) {
@@ -363,11 +367,13 @@
}
void DwarfStreamer::emitDwarfDebugRangesTableFragment(
- const CompileUnit &Unit, const AddressRanges &LinkedRanges) {
- unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
+ const CompileUnit &Unit, const AddressRanges &LinkedRanges,
+ PatchLocation Patch) {
+ Patch.set(RangesSectionSize);
// Make .debug_ranges to be current section.
MS->switchSection(MC->getObjectFileInfo()->getDwarfRangesSection());
+ unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
// Emit ranges.
uint64_t BaseAddress = 0;
@@ -390,27 +396,91 @@
RangesSectionSize += AddressSize;
}
-/// Emit the debug_aranges contribution of a unit and
-/// if \p DoDebugRanges is true the debug_range contents for a
-/// compile_unit level DW_AT_ranges attribute (Which are basically the
-/// same thing with a different base address).
-/// Just aggregate all the ranges gathered inside that unit.
-void DwarfStreamer::emitUnitRangesEntries(CompileUnit &Unit,
- bool DoDebugRanges) {
- const RangesTy &FunctionRanges = Unit.getFunctionRanges();
+MCSymbol *
+DwarfStreamer::emitDwarfDebugRangeListHeader(const CompileUnit &Unit) {
+ if (Unit.getOrigUnit().getVersion() < 5)
+ return nullptr;
- // Linked addresses might end up in a different order.
- // Build linked address ranges.
- AddressRanges LinkedRanges;
- for (const AddressRangeValuePair &Range : FunctionRanges)
- LinkedRanges.insert(
- {Range.Range.start() + Range.Value, Range.Range.end() + Range.Value});
+ // Make .debug_rnglists to be current section.
+ MS->switchSection(MC->getObjectFileInfo()->getDwarfRnglistsSection());
- if (!FunctionRanges.empty())
- emitDwarfDebugArangesTable(Unit, LinkedRanges);
+ MCSymbol *BeginLabel = Asm->createTempSymbol("Brnglists");
+ MCSymbol *EndLabel = Asm->createTempSymbol("Ernglists");
+ unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
- if (DoDebugRanges)
- emitDwarfDebugRangesTableFragment(Unit, LinkedRanges);
+ // Length
+ Asm->emitLabelDifference(EndLabel, BeginLabel, sizeof(uint32_t));
+ Asm->OutStreamer->emitLabel(BeginLabel);
+ RngListsSectionSize += sizeof(uint32_t);
+
+ // Version.
+ MS->emitInt16(5);
+ RngListsSectionSize += sizeof(uint16_t);
+
+ // Address size.
+ MS->emitInt8(AddressSize);
+ RngListsSectionSize++;
+
+ // Seg_size
+ MS->emitInt8(0);
+ RngListsSectionSize++;
+
+ // Offset entry count
+ MS->emitInt32(0);
+ RngListsSectionSize += sizeof(uint32_t);
+
+ return EndLabel;
+}
+
+void DwarfStreamer::emitDwarfDebugRangeListFragment(
+ const CompileUnit &Unit, const AddressRanges &LinkedRanges,
+ PatchLocation Patch) {
+ if (Unit.getOrigUnit().getVersion() < 5) {
+ emitDwarfDebugRangesTableFragment(Unit, LinkedRanges, Patch);
+ return;
+ }
+
+ emitDwarfDebugRngListsTableFragment(Unit, LinkedRanges, Patch);
+}
+
+void DwarfStreamer::emitDwarfDebugRangeListFooter(const CompileUnit &Unit,
+ MCSymbol *EndLabel) {
+ if (Unit.getOrigUnit().getVersion() < 5)
+ return;
+
+ // Make .debug_rnglists to be current section.
+ MS->switchSection(MC->getObjectFileInfo()->getDwarfRnglistsSection());
+
+ if (EndLabel != nullptr)
+ Asm->OutStreamer->emitLabel(EndLabel);
+}
+
+void DwarfStreamer::emitDwarfDebugRngListsTableFragment(
+ const CompileUnit &Unit, const AddressRanges &LinkedRanges,
+ PatchLocation Patch) {
+ Patch.set(RngListsSectionSize);
+
+ // Make .debug_rnglists to be current section.
+ MS->switchSection(MC->getObjectFileInfo()->getDwarfRnglistsSection());
+
+ unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
+
+ for (const AddressRange &Range : LinkedRanges) {
+ // Emit type of entry.
+ MS->emitInt8(dwarf::DW_RLE_start_length);
+ RngListsSectionSize += 1;
+
+ // Emit start address.
+ MS->emitIntValue(Range.start(), AddressSize);
+ RngListsSectionSize += AddressSize;
+
+ // Emit length of the range.
+ RngListsSectionSize += MS->emitSLEB128IntValue(Range.end() - Range.start());
+ }
+
+ // Emit the terminator entry.
+ MS->emitInt8(dwarf::DW_RLE_end_of_list);
+ RngListsSectionSize += 1;
}
/// Emit location lists for \p Unit and update attributes to point to the new