[llvm] 536f35e - [DWARFLinker][DWARFv5] Support debug_loclists.

Alexey Lapshin via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 15 03:51:21 PDT 2023


Author: Alexey Lapshin
Date: 2023-03-15T11:36:59+01:00
New Revision: 536f35ea62c62d9b28444b33d173d5f556945c90

URL: https://github.com/llvm/llvm-project/commit/536f35ea62c62d9b28444b33d173d5f556945c90
DIFF: https://github.com/llvm/llvm-project/commit/536f35ea62c62d9b28444b33d173d5f556945c90.diff

LOG: [DWARFLinker][DWARFv5] Support debug_loclists.

This patch adds support of DWARFv5 .debug_loclists 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
location lists of DW_FORM_loclistx form into the DW_FORM_sec_offset.
For the --update case all DW_FORM_addrx, DW_FORM_loclistx
are preserved as is.

Depends On D145499

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

Added: 
    llvm/test/tools/dsymutil/Inputs/dwarf5-loclists.o
    llvm/test/tools/dsymutil/X86/dwarf5-loclists.test
    llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-loclists.test

Modified: 
    llvm/include/llvm/DWARFLinker/DWARFLinker.h
    llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h
    llvm/include/llvm/DWARFLinker/DWARFStreamer.h
    llvm/lib/DWARFLinker/DWARFLinker.cpp
    llvm/lib/DWARFLinker/DWARFStreamer.cpp
    llvm/test/tools/dsymutil/X86/debug-loc-base-addr.test

Removed: 
    llvm/test/tools/llvm-dwarfutil/ELF/X86/warning-skipped-loclists.test


