[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