################################################################################
diff  --git a/llvm/include/llvm/DWARFLinker/DWARFLinker.h b/llvm/include/llvm/DWARFLinker/DWARFLinker.h
index ebfac89d4e670..f58bb3f6ec32b 100644
--- a/llvm/include/llvm/DWARFLinker/DWARFLinker.h
+++ b/llvm/include/llvm/DWARFLinker/DWARFLinker.h
@@ -117,19 +117,32 @@ class DwarfEmitter {
   virtual void
   emitAppleTypes(AccelTable<AppleAccelTableStaticTypeData> &Table) = 0;
 
-  /// Emit debug ranges(.debug_ranges, .debug_rnglists) header.
+  /// Emit debug ranges (.debug_ranges, .debug_rnglists) header.
   virtual MCSymbol *emitDwarfDebugRangeListHeader(const CompileUnit &Unit) = 0;
 
-  /// Emit debug ranges(.debug_ranges, .debug_rnglists) fragment.
+  /// Emit debug ranges (.debug_ranges, .debug_rnglists) fragment.
   virtual void
   emitDwarfDebugRangeListFragment(const CompileUnit &Unit,
                                   const AddressRanges &LinkedRanges,
                                   PatchLocation Patch) = 0;
 
-  /// Emit debug ranges(.debug_ranges, .debug_rnglists) footer.
+  /// Emit debug ranges (.debug_ranges, .debug_rnglists) footer.
   virtual void emitDwarfDebugRangeListFooter(const CompileUnit &Unit,
                                              MCSymbol *EndLabel) = 0;
 
+  /// Emit debug locations (.debug_loc, .debug_loclists) header.
+  virtual MCSymbol *emitDwarfDebugLocListHeader(const CompileUnit &Unit) = 0;
+
+  /// Emit debug locations (.debug_loc, .debug_loclists) fragment.
+  virtual void emitDwarfDebugLocListFragment(
+      const CompileUnit &Unit,
+      const DWARFLocationExpressionsVector &LinkedLocationExpression,
+      PatchLocation Patch) = 0;
+
+  /// Emit debug locations (.debug_loc, .debug_loclists) footer.
+  virtual void emitDwarfDebugLocListFooter(const CompileUnit &Unit,
+                                           MCSymbol *EndLabel) = 0;
+
   /// Emit .debug_aranges entries for \p Unit
   virtual void
   emitDwarfDebugArangesTable(const CompileUnit &Unit,
@@ -159,14 +172,6 @@ class DwarfEmitter {
   virtual void emitFDE(uint32_t CIEOffset, uint32_t AddreSize, uint64_t Address,
                        StringRef Bytes) = 0;
 
-  /// Emit the .debug_loc contribution for \p Unit by copying the entries from
-  /// \p Dwarf and offsetting them. Update the location attributes to point to
-  /// the new entries.
-  virtual void emitLocationsForUnit(
-      const CompileUnit &Unit, DWARFContext &Dwarf,
-      std::function<void(StringRef, SmallVectorImpl<uint8_t> &)>
-          ProcessExpr) = 0;
-
   /// Emit the compilation unit header for \p Unit in the
   /// .debug_info section.
   ///
@@ -207,6 +212,9 @@ class DwarfEmitter {
 
   /// Returns size of generated .debug_macro section.
   virtual uint64_t getDebugMacroSectionSize() const = 0;
+
+  /// Returns size of generated .debug_loclists section.
+  virtual uint64_t getLocListsSectionSize() const = 0;
 };
 
 using UnitListTy = std::vector<std::unique_ptr<CompileUnit>>;
@@ -738,6 +746,14 @@ class DWARFLinker {
   /// .debug_rnglists) for \p Unit, patch the attributes referencing it.
   void generateUnitRanges(CompileUnit &Unit, const DWARFFile &File) const;
 
+  using ExpressionHandlerRef = function_ref<void(SmallVectorImpl<uint8_t> &,
+                                                 SmallVectorImpl<uint8_t> &)>;
+
+  /// Compute and emit debug locations (.debug_loc, .debug_loclists)
+  /// for \p Unit, patch the attributes referencing it.
+  void generateUnitLocations(CompileUnit &Unit, const DWARFFile &File,
+                             ExpressionHandlerRef ExprHandler) const;
+
   /// Extract the line tables from the original dwarf, extract the relevant
   /// parts according to the linked function ranges and emit the result in the
   /// .debug_line section.

diff  --git a/llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h b/llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h
index 39305a3de8680..cfbd13414f703 100644
--- a/llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h
+++ b/llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h
@@ -44,6 +44,7 @@ struct PatchLocation {
 };
 
 using RngListAttributesTy = SmallVector<PatchLocation>;
+using LocListAttributesTy = SmallVector<std::pair<PatchLocation, int64_t>>;
 
 /// Stores all information relating to a compile unit, be it in its original
 /// instance in the object file to its brand new cloned and generated DIE tree.
@@ -153,8 +154,7 @@ class CompileUnit {
     return UnitRangeAttribute;
   }
 
-  const std::vector<std::pair<PatchLocation, int64_t>> &
-  getLocationAttributes() const {
+  const LocListAttributesTy &getLocationAttributes() const {
     return LocationAttributes;
   }
 
@@ -289,7 +289,7 @@ class CompileUnit {
   /// original debug_loc section to the liked one. They are stored
   /// along with the PC offset that is to be applied to their
   /// function's address.
-  std::vector<std::pair<PatchLocation, int64_t>> LocationAttributes;
+  LocListAttributesTy LocationAttributes;
 
   /// Accelerator entries for the unit, both for the pub*
   /// sections and the apple* ones.

diff  --git a/llvm/include/llvm/DWARFLinker/DWARFStreamer.h b/llvm/include/llvm/DWARFLinker/DWARFStreamer.h
index 69d1f9348449a..c96dd4007c23f 100644
--- a/llvm/include/llvm/DWARFLinker/DWARFStreamer.h
+++ b/llvm/include/llvm/DWARFLinker/DWARFStreamer.h
@@ -105,6 +105,19 @@ class DwarfStreamer : public DwarfEmitter {
   void emitDwarfDebugRangeListFooter(const CompileUnit &Unit,
                                      MCSymbol *EndLabel) override;
 
+  /// Emit debug locations(.debug_loc, .debug_loclists) header.
+  MCSymbol *emitDwarfDebugLocListHeader(const CompileUnit &Unit) override;
+
+  /// Emit debug ranges(.debug_loc, .debug_loclists) fragment.
+  void emitDwarfDebugLocListFragment(
+      const CompileUnit &Unit,
+      const DWARFLocationExpressionsVector &LinkedLocationExpression,
+      PatchLocation Patch) override;
+
+  /// Emit debug ranges(.debug_loc, .debug_loclists) footer.
+  void emitDwarfDebugLocListFooter(const CompileUnit &Unit,
+                                   MCSymbol *EndLabel) override;
+
   /// Emit .debug_aranges entries for \p Unit
   void emitDwarfDebugArangesTable(const CompileUnit &Unit,
                                   const AddressRanges &LinkedRanges) override;
@@ -115,14 +128,6 @@ class DwarfStreamer : public DwarfEmitter {
     return RngListsSectionSize;
   }
 
-  /// Emit the debug_loc contribution for \p Unit by copying the entries from
-  /// \p Dwarf and offsetting them. Update the location attributes to point to
-  /// the new entries.
-  void emitLocationsForUnit(
-      const CompileUnit &Unit, DWARFContext &Dwarf,
-      std::function<void(StringRef, SmallVectorImpl<uint8_t> &)> ProcessExpr)
-      override;
-
   /// Emit the line table described in \p Rows into the debug_line section.
   void emitLineTableForUnit(MCDwarfLineTableParams Params,
                             StringRef PrologueBytes, unsigned MinInstLength,
@@ -181,6 +186,10 @@ class DwarfStreamer : public DwarfEmitter {
     return MacroSectionSize;
   }
 
+  uint64_t getLocListsSectionSize() const override {
+    return LocListsSectionSize;
+  }
+
   void emitMacroTables(DWARFContext *Context,
                        const Offset2UnitMap &UnitMacroMap,
                        OffsetsStringPool &StringPool) override;
@@ -210,6 +219,18 @@ class DwarfStreamer : public DwarfEmitter {
                                            const AddressRanges &LinkedRanges,
                                            PatchLocation Patch);
 
+  /// Emit piece of .debug_loc for \p LinkedRanges.
+  void emitDwarfDebugLocTableFragment(
+      const CompileUnit &Unit,
+      const DWARFLocationExpressionsVector &LinkedLocationExpression,
+      PatchLocation Patch);
+
+  /// Emit piece of .debug_loclists for \p LinkedRanges.
+  void emitDwarfDebugLocListsTableFragment(
+      const CompileUnit &Unit,
+      const DWARFLocationExpressionsVector &LinkedLocationExpression,
+      PatchLocation Patch);
+
   /// \defgroup MCObjects MC layer objects constructed by the streamer
   /// @{
   std::unique_ptr<MCRegisterInfo> MRI;
@@ -234,6 +255,7 @@ class DwarfStreamer : public DwarfEmitter {
   uint64_t RangesSectionSize = 0;
   uint64_t RngListsSectionSize = 0;
   uint64_t LocSectionSize = 0;
+  uint64_t LocListsSectionSize = 0;
   uint64_t LineSectionSize = 0;
   uint64_t FrameSectionSize = 0;
   uint64_t DebugInfoSectionSize = 0;

diff  --git a/llvm/lib/DWARFLinker/DWARFLinker.cpp b/llvm/lib/DWARFLinker/DWARFLinker.cpp
index ae9fb16907356..980b7f9da86b5 100644
--- a/llvm/lib/DWARFLinker/DWARFLinker.cpp
+++ b/llvm/lib/DWARFLinker/DWARFLinker.cpp
@@ -1261,8 +1261,13 @@ unsigned DWARFLinker::DIECloner::cloneScalarAttribute(
     }
     if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value)
       Info.IsDeclaration = true;
-    Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr),
-                 dwarf::Form(AttrSpec.Form), DIEInteger(Value));
+
+    if (AttrSpec.Form == dwarf::DW_FORM_loclistx)
+      Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr),
+                   dwarf::Form(AttrSpec.Form), DIELocList(Value));
+    else
+      Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr),
+                   dwarf::Form(AttrSpec.Form), DIEInteger(Value));
     return AttrSize;
   }
 
@@ -1285,6 +1290,27 @@ unsigned DWARFLinker::DIECloner::cloneScalarAttribute(
       return 0;
     }
 
+    Value = *Offset;
+    AttrSpec.Form = dwarf::DW_FORM_sec_offset;
+    AttrSize = Unit.getOrigUnit().getFormParams().getDwarfOffsetByteSize();
+  } else if (AttrSpec.Form == dwarf::DW_FORM_loclistx) {
+    // DWARFLinker does not generate .debug_addr table. Thus we need to change
+    // all "addrx" related forms to "addr" version. Change DW_FORM_loclistx
+    // to DW_FORM_sec_offset here.
+    std::optional<uint64_t> Index = Val.getAsSectionOffset();
+    if (!Index) {
+      Linker.reportWarning("Cannot read the attribute. Dropping.", File,
+                           &InputDIE);
+      return 0;
+    }
+    std::optional<uint64_t> Offset =
+        Unit.getOrigUnit().getLoclistOffset(*Index);
+    if (!Offset) {
+      Linker.reportWarning("Cannot read the attribute. Dropping.", File,
+                           &InputDIE);
+      return 0;
+    }
+
     Value = *Offset;
     AttrSpec.Form = dwarf::DW_FORM_sec_offset;
     AttrSize = Unit.getOrigUnit().getFormParams().getDwarfOffsetByteSize();
@@ -1307,6 +1333,7 @@ unsigned DWARFLinker::DIECloner::cloneScalarAttribute(
         &InputDIE);
     return 0;
   }
+
   PatchLocation Patch =
       Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr),
                    dwarf::Form(AttrSpec.Form), DIEInteger(Value));
@@ -1314,13 +1341,10 @@ unsigned DWARFLinker::DIECloner::cloneScalarAttribute(
       AttrSpec.Attr == dwarf::DW_AT_start_scope) {
     Unit.noteRangeAttribute(Die, Patch);
     Info.HasRanges = true;
-  }
-  // A more generic way to check for location attributes would be
-  // nice, but it's very unlikely that any other attribute needs a
-  // location list.
-  // FIXME: use DWARFAttribute::mayHaveLocationDescription().
-  else if (AttrSpec.Attr == dwarf::DW_AT_location ||
-           AttrSpec.Attr == dwarf::DW_AT_frame_base) {
+  } else if (DWARFAttribute::mayHaveLocationList(AttrSpec.Attr) &&
+             dwarf::doesFormBelongToClass(AttrSpec.Form,
+                                          DWARFFormValue::FC_SectionOffset,
+                                          Unit.getOrigUnit().getVersion())) {
     Unit.noteLocationAttribute(Patch, Info.PCOffset);
   } else if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value)
     Info.IsDeclaration = true;
@@ -1383,6 +1407,7 @@ unsigned DWARFLinker::DIECloner::cloneAttribute(
   case dwarf::DW_FORM_flag:
   case dwarf::DW_FORM_flag_present:
   case dwarf::DW_FORM_rnglistx:
+  case dwarf::DW_FORM_loclistx:
     return cloneScalarAttribute(Die, InputDIE, File, Unit, AttrSpec, Val,
                                 AttrSize, Info);
   default:
@@ -1464,6 +1489,12 @@ static bool shouldSkipAttribute(
   case dwarf::DW_AT_str_offsets_base:
     // FIXME: Use the string offset table with Dwarf 5.
     return true;
+  case dwarf::DW_AT_loclists_base:
+    // In case !Update the .debug_addr table is not generated/preserved.
+    // Thus instead of DW_FORM_loclistx the DW_FORM_sec_offset is used.
+    // Since DW_AT_loclists_base is used for only DW_FORM_loclistx the
+    // DW_AT_loclists_base is removed.
+    return !Update;
   case dwarf::DW_AT_location:
   case dwarf::DW_AT_frame_base:
     // FIXME: for some reason dsymutil-classic keeps the location attributes
@@ -1732,6 +1763,61 @@ void DWARFLinker::generateUnitRanges(CompileUnit &Unit,
   }
 }
 
+void DWARFLinker::generateUnitLocations(
+    CompileUnit &Unit, const DWARFFile &File,
+    ExpressionHandlerRef ExprHandler) const {
+  if (LLVM_UNLIKELY(Options.Update))
+    return;
+
+  const LocListAttributesTy &AllLocListAttributes =
+      Unit.getLocationAttributes();
+
+  if (AllLocListAttributes.empty())
+    return;
+
+  // Emit locations list table header.
+  MCSymbol *EndLabel = TheDwarfEmitter->emitDwarfDebugLocListHeader(Unit);
+
+  for (auto &CurLocAttr : AllLocListAttributes) {
+    // Get location expressions vector corresponding to the current attribute
+    // from the source DWARF.
+    Expected<DWARFLocationExpressionsVector> OriginalLocations =
+        Unit.getOrigUnit().findLoclistFromOffset((CurLocAttr.first).get());
+
+    if (!OriginalLocations) {
+      llvm::consumeError(OriginalLocations.takeError());
+      reportWarning("Invalid location attribute ignored.", File);
+      continue;
+    }
+
+    DWARFLocationExpressionsVector LinkedLocationExpressions;
+    for (DWARFLocationExpression &CurExpression : *OriginalLocations) {
+
+      DWARFLocationExpression LinkedExpression;
+
+      if (CurExpression.Range) {
+        // Relocate address range.
+        LinkedExpression.Range = {
+            CurExpression.Range->LowPC + CurLocAttr.second,
+            CurExpression.Range->HighPC + CurLocAttr.second};
+      }
+
+      // Clone expression.
+      LinkedExpression.Expr.reserve(CurExpression.Expr.size());
+      ExprHandler(CurExpression.Expr, LinkedExpression.Expr);
+
+      LinkedLocationExpressions.push_back(LinkedExpression);
+    }
+
+    // Emit locations list table fragment corresponding to the CurLocAttr.
+    TheDwarfEmitter->emitDwarfDebugLocListFragment(
+        Unit, LinkedLocationExpressions, CurLocAttr.first);
+  }
+
+  // Emit locations list table footer.
+  TheDwarfEmitter->emitDwarfDebugLocListFooter(Unit, EndLabel);
+}
+
 /// Insert the new line info sequence \p Seq into the current
 /// set of already linked line info \p Rows.
 static void insertLineSequence(std::vector<DWARFDebugLine::Row> &Seq,
@@ -2314,17 +2400,17 @@ uint64_t DWARFLinker::DIECloner::cloneAllCompileUnits(
 
       Linker.generateUnitRanges(*CurrentUnit, File);
 
-      auto ProcessExpr = [&](StringRef Bytes,
-                             SmallVectorImpl<uint8_t> &Buffer) {
+      auto ProcessExpr = [&](SmallVectorImpl<uint8_t> &SrcBytes,
+                             SmallVectorImpl<uint8_t> &OutBytes) {
         DWARFUnit &OrigUnit = CurrentUnit->getOrigUnit();
-        DataExtractor Data(Bytes, IsLittleEndian,
+        DataExtractor Data(SrcBytes, IsLittleEndian,
                            OrigUnit.getAddressByteSize());
         cloneExpression(Data,
                         DWARFExpression(Data, OrigUnit.getAddressByteSize(),
                                         OrigUnit.getFormParams().Format),
-                        File, *CurrentUnit, Buffer);
+                        File, *CurrentUnit, OutBytes);
       };
-      Emitter->emitLocationsForUnit(*CurrentUnit, DwarfContext, ProcessExpr);
+      Linker.generateUnitLocations(*CurrentUnit, File, ProcessExpr);
     }
   }
 
@@ -2433,6 +2519,8 @@ void DWARFLinker::copyInvariantDebugSection(DWARFContext &Dwarf) {
       Dwarf.getDWARFObj().getAddrSection().Data, "debug_addr");
   TheDwarfEmitter->emitSectionContents(
       Dwarf.getDWARFObj().getRnglistsSection().Data, "debug_rnglists");
+  TheDwarfEmitter->emitSectionContents(
+      Dwarf.getDWARFObj().getLoclistsSection().Data, "debug_loclists");
 }
 
 void DWARFLinker::addObjectFile(DWARFFile &File, objFileLoader Loader,
@@ -2518,20 +2606,6 @@ Error DWARFLinker::link() {
       continue;
     }
 
-    // Check for unsupported sections. Following sections can be referenced
-    // from .debug_info section. Current DWARFLinker implementation does not
-    // support or update references to these tables. Thus we report warning
-    // and skip corresponding object file.
-    if (!OptContext.File.Dwarf->getDWARFObj()
-             .getLoclistsSection()
-             .Data.empty()) {
-      reportWarning("'.debug_loclists' is not currently supported: file "
-                    "will be skipped",
-                    OptContext.File);
-      OptContext.Skip = true;
-      continue;
-    }
-
     // In a first phase, just read in the debug info and load all clang modules.
     OptContext.CompileUnits.reserve(
         OptContext.File.Dwarf->getNumCompileUnits());

diff  --git a/llvm/lib/DWARFLinker/DWARFStreamer.cpp b/llvm/lib/DWARFLinker/DWARFStreamer.cpp
index 3af7cde52509d..1593ea65065d5 100644
--- a/llvm/lib/DWARFLinker/DWARFStreamer.cpp
+++ b/llvm/lib/DWARFLinker/DWARFStreamer.cpp
@@ -110,6 +110,7 @@ bool DwarfStreamer::init(Triple TheTriple,
   RangesSectionSize = 0;
   RngListsSectionSize = 0;
   LocSectionSize = 0;
+  LocListsSectionSize = 0;
   LineSectionSize = 0;
   FrameSectionSize = 0;
   DebugInfoSectionSize = 0;
@@ -206,6 +207,8 @@ void DwarfStreamer::emitSectionContents(StringRef SecData, StringRef SecName) {
           .Case("debug_addr", MC->getObjectFileInfo()->getDwarfAddrSection())
           .Case("debug_rnglists",
                 MC->getObjectFileInfo()->getDwarfRnglistsSection())
+          .Case("debug_loclists",
+                MC->getObjectFileInfo()->getDwarfLoclistsSection())
           .Default(nullptr);
 
   if (Section) {
@@ -483,73 +486,149 @@ void DwarfStreamer::emitDwarfDebugRngListsTableFragment(
   RngListsSectionSize += 1;
 }
 
-/// Emit location lists for \p Unit and update attributes to point to the new
-/// entries.
-void DwarfStreamer::emitLocationsForUnit(
-    const CompileUnit &Unit, DWARFContext &Dwarf,
-    std::function<void(StringRef, SmallVectorImpl<uint8_t> &)> ProcessExpr) {
-  const auto &Attributes = Unit.getLocationAttributes();
+/// Emit debug locations(.debug_loc, .debug_loclists) header.
+MCSymbol *DwarfStreamer::emitDwarfDebugLocListHeader(const CompileUnit &Unit) {
+  if (Unit.getOrigUnit().getVersion() < 5)
+    return nullptr;
+
+  // Make .debug_loclists the current section.
+  MS->switchSection(MC->getObjectFileInfo()->getDwarfLoclistsSection());
+
+  MCSymbol *BeginLabel = Asm->createTempSymbol("Bloclists");
+  MCSymbol *EndLabel = Asm->createTempSymbol("Eloclists");
+  unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
+
+  // Length
+  Asm->emitLabelDifference(EndLabel, BeginLabel, sizeof(uint32_t));
+  Asm->OutStreamer->emitLabel(BeginLabel);
+  LocListsSectionSize += sizeof(uint32_t);
+
+  // Version.
+  MS->emitInt16(5);
+  LocListsSectionSize += sizeof(uint16_t);
+
+  // Address size.
+  MS->emitInt8(AddressSize);
+  LocListsSectionSize++;
+
+  // Seg_size
+  MS->emitInt8(0);
+  LocListsSectionSize++;
 
-  if (Attributes.empty())
+  // Offset entry count
+  MS->emitInt32(0);
+  LocListsSectionSize += sizeof(uint32_t);
+
+  return EndLabel;
+}
+
+/// Emit debug locations(.debug_loc, .debug_loclists) fragment.
+void DwarfStreamer::emitDwarfDebugLocListFragment(
+    const CompileUnit &Unit,
+    const DWARFLocationExpressionsVector &LinkedLocationExpression,
+    PatchLocation Patch) {
+  if (Unit.getOrigUnit().getVersion() < 5) {
+    emitDwarfDebugLocTableFragment(Unit, LinkedLocationExpression, Patch);
     return;
+  }
 
-  MS->switchSection(MC->getObjectFileInfo()->getDwarfLocSection());
+  emitDwarfDebugLocListsTableFragment(Unit, LinkedLocationExpression, Patch);
+}
+
+/// Emit debug locations(.debug_loc, .debug_loclists) footer.
+void DwarfStreamer::emitDwarfDebugLocListFooter(const CompileUnit &Unit,
+                                                MCSymbol *EndLabel) {
+  if (Unit.getOrigUnit().getVersion() < 5)
+    return;
+
+  // Make .debug_loclists the current section.
+  MS->switchSection(MC->getObjectFileInfo()->getDwarfLoclistsSection());
+
+  if (EndLabel != nullptr)
+    Asm->OutStreamer->emitLabel(EndLabel);
+}
 
+/// Emit piece of .debug_loc for \p LinkedLocationExpression.
+void DwarfStreamer::emitDwarfDebugLocTableFragment(
+    const CompileUnit &Unit,
+    const DWARFLocationExpressionsVector &LinkedLocationExpression,
+    PatchLocation Patch) {
+  Patch.set(LocSectionSize);
+
+  // Make .debug_loc to be current section.
+  MS->switchSection(MC->getObjectFileInfo()->getDwarfLocSection());
   unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
-  uint64_t BaseAddressMarker = (AddressSize == 8)
-                                   ? std::numeric_limits<uint64_t>::max()
-                                   : std::numeric_limits<uint32_t>::max();
-  const DWARFSection &InputSec = Dwarf.getDWARFObj().getLocSection();
-  DataExtractor Data(InputSec.Data, Dwarf.isLittleEndian(), AddressSize);
-  DWARFUnit &OrigUnit = Unit.getOrigUnit();
-  auto OrigUnitDie = OrigUnit.getUnitDIE(false);
-  int64_t UnitPcOffset = 0;
-  if (auto OrigLowPc =
-          dwarf::toAddress(OrigUnitDie.find(dwarf::DW_AT_low_pc))) {
-    assert(Unit.getLowPc());
-    UnitPcOffset = int64_t(*OrigLowPc) - *Unit.getLowPc();
+
+  // Emit ranges.
+  uint64_t BaseAddress = 0;
+  if (std::optional<uint64_t> LowPC = Unit.getLowPc())
+    BaseAddress = *LowPC;
+
+  for (const DWARFLocationExpression &LocExpression :
+       LinkedLocationExpression) {
+    if (LocExpression.Range) {
+      MS->emitIntValue(LocExpression.Range->LowPC - BaseAddress, AddressSize);
+      MS->emitIntValue(LocExpression.Range->HighPC - BaseAddress, AddressSize);
+
+      LocSectionSize += AddressSize;
+      LocSectionSize += AddressSize;
+    }
+
+    Asm->OutStreamer->emitIntValue(LocExpression.Expr.size(), 2);
+    Asm->OutStreamer->emitBytes(StringRef(
+        (const char *)LocExpression.Expr.data(), LocExpression.Expr.size()));
+    LocSectionSize += LocExpression.Expr.size() + 2;
   }
 
-  SmallVector<uint8_t, 32> Buffer;
-  for (const auto &Attr : Attributes) {
-    uint64_t Offset = Attr.first.get();
-    Attr.first.set(LocSectionSize);
-    // This is the quantity to add to the old location address to get
-    // the correct address for the new one.
-    int64_t LocPcOffset = Attr.second + UnitPcOffset;
-    while (Data.isValidOffset(Offset)) {
-      uint64_t Low = Data.getUnsigned(&Offset, AddressSize);
-      uint64_t High = Data.getUnsigned(&Offset, AddressSize);
-      LocSectionSize += 2 * AddressSize;
-      // End of list entry.
-      if (Low == 0 && High == 0) {
-        Asm->OutStreamer->emitIntValue(0, AddressSize);
-        Asm->OutStreamer->emitIntValue(0, AddressSize);
-        break;
-      }
-      // Base address selection entry.
-      if (Low == BaseAddressMarker) {
-        Asm->OutStreamer->emitIntValue(BaseAddressMarker, AddressSize);
-        Asm->OutStreamer->emitIntValue(High + Attr.second, AddressSize);
-        LocPcOffset = 0;
-        continue;
-      }
-      // Location list entry.
-      Asm->OutStreamer->emitIntValue(Low + LocPcOffset, AddressSize);
-      Asm->OutStreamer->emitIntValue(High + LocPcOffset, AddressSize);
-      uint64_t Length = Data.getU16(&Offset);
-      Asm->OutStreamer->emitIntValue(Length, 2);
-      // Copy the bytes into to the buffer, process them, emit them.
-      Buffer.reserve(Length);
-      Buffer.resize(0);
-      StringRef Input = InputSec.Data.substr(Offset, Length);
-      ProcessExpr(Input, Buffer);
-      Asm->OutStreamer->emitBytes(
-          StringRef((const char *)Buffer.data(), Length));
-      Offset += Length;
-      LocSectionSize += Length + 2;
+  // Add the terminator entry.
+  MS->emitIntValue(0, AddressSize);
+  MS->emitIntValue(0, AddressSize);
+
+  LocSectionSize += AddressSize;
+  LocSectionSize += AddressSize;
+}
+
+/// Emit piece of .debug_loclists for \p LinkedLocationExpression.
+void DwarfStreamer::emitDwarfDebugLocListsTableFragment(
+    const CompileUnit &Unit,
+    const DWARFLocationExpressionsVector &LinkedLocationExpression,
+    PatchLocation Patch) {
+  Patch.set(LocListsSectionSize);
+
+  // Make .debug_loclists the current section.
+  MS->switchSection(MC->getObjectFileInfo()->getDwarfLoclistsSection());
+
+  unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
+
+  for (const DWARFLocationExpression &LocExpression :
+       LinkedLocationExpression) {
+    if (LocExpression.Range) {
+      // Emit type of entry.
+      MS->emitInt8(dwarf::DW_LLE_start_length);
+      LocListsSectionSize += 1;
+
+      // Emit start address.
+      MS->emitIntValue(LocExpression.Range->LowPC, AddressSize);
+      LocListsSectionSize += AddressSize;
+
+      // Emit length of the range.
+      LocListsSectionSize += MS->emitSLEB128IntValue(
+          LocExpression.Range->HighPC - LocExpression.Range->LowPC);
+    } else {
+      // Emit type of entry.
+      MS->emitInt8(dwarf::DW_LLE_default_location);
+      LocListsSectionSize += 1;
     }
+
+    LocListsSectionSize += MS->emitULEB128IntValue(LocExpression.Expr.size());
+    Asm->OutStreamer->emitBytes(StringRef(
+        (const char *)LocExpression.Expr.data(), LocExpression.Expr.size()));
+    LocListsSectionSize += LocExpression.Expr.size();
   }
+
+  // Emit the terminator entry.
+  MS->emitInt8(dwarf::DW_LLE_end_of_list);
+  LocListsSectionSize += 1;
 }
 
 void DwarfStreamer::emitLineTableForUnit(MCDwarfLineTableParams Params,

diff  --git a/llvm/test/tools/dsymutil/Inputs/dwarf5-loclists.o b/llvm/test/tools/dsymutil/Inputs/dwarf5-loclists.o
new file mode 100644
index 0000000000000..694346426c8c4
Binary files /dev/null and b/llvm/test/tools/dsymutil/Inputs/dwarf5-loclists.o 
diff er

diff  --git a/llvm/test/tools/dsymutil/X86/debug-loc-base-addr.test b/llvm/test/tools/dsymutil/X86/debug-loc-base-addr.test
index 07244c288a13b..a36e9139bcf0b 100644
--- a/llvm/test/tools/dsymutil/X86/debug-loc-base-addr.test
+++ b/llvm/test/tools/dsymutil/X86/debug-loc-base-addr.test
@@ -1,4 +1,4 @@
-RUN: dsymutil -oso-prepend-path %p/../Inputs %p/../Inputs/private/tmp/baseaddr/loc1.x86_64 -f -o - | llvm-dwarfdump -debug-loc - | FileCheck %s
+RUN: dsymutil -oso-prepend-path %p/../Inputs %p/../Inputs/private/tmp/baseaddr/loc1.x86_64 -f -o - | llvm-dwarfdump --debug-info - | FileCheck %s
 
 The test was compiled from a single source:
 $ cat loc1.cpp
@@ -17,10 +17,14 @@ int main() {
   return 0;
 }
 
-CHECK: .debug_loc contents:
-CHECK: [0x0000000100000f94,  0x0000000100000f97): DW_OP_consts +3, DW_OP_stack_value
-CHECK: [0x0000000100000f97,  0x0000000100000f99): DW_OP_consts +4, DW_OP_stack_value
-
-CHECK: [0x0000000100000f94,  0x0000000100000f97): DW_OP_consts +5, DW_OP_stack_value
-
-CHECK: [0x0000000100000f97,  0x0000000100000f99): DW_OP_reg0 RAX
+CHECK: DW_TAG_compile_unit
+CHECK: DW_TAG_variable
+CHECK: DW_AT_location
+CHECK: [0x0000000100000f94, 0x0000000100000f97): DW_OP_consts +3, DW_OP_stack_value
+CHECK: [0x0000000100000f97, 0x0000000100000f99): DW_OP_consts +4, DW_OP_stack_value
+CHECK: DW_TAG_variable
+CHECK: DW_AT_location
+CHECK: [0x0000000100000f94, 0x0000000100000f97): DW_OP_consts +5, DW_OP_stack_value
+CHECK: DW_TAG_variable
+CHECK: DW_AT_location
+CHECK: [0x0000000100000f97, 0x0000000100000f99): DW_OP_reg0 RAX

diff  --git a/llvm/test/tools/dsymutil/X86/dwarf5-loclists.test b/llvm/test/tools/dsymutil/X86/dwarf5-loclists.test
new file mode 100644
index 0000000000000..d393cda76af52
--- /dev/null
+++ b/llvm/test/tools/dsymutil/X86/dwarf5-loclists.test
@@ -0,0 +1,107 @@
+## This test checks that .debug_loclists table is correclty handled
+## and transformed into the DW_FORM_sec_offset form in case
+## --no-update. Or correctly preserved in --update case.
+
+## cat dwarf5-loclists.c
+## #include <stdio.h>
+##
+## int main ( int argv, char** argc ) {
+##   printf ("\n argv %d", argv );
+##   argv++;
+##   printf ("\n argv %d", argv );
+##   argv++;
+##   printf ("\n argv %d", &argv );
+##   return 0;
+## }
+
+## $ clang -gdwarf-5 dwarf5-loclists.c -c -O2 -o dwarf5-rnglists.o
+
+#RUN: dsymutil -oso-prepend-path %p/../Inputs -y %s -o %t.dSYM
+#RUN: llvm-dwarfdump --verify  %t.dSYM | FileCheck %s
+#RUN: llvm-dwarfdump -a --verbose  %t.dSYM | FileCheck %s --check-prefix DWARF-CHECK
+
+#RUN: dsymutil --update -oso-prepend-path %p/../Inputs -y %s -o %t.dSYM
+#RUN: llvm-dwarfdump --verify  %t.dSYM | FileCheck %s
+#RUN: llvm-dwarfdump -a --verbose  %t.dSYM | FileCheck %s --check-prefix UPD-DWARF-CHECK
+
+#CHECK: No errors.
+
+#DWARF-CHECK: DW_TAG_formal_parameter
+#DWARF-CHECK: DW_AT_name {{.*}} "dwarf5-loclists.c"
+#DWARF-CHECK-NOT: DW_AT_loclists_base
+#DWARF-CHECK: DW_TAG_formal_parameter
+#DWARF-CHECK:   DW_AT_location [DW_FORM_sec_offset]   (0x0000000c:
+#DWARF-CHECK:     [0x0000000100000f70, 0x0000000100000f87): DW_OP_reg5 RDI
+#DWARF-CHECK:     [0x0000000100000f87, 0x0000000100000f93): DW_OP_reg3 RBX
+#DWARF-CHECK:     [0x0000000100000f93, 0x0000000100000f9d): DW_OP_reg4 RSI
+#DWARF-CHECK:     [0x0000000100000fa0, 0x0000000100000fa3): DW_OP_reg3 RBX
+#DWARF-CHECK:     [0x0000000100000fa3, 0x0000000100000fbc): DW_OP_breg6 RBP-20)
+#DWARF-CHECK:   DW_AT_name {{.*}} "argv"
+#DWARF-CHECK: DW_TAG_formal_parameter
+#DWARF-CHECK: DW_AT_location [DW_FORM_sec_offset]   (0x0000004a:
+#DWARF-CHECK:     [0x0000000100000f70, 0x0000000100000f89): DW_OP_reg4 RSI
+#DWARF-CHECK:     [0x0000000100000f89, 0x0000000100000fbc): DW_OP_entry_value(DW_OP_reg4 RSI), DW_OP_stack_value)
+#DWARF-CHECK:   DW_AT_name {{.*}} "argc"
+#DWARF-CHECK: .debug_loclists contents:
+#DWARF-CHECK: 0x00000000: locations list header: length = 0x00000062, format = DWARF32, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
+#DWARF-CHECK: 0x0000000c:
+#DWARF-CHECK:     DW_LLE_start_length    (0x0000000100000f70, 0x0000000000000017)
+#DWARF-CHECK:                => [0x0000000100000f70, 0x0000000100000f87): DW_OP_reg5 RDI
+#DWARF-CHECK:     DW_LLE_start_length    (0x0000000100000f87, 0x000000000000000c)
+#DWARF-CHECK:                => [0x0000000100000f87, 0x0000000100000f93): DW_OP_reg3 RBX
+#DWARF-CHECK:     DW_LLE_start_length    (0x0000000100000f93, 0x000000000000000a)
+#DWARF-CHECK:                => [0x0000000100000f93, 0x0000000100000f9d): DW_OP_reg4 RSI
+#DWARF-CHECK:     DW_LLE_start_length    (0x0000000100000fa0, 0x0000000000000003)
+#DWARF-CHECK:                => [0x0000000100000fa0, 0x0000000100000fa3): DW_OP_reg3 RBX
+#DWARF-CHECK:     DW_LLE_start_length    (0x0000000100000fa3, 0x0000000000000019)
+#DWARF-CHECK:                => [0x0000000100000fa3, 0x0000000100000fbc): DW_OP_breg6 RBP-20
+#DWARF-CHECK:     DW_LLE_end_of_list     ()
+#DWARF-CHECK: 0x0000004a:
+#DWARF-CHECK:     DW_LLE_start_length    (0x0000000100000f70, 0x0000000000000019)
+#DWARF-CHECK:                => [0x0000000100000f70, 0x0000000100000f89): DW_OP_reg4 RSI
+#DWARF-CHECK:     DW_LLE_start_length    (0x0000000100000f89, 0x0000000000000033)
+#DWARF-CHECK:                => [0x0000000100000f89, 0x0000000100000fbc): DW_OP_entry_value(DW_OP_reg4 RSI), DW_OP_stack_value
+#DWARF-CHECK:     DW_LLE_end_of_list     ()
+
+#UPD-DWARF-CHECK: DW_TAG_compile_unit
+#UPD-DWARF-CHECK: DW_AT_name {{.*}} "dwarf5-loclists.c"
+#UPD-DWARF-CHECK: DW_AT_loclists_base [DW_FORM_sec_offset]  (0x0000000c)
+#UPD-DWARF-CHECK: DW_TAG_formal_parameter [8]   (0x00000058)
+#UPD-DWARF-CHECK:   DW_AT_location [DW_FORM_loclistx]     (indexed (0x0) loclist = 0x00000014:
+#UPD-DWARF-CHECK:    [0x0000000000000000, 0x0000000000000017): DW_OP_reg5 RDI
+#UPD-DWARF-CHECK:    [0x0000000000000017, 0x0000000000000023): DW_OP_reg3 RBX
+#UPD-DWARF-CHECK:    [0x0000000000000023, 0x000000000000002d): DW_OP_reg4 RSI
+#UPD-DWARF-CHECK:    [0x0000000000000030, 0x0000000000000033): DW_OP_reg3 RBX
+#UPD-DWARF-CHECK:    [0x0000000000000033, 0x000000000000004c): DW_OP_breg6 RBP-20)
+#UPD-DWARF-CHECK:   DW_AT_name {{.*}} "argv"
+#UPD-DWARF-CHECK: DW_TAG_formal_parameter [8]   (0x00000058)
+#UPD-DWARF-CHECK:   DW_AT_location [DW_FORM_loclistx]     (indexed (0x1) loclist = 0x0000002f:
+#UPD-DWARF-CHECK:    [0x0000000000000000, 0x0000000000000019): DW_OP_reg4 RSI
+#UPD-DWARF-CHECK:    [0x0000000000000019, 0x000000000000004c): DW_OP_entry_value(DW_OP_reg4 RSI), DW_OP_stack_value)
+#UPD-DWARF-CHECK:   DW_AT_name {{.*}} "argc"
+#UPD-DWARF-CHECK: .debug_loclists contents:
+#UPD-DWARF-CHECK: 0x00000000: locations list header: length = 0x00000039, format = DWARF32, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000002
+#UPD-DWARF-CHECK: offsets: [
+#UPD-DWARF-CHECK: 0x00000008 => 0x00000014
+#UPD-DWARF-CHECK: 0x00000023 => 0x0000002f
+#UPD-DWARF-CHECK: ]
+#UPD-DWARF-CHECK: 0x00000014:
+#UPD-DWARF-CHECK:    DW_LLE_offset_pair     (0x0000000000000000, 0x0000000000000017): DW_OP_reg5 RDI
+#UPD-DWARF-CHECK:    DW_LLE_offset_pair     (0x0000000000000017, 0x0000000000000023): DW_OP_reg3 RBX
+#UPD-DWARF-CHECK:    DW_LLE_offset_pair     (0x0000000000000023, 0x000000000000002d): DW_OP_reg4 RSI
+#UPD-DWARF-CHECK:    DW_LLE_offset_pair     (0x0000000000000030, 0x0000000000000033): DW_OP_reg3 RBX
+#UPD-DWARF-CHECK:    DW_LLE_offset_pair     (0x0000000000000033, 0x000000000000004c): DW_OP_breg6 RBP-20
+#UPD-DWARF-CHECK:    DW_LLE_end_of_list     ()
+#UPD-DWARF-CHECK: 0x0000002f:
+#UPD-DWARF-CHECK:    DW_LLE_offset_pair     (0x0000000000000000, 0x0000000000000019): DW_OP_reg4 RSI
+#UPD-DWARF-CHECK:    DW_LLE_offset_pair     (0x0000000000000019, 0x000000000000004c): DW_OP_entry_value(DW_OP_reg4 RSI), DW_OP_stack_value
+#UPD-DWARF-CHECK:    DW_LLE_end_of_list     ()
+
+---
+triple:          'x86_64-apple-darwin'
+objects:
+  - filename:        'dwarf5-loclists.o'
+    timestamp:       1676048242
+    symbols:
+      - { sym: _main, objAddr: 0x0, binAddr: 0x100000F70, size: 0x48 }
+      - { sym: _g1, binAddr: 0x100001000, size: 0x0 }

diff  --git a/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-loclists.test b/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-loclists.test
new file mode 100644
index 0000000000000..89b01c565aa0a
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-loclists.test
@@ -0,0 +1,201 @@
+## Test that DWARFv5 .debug_loclists is correctly recognized
+## and converted into the DW_FORM_sec_offset form in --garbage-collection
+## case or correctly preserved in --no-garbage-collection case.
+
+# RUN: yaml2obj %s -o %t.o
+
+# RUN: llvm-dwarfutil %t.o %t1
+# RUN: llvm-dwarfdump -verify %t1 | FileCheck %s
+# RUN: llvm-dwarfdump -a --verbose %t1 | FileCheck %s --check-prefix DWARF-CHECK
+
+# RUN: llvm-dwarfutil --no-garbage-collection %t.o %t1
+# RUN: llvm-dwarfdump -verify %t1 | FileCheck %s
+# RUN: llvm-dwarfdump -a --verbose %t1 | FileCheck %s --check-prefix UPD-DWARF-CHECK
+
+# RUN: llvm-dwarfutil --no-garbage-collection --build-accelerator=DWARF %t.o %t1
+# RUN: llvm-dwarfdump -verify %t1 | FileCheck %s
+# RUN: llvm-dwarfdump -a --verbose %t1 | FileCheck %s --check-prefix UPD-DWARF-CHECK
+
+#CHECK: No errors.
+
+#DWARF-CHECK: DW_TAG_compile_unit
+#DWARF-CHECK: DW_AT_name {{.*}}"CU1"
+#DWARF-CHECK-NOT: DW_AT_loclists_base
+#DWARF-CHECK: DW_TAG_variable
+#DWARF-CHECK: DW_AT_name {{.*}}"var1"
+#DWARF-CHECK: DW_AT_location [DW_FORM_sec_offset]      (0x0000000c:
+#DWARF-CHECK: [0x0000000000001130, 0x0000000000001140): DW_OP_reg5 RDI)
+#DWARF-CHECK: DW_AT_name {{.*}}"var2"
+#DWARF-CHECK: DW_AT_location [DW_FORM_sec_offset]     (0x00000019:
+#DWARF-CHECK: <default>: DW_OP_reg5 RDI)
+#DWARF-CHECK: DW_TAG_variable
+#DWARF-CHECK: DW_AT_name {{.*}}"var3"
+#DWARF-CHECK: DW_AT_location [DW_FORM_sec_offset]     (0x0000001d:
+#DWARF-CHECK: [0x0000000000001140, 0x0000000000001150): DW_OP_reg5 RDI
+#DWARF-CHECK: [0x0000000000001160, 0x0000000000001170): DW_OP_reg6 RBP)
+
+#UPD-DWARF-CHECK: DW_TAG_compile_unit
+#UPD-DWARF-CHECK:   DW_AT_name {{.*}}"CU1"
+#UPD-DWARF-CHECK:              DW_AT_loclists_base [DW_FORM_sec_offset]  (0x0000000c)
+#UPD-DWARF-CHECK:   DW_TAG_variable
+#UPD-DWARF-CHECK:     DW_AT_name {{.*}}"var1"
+#UPD-DWARF-CHECK:     DW_AT_location [DW_FORM_loclistx]       (indexed (0x0) loclist = 0x00000018:
+#UPD-DWARF-CHECK:     [0x0000000000001130, 0x0000000000001140): DW_OP_reg5 RDI)
+#UPD-DWARF-CHECK:   DW_TAG_variable
+#UPD-DWARF-CHECK:     DW_AT_name {{.*}}"var2"
+#UPD-DWARF-CHECK:     DW_AT_location [DW_FORM_loclistx]       (indexed (0x1) loclist = 0x0000001e:
+#UPD-DWARF-CHECK:        <default>: DW_OP_reg5 RDI)
+#UPD-DWARF-CHECK:   DW_TAG_variable
+#UPD-DWARF-CHECK:     DW_AT_name {{.*}}"var3"
+#UPD-DWARF-CHECK:     DW_AT_location [DW_FORM_loclistx]       (indexed (0x2) loclist = 0x00000022:
+#UPD-DWARF-CHECK:        [0x0000000000001140, 0x0000000000001150): DW_OP_reg5 RDI
+#UPD-DWARF-CHECK:        [0x0000000000001160, 0x0000000000001170): DW_OP_reg6 RBP)
+
+## Following yaml description has Content of the .debug_rnglists exactly like following data vvvvvvvvvvv
+## .debug_rnglists contents:
+## 0x00000000: range list header: length = 0x0000003e, format = DWARF32, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000005
+## offsets: [
+## 0x00000014 => 0x00000020
+## 0x00000018 => 0x00000024
+## 0x0000001c => 0x00000028
+## 0x00000027 => 0x00000033
+## 0x00000032 => 0x0000003e
+## ]
+## ranges:
+## 0x00000020: [DW_RLE_startx_length]:  0x0000000000000000, 0x0000000000000010 => [0x0000000000001130, 0x0000000000001140)
+## 0x00000023: [DW_RLE_end_of_list  ]
+## 0x00000024: [DW_RLE_startx_length]:  0x0000000000000001, 0x0000000000000010 => [0x0000000000001140, 0x0000000000001150)
+## 0x00000027: [DW_RLE_end_of_list  ]
+## 0x00000028: [DW_RLE_start_length ]:  0x0000000000001150, 0x0000000000000010 => [0x0000000000001150, 0x0000000000001160)
+## 0x00000032: [DW_RLE_end_of_list  ]
+## 0x00000033: [DW_RLE_start_length ]:  0x0000000000001160, 0x0000000000000010 => [0x0000000000001160, 0x0000000000001170)
+## 0x0000003d: [DW_RLE_end_of_list  ]
+## 0x0000003e: [DW_RLE_startx_length]:  0x0000000000000000, 0x0000000000000040 => [0x0000000000001130, 0x0000000000001170)
+## 0x00000041: [DW_RLE_end_of_list  ]
+
+
+## Following yaml description has Content of the .debug_loclists exactly like following data vvvvvvvvvvv
+## .debug_loclists contents:
+## 0x00000000: locations list header: length = 0x00000029, format = DWARF32, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000003
+## offsets: [
+## 0x0000000c => 0x00000018
+## 0x00000012 => 0x0000001e
+## 0x00000016 => 0x00000022
+## ]
+## 0x00000018:
+##             DW_LLE_startx_length   (0x0000000000000000, 0x0000000000000010): DW_OP_reg5 RDI
+##             DW_LLE_end_of_list     ()
+##
+## 0x0000001e:
+##             DW_LLE_default_location()
+##                       => <default>: DW_OP_reg5 RDI
+##             DW_LLE_end_of_list     ()
+##
+## 0x00000022:
+##             DW_LLE_startx_length   (0x0000000000000001, 0x0000000000000010): DW_OP_reg5 RDI
+##             DW_LLE_startx_length   (0x0000000000000003, 0x0000000000000010): DW_OP_reg6 RBP
+##             DW_LLE_end_of_list     ()
+
+--- !ELF
+FileHeader:
+  Class:    ELFCLASS64
+  Data:     ELFDATA2LSB
+  Type:     ET_REL
+  Machine:  EM_X86_64
+Sections:
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:         0x1130
+    Size:            0x70
+  - Name:            .debug_rnglists
+    Type:            SHT_PROGBITS
+    Flags:           [  ]
+    Content:        "3e000000050008000500000014000000180000001c000000270000003200000003001000030110000750110000000000001000076011000000000000100003004000"
+  - Name:            .debug_loclists
+    Type:            SHT_PROGBITS
+    Flags:           [  ]
+    Content:        "2900000005000800030000000c0000001200000016000000030010015500050155000301100155030310015600"
+DWARF:
+  debug_abbrev:
+    - Table:
+      - Tag:      DW_TAG_compile_unit
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_producer
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_language
+            Form:      DW_FORM_data2
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_low_pc
+            Form:      DW_FORM_addrx
+          - Attribute: DW_AT_ranges
+            Form:      DW_FORM_rnglistx
+          - Attribute: DW_AT_rnglists_base
+            Form:      DW_FORM_sec_offset
+          - Attribute: DW_AT_loclists_base
+            Form:      DW_FORM_sec_offset
+          - Attribute: DW_AT_addr_base
+            Form:      DW_FORM_sec_offset
+      - Tag:      DW_TAG_base_type
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_variable
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_const_value
+            Form:      DW_FORM_data4
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+          - Attribute: DW_AT_location
+            Form:      DW_FORM_loclistx
+  debug_info:
+    - Version: 5
+      UnitType:   DW_UT_compile
+      Entries:
+        - AbbrCode: 1
+          Values:
+            - CStr: by_hand
+            - Value:  0x04
+            - CStr: CU1
+            - Value:  0x0
+            - Value:  0x4
+            - Value:  0xc
+            - Value:  0xc
+            - Value:  0x8
+        - AbbrCode: 2
+          Values:
+            - CStr: int
+        - AbbrCode: 3
+          Values:
+            - CStr: var1
+            - Value:  0x00000000
+            - Value:  0x00000029
+            - Value:  0x0
+        - AbbrCode: 3
+          Values:
+            - CStr: var2
+            - Value:  0x00000000
+            - Value:  0x00000029
+            - Value:  0x1
+        - AbbrCode: 3
+          Values:
+            - CStr: var3
+            - Value:  0x00000000
+            - Value:  0x00000029
+            - Value:  0x2
+        - AbbrCode: 0
+  debug_addr:
+    - Version: 5
+      AddressSize: 0x08
+      Entries:
+        - Address: 0x1130
+        - Address: 0x1140
+        - Address: 0x1150
+        - Address: 0x1160
+...

diff  --git a/llvm/test/tools/llvm-dwarfutil/ELF/X86/warning-skipped-loclists.test b/llvm/test/tools/llvm-dwarfutil/ELF/X86/warning-skipped-loclists.test
deleted file mode 100644
index 09e2cea4993da..0000000000000
--- a/llvm/test/tools/llvm-dwarfutil/ELF/X86/warning-skipped-loclists.test
+++ /dev/null
@@ -1,54 +0,0 @@
-## This test checks the warning message displayed if input file
-## contains .debug_loclists section.
-
-# RUN: yaml2obj %s -o %t.o
-
-# RUN: llvm-dwarfutil --garbage-collection %t.o %t1 2>&1 | FileCheck %s -DFILE=%t.o
-
-# CHECK: [[FILE]]: warning: '.debug_loclists' is not currently supported: file will be skipped
-
---- !ELF
-FileHeader:
-  Class:    ELFCLASS64
-  Data:     ELFDATA2LSB
-  Type:     ET_REL
-  Machine:  EM_X86_64
-Sections:
-  - Name:            .text
-    Type:            SHT_PROGBITS
-    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
-    Address:         0x1000
-    AddressAlign:    0x0000000000000010
-    Content:        "FFFFFFFF"
-  - Name:            .debug_loclists
-    Type:            SHT_PROGBITS
-    Flags:           [  ]
-    Content:        "0000000000000000000000"
-DWARF:
-  debug_abbrev:
-    - Table:
-      - Tag:      DW_TAG_compile_unit
-        Children: DW_CHILDREN_yes
-        Attributes:
-          - Attribute: DW_AT_producer
-            Form:      DW_FORM_string
-          - Attribute: DW_AT_language
-            Form:      DW_FORM_data2
-          - Attribute: DW_AT_name
-            Form:      DW_FORM_string
-          - Attribute: DW_AT_low_pc
-            Form:      DW_FORM_addr
-          - Attribute: DW_AT_high_pc
-            Form:      DW_FORM_data8
-  debug_info:
-    - Version: 4
-      Entries:
-        - AbbrCode: 1
-          Values:
-            - CStr: by_hand
-            - Value:  0x04
-            - CStr: CU1
-            - Value:  0x1000
-            - Value:  0x4
-        - AbbrCode: 0
-...


        


More information about the llvm-commits mailing list