diff --git a/bolt/include/bolt/Core/BinaryContext.h b/bolt/include/bolt/Core/BinaryContext.h
--- a/bolt/include/bolt/Core/BinaryContext.h
+++ b/bolt/include/bolt/Core/BinaryContext.h
@@ -204,6 +204,9 @@
   using DWOIdToCUMapType = std::unordered_map<uint64_t, DWARFUnit *>;
   DWOIdToCUMapType DWOCUs;
 
+  bool ContainsDwarf5{false};
+  bool ContainsDwarfLegacy{false};
+
   /// Preprocess DWO debug information.
   void preprocessDWODebugInfo();
 
@@ -234,7 +237,13 @@
   /// Get Number of DWOCUs in a map.
   uint32_t getNumDWOCUs() { return DWOCUs.size(); }
 
-  const std::map<unsigned, DwarfLineTable> &getDwarfLineTables() const {
+  /// Returns true if DWARF5 is used.
+  bool isDWARF5Used() const { return ContainsDwarf5; }
+
+  /// Returns true if DWARF4 or lower is used.
+  bool isDWARFLegacyUsed() const { return ContainsDwarfLegacy; }
+
+  std::map<unsigned, DwarfLineTable> &getDwarfLineTables() {
     return DwarfLineTablesCUMap;
   }
 
@@ -245,7 +254,8 @@
   Expected<unsigned> getDwarfFile(StringRef Directory, StringRef FileName,
                                   unsigned FileNumber,
                                   Optional<MD5::MD5Result> Checksum,
-                                  Optional<StringRef> Source, unsigned CUID);
+                                  Optional<StringRef> Source, unsigned CUID,
+                                  unsigned DWARFVersion);
 
   /// [start memory address] -> [segment info] mapping.
   std::map<uint64_t, SegmentInfo> SegmentMapInfo;
diff --git a/bolt/include/bolt/Core/DebugData.h b/bolt/include/bolt/Core/DebugData.h
--- a/bolt/include/bolt/Core/DebugData.h
+++ b/bolt/include/bolt/Core/DebugData.h
@@ -34,6 +34,21 @@
 
 namespace bolt {
 
+// DWARF5 Header in order of encoding.
+// Types represent encodnig sizes.
+using UnitLengthType = uint32_t;
+using VersionType = uint16_t;
+using AddressSizeType = uint8_t;
+using SegmentSelectorType = uint8_t;
+using OffsetEntryCountType = uint32_t;
+/// Get DWARF5 Header size.
+/// Rangelists and Loclists have the same header.
+constexpr uint32_t getDWARF5RngListLocListHeaderSize() {
+  return sizeof(UnitLengthType) + sizeof(VersionType) +
+         sizeof(AddressSizeType) + sizeof(SegmentSelectorType) +
+         sizeof(OffsetEntryCountType);
+}
+
 class BinaryContext;
 
 /// Address range representation. Takes less space than DWARFAddressRange.
@@ -114,18 +129,23 @@
 };
 using CUOffsetMap = std::map<uint32_t, CUInfo>;
 
+enum class RangesWriterKind { DebugRangesWriter, DebugRangeListsWriter };
 /// Serializes the .debug_ranges DWARF section.
 class DebugRangesSectionWriter {
 public:
   DebugRangesSectionWriter();
 
+  DebugRangesSectionWriter(RangesWriterKind K) : Kind(K){};
+
+  virtual ~DebugRangesSectionWriter(){};
+
   /// Add ranges with caching.
-  uint64_t
+  virtual uint64_t
   addRanges(DebugAddressRangesVector &&Ranges,
             std::map<DebugAddressRangesVector, uint64_t> &CachedRanges);
 
   /// Add ranges and return offset into section.
-  uint64_t addRanges(const DebugAddressRangesVector &Ranges);
+  virtual uint64_t addRanges(const DebugAddressRangesVector &Ranges);
 
   /// Returns an offset of an empty address ranges list that is always written
   /// to .debug_ranges
@@ -134,11 +154,18 @@
   /// Returns the SectionOffset.
   uint64_t getSectionOffset();
 
-  std::unique_ptr<DebugBufferVector> finalize() {
+  /// Returns a buffer containing Ranges.
+  virtual std::unique_ptr<DebugBufferVector> finalize() {
     return std::move(RangesBuffer);
   }
 
-private:
+  RangesWriterKind getKind() const { return Kind; }
+
+  static bool classof(const DebugRangesSectionWriter *Writer) {
+    return Writer->getKind() == RangesWriterKind::DebugRangesWriter;
+  }
+
+protected:
   std::unique_ptr<DebugBufferVector> RangesBuffer;
 
   std::unique_ptr<raw_svector_ostream> RangesStream;
@@ -151,6 +178,62 @@
 
   /// Offset of an empty address ranges list.
   static constexpr uint64_t EmptyRangesOffset{0};
+
+private:
+  RangesWriterKind Kind;
+};
+
+class DebugAddrWriter;
+class DebugRangelistsSectionWriter : public DebugRangesSectionWriter {
+public:
+  DebugRangelistsSectionWriter()
+      : DebugRangesSectionWriter(RangesWriterKind::DebugRangeListsWriter) {
+    RangesBuffer = std::make_unique<DebugBufferVector>();
+    RangesStream = std::make_unique<raw_svector_ostream>(*RangesBuffer);
+  };
+  virtual ~DebugRangelistsSectionWriter(){};
+
+  static void setAddressWriter(DebugAddrWriter *AddrW) { AddrWriter = AddrW; }
+
+  /// Add ranges with caching.
+  virtual uint64_t addRanges(
+      DebugAddressRangesVector &&Ranges,
+      std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) override;
+
+  /// Add ranges and return offset into section.
+  virtual uint64_t addRanges(const DebugAddressRangesVector &Ranges) override;
+
+  virtual std::unique_ptr<DebugBufferVector> finalize() override {
+    return std::move(RangesBuffer);
+  }
+
+  /// Needs to be invoked before each CU is processed.
+  /// \p CUID is a unique ID of each CU.
+  void initSection(uint64_t CID);
+
+  /// Returns a buffer containing Ranges.
+  void finalizeSection();
+
+  RangesWriterKind getKind() const {
+    return DebugRangesSectionWriter::getKind();
+  }
+
+  static bool classof(const DebugRangesSectionWriter *Writer) {
+    return Writer->getKind() == RangesWriterKind::DebugRangeListsWriter;
+  }
+
+private:
+  static DebugAddrWriter *AddrWriter;
+  /// Unique ID of CU being processed.
+  uint64_t CUId{0};
+  /// Current relative offset of range list entry within this CUs rangelist
+  /// body.
+  uint32_t CurrentOffset{0};
+  /// Contains relative offset of each range list entry.
+  SmallVector<uint32_t, 1> RangeEntries;
+
+  std::unique_ptr<DebugBufferVector> CUBodyBuffer;
+  std::unique_ptr<raw_svector_ostream> CUBodyStream;
 };
 
 /// Serializes the .debug_aranges DWARF section.
@@ -193,23 +276,24 @@
 public:
   DebugAddrWriter() = delete;
   DebugAddrWriter(BinaryContext *BC_);
+  virtual ~DebugAddrWriter(){};
   /// Given an address returns an index in .debug_addr.
   /// Adds Address to map.
-  uint32_t getIndexFromAddress(uint64_t Address, uint64_t DWOId);
+  uint32_t getIndexFromAddress(uint64_t Address, uint64_t CUId);
 
   /// Adds {Address, Index} to DWO ID CU.
-  void addIndexAddress(uint64_t Address, uint32_t Index, uint64_t DWOId);
+  void addIndexAddress(uint64_t Address, uint32_t Index, uint64_t CUId);
 
   /// Creates consolidated .debug_addr section, and builds DWOID to offset map.
-  AddressSectionBuffer finalize();
+  virtual AddressSectionBuffer finalize();
 
   /// Given DWOID returns offset of this CU in to .debug_addr section.
-  uint64_t getOffset(uint64_t DWOId);
+  virtual uint64_t getOffset(DWARFUnit &Unit);
 
   /// Returns False if .debug_addr section was created..
   bool isInitialized() const { return !AddressMaps.empty(); }
 
-private:
+protected:
   class AddressForDWOCU {
   public:
     AddressToIndexMap::iterator find(uint64_t Adddress) {
@@ -266,6 +350,19 @@
   std::mutex WriterMutex;
 };
 
+class DebugAddrWriterDwarf5 : public DebugAddrWriter {
+public:
+  DebugAddrWriterDwarf5() = delete;
+  DebugAddrWriterDwarf5(BinaryContext *Bc) : DebugAddrWriter(Bc) {}
+  virtual ~DebugAddrWriterDwarf5(){};
+
+  /// Creates consolidated .debug_addr section, and builds DWOID to offset map.
+  virtual AddressSectionBuffer finalize() override;
+  /// Given DWARFUnit \p Unit returns offset of this CU in to .debug_addr
+  /// section.
+  virtual uint64_t getOffset(DWARFUnit &Unit) override;
+};
+
 using DebugStrBufferVector = SmallVector<char, 16>;
 class DebugStrWriter {
 public:
@@ -302,10 +399,14 @@
 public:
   DebugLocWriter() = delete;
   DebugLocWriter(BinaryContext *BC);
+  DebugLocWriter(BinaryContext *BC, LocWriterKind K) : DebugLocWriter(BC) {
+    Kind = K;
+  }
   virtual ~DebugLocWriter(){};
 
   /// Writes out location lists and stores internal patches.
-  virtual void addList(uint64_t AttrOffset, DebugLocationsVector &&LocList);
+  virtual void addList(uint64_t AttrOffset, uint32_t LocListIndex,
+                       DebugLocationsVector &&LocList);
 
   /// Writes out locations in to a local buffer, and adds Debug Info patches.
   virtual void finalize(uint64_t SectionOffset,
@@ -314,6 +415,9 @@
   /// Return internal buffer.
   virtual std::unique_ptr<DebugBufferVector> getBuffer();
 
+  /// Returns DWARF version.
+  uint8_t getDwarfVersion() const { return DwarfVersion; }
+
   /// Offset of an empty location list.
   static constexpr uint32_t EmptyListOffset = 0;
 
@@ -325,16 +429,16 @@
 
 protected:
   std::unique_ptr<DebugBufferVector> LocBuffer;
-
   std::unique_ptr<raw_svector_ostream> LocStream;
   /// Current offset in the section (updated as new entries are written).
   /// Starts with 0 here since this only writes part of a full location lists
   /// section. In the final section, the first 16 bytes are reserved for an
   /// empty list.
   uint32_t SectionOffset{0};
-  LocWriterKind Kind{LocWriterKind::DebugLocWriter};
+  uint8_t DwarfVersion{4};
 
 private:
+  LocWriterKind Kind{LocWriterKind::DebugLocWriter};
   struct LocListDebugInfoPatchType {
     uint64_t DebugInfoAttrOffset;
     uint64_t LocListOffset;
@@ -354,9 +458,11 @@
 public:
   ~DebugLoclistWriter() {}
   DebugLoclistWriter() = delete;
-  DebugLoclistWriter(BinaryContext *BC, uint64_t DWOId_)
-      : DebugLocWriter(BC), DWOId(DWOId_) {
-    Kind = LocWriterKind::DebugLoclistWriter;
+  DebugLoclistWriter(BinaryContext *BC, uint64_t CID,
+                     uint32_t LocListsBaseAttrOffset, uint8_t DV, bool SD)
+      : DebugLocWriter(BC, LocWriterKind::DebugLoclistWriter), CUId(CID),
+        LocListsBaseAttrOffset(LocListsBaseAttrOffset), IsSplitDwarf(SD) {
+    DwarfVersion = DV;
     assert(DebugLoclistWriter::AddrWriter &&
            "Please use SetAddressWriter to initialize "
            "DebugAddrWriter before instantiation.");
@@ -365,7 +471,7 @@
   static void setAddressWriter(DebugAddrWriter *AddrW) { AddrWriter = AddrW; }
 
   /// Stores location lists internally to be written out during finalize phase.
-  virtual void addList(uint64_t AttrOffset,
+  virtual void addList(uint64_t AttrOffset, uint32_t LocListIndex,
                        DebugLocationsVector &&LocList) override;
 
   /// Writes out locations in to a local buffer and applies debug info patches.
@@ -373,15 +479,31 @@
                 SimpleBinaryPatcher &DebugInfoPatcher) override;
 
   /// Returns DWO ID.
-  uint64_t getDWOID() const { return DWOId; }
+  uint64_t getCUID() const { return CUId; }
+
+  LocWriterKind getKind() const { return DebugLocWriter::getKind(); }
 
   static bool classof(const DebugLocWriter *Writer) {
     return Writer->getKind() == LocWriterKind::DebugLoclistWriter;
   }
 
+  bool isSplitDwarf() const { return IsSplitDwarf; }
+
+  static uint32_t InvalidIndex;
+  static uint32_t InvalidLocListsBaseAttrOffset;
+
 private:
+  /// Writes out locations in to a local buffer and applies debug info patches.
+  void finalizeDWARFLegacy(uint64_t SectionOffset,
+                           SimpleBinaryPatcher &DebugInfoPatcher);
+
+  /// Writes out locations in to a local buffer and applies debug info patches.
+  void finalizeDWARF5(uint64_t SectionOffset,
+                      SimpleBinaryPatcher &DebugInfoPatcher);
+
   struct LocPatch {
     uint64_t AttrOffset{0};
+    uint32_t Index;
     DebugLocationsVector LocList;
   };
   using LocPatchVec = SmallVector<LocPatch, 4>;
@@ -395,7 +517,9 @@
     uint64_t Address{0};
   };
   static DebugAddrWriter *AddrWriter;
-  uint64_t DWOId{0};
+  uint64_t CUId{0};
+  uint32_t LocListsBaseAttrOffset{InvalidLocListsBaseAttrOffset};
+  bool IsSplitDwarf{false};
 };
 
 enum class PatcherKind { SimpleBinaryPatcher, DebugInfoBinaryPatcher };
@@ -914,6 +1038,9 @@
   /// Raw data representing complete debug line section for the unit.
   StringRef RawData;
 
+  /// DWARF Version
+  uint16_t DwarfVersion;
+
 public:
   /// Emit line info for all units in the binary context.
   static void emit(BinaryContext &BC, MCStreamer &Streamer);
@@ -937,6 +1064,14 @@
 
   void setLabel(MCSymbol *Label) { Header.Label = Label; }
 
+  /// Sets the root file \p Directory, \p FileName, optional \p CheckSum, and
+  /// optional \p Source.
+  void setRootFile(StringRef Directory, StringRef FileName,
+                   Optional<MD5::MD5Result> Checksum,
+                   Optional<StringRef> Source) {
+    Header.setRootFile(Directory, FileName, Checksum, Source);
+  }
+
   /// Access to MC line info.
   MCLineSection &getMCLineSections() { return MCLineSections; }
 
@@ -956,6 +1091,12 @@
   void addRawContents(StringRef DebugLineContents) {
     RawData = DebugLineContents;
   }
+
+  /// Sets DWARF version for this line table.
+  void setDwarfVersion(uint16_t V) { DwarfVersion = V; }
+
+  // Returns DWARF Version for this line table.
+  uint16_t getDwarfVersion() { return DwarfVersion; }
 };
 
 struct AttrInfo {
diff --git a/bolt/include/bolt/Rewrite/DWARFRewriter.h b/bolt/include/bolt/Rewrite/DWARFRewriter.h
--- a/bolt/include/bolt/Rewrite/DWARFRewriter.h
+++ b/bolt/include/bolt/Rewrite/DWARFRewriter.h
@@ -51,8 +51,7 @@
   /// .debug_abbrev section writer for the main binary.
   std::unique_ptr<DebugAbbrevWriter> AbbrevWriter;
 
-  using LocWriters =
-      std::unordered_map<uint64_t, std::unique_ptr<DebugLocWriter>>;
+  using LocWriters = std::map<uint64_t, std::unique_ptr<DebugLocWriter>>;
   /// Use a separate location list writer for each compilation unit
   LocWriters LocListWritersByCU;
 
@@ -68,11 +67,15 @@
 
   std::mutex LocListDebugInfoPatchesMutex;
 
+  /// DWARFLegacy is all DWARF versions before DWARF 5.
+  enum class DWARFVersion { DWARFLegacy, DWARF5 };
+
   /// Update debug info for all DIEs in \p Unit.
   void updateUnitDebugInfo(DWARFUnit &Unit,
                            DebugInfoBinaryPatcher &DebugInfoPatcher,
                            DebugAbbrevWriter &AbbrevWriter,
                            DebugLocWriter &DebugLocWriter,
+                           DebugRangesSectionWriter &RangesWriter,
                            Optional<uint64_t> RangesBase = None);
 
   /// Patches the binary for an object's address ranges to be updated.
@@ -91,7 +94,8 @@
                                       Optional<uint64_t> RangesBase = None);
 
   std::unique_ptr<DebugBufferVector>
-  makeFinalLocListsSection(SimpleBinaryPatcher &DebugInfoPatcher);
+  makeFinalLocListsSection(SimpleBinaryPatcher &DebugInfoPatcher,
+                           DWARFVersion Version);
 
   /// Finalize debug sections in the main binary.
   CUOffsetMap finalizeDebugSections(DebugInfoBinaryPatcher &DebugInfoPatcher);
diff --git a/bolt/lib/Core/BinaryContext.cpp b/bolt/lib/Core/BinaryContext.cpp
--- a/bolt/lib/Core/BinaryContext.cpp
+++ b/bolt/lib/Core/BinaryContext.cpp
@@ -1320,14 +1320,13 @@
   }
 }
 
-Expected<unsigned>
-BinaryContext::getDwarfFile(StringRef Directory, StringRef FileName,
-                            unsigned FileNumber,
-                            Optional<MD5::MD5Result> Checksum,
-                            Optional<StringRef> Source, unsigned CUID) {
+Expected<unsigned> BinaryContext::getDwarfFile(
+    StringRef Directory, StringRef FileName, unsigned FileNumber,
+    Optional<MD5::MD5Result> Checksum, Optional<StringRef> Source,
+    unsigned CUID, unsigned DWARFVersion) {
   DwarfLineTable &Table = DwarfLineTablesCUMap[CUID];
-  return Table.tryGetFile(Directory, FileName, Checksum, Source,
-                          Ctx->getDwarfVersion(), FileNumber);
+  return Table.tryGetFile(Directory, FileName, Checksum, Source, DWARFVersion,
+                          FileNumber);
 }
 
 unsigned BinaryContext::addDebugFilenameToUnit(const uint32_t DestCUID,
@@ -1355,7 +1354,9 @@
           dwarf::toString(FileNames[FileIndex - 1].Name))
     FileName = *FName;
   assert(FileName != "");
-  return cantFail(getDwarfFile(Dir, FileName, 0, None, None, DestCUID));
+  DWARFCompileUnit *DstUnit = DwCtx->getCompileUnitForOffset(DestCUID);
+  return cantFail(getDwarfFile(Dir, FileName, 0, None, None, DestCUID,
+                               DstUnit->getVersion()));
 }
 
 std::vector<BinaryFunction *> BinaryContext::getSortedFunctions() {
@@ -1453,6 +1454,9 @@
       if (containsAddress(Range.LowPC))
         AllRanges.emplace_back(CURange{Range.LowPC, Range.HighPC, CU.get()});
     }
+
+    ContainsDwarf5 |= CU->getVersion() == 5;
+    ContainsDwarfLegacy |= CU->getVersion() < 5;
   }
 
   std::sort(AllRanges.begin(), AllRanges.end());
@@ -1491,7 +1495,9 @@
   StringRef GlobalPrefix = AsmInfo->getPrivateGlobalPrefix();
   for (const std::unique_ptr<DWARFUnit> &CU : DwCtx->compile_units()) {
     const uint64_t CUID = CU->getOffset();
-    getDwarfLineTable(CUID).setLabel(Ctx->getOrCreateSymbol(
+    DWARFDataExtractor LineData(CU->getLineSection().Data, true, 0);
+    DwarfLineTable &BoltLineTable = getDwarfLineTable(CUID);
+    BoltLineTable.setLabel(Ctx->getOrCreateSymbol(
         GlobalPrefix + "line_table_start" + Twine(CUID)));
 
     if (!ProcessedCUs.count(CU.get()))
@@ -1502,26 +1508,44 @@
     const std::vector<DWARFDebugLine::FileNameEntry> &FileNames =
         LineTable->Prologue.FileNames;
 
+    uint16_t DwarfVersion = LineTable->Prologue.getVersion();
+    if (DwarfVersion == 5) {
+      Optional<MD5::MD5Result> Checksum =
+          LineTable->Prologue.FileNames[0].Checksum;
+      BoltLineTable.setRootFile(
+          CU->getCompilationDir(),
+          dwarf::toString(CU->getUnitDIE().find(dwarf::DW_AT_name), nullptr),
+          Checksum, None);
+    }
+
+    BoltLineTable.setDwarfVersion(DwarfVersion);
+
     // Assign a unique label to every line table, one per CU.
     // Make sure empty debug line tables are registered too.
     if (FileNames.empty()) {
-      cantFail(getDwarfFile("", "<unknown>", 0, None, None, CUID));
+      cantFail(
+          getDwarfFile("", "<unknown>", 0, None, None, CUID, DwarfVersion));
       continue;
     }
+    uint32_t Offset = DwarfVersion < 5 ? 1 : 0;
     for (size_t I = 0, Size = FileNames.size(); I != Size; ++I) {
       // Dir indexes start at 1, as DWARF file numbers, and a dir index 0
       // means empty dir.
       StringRef Dir = "";
-      if (FileNames[I].DirIdx != 0)
+      if (FileNames[I].DirIdx != 0 || DwarfVersion == 5)
         if (Optional<const char *> DirName = dwarf::toString(
                 LineTable->Prologue
-                    .IncludeDirectories[FileNames[I].DirIdx - 1]))
+                    .IncludeDirectories[FileNames[I].DirIdx - Offset]))
           Dir = *DirName;
       StringRef FileName = "";
       if (Optional<const char *> FName = dwarf::toString(FileNames[I].Name))
         FileName = *FName;
       assert(FileName != "");
-      cantFail(getDwarfFile(Dir, FileName, 0, None, None, CUID));
+      Optional<MD5::MD5Result> Checksum = None;
+      if (DwarfVersion == 5)
+        Checksum = LineTable->Prologue.FileNames[I].Checksum;
+      cantFail(
+          getDwarfFile(Dir, FileName, 0, Checksum, None, CUID, DwarfVersion));
     }
   }
 
diff --git a/bolt/lib/Core/DebugData.cpp b/bolt/lib/Core/DebugData.cpp
--- a/bolt/lib/Core/DebugData.cpp
+++ b/bolt/lib/Core/DebugData.cpp
@@ -15,6 +15,7 @@
 #include "bolt/Utils/Utils.h"
 #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugAddr.h"
 #include "llvm/MC/MCAssembler.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCObjectStreamer.h"
@@ -118,6 +119,7 @@
   // Add an empty range as the first entry;
   SectionOffset +=
       writeAddressRanges(*RangesStream.get(), DebugAddressRangesVector{});
+  Kind = RangesWriterKind::DebugRangesWriter;
 }
 
 uint64_t DebugRangesSectionWriter::addRanges(
@@ -155,6 +157,94 @@
   return SectionOffset;
 }
 
+DebugAddrWriter *DebugRangelistsSectionWriter::AddrWriter = nullptr;
+
+uint64_t DebugRangelistsSectionWriter::addRanges(
+    DebugAddressRangesVector &&Ranges,
+    std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) {
+  return addRanges(Ranges);
+}
+
+struct LoclistsRangelistsHeader {
+  UnitLengthType UnitLength; // Size of loclist entris section, not including
+                             // size of header.
+  VersionType Version;
+  AddressSizeType AddressSize;
+  SegmentSelectorType SegmentSelector;
+  OffsetEntryCountType OffsetEntryCount;
+};
+
+static std::unique_ptr<DebugBufferVector>
+getDWARF5Header(const LoclistsRangelistsHeader &Header) {
+  std::unique_ptr<DebugBufferVector> HeaderBuffer =
+      std::make_unique<DebugBufferVector>();
+  std::unique_ptr<raw_svector_ostream> HeaderStream =
+      std::make_unique<raw_svector_ostream>(*HeaderBuffer);
+
+  // 7.29 length of the set of entries for this compilation unit, not including
+  // the length field itself
+  uint32_t HeaderSize =
+      getDWARF5RngListLocListHeaderSize() - sizeof(UnitLengthType);
+
+  support::endian::write(*HeaderStream, Header.UnitLength + HeaderSize,
+                         support::little);
+  support::endian::write(*HeaderStream, Header.Version, support::little);
+  support::endian::write(*HeaderStream, Header.AddressSize, support::little);
+  support::endian::write(*HeaderStream, Header.SegmentSelector,
+                         support::little);
+  support::endian::write(*HeaderStream, Header.OffsetEntryCount,
+                         support::little);
+  return HeaderBuffer;
+}
+
+uint64_t DebugRangelistsSectionWriter::addRanges(
+    const DebugAddressRangesVector &Ranges) {
+  std::lock_guard<std::mutex> Lock(WriterMutex);
+
+  RangeEntries.push_back(CurrentOffset);
+  for (const DebugAddressRange &Range : Ranges) {
+    support::endian::write(*CUBodyStream,
+                           static_cast<uint8_t>(dwarf::DW_RLE_startx_length),
+                           support::little);
+    uint32_t Index = AddrWriter->getIndexFromAddress(Range.LowPC, CUId);
+    encodeULEB128(Index, *CUBodyStream);
+    encodeULEB128(Range.HighPC - Range.LowPC, *CUBodyStream);
+  }
+  support::endian::write(*CUBodyStream,
+                         static_cast<uint8_t>(dwarf::DW_RLE_end_of_list),
+                         support::little);
+  CurrentOffset = CUBodyBuffer->size();
+  return RangeEntries.size() - 1;
+}
+
+void DebugRangelistsSectionWriter::finalizeSection() {
+  std::unique_ptr<DebugBufferVector> CUArrayBuffer =
+      std::make_unique<DebugBufferVector>();
+  std::unique_ptr<raw_svector_ostream> CUArrayStream =
+      std::make_unique<raw_svector_ostream>(*CUArrayBuffer);
+  constexpr uint32_t SizeOfArrayEntry = 4;
+  uint32_t SizeOfArraySection = RangeEntries.size() * SizeOfArrayEntry;
+  for (uint32_t Offset : RangeEntries)
+    support::endian::write(*CUArrayStream, Offset + SizeOfArraySection,
+                           support::little);
+
+  std::unique_ptr<DebugBufferVector> Header = getDWARF5Header(
+      {static_cast<uint32_t>(SizeOfArraySection + CUBodyBuffer.get()->size()),
+       5, 8, 0, static_cast<uint32_t>(RangeEntries.size())});
+  *RangesStream << *Header;
+  *RangesStream << *CUArrayBuffer;
+  *RangesStream << *CUBodyBuffer;
+  SectionOffset = RangesBuffer->size();
+}
+
+void DebugRangelistsSectionWriter::initSection(uint64_t CID) {
+  CUBodyBuffer = std::make_unique<DebugBufferVector>();
+  CUBodyStream = std::make_unique<raw_svector_ostream>(*CUBodyBuffer);
+  RangeEntries.clear();
+  CurrentOffset = 0;
+  CUId = CID;
+}
+
 void DebugARangesSectionWriter::addCURanges(uint64_t CUOffset,
                                             DebugAddressRangesVector &&Ranges) {
   std::lock_guard<std::mutex> Lock(CUAddressRangesMutex);
@@ -220,13 +310,12 @@
   for (auto &Pair : SortedMap)
     dbgs() << Twine::utohexstr(Pair.second) << "\t" << Pair.first << "\n";
 }
-uint32_t DebugAddrWriter::getIndexFromAddress(uint64_t Address,
-                                              uint64_t DWOId) {
+uint32_t DebugAddrWriter::getIndexFromAddress(uint64_t Address, uint64_t CUId) {
   std::lock_guard<std::mutex> Lock(WriterMutex);
-  if (!AddressMaps.count(DWOId))
-    AddressMaps[DWOId] = AddressForDWOCU();
+  if (!AddressMaps.count(CUId))
+    AddressMaps[CUId] = AddressForDWOCU();
 
-  AddressForDWOCU &Map = AddressMaps[DWOId];
+  AddressForDWOCU &Map = AddressMaps[CUId];
   auto Entry = Map.find(Address);
   if (Entry == Map.end()) {
     auto Index = Map.getNextIndex();
@@ -240,9 +329,9 @@
 // IndexToAddrss. Case3) Address is in the map but Index is lower. Need to
 // update AddressToIndex and IndexToAddress
 void DebugAddrWriter::addIndexAddress(uint64_t Address, uint32_t Index,
-                                      uint64_t DWOId) {
+                                      uint64_t CUId) {
   std::lock_guard<std::mutex> Lock(WriterMutex);
-  AddressForDWOCU &Map = AddressMaps[DWOId];
+  AddressForDWOCU &Map = AddressMaps[CUId];
   auto Entry = Map.find(Address);
   if (Entry != Map.end()) {
     if (Entry->second > Index)
@@ -265,6 +354,7 @@
     if (!DWOId)
       continue;
     auto AM = AddressMaps.find(*DWOId);
+    assert(AM != AddressMaps.end() && "Address Map not found.");
     // Adding to map even if it did not contribute to .debug_addr.
     // The Skeleton CU will still have DW_AT_GNU_addr_base.
     DWOIdToOffsetMap[*DWOId] = Buffer.size();
@@ -306,9 +396,98 @@
 
   return Buffer;
 }
+AddressSectionBuffer DebugAddrWriterDwarf5::finalize() {
+  // Need to layout all sections within .debug_addr
+  // Within each section sort Address by index.
+  AddressSectionBuffer Buffer;
+  raw_svector_ostream AddressStream(Buffer);
+  endianness Endian =
+      BC->DwCtx->isLittleEndian() ? support::little : support::big;
+  const DWARFSection &AddrSec = BC->DwCtx->getDWARFObj().getAddrSection();
+  DWARFDataExtractor AddrData(BC->DwCtx->getDWARFObj(), AddrSec, Endian, 0);
+  DWARFDebugAddrTable AddrTable;
+  DIDumpOptions DumpOpts;
+  constexpr uint32_t HeaderSize = 8;
+  for (std::unique_ptr<DWARFUnit> &CU : BC->DwCtx->compile_units()) {
+    uint64_t CUId = CU->getOffset();
+    uint8_t AddrSize = CU->getAddressByteSize();
+    auto AM = AddressMaps.find(CUId);
+    // A case where CU has entry in .debug_addr, but we don't modify addresses
+    // for it.
+    if (AM == AddressMaps.end()) {
+      AM = AddressMaps.insert({CUId, AddressForDWOCU()}).first;
+      auto BaseOffset = CU->getAddrOffsetSectionBase();
+      if (!BaseOffset)
+        continue;
+      // Address base offset is to the first entry.
+      // The size of header is 8 bytes.
+      uint64_t Offset = *BaseOffset - HeaderSize;
+      if (Error Err = AddrTable.extract(AddrData, &Offset, 5, AddrSize,
+                                        DumpOpts.WarningHandler)) {
+        DumpOpts.RecoverableErrorHandler(std::move(Err));
+        continue;
+      }
+      uint32_t Index = 0;
+      for (uint64_t Addr : AddrTable.getAddressEntries()) {
+        AM->second.insert(Addr, Index++);
+      }
+    }
+
+    DWOIdToOffsetMap[CUId] = Buffer.size() + HeaderSize;
+
+    std::vector<IndexAddressPair> SortedMap(AM->second.indexToAddressBegin(),
+                                            AM->second.indexToAdddessEnd());
+    // Sorting address in increasing order of indices.
+    std::sort(SortedMap.begin(), SortedMap.end(),
+              [](const IndexAddressPair &A, const IndexAddressPair &B) {
+                return A.first < B.first;
+              });
+    // Writing out Header
+    uint32_t Length = SortedMap.size() * AddrSize + 4;
+    support::endian::write(AddressStream, Length, Endian);
+    support::endian::write(AddressStream, static_cast<uint16_t>(5), Endian);
+    support::endian::write(AddressStream, static_cast<uint8_t>(AddrSize),
+                           Endian);
+    support::endian::write(AddressStream, static_cast<uint8_t>(0), Endian);
+
+    uint32_t Counter = 0;
+    auto WriteAddress = [&](uint64_t Address) -> void {
+      ++Counter;
+      switch (AddrSize) {
+      default:
+        assert(false && "Address Size is invalid.");
+        break;
+      case 4:
+        support::endian::write(AddressStream, static_cast<uint32_t>(Address),
+                               Endian);
+        break;
+      case 8:
+        support::endian::write(AddressStream, Address, Endian);
+        break;
+      }
+    };
+
+    for (const IndexAddressPair &Val : SortedMap) {
+      while (Val.first > Counter)
+        WriteAddress(0);
+      WriteAddress(Val.second);
+    }
+  }
+
+  return Buffer;
+}
 
-uint64_t DebugAddrWriter::getOffset(uint64_t DWOId) {
-  auto Iter = DWOIdToOffsetMap.find(DWOId);
+uint64_t DebugAddrWriter::getOffset(DWARFUnit &Unit) {
+  auto DWOId = Unit.getDWOId();
+  assert(DWOId && "Can't get offset, not a skeleton CU.");
+  auto Iter = DWOIdToOffsetMap.find(*DWOId);
+  assert(Iter != DWOIdToOffsetMap.end() &&
+         "Offset in to.debug_addr was not found for DWO ID.");
+  return Iter->second;
+}
+
+uint64_t DebugAddrWriterDwarf5::getOffset(DWARFUnit &Unit) {
+  auto Iter = DWOIdToOffsetMap.find(Unit.getOffset());
   assert(Iter != DWOIdToOffsetMap.end() &&
          "Offset in to.debug_addr was not found for DWO ID.");
   return Iter->second;
@@ -319,7 +498,7 @@
   LocStream = std::make_unique<raw_svector_ostream>(*LocBuffer);
 }
 
-void DebugLocWriter::addList(uint64_t AttrOffset,
+void DebugLocWriter::addList(uint64_t AttrOffset, uint32_t LocListIndex,
                              DebugLocationsVector &&LocList) {
   if (LocList.empty()) {
     EmptyAttrLists.push_back(AttrOffset);
@@ -345,9 +524,12 @@
   LocListDebugInfoPatches.push_back({AttrOffset, EntryOffset});
 }
 
-void DebugLoclistWriter::addList(uint64_t AttrOffset,
+uint32_t DebugLoclistWriter::InvalidIndex = UINT32_MAX;
+uint32_t DebugLoclistWriter::InvalidLocListsBaseAttrOffset = UINT32_MAX;
+
+void DebugLoclistWriter::addList(uint64_t AttrOffset, uint32_t LocListIndex,
                                  DebugLocationsVector &&LocList) {
-  Patches.push_back({AttrOffset, std::move(LocList)});
+  Patches.push_back({AttrOffset, LocListIndex, std::move(LocList)});
 }
 
 std::unique_ptr<DebugBufferVector> DebugLocWriter::getBuffer() {
@@ -368,8 +550,95 @@
                                   DebugLocWriter::EmptyListOffset);
 }
 
-void DebugLoclistWriter::finalize(uint64_t SectionOffset,
-                                  SimpleBinaryPatcher &DebugInfoPatcher) {
+static void writeEmptyListDwarf5(raw_svector_ostream &Stream) {
+  support::endian::write(Stream, static_cast<uint32_t>(4), support::little);
+  support::endian::write(Stream, static_cast<uint8_t>(dwarf::DW_LLE_start_end),
+                         support::little);
+
+  const char Zeroes[16] = {0};
+  Stream << StringRef(Zeroes, 16);
+  encodeULEB128(0, Stream);
+  support::endian::write(
+      Stream, static_cast<uint8_t>(dwarf::DW_LLE_end_of_list), support::little);
+}
+
+void DebugLoclistWriter::finalizeDWARF5(uint64_t SectionOffset,
+                                        SimpleBinaryPatcher &DebugInfoPatcher) {
+
+  std::unique_ptr<DebugBufferVector> LocArrayBuffer =
+      std::make_unique<DebugBufferVector>();
+  std::unique_ptr<raw_svector_ostream> LocArrayStream =
+      std::make_unique<raw_svector_ostream>(*LocArrayBuffer);
+  std::unique_ptr<DebugBufferVector> LocBodyBuffer =
+      std::make_unique<DebugBufferVector>();
+  std::unique_ptr<raw_svector_ostream> LocBodyStream =
+      std::make_unique<raw_svector_ostream>(*LocBodyBuffer);
+
+  uint32_t SizeOfArraySection = Patches.size() * sizeof(uint32_t);
+  std::sort(Patches.begin(), Patches.end(),
+            [](const LocPatch &p1, const LocPatch &p2) -> bool {
+              return p1.Index < p2.Index;
+            });
+
+  if (LocListsBaseAttrOffset != InvalidLocListsBaseAttrOffset)
+    DebugInfoPatcher.addLE32Patch(LocListsBaseAttrOffset,
+                                  SectionOffset +
+                                      getDWARF5RngListLocListHeaderSize());
+
+  uint32_t Index{0};
+  for (LocPatch &Patch : Patches) {
+    const uint32_t EntryOffset = LocBodyBuffer->size();
+    if (Patch.LocList.empty()) {
+      if (Patch.Index == DebugLoclistWriter::InvalidIndex)
+        DebugInfoPatcher.addLE32Patch(Patch.AttrOffset, EntryOffset);
+
+      writeEmptyListDwarf5(*LocBodyStream);
+      continue;
+    }
+
+    assert(Patch.Index == DebugLoclistWriter::InvalidIndex ||
+           Patch.Index == Index++ && "Gap in LocList Index Array.");
+
+    std::vector<uint64_t> OffsetsArray;
+    for (const DebugLocationEntry &Entry : Patch.LocList) {
+      support::endian::write(*LocBodyStream,
+                             static_cast<uint8_t>(dwarf::DW_LLE_startx_length),
+                             support::little);
+      uint32_t Index = AddrWriter->getIndexFromAddress(Entry.LowPC, CUId);
+      encodeULEB128(Index, *LocBodyStream);
+      encodeULEB128(Entry.HighPC - Entry.LowPC, *LocBodyStream);
+      encodeULEB128(Entry.Expr.size(), *LocBodyStream);
+      *LocBodyStream << StringRef(
+          reinterpret_cast<const char *>(Entry.Expr.data()), Entry.Expr.size());
+    }
+    support::endian::write(*LocBodyStream,
+                           static_cast<uint8_t>(dwarf::DW_LLE_end_of_list),
+                           support::little);
+
+    // Write out IndexArray
+    support::endian::write(
+        *LocArrayStream,
+        static_cast<uint32_t>(SizeOfArraySection + EntryOffset),
+        support::little);
+    // Don't need to patch Index since we are re-using them.
+    if (Patch.Index == DebugLoclistWriter::InvalidIndex)
+      DebugInfoPatcher.addLE32Patch(Patch.AttrOffset, EntryOffset);
+    clearList(Patch.LocList);
+  }
+  if (!Patches.empty()) {
+    std::unique_ptr<DebugBufferVector> Header =
+        getDWARF5Header({static_cast<uint32_t>(SizeOfArraySection +
+                                               LocBodyBuffer.get()->size()),
+                         5, 8, 0, static_cast<uint32_t>(Patches.size())});
+    *LocStream << *Header;
+    *LocStream << *LocArrayBuffer;
+    *LocStream << *LocBodyBuffer;
+  }
+  clearList(Patches);
+}
+
+void DebugLoclistWriter::finalizeDWARFLegacy(
+    uint64_t SectionOffset, SimpleBinaryPatcher &DebugInfoPatcher) {
   for (LocPatch &Patch : Patches) {
     if (Patch.LocList.empty()) {
       DebugInfoPatcher.addLE32Patch(Patch.AttrOffset,
@@ -381,7 +650,7 @@
       support::endian::write(*LocStream,
                              static_cast<uint8_t>(dwarf::DW_LLE_startx_length),
                              support::little);
-      uint32_t Index = AddrWriter->getIndexFromAddress(Entry.LowPC, DWOId);
+      uint32_t Index = AddrWriter->getIndexFromAddress(Entry.LowPC, CUId);
       encodeULEB128(Index, *LocStream);
 
       // TODO: Support DWARF5
@@ -403,6 +672,14 @@
   clearList(Patches);
 }
 
+void DebugLoclistWriter::finalize(uint64_t SectionOffset,
+                                  SimpleBinaryPatcher &DebugInfoPatcher) {
+  if (DwarfVersion < 5)
+    finalizeDWARFLegacy(SectionOffset, DebugInfoPatcher);
+  else
+    finalizeDWARF5(SectionOffset, DebugInfoPatcher);
+}
+
 DebugAddrWriter *DebugLoclistWriter::AddrWriter = nullptr;
 
 void DebugInfoBinaryPatcher::addUnitBaseOffsetLabel(uint64_t Offset) {
@@ -1153,7 +1430,7 @@
       MCOS->emitULEB128IntValue(Column);
     }
     if (Discriminator != LineEntry.getDiscriminator() &&
-        MCOS->getContext().getDwarfVersion() >= 4) {
+        MCOS->getContext().getDwarfVersion() >= 2) {
       Discriminator = LineEntry.getDiscriminator();
       unsigned Size = getULEB128Size(Discriminator);
       MCOS->emitInt8(dwarf::DW_LNS_extended_op);
@@ -1227,6 +1504,32 @@
   MCOS->emitLabel(LineEndSym);
 }
 
+// Helper function to parse .debug_line_str, and populate one we are using.
+// For functions that we do not modify we output them as raw data.
+// Re-constructing .debug_line_str so that offsets are correct for those
+// debut line tables.
+// Bonus is that when we output a final binary we can re-use .debug_line_str
+// section. So we don't have to do the SHF_ALLOC trick we did with
+// .debug_line.
+static void parseAndPopulateDebugLineStr(BinarySection &LineStrSection,
+                                         MCDwarfLineStr &LineStr,
+                                         BinaryContext &BC,
+                                         MCStreamer &Streamer) {
+  DataExtractor StrData(LineStrSection.getContents(),
+                        BC.DwCtx->isLittleEndian(), 0);
+  uint64_t Offset = 0;
+  while (StrData.isValidOffset(Offset)) {
+    Error Err = Error::success();
+    const char *CStr = StrData.getCStr(&Offset, &Err);
+    if (Err) {
+      llvm::errs()
+          << "BOLT-ERROR: could not extract string from .debug_line_str.";
+      continue;
+    }
+    LineStr.emitRef(&Streamer, CStr);
+  }
+}
+
 void DwarfLineTable::emit(BinaryContext &BC, MCStreamer &Streamer) {
   MCAssembler &Assembler =
       static_cast<MCObjectStreamer *>(&Streamer)->getAssembler();
@@ -1239,19 +1542,35 @@
   // in doing so create an unnecessary (if empty) section.
   if (LineTables.empty())
     return;
-
   // In a v5 non-split line table, put the strings in a separate section.
   Optional<MCDwarfLineStr> LineStr(None);
-  if (BC.Ctx->getDwarfVersion() >= 5)
+  ErrorOr<BinarySection &> LineStrSection =
+      BC.getUniqueSectionByName(".debug_line_str");
+  // Some versions of GCC output DWARF5 .debug_info, but DWARF4 or lower
+  // .debug_line
+  if (LineStrSection) {
     LineStr = MCDwarfLineStr(*BC.Ctx);
+    parseAndPopulateDebugLineStr(*LineStrSection, *LineStr, BC, Streamer);
+  }
 
   // Switch to the section where the table will be emitted into.
   Streamer.SwitchSection(BC.MOFI->getDwarfLineSection());
 
+  uint16_t DwarfVersion = BC.Ctx->getDwarfVersion();
   // Handle the rest of the Compile Units.
   for (auto &CUIDTablePair : LineTables) {
+    Streamer.getContext().setDwarfVersion(
+        CUIDTablePair.second.getDwarfVersion());
     CUIDTablePair.second.emitCU(&Streamer, Params, LineStr, BC);
   }
+
+  // Resetting DWARF version for rest of the flow.
+  BC.Ctx->setDwarfVersion(DwarfVersion);
+
+  // Still need to write the section out for the ExecutionEngine, and temp in
+  // memory object we are constructing.
+  if (LineStr)
+    LineStr->emitSection(&Streamer);
 }
 
 } // namespace bolt
diff --git a/bolt/lib/Rewrite/DWARFRewriter.cpp b/bolt/lib/Rewrite/DWARFRewriter.cpp
--- a/bolt/lib/Rewrite/DWARFRewriter.cpp
+++ b/bolt/lib/Rewrite/DWARFRewriter.cpp
@@ -72,6 +72,21 @@
     return None;
   return findAttributeInfo(DIE, AbbrevDecl, *Index);
 }
+
+/// Finds attributes FormValue and Offset.
+///
+/// \param DIE die to look up in.
+/// \param Attrs finds the first attribute that matches and extracts it.
+/// \return an optional AttrInfo with DWARFFormValue and Offset.
+Optional<AttrInfo> findAttributeInfo(const DWARFDie DIE,
+                                     std::vector<dwarf::Attribute> Attrs) {
+  for (dwarf::Attribute &Attr : Attrs) {
+    if (Optional<AttrInfo> Info = findAttributeInfo(DIE, Attr)) {
+      return Info;
+    }
+  }
+  return None;
+}
 } // namespace bolt
 } // namespace llvm
 
@@ -149,10 +164,6 @@
   return DWOName;
 }
 
-static bool isHighPcFormEightBytes(dwarf::Form DwarfForm) {
-  return DwarfForm == dwarf::DW_FORM_addr || DwarfForm == dwarf::DW_FORM_data8;
-}
-
 void DWARFRewriter::updateDebugInfo() {
   ErrorOr<BinarySection &> DebugInfo = BC.getUniqueSectionByName(".debug_info");
   if (!DebugInfo)
@@ -162,24 +173,40 @@
       static_cast<DebugInfoBinaryPatcher *>(DebugInfo->getPatcher());
 
   ARangesSectionWriter = std::make_unique<DebugARangesSectionWriter>();
-  RangesSectionWriter = std::make_unique<DebugRangesSectionWriter>();
   StrWriter = std::make_unique<DebugStrWriter>(&BC);
   AbbrevWriter = std::make_unique<DebugAbbrevWriter>(*BC.DwCtx);
 
-  AddrWriter = std::make_unique<DebugAddrWriter>(&BC);
-  DebugLoclistWriter::setAddressWriter(AddrWriter.get());
-
-  uint64_t NumCUs = BC.DwCtx->getNumCompileUnits();
-  if ((opts::NoThreads || opts::DeterministicDebugInfo) &&
-      BC.getNumDWOCUs() == 0) {
-    // Use single entry for efficiency when running single-threaded
-    NumCUs = 1;
+  if (BC.isDWARF5Used()) {
+    // Disabling none deterministic mode for dwarf5, to keep implementation
+    // simpler.
+    opts::DeterministicDebugInfo = true;
+    AddrWriter = std::make_unique<DebugAddrWriterDwarf5>(&BC);
+    RangesSectionWriter = std::make_unique<DebugRangelistsSectionWriter>();
+    DebugRangelistsSectionWriter::setAddressWriter(AddrWriter.get());
+  } else {
+    AddrWriter = std::make_unique<DebugAddrWriter>(&BC);
+    RangesSectionWriter = std::make_unique<DebugRangesSectionWriter>();
   }
 
-  LocListWritersByCU.reserve(NumCUs);
+  DebugLoclistWriter::setAddressWriter(AddrWriter.get());
 
-  for (size_t CUIndex = 0; CUIndex < NumCUs; ++CUIndex)
-    LocListWritersByCU[CUIndex] = std::make_unique<DebugLocWriter>(&BC);
+  size_t CUIndex = 0;
+  for (std::unique_ptr<DWARFUnit> &CU : BC.DwCtx->compile_units()) {
+    if (CU->getVersion() == 5) {
+      uint32_t AttrInfoOffset =
+          DebugLoclistWriter::InvalidLocListsBaseAttrOffset;
+      if (Optional<AttrInfo> AttrInfoVal =
+              findAttributeInfo(CU->getUnitDIE(), dwarf::DW_AT_loclists_base))
+        AttrInfoOffset = AttrInfoVal->Offset;
+
+      LocListWritersByCU[CUIndex] = std::make_unique<DebugLoclistWriter>(
+          &BC, CU->isDWOUnit() ? *CU->getDWOId() : CU->getOffset(),
+          AttrInfoOffset, 5, false);
+    } else {
+      LocListWritersByCU[CUIndex] = std::make_unique<DebugLocWriter>(&BC);
+    }
+    ++CUIndex;
+  }
 
   // Unordered maps to handle name collision if output DWO directory is
   // specified.
@@ -189,8 +216,8 @@
 
   auto updateDWONameCompDir = [&](DWARFUnit &Unit) -> void {
     const DWARFDie &DIE = Unit.getUnitDIE();
-    Optional<AttrInfo> AttrInfoVal =
-        findAttributeInfo(DIE, dwarf::DW_AT_GNU_dwo_name);
+    Optional<AttrInfo> AttrInfoVal = findAttributeInfo(
+        DIE, {dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name});
     (void)AttrInfoVal;
     assert(AttrInfoVal && "Skeleton CU doesn't have dwo_name.");
 
@@ -238,8 +265,8 @@
         std::lock_guard<std::mutex> Lock(AccessMutex);
         DebugLocWriter =
             LocListWritersByCU
-                .insert(
-                    {*DWOId, std::make_unique<DebugLoclistWriter>(&BC, *DWOId)})
+                .insert({*DWOId, std::make_unique<DebugLoclistWriter>(
+                                     &BC, *DWOId, 0, Unit->getVersion(), true)})
                 .first->second.get();
       }
       DebugInfoBinaryPatcher *DwoDebugInfoPatcher =
@@ -255,7 +282,7 @@
       DebugAbbrevWriter *DWOAbbrevWriter =
           createBinaryDWOAbbrevWriter((*SplitCU)->getContext(), *DWOId);
       updateUnitDebugInfo(*(*SplitCU), *DwoDebugInfoPatcher, *DWOAbbrevWriter,
-                          *DebugLocWriter);
+                          *DebugLocWriter, *RangesSectionWriter);
       DwoDebugInfoPatcher->clearDestinationLabels();
       if (!DwoDebugInfoPatcher->getWasRangBasedUsed())
         RangesBase = None;
@@ -265,18 +292,33 @@
       std::lock_guard<std::mutex> Lock(AccessMutex);
       DebugLocWriter = LocListWritersByCU[CUIndex].get();
     }
+    if (Unit->getVersion() == 5) {
+      RangesBase = RangesSectionWriter->getSectionOffset() +
+                   getDWARF5RngListLocListHeaderSize();
+      reinterpret_cast<DebugRangelistsSectionWriter *>(
+          RangesSectionWriter.get())
+          ->initSection(Unit->getOffset());
+    }
+
     DebugInfoPatcher->addUnitBaseOffsetLabel(Unit->getOffset());
     updateUnitDebugInfo(*Unit, *DebugInfoPatcher, *AbbrevWriter,
-                        *DebugLocWriter, RangesBase);
+                        *DebugLocWriter, *RangesSectionWriter, RangesBase);
+    if (Unit->getVersion() == 5)
+      reinterpret_cast<DebugRangelistsSectionWriter *>(
+          RangesSectionWriter.get())
+          ->finalizeSection();
   };
 
+  CUIndex = 0;
   if (opts::NoThreads || opts::DeterministicDebugInfo) {
-    for (std::unique_ptr<DWARFUnit> &CU : BC.DwCtx->compile_units())
-      processUnitDIE(0, CU.get());
+    for (std::unique_ptr<DWARFUnit> &CU : BC.DwCtx->compile_units()) {
+      processUnitDIE(CUIndex, CU.get());
+      if (CU->getVersion() == 5)
+        ++CUIndex;
+    }
   } else {
     // Update unit debug info in parallel
     ThreadPool &ThreadPool = ParallelUtilities::getThreadPool();
-    size_t CUIndex = 0;
     for (std::unique_ptr<DWARFUnit> &CU : BC.DwCtx->compile_units()) {
       ThreadPool.async(processUnitDIE, CUIndex, CU.get());
       CUIndex++;
@@ -295,9 +337,18 @@
   updateGdbIndexSection(OffsetMap);
 }
 
+static uint64_t getCUId(DWARFUnit &Unit) {
+  if (Unit.getVersion() == 5)
+    return Unit.getOffset();
+
+  assert(Unit.isDWOUnit() && "Unit is not Skeleton CU.");
+  return *Unit.getDWOId();
+}
+
 void DWARFRewriter::updateUnitDebugInfo(
     DWARFUnit &Unit, DebugInfoBinaryPatcher &DebugInfoPatcher,
     DebugAbbrevWriter &AbbrevWriter, DebugLocWriter &DebugLocWriter,
+    DebugRangesSectionWriter &RangesSectionWriter,
     Optional<uint64_t> RangesBase) {
   // Cache debug ranges so that the offset for identical ranges could be reused.
   std::map<DebugAddressRangesVector, uint64_t> CachedRanges;
@@ -324,7 +375,6 @@
     }
 
     DWARFDie DIE(&Unit, &Die);
-
     switch (DIE.getTag()) {
     case dwarf::DW_TAG_compile_unit: {
       auto ModuleRangesOrError = DIE.getAddressRanges();
@@ -336,7 +386,7 @@
       DebugAddressRangesVector OutputRanges =
           BC.translateModuleAddressRanges(ModuleRanges);
       const uint64_t RangesSectionOffset =
-          RangesSectionWriter->addRanges(OutputRanges);
+          RangesSectionWriter.addRanges(OutputRanges);
       if (!Unit.isDWOUnit())
         ARangesSectionWriter->addCURanges(Unit.getOffset(),
                                           std::move(OutputRanges));
@@ -375,7 +425,7 @@
         FunctionRanges.push_back({0, 0});
 
       updateDWARFObjectAddressRanges(
-          DIE, RangesSectionWriter->addRanges(FunctionRanges), DebugInfoPatcher,
+          DIE, RangesSectionWriter.addRanges(FunctionRanges), DebugInfoPatcher,
           AbbrevWriter);
 
       break;
@@ -384,8 +434,7 @@
     case dwarf::DW_TAG_inlined_subroutine:
     case dwarf::DW_TAG_try_block:
     case dwarf::DW_TAG_catch_block: {
-      uint64_t RangesSectionOffset =
-          RangesSectionWriter->getEmptyRangesOffset();
+      uint64_t RangesSectionOffset = RangesSectionWriter.getEmptyRangesOffset();
       Expected<DWARFAddressRangesVector> RangesOrError = DIE.getAddressRanges();
       const BinaryFunction *Function =
           RangesOrError && !RangesOrError->empty()
@@ -400,7 +449,7 @@
                  << Twine::utohexstr(DIE.getOffset()) << " in CU at 0x"
                  << Twine::utohexstr(Unit.getOffset()) << '\n';
         });
-        RangesSectionOffset = RangesSectionWriter->addRanges(
+        RangesSectionOffset = RangesSectionWriter.addRanges(
             std::move(OutputRanges), CachedRanges);
       } else if (!RangesOrError) {
         consumeError(RangesOrError.takeError());
@@ -430,6 +479,12 @@
           if (SectionAddress)
             BaseAddress = SectionAddress->Address;
 
+          if (Unit.getVersion() == 5) {
+            Optional<uint64_t> LocOffset = Unit.getLoclistOffset(Offset);
+            assert(LocOffset && "Location Offset is invalid.");
+            Offset = *LocOffset;
+          }
+
           Error E = Unit.getLocationTable().visitLocationList(
               &Offset, [&](const DWARFLocationEntry &Entry) {
                 switch (Entry.Kind) {
@@ -437,12 +492,13 @@
                   llvm_unreachable("Unsupported DWARFLocationEntry Kind.");
                 case dwarf::DW_LLE_end_of_list:
                   return false;
-                case dwarf::DW_LLE_base_address:
+                case dwarf::DW_LLE_base_address: {
                   assert(Entry.SectionIndex == SectionedAddress::UndefSection &&
                          "absolute address expected");
                   BaseAddress = Entry.Value0;
                   break;
-                case dwarf::DW_LLE_offset_pair:
+                }
+                case dwarf::DW_LLE_offset_pair: {
                   assert(
                       (Entry.SectionIndex == SectionedAddress::UndefSection &&
                        !Unit.isDWOUnit()) &&
@@ -451,9 +507,20 @@
                       BaseAddress + Entry.Value0, BaseAddress + Entry.Value1,
                       Entry.Loc});
                   break;
-                case dwarf::DW_LLE_startx_length:
-                  assert(Unit.isDWOUnit() &&
-                         "None DWO Unit with DW_LLE_startx_length encoding.");
+                }
+                case dwarf::DW_RLE_start_length: {
+                  InputLL.emplace_back(DebugLocationEntry{
+                      Entry.Value0, Entry.Value0 + Entry.Value1, Entry.Loc});
+                  break;
+                }
+                case dwarf::DW_LLE_base_addressx: {
+                  Optional<object::SectionedAddress> EntryAddress =
+                      Unit.getAddrOffsetSectionItem(Entry.Value0);
+                  assert(EntryAddress && "base Address not found.");
+                  BaseAddress = EntryAddress->Address;
+                  break;
+                }
+                case dwarf::DW_LLE_startx_length: {
                   Optional<object::SectionedAddress> EntryAddress =
                       Unit.getAddrOffsetSectionItem(Entry.Value0);
                   assert(EntryAddress && "Address does not exist.");
@@ -462,6 +529,18 @@
                       EntryAddress->Address + Entry.Value1, Entry.Loc});
                   break;
                 }
+                case dwarf::DW_LLE_startx_endx: {
+                  Optional<object::SectionedAddress> StartAddress =
+                      Unit.getAddrOffsetSectionItem(Entry.Value0);
+                  assert(StartAddress && "Start Address does not exist.");
+                  Optional<object::SectionedAddress> EndAddress =
+                      Unit.getAddrOffsetSectionItem(Entry.Value1);
+                  assert(EndAddress && "Start Address does not exist.");
+                  InputLL.emplace_back(DebugLocationEntry{
+                      StartAddress->Address, EndAddress->Address, Entry.Loc});
+                  break;
+                }
+                }
                 return true;
               });
 
@@ -472,42 +551,84 @@
                    << Twine::utohexstr(Unit.getOffset()) << '\n';
           } else {
             const uint64_t Address = InputLL.front().LowPC;
+            DebugLocationsVector OutputLL;
             if (const BinaryFunction *Function =
                     BC.getBinaryFunctionContainingAddress(Address)) {
-              DebugLocationsVector OutputLL =
-                  Function->translateInputToOutputLocationList(InputLL);
+              OutputLL = Function->translateInputToOutputLocationList(InputLL);
               LLVM_DEBUG(if (OutputLL.empty()) {
                 dbgs() << "BOLT-DEBUG: location list translated to an empty "
                           "one at 0x"
                        << Twine::utohexstr(DIE.getOffset()) << " in CU at 0x"
                        << Twine::utohexstr(Unit.getOffset()) << '\n';
               });
-              DebugLocWriter.addList(AttrOffset, std::move(OutputLL));
+            } else {
+              // I have seen this building CLANG-15 where subprogram was removed
+              // and has address of 0. Adding this entry to output to preserve
+              // debug information.
+              OutputLL = InputLL;
             }
+            uint32_t LocListIndex = 0;
+            dwarf::Form Form = Value.getForm();
+            if (Form == dwarf::DW_FORM_sec_offset ||
+                Form == dwarf::DW_FORM_data4) {
+              // For DWARF5 we can access location list entry either using
+              // index, or offset. If it's offset, then it's from begnning of
+              // the file. This implemetnation was before we could add entries
+              // to the DIE. For DWARF4 this is no-op.
+              // TODO: For DWARF5 convert all the offset based entries to index
+              // based, and insert loclist_base if necessary.
+              LocListIndex = DebugLoclistWriter::InvalidIndex;
+            } else if (Form == dwarf::DW_FORM_loclistx)
+              LocListIndex = Value.getRawUValue();
+            else
+              llvm_unreachable("Unsupported LocList access Form.");
+            DebugLocWriter.addList(AttrOffset, LocListIndex,
+                                   std::move(OutputLL));
           }
         } else {
           assert((Value.isFormClass(DWARFFormValue::FC_Exprloc) ||
                   Value.isFormClass(DWARFFormValue::FC_Block)) &&
                  "unexpected DW_AT_location form");
-          if (Unit.isDWOUnit()) {
+          if (Unit.isDWOUnit() || Unit.getVersion()) {
             ArrayRef<uint8_t> Expr = *Value.getAsBlock();
             DataExtractor Data(
                 StringRef((const char *)Expr.data(), Expr.size()),
                 Unit.getContext().isLittleEndian(), 0);
             DWARFExpression LocExpr(Data, Unit.getAddressByteSize(),
                                     Unit.getFormParams().Format);
+            uint32_t PrevOffset = 0;
+            constexpr uint32_t SizeOfOpcode = 1;
+            constexpr uint32_t SizeOfForm = 1;
             for (auto &Expr : LocExpr) {
-              if (Expr.getCode() != dwarf::DW_OP_GNU_addr_index)
+              if (!(Expr.getCode() == dwarf::DW_OP_GNU_addr_index ||
+                    Expr.getCode() == dwarf::DW_OP_addrx))
                 continue;
+
               uint64_t Index = Expr.getRawOperand(0);
               Optional<object::SectionedAddress> EntryAddress =
                   Unit.getAddrOffsetSectionItem(Index);
               assert(EntryAddress && "Address is not found.");
               assert(Index <= std::numeric_limits<uint32_t>::max() &&
                      "Invalid Operand Index.");
-              AddrWriter->addIndexAddress(EntryAddress->Address,
-                                          static_cast<uint32_t>(Index),
-                                          *Unit.getDWOId());
+              if (Expr.getCode() == dwarf::DW_OP_addrx) {
+                uint32_t EncodingSize =
+                    Expr.getOperandEndOffset(0) - PrevOffset - SizeOfOpcode;
+                uint32_t Index = AddrWriter->getIndexFromAddress(
+                    EntryAddress->Address, getCUId(Unit));
+                DebugInfoPatcher.addUDataPatch(AttrOffset + PrevOffset +
+                                                   SizeOfOpcode + SizeOfForm,
+                                               Index, EncodingSize);
+              } else {
+                // TODO: Re-do this as DWARF5.
+                AddrWriter->addIndexAddress(EntryAddress->Address,
+                                            static_cast<uint32_t>(Index),
+                                            getCUId(Unit));
+              }
+              if (Expr.getDescription().Op[1] ==
+                  DWARFExpression::Operation::SizeNA)
+                PrevOffset = Expr.getOperandEndOffset(0);
+              else
+                PrevOffset = Expr.getOperandEndOffset(1);
             }
           }
         }
@@ -534,15 +655,20 @@
                  "DW_FORM_LLVM_addrx_offset is not supported");
           std::lock_guard<std::mutex> Lock(DebugInfoPatcherMutex);
           if (Form == dwarf::DW_FORM_GNU_addr_index) {
-            assert(Unit.isDWOUnit() &&
-                   "DW_FORM_GNU_addr_index in Non DWO unit.");
             uint64_t Index = Value.getRawUValue();
             // If there is no new address, storing old address.
             // Re-using Index to make implementation easier.
-            // DW_FORM_GNU_addr_index is variable lenght encoding so we either
-            // have to create indices of same sizes, or use same index.
+            // DW_FORM_GNU_addr_index is variable lenght encoding
+            // so we either have to create indices of same sizes, or use same
+            // index.
+            // TODO: We can now re-write .debug_info can simplify this by just
+            // getting new index and creating a patch.
             AddrWriter->addIndexAddress(NewAddress ? NewAddress : Address,
-                                        Index, *Unit.getDWOId());
+                                        Index, getCUId(Unit));
+          } else if (Form == dwarf::DW_FORM_addrx) {
+            uint32_t Index = AddrWriter->getIndexFromAddress(
+                NewAddress ? NewAddress : Address, getCUId(Unit));
+            DebugInfoPatcher.addUDataPatch(AttrOffset, Index, AttrVal->Size);
           } else {
             DebugInfoPatcher.addLE64Patch(AttrOffset, NewAddress);
           }
@@ -616,6 +742,9 @@
     // are needed for ranges base.
     Optional<AttrInfo> RangesBaseAttrInfo =
         findAttributeInfo(DIE, dwarf::DW_AT_GNU_ranges_base);
+    if (!RangesBaseAttrInfo)
+      RangesBaseAttrInfo = findAttributeInfo(DIE, dwarf::DW_AT_rnglists_base);
+
     if (RangesBaseAttrInfo) {
       DebugInfoPatcher.addLE32Patch(RangesBaseAttrInfo->Offset,
                                     static_cast<uint32_t>(*RangesBase),
@@ -626,15 +755,28 @@
 
   Optional<AttrInfo> LowPCAttrInfo =
       findAttributeInfo(DIE, dwarf::DW_AT_low_pc);
-  if (AbbreviationDecl->findAttributeIndex(dwarf::DW_AT_ranges)) {
+  if (Optional<AttrInfo> AttrVal =
+          findAttributeInfo(DIE, dwarf::DW_AT_ranges)) {
     // Case 1: The object was already non-contiguous and had DW_AT_ranges.
     // In this case we simply need to update the value of DW_AT_ranges
     // and introduce DW_AT_GNU_ranges_base if required.
-    Optional<AttrInfo> AttrVal = findAttributeInfo(DIE, dwarf::DW_AT_ranges);
     std::lock_guard<std::mutex> Lock(DebugInfoPatcherMutex);
-    DebugInfoPatcher.addLE32Patch(
-        AttrVal->Offset, DebugRangesOffset - DebugInfoPatcher.getRangeBase(),
-        AttrVal->Size);
+    // For DWARF5 converting all of DW_AT_ranges into DW_FORM_rnglistx
+    bool Converted = false;
+    if (DIE.getDwarfUnit()->getVersion() == 5 &&
+        AttrVal->V.getForm() == dwarf::DW_FORM_sec_offset) {
+      AbbrevWriter.addAttributePatch(*DIE.getDwarfUnit(), AbbreviationDecl,
+                                     dwarf::DW_AT_ranges, dwarf::DW_AT_ranges,
+                                     dwarf::DW_FORM_rnglistx);
+      Converted = true;
+    }
+    if (Converted || AttrVal->V.getForm() == dwarf::DW_FORM_rnglistx)
+      DebugInfoPatcher.addUDataPatch(AttrVal->Offset, DebugRangesOffset,
+                                     AttrVal->Size);
+    else
+      DebugInfoPatcher.addLE32Patch(
+          AttrVal->Offset, DebugRangesOffset - DebugInfoPatcher.getRangeBase(),
+          AttrVal->Size);
 
     if (!RangesBase) {
       if (LowPCAttrInfo &&
@@ -769,15 +911,27 @@
 
   std::unique_ptr<DebugBufferVector> RangesSectionContents =
       RangesSectionWriter->finalize();
-  BC.registerOrUpdateNoteSection(".debug_ranges",
-                                 copyByteArray(*RangesSectionContents),
-                                 RangesSectionContents->size());
+  BC.registerOrUpdateNoteSection(
+      llvm::isa<DebugRangelistsSectionWriter>(*RangesSectionWriter)
+          ? ".debug_rnglists"
+          : ".debug_ranges",
+      copyByteArray(*RangesSectionContents), RangesSectionContents->size());
+
+  if (BC.isDWARF5Used()) {
+    std::unique_ptr<DebugBufferVector> LocationListSectionContents =
+        makeFinalLocListsSection(DebugInfoPatcher, DWARFVersion::DWARF5);
+    BC.registerOrUpdateNoteSection(".debug_loclists",
+                                   copyByteArray(*LocationListSectionContents),
+                                   LocationListSectionContents->size());
+  }
 
-  std::unique_ptr<DebugBufferVector> LocationListSectionContents =
-      makeFinalLocListsSection(DebugInfoPatcher);
-  BC.registerOrUpdateNoteSection(".debug_loc",
-                                 copyByteArray(*LocationListSectionContents),
-                                 LocationListSectionContents->size());
+  if (BC.isDWARFLegacyUsed()) {
+    std::unique_ptr<DebugBufferVector> LocationListSectionContents =
+        makeFinalLocListsSection(DebugInfoPatcher, DWARFVersion::DWARFLegacy);
+    BC.registerOrUpdateNoteSection(".debug_loc",
+                                   copyByteArray(*LocationListSectionContents),
+                                   LocationListSectionContents->size());
+  }
 
   // AddrWriter should be finalized after debug_loc since more addresses can be
   // added there.
@@ -788,12 +942,40 @@
                                    AddressSectionContents.size());
     for (auto &CU : BC.DwCtx->compile_units()) {
       DWARFDie DIE = CU->getUnitDIE();
-      if (Optional<AttrInfo> AttrVal =
-              findAttributeInfo(DIE, dwarf::DW_AT_GNU_addr_base)) {
-        uint64_t Offset = AddrWriter->getOffset(*CU->getDWOId());
-        DebugInfoPatcher.addLE32Patch(
-            AttrVal->Offset, static_cast<int32_t>(Offset), AttrVal->Size);
+      uint64_t Offset = 0;
+      uint64_t AttrOffset = 0;
+      uint32_t Size = 0;
+      Optional<AttrInfo> AttrValGnu =
+          findAttributeInfo(DIE, dwarf::DW_AT_GNU_addr_base);
+      Optional<AttrInfo> AttrVal =
+          findAttributeInfo(DIE, dwarf::DW_AT_addr_base);
+      Offset = AddrWriter->getOffset(*CU);
+
+      if (AttrValGnu) {
+        AttrOffset = AttrValGnu->Offset;
+        Size = AttrValGnu->Size;
+      }
+
+      if (AttrVal) {
+        AttrOffset = AttrVal->Offset;
+        Size = AttrVal->Size;
       }
+
+      if (AttrValGnu || AttrVal)
+        DebugInfoPatcher.addLE32Patch(AttrOffset, static_cast<int32_t>(Offset),
+                                      Size);
+      else if (CU->getVersion() == 5) {
+        // A case where we were not using .debug_addr section, but after update
+        // now using it.
+        const DWARFAbbreviationDeclaration *Abbrev =
+            DIE.getAbbreviationDeclarationPtr();
+        AbbrevWriter->addAttribute(*CU, Abbrev, dwarf::DW_AT_addr_base,
+                                   dwarf::DW_FORM_sec_offset);
+        DebugInfoPatcher.insertNewEntry(DIE, static_cast<int32_t>(Offset));
+      } else
+        assert(
+            false &&
+            "DWO CU uses .debug_address, but DW_AT_GNU_addr_base is missin.");
     }
   }
 
@@ -811,13 +993,22 @@
     if (Unit->getAbbreviationsOffset() == NewAbbrevOffset)
       continue;
 
-    // DWARFv4
+    // DWARFv4 or earlier
     // unit_length - 4 bytes
     // version - 2 bytes
     // So + 6 to patch debug_abbrev_offset
-    constexpr uint64_t AbbrevFieldOffset = 6;
-    if (!Unit->isTypeUnit()) {
-      DebugInfoPatcher.addLE32Patch(Unit->getOffset() + AbbrevFieldOffset,
+    constexpr uint64_t AbbrevFieldOffsetLegacy = 6;
+    // DWARFv5
+    // unit_length - 4 bytes
+    // version - 2 bytes
+    // unit_type - 1 byte
+    // address_size - 1 byte
+    // So + 8 to patch debug_abbrev_offset
+    constexpr uint64_t AbbrevFieldOffsetV5 = 8;
+    uint64_t AbbrevOffset =
+        Unit->getVersion() == 5 ? AbbrevFieldOffsetV5 : AbbrevFieldOffsetLegacy;
+    if (!Unit->isTypeUnit() || Unit->getVersion() == 5) {
+      DebugInfoPatcher.addLE32Patch(Unit->getOffset() + AbbrevOffset,
                                     static_cast<uint32_t>(NewAbbrevOffset));
       continue;
     }
@@ -829,7 +1020,7 @@
       DebugTypesPatcher =
           static_cast<SimpleBinaryPatcher *>(DebugTypes->getPatcher());
     }
-    DebugTypesPatcher->addLE32Patch(Unit->getOffset() + AbbrevFieldOffset,
+    DebugTypesPatcher->addLE32Patch(Unit->getOffset() + AbbrevOffset,
                                     static_cast<uint32_t>(NewAbbrevOffset));
   }
 
@@ -1295,25 +1486,40 @@
 }
 
 std::unique_ptr<DebugBufferVector>
-DWARFRewriter::makeFinalLocListsSection(SimpleBinaryPatcher &DebugInfoPatcher) {
+DWARFRewriter::makeFinalLocListsSection(SimpleBinaryPatcher &DebugInfoPatcher,
+                                        DWARFVersion Version) {
   auto LocBuffer = std::make_unique<DebugBufferVector>();
   auto LocStream = std::make_unique<raw_svector_ostream>(*LocBuffer);
   auto Writer =
       std::unique_ptr<MCObjectWriter>(BC.createObjectWriter(*LocStream));
 
   uint64_t SectionOffset = 0;
-
   // Add an empty list as the first entry;
-  const char Zeroes[16] = {0};
-  *LocStream << StringRef(Zeroes, 16);
-  SectionOffset += 2 * 8;
+  if (LocListWritersByCU.empty() ||
+      LocListWritersByCU.begin()->second.get()->getDwarfVersion() < 5) {
+    // Should be fine for both DWARF4 and DWARF5?
+    const char Zeroes[16] = {0};
+    *LocStream << StringRef(Zeroes, 16);
+    SectionOffset += 2 * 8;
+  }
 
   for (std::pair<const uint64_t, std::unique_ptr<DebugLocWriter>> &Loc :
        LocListWritersByCU) {
     DebugLocWriter *LocWriter = Loc.second.get();
-    if (auto *LocListWriter = llvm::dyn_cast<DebugLoclistWriter>(LocWriter)) {
+    auto *LocListWriter = llvm::dyn_cast<DebugLoclistWriter>(LocWriter);
+
+    if (Version == DWARFVersion::DWARF5 &&
+        (!LocListWriter || LocListWriter->getDwarfVersion() == 4))
+      continue;
+
+    if (Version == DWARFVersion::DWARFLegacy &&
+        (LocListWriter && LocListWriter->getDwarfVersion() == 5))
+      continue;
+    if (LocListWriter && (LocListWriter->getDwarfVersion() == 4 ||
+                          (LocListWriter->getDwarfVersion() == 5 &&
+                           LocListWriter->isSplitDwarf()))) {
       SimpleBinaryPatcher *Patcher =
-          getBinaryDWODebugInfoPatcher(LocListWriter->getDWOID());
+          getBinaryDWODebugInfoPatcher(LocListWriter->getCUID());
       LocListWriter->finalize(0, *Patcher);
       continue;
     }
@@ -1339,7 +1545,8 @@
   dwarf::Form HighPCForm = HighPCVal->V.getForm();
 
   if (LowPCForm != dwarf::DW_FORM_addr &&
-      LowPCForm != dwarf::DW_FORM_GNU_addr_index) {
+      LowPCForm != dwarf::DW_FORM_GNU_addr_index &&
+      LowPCForm != dwarf::DW_FORM_addrx) {
     errs() << "BOLT-WARNING: unexpected low_pc form value. Cannot update DIE "
            << "at offset 0x" << Twine::utohexstr(DIE.getOffset()) << "\n";
     return;
@@ -1354,7 +1561,8 @@
     return;
   }
   if ((LowPCOffset == -1U || (LowPCOffset + 8 != HighPCOffset)) &&
-      LowPCForm != dwarf::DW_FORM_GNU_addr_index) {
+      LowPCForm != dwarf::DW_FORM_GNU_addr_index &&
+      LowPCForm != dwarf::DW_FORM_addrx) {
     errs() << "BOLT-WARNING: high_pc expected immediately after low_pc. "
            << "Cannot update DIE at offset 0x"
            << Twine::utohexstr(DIE.getOffset()) << '\n';
@@ -1367,24 +1575,27 @@
 void DWARFRewriter::convertToRangesPatchAbbrev(
     const DWARFUnit &Unit, const DWARFAbbreviationDeclaration *Abbrev,
     DebugAbbrevWriter &AbbrevWriter, Optional<uint64_t> RangesBase) {
-  auto getAttributeForm = [&Abbrev](const dwarf::Attribute Attr) {
-    Optional<uint32_t> Index = Abbrev->findAttributeIndex(Attr);
-    assert(Index && "attribute not found");
-    return Abbrev->getFormByIndex(*Index);
-  };
-  dwarf::Form LowPCForm = getAttributeForm(dwarf::DW_AT_low_pc);
 
-  // DW_FORM_GNU_addr_index is already variable encoding so nothing to do
-  // there.
-  if (RangesBase) {
-    assert(LowPCForm != dwarf::DW_FORM_GNU_addr_index);
-    AbbrevWriter.addAttribute(Unit, Abbrev, dwarf::DW_AT_GNU_ranges_base,
-                              dwarf::DW_FORM_sec_offset);
+  dwarf::Attribute RangeBaseAttribute = dwarf::DW_AT_GNU_ranges_base;
+  dwarf::Form RangesForm = dwarf::DW_FORM_sec_offset;
+
+  if (Unit.getVersion() == 5) {
+    RangeBaseAttribute = dwarf::DW_AT_rnglists_base;
+    RangesForm = dwarf::DW_FORM_rnglistx;
   }
+  // If we hit this point it means we converted subprogram DIEs from
+  // low_pc/high_pc into ranges. The CU originally didn't have DW_AT_*_base, so
+  // we re adding it here.
+  if (RangesBase)
+    AbbrevWriter.addAttribute(Unit, Abbrev, RangeBaseAttribute,
+                              dwarf::DW_FORM_sec_offset);
 
+  // Converting DW_AT_high_pc into DW_AT_ranges.
+  // For DWARF4 it's DW_FORM_sec_offset.
+  // For DWARF5 it can be either DW_FORM_sec_offset or DW_FORM_rnglistx.
+  // For consistency for DWARF5 we always use DW_FORM_rnglistx.
   AbbrevWriter.addAttributePatch(Unit, Abbrev, dwarf::DW_AT_high_pc,
-                                 dwarf::DW_AT_ranges,
-                                 dwarf::DW_FORM_sec_offset);
+                                 dwarf::DW_AT_ranges, RangesForm);
 }
 
 void DWARFRewriter::convertToRangesPatchDebugInfo(
@@ -1398,19 +1609,42 @@
 
   std::lock_guard<std::mutex> Lock(DebugInfoPatcherMutex);
   uint32_t BaseOffset = 0;
-  if (LowPCVal->V.getForm() == dwarf::DW_FORM_GNU_addr_index) {
+  dwarf::Form LowForm = LowPCVal->V.getForm();
+
+  // In DWARF4 for DW_AT_low_pc in binary DW_FORM_addr is used. In the DWO
+  // section DW_FORM_GNU_addr_index is used. So for if we are converting
+  // DW_AT_low_pc/DW_AT_high_pc and see DW_FORM_GNU_addr_index. We are
+  // converting in DWO section, and DW_AT_ranges [DW_FORM_sec_offset] is
+  // relative to DW_AT_GNU_ranges_base.
+  if (LowForm == dwarf::DW_FORM_GNU_addr_index) {
     // Use ULEB128 for the value.
-    DebugInfoPatcher.addUDataPatch(LowPCOffset, 0,
-                                   std::abs(int(HighPCOffset - LowPCOffset)));
+    DebugInfoPatcher.addUDataPatch(LowPCOffset, 0, LowPCVal->Size);
     // Ranges are relative to DW_AT_GNU_ranges_base.
     BaseOffset = DebugInfoPatcher.getRangeBase();
   } else {
-    DebugInfoPatcher.addLE64Patch(LowPCOffset, 0);
-    // If DW_AT_GNU_ranges_base was inserted.
+    // In DWARF 5 we can have DW_AT_low_pc either as DW_FORM_addr, or
+    // DW_FORM_addrx. Former is when DW_AT_rnglists_base is present. Latter is
+    // when it's absent.
+    if (LowForm == dwarf::DW_FORM_addrx) {
+      uint32_t Index =
+          AddrWriter->getIndexFromAddress(0, DIE.getDwarfUnit()->getOffset());
+      DebugInfoPatcher.addUDataPatch(LowPCOffset, Index, LowPCVal->Size);
+    } else
+      DebugInfoPatcher.addLE64Patch(LowPCOffset, 0);
+
+    // Original CU didn't have DW_AT_*_base. We converted it's children (or
+    // dwo), so need to insert it into CU.
     if (RangesBase)
       reinterpret_cast<DebugInfoBinaryPatcher &>(DebugInfoPatcher)
           .insertNewEntry(DIE, *RangesBase);
   }
-  DebugInfoPatcher.addLE32Patch(HighPCOffset, RangesSectionOffset - BaseOffset,
-                                HighPCVal->Size);
+
+  // HighPC was conveted into DW_AT_ranges.
+  // For DWARF5 we only access ranges throught index.
+  if (DIE.getDwarfUnit()->getVersion() == 5)
+    DebugInfoPatcher.addUDataPatch(HighPCOffset, RangesSectionOffset,
+                                   HighPCVal->Size);
+  else
+    DebugInfoPatcher.addLE32Patch(
+        HighPCOffset, RangesSectionOffset - BaseOffset, HighPCVal->Size);
 }
diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp
--- a/bolt/lib/Rewrite/RewriteInstance.cpp
+++ b/bolt/lib/Rewrite/RewriteInstance.cpp
@@ -311,8 +311,9 @@
 
 constexpr const char *RewriteInstance::SectionsToOverwrite[];
 std::vector<std::string> RewriteInstance::DebugSectionsToOverwrite = {
-    ".debug_abbrev", ".debug_aranges", ".debug_line", ".debug_loc",
-    ".debug_ranges", ".gdb_index",     ".debug_addr"};
+    ".debug_abbrev",   ".debug_aranges",  ".debug_line",
+    ".debug_loc",      ".debug_loclists", ".debug_ranges",
+    ".debug_rnglists", ".gdb_index",      ".debug_addr"};
 
 const char RewriteInstance::TimerGroupName[] = "rewrite";
 const char RewriteInstance::TimerGroupDesc[] = "Rewrite passes";
diff --git a/bolt/test/X86/Inputs/dwarf5_helper.s b/bolt/test/X86/Inputs/dwarf5_helper.s
new file mode 100644
--- /dev/null
+++ b/bolt/test/X86/Inputs/dwarf5_helper.s
@@ -0,0 +1,424 @@
+# clang++ helper.cpp -g -O2 -S
+# int fooVar = 0;
+# void useFoo(int * x) {
+# *x += 4;
+# }
+#
+# int  foo(int argc) {
+#    int x = argc;
+#    useFoo(&x);
+#    return x;
+# }
+	.text
+	.file	"foo.cpp"
+	.file	0 "/testLocListMultiple" "foo.cpp" md5 0x9410f31145d031fcc1f2464b809e409a
+	.globl	_Z6useFooPi                     # -- Begin function _Z6useFooPi
+	.p2align	4, 0x90
+	.type	_Z6useFooPi,@function
+_Z6useFooPi:                            # @_Z6useFooPi
+.Lfunc_begin0:
+	.loc	0 2 0                           # foo.cpp:2:0
+	.cfi_startproc
+# %bb.0:                                # %entry
+	#DEBUG_VALUE: useFoo:x <- $rdi
+	.loc	0 3 4 prologue_end              # foo.cpp:3:4
+	addl	$4, (%rdi)
+	.loc	0 4 1                           # foo.cpp:4:1
+	retq
+.Ltmp0:
+.Lfunc_end0:
+	.size	_Z6useFooPi, .Lfunc_end0-_Z6useFooPi
+	.cfi_endproc
+                                        # -- End function
+	.globl	_Z3fooi                         # -- Begin function _Z3fooi
+	.p2align	4, 0x90
+	.type	_Z3fooi,@function
+_Z3fooi:                                # @_Z3fooi
+.Lfunc_begin1:
+	.loc	0 6 0                           # foo.cpp:6:0
+	.cfi_startproc
+# %bb.0:                                # %entry
+	#DEBUG_VALUE: foo:argc <- $edi
+	#DEBUG_VALUE: foo:x <- $edi
+                                        # kill: def $edi killed $edi def $rdi
+	#DEBUG_VALUE: useFoo:x <- undef
+	.loc	0 3 4 prologue_end              # foo.cpp:3:4
+	leal	4(%rdi), %eax
+.Ltmp1:
+	#DEBUG_VALUE: foo:x <- $eax
+	.loc	0 9 4                           # foo.cpp:9:4
+	retq
+.Ltmp2:
+.Lfunc_end1:
+	.size	_Z3fooi, .Lfunc_end1-_Z3fooi
+	.cfi_endproc
+                                        # -- End function
+	.type	fooVar,@object                  # @fooVar
+	.bss
+	.globl	fooVar
+	.p2align	2
+fooVar:
+	.long	0                               # 0x0
+	.size	fooVar, 4
+
+	.section	.debug_loclists,"",@progbits
+	.long	.Ldebug_list_header_end0-.Ldebug_list_header_start0 # Length
+.Ldebug_list_header_start0:
+	.short	5                               # Version
+	.byte	8                               # Address size
+	.byte	0                               # Segment selector size
+	.long	1                               # Offset entry count
+.Lloclists_table_base0:
+	.long	.Ldebug_loc0-.Lloclists_table_base0
+.Ldebug_loc0:
+	.byte	4                               # DW_LLE_offset_pair
+	.uleb128 .Lfunc_begin1-.Lfunc_begin0    #   starting offset
+	.uleb128 .Ltmp1-.Lfunc_begin0           #   ending offset
+	.byte	1                               # Loc expr size
+	.byte	85                              # super-register DW_OP_reg5
+	.byte	4                               # DW_LLE_offset_pair
+	.uleb128 .Ltmp1-.Lfunc_begin0           #   starting offset
+	.uleb128 .Lfunc_end1-.Lfunc_begin0      #   ending offset
+	.byte	1                               # Loc expr size
+	.byte	80                              # super-register DW_OP_reg0
+	.byte	0                               # DW_LLE_end_of_list
+.Ldebug_list_header_end0:
+	.section	.debug_abbrev,"",@progbits
+	.byte	1                               # Abbreviation Code
+	.byte	17                              # DW_TAG_compile_unit
+	.byte	1                               # DW_CHILDREN_yes
+	.byte	37                              # DW_AT_producer
+	.byte	37                              # DW_FORM_strx1
+	.byte	19                              # DW_AT_language
+	.byte	5                               # DW_FORM_data2
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	114                             # DW_AT_str_offsets_base
+	.byte	23                              # DW_FORM_sec_offset
+	.byte	16                              # DW_AT_stmt_list
+	.byte	23                              # DW_FORM_sec_offset
+	.byte	27                              # DW_AT_comp_dir
+	.byte	37                              # DW_FORM_strx1
+	.byte	17                              # DW_AT_low_pc
+	.byte	27                              # DW_FORM_addrx
+	.byte	18                              # DW_AT_high_pc
+	.byte	6                               # DW_FORM_data4
+	.byte	115                             # DW_AT_addr_base
+	.byte	23                              # DW_FORM_sec_offset
+	.ascii	"\214\001"                      # DW_AT_loclists_base
+	.byte	23                              # DW_FORM_sec_offset
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	2                               # Abbreviation Code
+	.byte	52                              # DW_TAG_variable
+	.byte	0                               # DW_CHILDREN_no
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	73                              # DW_AT_type
+	.byte	19                              # DW_FORM_ref4
+	.byte	63                              # DW_AT_external
+	.byte	25                              # DW_FORM_flag_present
+	.byte	58                              # DW_AT_decl_file
+	.byte	11                              # DW_FORM_data1
+	.byte	59                              # DW_AT_decl_line
+	.byte	11                              # DW_FORM_data1
+	.byte	2                               # DW_AT_location
+	.byte	24                              # DW_FORM_exprloc
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	3                               # Abbreviation Code
+	.byte	36                              # DW_TAG_base_type
+	.byte	0                               # DW_CHILDREN_no
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	62                              # DW_AT_encoding
+	.byte	11                              # DW_FORM_data1
+	.byte	11                              # DW_AT_byte_size
+	.byte	11                              # DW_FORM_data1
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	4                               # Abbreviation Code
+	.byte	46                              # DW_TAG_subprogram
+	.byte	1                               # DW_CHILDREN_yes
+	.byte	17                              # DW_AT_low_pc
+	.byte	27                              # DW_FORM_addrx
+	.byte	18                              # DW_AT_high_pc
+	.byte	6                               # DW_FORM_data4
+	.byte	64                              # DW_AT_frame_base
+	.byte	24                              # DW_FORM_exprloc
+	.byte	122                             # DW_AT_call_all_calls
+	.byte	25                              # DW_FORM_flag_present
+	.byte	49                              # DW_AT_abstract_origin
+	.byte	19                              # DW_FORM_ref4
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	5                               # Abbreviation Code
+	.byte	5                               # DW_TAG_formal_parameter
+	.byte	0                               # DW_CHILDREN_no
+	.byte	2                               # DW_AT_location
+	.byte	24                              # DW_FORM_exprloc
+	.byte	49                              # DW_AT_abstract_origin
+	.byte	19                              # DW_FORM_ref4
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	6                               # Abbreviation Code
+	.byte	46                              # DW_TAG_subprogram
+	.byte	1                               # DW_CHILDREN_yes
+	.byte	110                             # DW_AT_linkage_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	58                              # DW_AT_decl_file
+	.byte	11                              # DW_FORM_data1
+	.byte	59                              # DW_AT_decl_line
+	.byte	11                              # DW_FORM_data1
+	.byte	63                              # DW_AT_external
+	.byte	25                              # DW_FORM_flag_present
+	.byte	32                              # DW_AT_inline
+	.byte	33                              # DW_FORM_implicit_const
+	.byte	1
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	7                               # Abbreviation Code
+	.byte	5                               # DW_TAG_formal_parameter
+	.byte	0                               # DW_CHILDREN_no
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	58                              # DW_AT_decl_file
+	.byte	11                              # DW_FORM_data1
+	.byte	59                              # DW_AT_decl_line
+	.byte	11                              # DW_FORM_data1
+	.byte	73                              # DW_AT_type
+	.byte	19                              # DW_FORM_ref4
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	8                               # Abbreviation Code
+	.byte	15                              # DW_TAG_pointer_type
+	.byte	0                               # DW_CHILDREN_no
+	.byte	73                              # DW_AT_type
+	.byte	19                              # DW_FORM_ref4
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	9                               # Abbreviation Code
+	.byte	46                              # DW_TAG_subprogram
+	.byte	1                               # DW_CHILDREN_yes
+	.byte	17                              # DW_AT_low_pc
+	.byte	27                              # DW_FORM_addrx
+	.byte	18                              # DW_AT_high_pc
+	.byte	6                               # DW_FORM_data4
+	.byte	64                              # DW_AT_frame_base
+	.byte	24                              # DW_FORM_exprloc
+	.byte	122                             # DW_AT_call_all_calls
+	.byte	25                              # DW_FORM_flag_present
+	.byte	110                             # DW_AT_linkage_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	58                              # DW_AT_decl_file
+	.byte	11                              # DW_FORM_data1
+	.byte	59                              # DW_AT_decl_line
+	.byte	11                              # DW_FORM_data1
+	.byte	73                              # DW_AT_type
+	.byte	19                              # DW_FORM_ref4
+	.byte	63                              # DW_AT_external
+	.byte	25                              # DW_FORM_flag_present
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	10                              # Abbreviation Code
+	.byte	5                               # DW_TAG_formal_parameter
+	.byte	0                               # DW_CHILDREN_no
+	.byte	2                               # DW_AT_location
+	.byte	24                              # DW_FORM_exprloc
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	58                              # DW_AT_decl_file
+	.byte	11                              # DW_FORM_data1
+	.byte	59                              # DW_AT_decl_line
+	.byte	11                              # DW_FORM_data1
+	.byte	73                              # DW_AT_type
+	.byte	19                              # DW_FORM_ref4
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	11                              # Abbreviation Code
+	.byte	52                              # DW_TAG_variable
+	.byte	0                               # DW_CHILDREN_no
+	.byte	2                               # DW_AT_location
+	.byte	34                              # DW_FORM_loclistx
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	58                              # DW_AT_decl_file
+	.byte	11                              # DW_FORM_data1
+	.byte	59                              # DW_AT_decl_line
+	.byte	11                              # DW_FORM_data1
+	.byte	73                              # DW_AT_type
+	.byte	19                              # DW_FORM_ref4
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	12                              # Abbreviation Code
+	.byte	29                              # DW_TAG_inlined_subroutine
+	.byte	0                               # DW_CHILDREN_no
+	.byte	49                              # DW_AT_abstract_origin
+	.byte	19                              # DW_FORM_ref4
+	.byte	17                              # DW_AT_low_pc
+	.byte	27                              # DW_FORM_addrx
+	.byte	18                              # DW_AT_high_pc
+	.byte	6                               # DW_FORM_data4
+	.byte	88                              # DW_AT_call_file
+	.byte	11                              # DW_FORM_data1
+	.byte	89                              # DW_AT_call_line
+	.byte	11                              # DW_FORM_data1
+	.byte	87                              # DW_AT_call_column
+	.byte	11                              # DW_FORM_data1
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	0                               # EOM(3)
+	.section	.debug_info,"",@progbits
+.Lcu_begin0:
+	.long	.Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+	.short	5                               # DWARF version number
+	.byte	1                               # DWARF Unit Type
+	.byte	8                               # Address Size (in bytes)
+	.long	.debug_abbrev                   # Offset Into Abbrev. Section
+	.byte	1                               # Abbrev [1] 0xc:0x83 DW_TAG_compile_unit
+	.byte	0                               # DW_AT_producer
+	.short	33                              # DW_AT_language
+	.byte	1                               # DW_AT_name
+	.long	.Lstr_offsets_base0             # DW_AT_str_offsets_base
+	.long	.Lline_table_start0             # DW_AT_stmt_list
+	.byte	2                               # DW_AT_comp_dir
+	.byte	1                               # DW_AT_low_pc
+	.long	.Lfunc_end1-.Lfunc_begin0       # DW_AT_high_pc
+	.long	.Laddr_table_base0              # DW_AT_addr_base
+	.long	.Lloclists_table_base0          # DW_AT_loclists_base
+	.byte	2                               # Abbrev [2] 0x27:0xb DW_TAG_variable
+	.byte	3                               # DW_AT_name
+	.long	50                              # DW_AT_type
+                                        # DW_AT_external
+	.byte	0                               # DW_AT_decl_file
+	.byte	1                               # DW_AT_decl_line
+	.byte	2                               # DW_AT_location
+	.byte	161
+	.byte	0
+	.byte	3                               # Abbrev [3] 0x32:0x4 DW_TAG_base_type
+	.byte	4                               # DW_AT_name
+	.byte	5                               # DW_AT_encoding
+	.byte	4                               # DW_AT_byte_size
+	.byte	4                               # Abbrev [4] 0x36:0x14 DW_TAG_subprogram
+	.byte	1                               # DW_AT_low_pc
+	.long	.Lfunc_end0-.Lfunc_begin0       # DW_AT_high_pc
+	.byte	1                               # DW_AT_frame_base
+	.byte	87
+                                        # DW_AT_call_all_calls
+	.long	74                              # DW_AT_abstract_origin
+	.byte	5                               # Abbrev [5] 0x42:0x7 DW_TAG_formal_parameter
+	.byte	1                               # DW_AT_location
+	.byte	85
+	.long	79                              # DW_AT_abstract_origin
+	.byte	0                               # End Of Children Mark
+	.byte	6                               # Abbrev [6] 0x4a:0xe DW_TAG_subprogram
+	.byte	5                               # DW_AT_linkage_name
+	.byte	6                               # DW_AT_name
+	.byte	0                               # DW_AT_decl_file
+	.byte	2                               # DW_AT_decl_line
+                                        # DW_AT_external
+                                        # DW_AT_inline
+	.byte	7                               # Abbrev [7] 0x4f:0x8 DW_TAG_formal_parameter
+	.byte	7                               # DW_AT_name
+	.byte	0                               # DW_AT_decl_file
+	.byte	2                               # DW_AT_decl_line
+	.long	88                              # DW_AT_type
+	.byte	0                               # End Of Children Mark
+	.byte	8                               # Abbrev [8] 0x58:0x5 DW_TAG_pointer_type
+	.long	50                              # DW_AT_type
+	.byte	9                               # Abbrev [9] 0x5d:0x31 DW_TAG_subprogram
+	.byte	2                               # DW_AT_low_pc
+	.long	.Lfunc_end1-.Lfunc_begin1       # DW_AT_high_pc
+	.byte	1                               # DW_AT_frame_base
+	.byte	87
+                                        # DW_AT_call_all_calls
+	.byte	8                               # DW_AT_linkage_name
+	.byte	9                               # DW_AT_name
+	.byte	0                               # DW_AT_decl_file
+	.byte	6                               # DW_AT_decl_line
+	.long	50                              # DW_AT_type
+                                        # DW_AT_external
+	.byte	10                              # Abbrev [10] 0x6d:0xa DW_TAG_formal_parameter
+	.byte	1                               # DW_AT_location
+	.byte	85
+	.byte	10                              # DW_AT_name
+	.byte	0                               # DW_AT_decl_file
+	.byte	6                               # DW_AT_decl_line
+	.long	50                              # DW_AT_type
+	.byte	11                              # Abbrev [11] 0x77:0x9 DW_TAG_variable
+	.byte	0                               # DW_AT_location
+	.byte	7                               # DW_AT_name
+	.byte	0                               # DW_AT_decl_file
+	.byte	7                               # DW_AT_decl_line
+	.long	50                              # DW_AT_type
+	.byte	12                              # Abbrev [12] 0x80:0xd DW_TAG_inlined_subroutine
+	.long	74                              # DW_AT_abstract_origin
+	.byte	2                               # DW_AT_low_pc
+	.long	.Ltmp1-.Lfunc_begin1            # DW_AT_high_pc
+	.byte	0                               # DW_AT_call_file
+	.byte	8                               # DW_AT_call_line
+	.byte	4                               # DW_AT_call_column
+	.byte	0                               # End Of Children Mark
+	.byte	0                               # End Of Children Mark
+.Ldebug_info_end0:
+	.section	.debug_str_offsets,"",@progbits
+	.long	48                              # Length of String Offsets Set
+	.short	5
+	.short	0
+.Lstr_offsets_base0:
+	.section	.debug_str,"MS",@progbits,1
+.Linfo_string0:
+	.asciz	"clang version 15.0.0)" # string offset=0
+.Linfo_string1:
+	.asciz	"foo.cpp"                       # string offset=134
+.Linfo_string2:
+	.asciz	"/testLocListMultiple" # string offset=142
+.Linfo_string3:
+	.asciz	"fooVar"                        # string offset=199
+.Linfo_string4:
+	.asciz	"int"                           # string offset=206
+.Linfo_string5:
+	.asciz	"_Z6useFooPi"                   # string offset=210
+.Linfo_string6:
+	.asciz	"useFoo"                        # string offset=222
+.Linfo_string7:
+	.asciz	"x"                             # string offset=229
+.Linfo_string8:
+	.asciz	"_Z3fooi"                       # string offset=231
+.Linfo_string9:
+	.asciz	"foo"                           # string offset=239
+.Linfo_string10:
+	.asciz	"argc"                          # string offset=243
+	.section	.debug_str_offsets,"",@progbits
+	.long	.Linfo_string0
+	.long	.Linfo_string1
+	.long	.Linfo_string2
+	.long	.Linfo_string3
+	.long	.Linfo_string4
+	.long	.Linfo_string5
+	.long	.Linfo_string6
+	.long	.Linfo_string7
+	.long	.Linfo_string8
+	.long	.Linfo_string9
+	.long	.Linfo_string10
+	.section	.debug_addr,"",@progbits
+	.long	.Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution
+.Ldebug_addr_start0:
+	.short	5                               # DWARF version number
+	.byte	8                               # Address size
+	.byte	0                               # Segment selector size
+.Laddr_table_base0:
+	.quad	fooVar
+	.quad	.Lfunc_begin0
+	.quad	.Lfunc_begin1
+.Ldebug_addr_end0:
+	.ident	"clang version 15.0.0"
+	.section	".note.GNU-stack","",@progbits
+	.addrsig
+	.section	.debug_line,"",@progbits
+.Lline_table_start0:
diff --git a/bolt/test/X86/Inputs/dwarf5_main.s b/bolt/test/X86/Inputs/dwarf5_main.s
new file mode 100644
--- /dev/null
+++ b/bolt/test/X86/Inputs/dwarf5_main.s
@@ -0,0 +1,394 @@
+# clang++ main.cpp -g -O2 -S
+# void use(int * x, int * y) {
+# *x += 4;
+# *y -= 2;
+# }
+#
+# extern int fooVar;
+# int  main(int argc, char *argv[]) {
+#    int x = argc;
+#    int y = fooVar + 3;
+#    use(&x, &y);
+#    return x + y;
+# }
+
+
+	.text
+	.file	"main.cpp"
+	.globl	_Z3usePiS_                      # -- Begin function _Z3usePiS_
+	.p2align	4, 0x90
+	.type	_Z3usePiS_,@function
+_Z3usePiS_:                             # @_Z3usePiS_
+.Lfunc_begin0:
+	.file	0 "/testLocListMultiple" "main.cpp" md5 0xb1a1551182284263b0faa0cae08277da
+	.loc	0 1 0                           # main.cpp:1:0
+	.cfi_startproc
+# %bb.0:                                # %entry
+	#DEBUG_VALUE: use:x <- $rdi
+	#DEBUG_VALUE: use:y <- $rsi
+	.loc	0 2 4 prologue_end              # main.cpp:2:4
+	addl	$4, (%rdi)
+	.loc	0 3 4                           # main.cpp:3:4
+	addl	$-2, (%rsi)
+	.loc	0 4 1                           # main.cpp:4:1
+	retq
+.Ltmp0:
+.Lfunc_end0:
+	.size	_Z3usePiS_, .Lfunc_end0-_Z3usePiS_
+	.cfi_endproc
+                                        # -- End function
+	.globl	main                            # -- Begin function main
+	.p2align	4, 0x90
+	.type	main,@function
+main:                                   # @main
+.Lfunc_begin1:
+	.loc	0 7 0                           # main.cpp:7:0
+	.cfi_startproc
+# %bb.0:                                # %entry
+	#DEBUG_VALUE: main:argc <- $edi
+	#DEBUG_VALUE: main:argv <- $rsi
+	#DEBUG_VALUE: main:x <- $edi
+                                        # kill: def $edi killed $edi def $rdi
+	.loc	0 9 12 prologue_end             # main.cpp:9:12
+	movl	fooVar(%rip), %eax
+.Ltmp1:
+	#DEBUG_VALUE: main:y <- [DW_OP_plus_uconst 3, DW_OP_stack_value] $eax
+	#DEBUG_VALUE: main:y <- [DW_OP_plus_uconst 1, DW_OP_stack_value] $eax
+	#DEBUG_VALUE: main:x <- [DW_OP_plus_uconst 4, DW_OP_stack_value] $edi
+	.loc	0 11 13                         # main.cpp:11:13
+	addl	%edi, %eax
+.Ltmp2:
+	addl	$5, %eax
+	.loc	0 11 4 is_stmt 0                # main.cpp:11:4
+	retq
+.Ltmp3:
+.Lfunc_end1:
+	.size	main, .Lfunc_end1-main
+	.cfi_endproc
+                                        # -- End function
+	.section	.debug_loclists,"",@progbits
+	.long	.Ldebug_list_header_end0-.Ldebug_list_header_start0 # Length
+.Ldebug_list_header_start0:
+	.short	5                               # Version
+	.byte	8                               # Address size
+	.byte	0                               # Segment selector size
+	.long	2                               # Offset entry count
+.Lloclists_table_base0:
+	.long	.Ldebug_loc0-.Lloclists_table_base0
+	.long	.Ldebug_loc1-.Lloclists_table_base0
+.Ldebug_loc0:
+	.byte	4                               # DW_LLE_offset_pair
+	.uleb128 .Lfunc_begin1-.Lfunc_begin0    #   starting offset
+	.uleb128 .Ltmp1-.Lfunc_begin0           #   ending offset
+	.byte	1                               # Loc expr size
+	.byte	85                              # super-register DW_OP_reg5
+	.byte	4                               # DW_LLE_offset_pair
+	.uleb128 .Ltmp1-.Lfunc_begin0           #   starting offset
+	.uleb128 .Lfunc_end1-.Lfunc_begin0      #   ending offset
+	.byte	10                              # Loc expr size
+	.byte	117                             # DW_OP_breg5
+	.byte	4                               # 4
+	.byte	16                              # DW_OP_constu
+	.byte	255                             # 4294967295
+	.byte	255                             #
+	.byte	255                             #
+	.byte	255                             #
+	.byte	15                              #
+	.byte	26                              # DW_OP_and
+	.byte	159                             # DW_OP_stack_value
+	.byte	0                               # DW_LLE_end_of_list
+.Ldebug_loc1:
+	.byte	4                               # DW_LLE_offset_pair
+	.uleb128 .Ltmp1-.Lfunc_begin0           #   starting offset
+	.uleb128 .Ltmp2-.Lfunc_begin0           #   ending offset
+	.byte	10                              # Loc expr size
+	.byte	112                             # DW_OP_breg0
+	.byte	1                               # 1
+	.byte	16                              # DW_OP_constu
+	.byte	255                             # 4294967295
+	.byte	255                             #
+	.byte	255                             #
+	.byte	255                             #
+	.byte	15                              #
+	.byte	26                              # DW_OP_and
+	.byte	159                             # DW_OP_stack_value
+	.byte	0                               # DW_LLE_end_of_list
+.Ldebug_list_header_end0:
+	.section	.debug_abbrev,"",@progbits
+	.byte	1                               # Abbreviation Code
+	.byte	17                              # DW_TAG_compile_unit
+	.byte	1                               # DW_CHILDREN_yes
+	.byte	37                              # DW_AT_producer
+	.byte	37                              # DW_FORM_strx1
+	.byte	19                              # DW_AT_language
+	.byte	5                               # DW_FORM_data2
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	114                             # DW_AT_str_offsets_base
+	.byte	23                              # DW_FORM_sec_offset
+	.byte	16                              # DW_AT_stmt_list
+	.byte	23                              # DW_FORM_sec_offset
+	.byte	27                              # DW_AT_comp_dir
+	.byte	37                              # DW_FORM_strx1
+	.byte	17                              # DW_AT_low_pc
+	.byte	27                              # DW_FORM_addrx
+	.byte	18                              # DW_AT_high_pc
+	.byte	6                               # DW_FORM_data4
+	.byte	115                             # DW_AT_addr_base
+	.byte	23                              # DW_FORM_sec_offset
+	.ascii	"\214\001"                      # DW_AT_loclists_base
+	.byte	23                              # DW_FORM_sec_offset
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	2                               # Abbreviation Code
+	.byte	46                              # DW_TAG_subprogram
+	.byte	1                               # DW_CHILDREN_yes
+	.byte	17                              # DW_AT_low_pc
+	.byte	27                              # DW_FORM_addrx
+	.byte	18                              # DW_AT_high_pc
+	.byte	6                               # DW_FORM_data4
+	.byte	64                              # DW_AT_frame_base
+	.byte	24                              # DW_FORM_exprloc
+	.byte	122                             # DW_AT_call_all_calls
+	.byte	25                              # DW_FORM_flag_present
+	.byte	110                             # DW_AT_linkage_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	58                              # DW_AT_decl_file
+	.byte	11                              # DW_FORM_data1
+	.byte	59                              # DW_AT_decl_line
+	.byte	11                              # DW_FORM_data1
+	.byte	63                              # DW_AT_external
+	.byte	25                              # DW_FORM_flag_present
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	3                               # Abbreviation Code
+	.byte	5                               # DW_TAG_formal_parameter
+	.byte	0                               # DW_CHILDREN_no
+	.byte	2                               # DW_AT_location
+	.byte	24                              # DW_FORM_exprloc
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	58                              # DW_AT_decl_file
+	.byte	11                              # DW_FORM_data1
+	.byte	59                              # DW_AT_decl_line
+	.byte	11                              # DW_FORM_data1
+	.byte	73                              # DW_AT_type
+	.byte	19                              # DW_FORM_ref4
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	4                               # Abbreviation Code
+	.byte	46                              # DW_TAG_subprogram
+	.byte	1                               # DW_CHILDREN_yes
+	.byte	17                              # DW_AT_low_pc
+	.byte	27                              # DW_FORM_addrx
+	.byte	18                              # DW_AT_high_pc
+	.byte	6                               # DW_FORM_data4
+	.byte	64                              # DW_AT_frame_base
+	.byte	24                              # DW_FORM_exprloc
+	.byte	122                             # DW_AT_call_all_calls
+	.byte	25                              # DW_FORM_flag_present
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	58                              # DW_AT_decl_file
+	.byte	11                              # DW_FORM_data1
+	.byte	59                              # DW_AT_decl_line
+	.byte	11                              # DW_FORM_data1
+	.byte	73                              # DW_AT_type
+	.byte	19                              # DW_FORM_ref4
+	.byte	63                              # DW_AT_external
+	.byte	25                              # DW_FORM_flag_present
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	5                               # Abbreviation Code
+	.byte	52                              # DW_TAG_variable
+	.byte	0                               # DW_CHILDREN_no
+	.byte	2                               # DW_AT_location
+	.byte	34                              # DW_FORM_loclistx
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	58                              # DW_AT_decl_file
+	.byte	11                              # DW_FORM_data1
+	.byte	59                              # DW_AT_decl_line
+	.byte	11                              # DW_FORM_data1
+	.byte	73                              # DW_AT_type
+	.byte	19                              # DW_FORM_ref4
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	6                               # Abbreviation Code
+	.byte	36                              # DW_TAG_base_type
+	.byte	0                               # DW_CHILDREN_no
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	62                              # DW_AT_encoding
+	.byte	11                              # DW_FORM_data1
+	.byte	11                              # DW_AT_byte_size
+	.byte	11                              # DW_FORM_data1
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	7                               # Abbreviation Code
+	.byte	15                              # DW_TAG_pointer_type
+	.byte	0                               # DW_CHILDREN_no
+	.byte	73                              # DW_AT_type
+	.byte	19                              # DW_FORM_ref4
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	0                               # EOM(3)
+	.section	.debug_info,"",@progbits
+.Lcu_begin0:
+	.long	.Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+	.short	5                               # DWARF version number
+	.byte	1                               # DWARF Unit Type
+	.byte	8                               # Address Size (in bytes)
+	.long	.debug_abbrev                   # Offset Into Abbrev. Section
+	.byte	1                               # Abbrev [1] 0xc:0x8a DW_TAG_compile_unit
+	.byte	0                               # DW_AT_producer
+	.short	33                              # DW_AT_language
+	.byte	1                               # DW_AT_name
+	.long	.Lstr_offsets_base0             # DW_AT_str_offsets_base
+	.long	.Lline_table_start0             # DW_AT_stmt_list
+	.byte	2                               # DW_AT_comp_dir
+	.byte	0                               # DW_AT_low_pc
+	.long	.Lfunc_end1-.Lfunc_begin0       # DW_AT_high_pc
+	.long	.Laddr_table_base0              # DW_AT_addr_base
+	.long	.Lloclists_table_base0          # DW_AT_loclists_base
+	.byte	2                               # Abbrev [2] 0x27:0x21 DW_TAG_subprogram
+	.byte	0                               # DW_AT_low_pc
+	.long	.Lfunc_end0-.Lfunc_begin0       # DW_AT_high_pc
+	.byte	1                               # DW_AT_frame_base
+	.byte	87
+                                        # DW_AT_call_all_calls
+	.byte	3                               # DW_AT_linkage_name
+	.byte	4                               # DW_AT_name
+	.byte	0                               # DW_AT_decl_file
+	.byte	1                               # DW_AT_decl_line
+                                        # DW_AT_external
+	.byte	3                               # Abbrev [3] 0x33:0xa DW_TAG_formal_parameter
+	.byte	1                               # DW_AT_location
+	.byte	85
+	.byte	7                               # DW_AT_name
+	.byte	0                               # DW_AT_decl_file
+	.byte	1                               # DW_AT_decl_line
+	.long	130                             # DW_AT_type
+	.byte	3                               # Abbrev [3] 0x3d:0xa DW_TAG_formal_parameter
+	.byte	1                               # DW_AT_location
+	.byte	84
+	.byte	8                               # DW_AT_name
+	.byte	0                               # DW_AT_decl_file
+	.byte	1                               # DW_AT_decl_line
+	.long	130                             # DW_AT_type
+	.byte	0                               # End Of Children Mark
+	.byte	4                               # Abbrev [4] 0x48:0x36 DW_TAG_subprogram
+	.byte	1                               # DW_AT_low_pc
+	.long	.Lfunc_end1-.Lfunc_begin1       # DW_AT_high_pc
+	.byte	1                               # DW_AT_frame_base
+	.byte	87
+                                        # DW_AT_call_all_calls
+	.byte	5                               # DW_AT_name
+	.byte	0                               # DW_AT_decl_file
+	.byte	7                               # DW_AT_decl_line
+	.long	126                             # DW_AT_type
+                                        # DW_AT_external
+	.byte	3                               # Abbrev [3] 0x57:0xa DW_TAG_formal_parameter
+	.byte	1                               # DW_AT_location
+	.byte	85
+	.byte	9                               # DW_AT_name
+	.byte	0                               # DW_AT_decl_file
+	.byte	7                               # DW_AT_decl_line
+	.long	126                             # DW_AT_type
+	.byte	3                               # Abbrev [3] 0x61:0xa DW_TAG_formal_parameter
+	.byte	1                               # DW_AT_location
+	.byte	84
+	.byte	10                              # DW_AT_name
+	.byte	0                               # DW_AT_decl_file
+	.byte	7                               # DW_AT_decl_line
+	.long	135                             # DW_AT_type
+	.byte	5                               # Abbrev [5] 0x6b:0x9 DW_TAG_variable
+	.byte	0                               # DW_AT_location
+	.byte	7                               # DW_AT_name
+	.byte	0                               # DW_AT_decl_file
+	.byte	8                               # DW_AT_decl_line
+	.long	126                             # DW_AT_type
+	.byte	5                               # Abbrev [5] 0x74:0x9 DW_TAG_variable
+	.byte	1                               # DW_AT_location
+	.byte	8                               # DW_AT_name
+	.byte	0                               # DW_AT_decl_file
+	.byte	9                               # DW_AT_decl_line
+	.long	126                             # DW_AT_type
+	.byte	0                               # End Of Children Mark
+	.byte	6                               # Abbrev [6] 0x7e:0x4 DW_TAG_base_type
+	.byte	6                               # DW_AT_name
+	.byte	5                               # DW_AT_encoding
+	.byte	4                               # DW_AT_byte_size
+	.byte	7                               # Abbrev [7] 0x82:0x5 DW_TAG_pointer_type
+	.long	126                             # DW_AT_type
+	.byte	7                               # Abbrev [7] 0x87:0x5 DW_TAG_pointer_type
+	.long	140                             # DW_AT_type
+	.byte	7                               # Abbrev [7] 0x8c:0x5 DW_TAG_pointer_type
+	.long	145                             # DW_AT_type
+	.byte	6                               # Abbrev [6] 0x91:0x4 DW_TAG_base_type
+	.byte	11                              # DW_AT_name
+	.byte	6                               # DW_AT_encoding
+	.byte	1                               # DW_AT_byte_size
+	.byte	0                               # End Of Children Mark
+.Ldebug_info_end0:
+	.section	.debug_str_offsets,"",@progbits
+	.long	52                              # Length of String Offsets Set
+	.short	5
+	.short	0
+.Lstr_offsets_base0:
+	.section	.debug_str,"MS",@progbits,1
+.Linfo_string0:
+	.asciz	"clang version 15.0.0" # string offset=0
+.Linfo_string1:
+	.asciz	"main.cpp"                      # string offset=134
+.Linfo_string2:
+	.asciz	"/testLocListMultiple" # string offset=143
+.Linfo_string3:
+	.asciz	"_Z3usePiS_"                    # string offset=200
+.Linfo_string4:
+	.asciz	"use"                           # string offset=211
+.Linfo_string5:
+	.asciz	"main"                          # string offset=215
+.Linfo_string6:
+	.asciz	"int"                           # string offset=220
+.Linfo_string7:
+	.asciz	"x"                             # string offset=224
+.Linfo_string8:
+	.asciz	"y"                             # string offset=226
+.Linfo_string9:
+	.asciz	"argc"                          # string offset=228
+.Linfo_string10:
+	.asciz	"argv"                          # string offset=233
+.Linfo_string11:
+	.asciz	"char"                          # string offset=238
+	.section	.debug_str_offsets,"",@progbits
+	.long	.Linfo_string0
+	.long	.Linfo_string1
+	.long	.Linfo_string2
+	.long	.Linfo_string3
+	.long	.Linfo_string4
+	.long	.Linfo_string5
+	.long	.Linfo_string6
+	.long	.Linfo_string7
+	.long	.Linfo_string8
+	.long	.Linfo_string9
+	.long	.Linfo_string10
+	.long	.Linfo_string11
+	.section	.debug_addr,"",@progbits
+	.long	.Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution
+.Ldebug_addr_start0:
+	.short	5                               # DWARF version number
+	.byte	8                               # Address size
+	.byte	0                               # Segment selector size
+.Laddr_table_base0:
+	.quad	.Lfunc_begin0
+	.quad	.Lfunc_begin1
+.Ldebug_addr_end0:
+	.ident	"clang version 15.0.0"
+	.section	".note.GNU-stack","",@progbits
+	.addrsig
+	.section	.debug_line,"",@progbits
+.Lline_table_start0:
diff --git a/bolt/test/X86/dwarf5_debug_info_dwarf4_debug_line.s b/bolt/test/X86/dwarf5_debug_info_dwarf4_debug_line.s
new file mode 100644
--- /dev/null
+++ b/bolt/test/X86/dwarf5_debug_info_dwarf4_debug_line.s
@@ -0,0 +1,167 @@
+# REQUIRES: system-linux
+
+# RUN: llvm-mc -dwarf-version=4 -filetype=obj -triple x86_64-unknown-linux %s -o %t1.o
+# RUN: %clang %cflags -dwarf-5 %t1.o -o %t.exe -Wl,-q
+# RUN: llvm-bolt %t.exe -o %t.bolt -update-debug-sections
+# RUN: llvm-dwarfdump --show-form --verbose --debug-line %t.exe | FileCheck --check-prefix=PRECHECK %s
+# RUN: llvm-dwarfdump --show-form --verbose --debug-line %t.bolt | FileCheck --check-prefix=POSTCHECK %s
+
+# This test checks that .debug_line gets generated correctly when .debug_info is DWARF5, and .debug_line is DWARF4.
+
+# PRECHECK: version: 4
+# PRECHECK: file_names[  1]:
+# PRECHECK-NEXT: name: "main.cpp"
+# PRECHECK-NEXT: dir_index: 0
+# PRECHECK-NEXT: mod_time: 0x00000000
+# PRECHECK-NEXT: length: 0x00000000
+
+# POSTCHECK: version: 4
+# POSTCHECK: file_names[  1]:
+# POSTCHECK-NEXT: name: "main.cpp"
+# POSTCHECK-NEXT: dir_index: 0
+# POSTCHECK-NEXT: mod_time: 0x00000000
+# POSTCHECK-NEXT: length: 0x00000000
+
+# int main() {
+#    return 0;
+# }
+
+
+	.file	"main.cpp"
+	.text
+.Ltext0:
+	.globl	main
+	.type	main, @function
+main:
+.LFB0:
+	.file 1 "main.cpp"
+	.loc 1 1 12
+	.cfi_startproc
+	pushq	%rbp
+	.cfi_def_cfa_offset 16
+	.cfi_offset 6, -16
+	movq	%rsp, %rbp
+	.cfi_def_cfa_register 6
+	.loc 1 2 10
+	movl	$0, %eax
+	.loc 1 3 1
+	popq	%rbp
+	.cfi_def_cfa 7, 8
+	ret
+	.cfi_endproc
+.LFE0:
+	.size	main, .-main
+.Letext0:
+	.section	.debug_info,"",@progbits
+.Ldebug_info0:
+	.long	0x50
+	.value	0x5
+	.byte	0x1
+	.byte	0x8
+	.long	.Ldebug_abbrev0
+	.uleb128 0x1
+	.long	.LASF0
+	.byte	0x21
+	.long	.LASF1
+	.long	.LASF2
+	.quad	.Ltext0
+	.quad	.Letext0-.Ltext0
+	.long	.Ldebug_line0
+	.uleb128 0x2
+	.long	.LASF3
+	.byte	0x1
+	.byte	0x1
+	.byte	0x5
+	.long	0x4c
+	.quad	.LFB0
+	.quad	.LFE0-.LFB0
+	.uleb128 0x1
+	.byte	0x9c
+	.uleb128 0x3
+	.byte	0x4
+	.byte	0x5
+	.string	"int"
+	.byte	0
+	.section	.debug_abbrev,"",@progbits
+.Ldebug_abbrev0:
+	.uleb128 0x1
+	.uleb128 0x11
+	.byte	0x1
+	.uleb128 0x25
+	.uleb128 0xe
+	.uleb128 0x13
+	.uleb128 0xb
+	.uleb128 0x3
+	.uleb128 0xe
+	.uleb128 0x1b
+	.uleb128 0xe
+	.uleb128 0x11
+	.uleb128 0x1
+	.uleb128 0x12
+	.uleb128 0x7
+	.uleb128 0x10
+	.uleb128 0x17
+	.byte	0
+	.byte	0
+	.uleb128 0x2
+	.uleb128 0x2e
+	.byte	0
+	.uleb128 0x3f
+	.uleb128 0x19
+	.uleb128 0x3
+	.uleb128 0xe
+	.uleb128 0x3a
+	.uleb128 0xb
+	.uleb128 0x3b
+	.uleb128 0xb
+	.uleb128 0x39
+	.uleb128 0xb
+	.uleb128 0x49
+	.uleb128 0x13
+	.uleb128 0x11
+	.uleb128 0x1
+	.uleb128 0x12
+	.uleb128 0x7
+	.uleb128 0x40
+	.uleb128 0x18
+	.uleb128 0x7a
+	.uleb128 0x19
+	.byte	0
+	.byte	0
+	.uleb128 0x3
+	.uleb128 0x24
+	.byte	0
+	.uleb128 0xb
+	.uleb128 0xb
+	.uleb128 0x3e
+	.uleb128 0xb
+	.uleb128 0x3
+	.uleb128 0x8
+	.byte	0
+	.byte	0
+	.byte	0
+	.section	.debug_aranges,"",@progbits
+	.long	0x2c
+	.value	0x2
+	.long	.Ldebug_info0
+	.byte	0x8
+	.byte	0
+	.value	0
+	.value	0
+	.quad	.Ltext0
+	.quad	.Letext0-.Ltext0
+	.quad	0
+	.quad	0
+	.section	.debug_line,"",@progbits
+.Ldebug_line0:
+	.section	.debug_str,"MS",@progbits,1
+.LASF0:
+	.string	"GNU C++14 8.5.0 20210514 (Red Hat 8.5.0-3) -mtune=generic -march=x86-64 -g2 -gdwarf-5"
+.LASF1:
+	.string	"main.cpp"
+.LASF3:
+	.string	"main"
+.LASF2:
+	.string	"."
+	.ident	"GCC: (GNU) 8.5.0 20210514 (Red Hat 8.5.0-3)"
+	.section	.note.GNU-stack,"",@progbits
diff --git a/bolt/test/X86/dwarf5_debug_line.s b/bolt/test/X86/dwarf5_debug_line.s
new file mode 100644
--- /dev/null
+++ b/bolt/test/X86/dwarf5_debug_line.s
@@ -0,0 +1,185 @@
+# REQUIRES: system-linux
+
+# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %s -o %t1.o
+# RUN: %clang %cflags -dwarf-5 %t1.o -o %t.exe -Wl,-q
+# RUN: llvm-bolt %t.exe -o %t.bolt -update-debug-sections
+# RUN: llvm-dwarfdump --show-form --verbose --debug-line %t.exe | FileCheck --check-prefix=PRECHECK %s
+# RUN: llvm-dwarfdump --show-form --verbose --debug-line %t.bolt | FileCheck --check-prefix=POSTCHECK %s
+
+# This test checks that DWARF5 .debug_line is handled correctly.
+
+# PRECHECK: version: 5
+# PRECHECK: include_directories[  0] =  .debug_line_str[0x00000000]
+# PRECHECK-NEXT: file_names[  0]:
+# PRECHECK-NEXT: name:  .debug_line_str[0x00000002] = "main.cpp"
+# PRECHECK-NEXT: dir_index: 0
+# PRECHECK-NEXT: md5_checksum: bb12fec8d002b1f0e06f7dee4604c6cc
+# PRECHECK-NOT: file_names[  1]:
+
+# POSTCHECK: version: 5
+# POSTCHECK: include_directories[  0] =  .debug_line_str[0x00000000]
+# POSTCHECK-NEXT: file_names[  0]:
+# POSTCHECK-NEXT: name:  .debug_line_str[0x00000002] = "main.cpp"
+# POSTCHECK-NEXT: dir_index: 0
+# POSTCHECK-NEXT: md5_checksum: bb12fec8d002b1f0e06f7dee4604c6cc
+# POSTCHECK-NOT: file_names[  1]:
+
+# int main() {
+#    return 0;
+# }
+
+	.text
+	.file	"main.cpp"
+	.globl	main                            # -- Begin function main
+	.p2align	4, 0x90
+	.type	main,@function
+main:                                   # @main
+.Lfunc_begin0:
+	.file	0 "." "main.cpp" md5 0xbb12fec8d002b1f0e06f7dee4604c6cc
+	.loc	0 1 0                           # main.cpp:1:0
+	.cfi_startproc
+# %bb.0:                                # %entry
+	pushq	%rbp
+	.cfi_def_cfa_offset 16
+	.cfi_offset %rbp, -16
+	movq	%rsp, %rbp
+	.cfi_def_cfa_register %rbp
+	movl	$0, -4(%rbp)
+.Ltmp0:
+	.loc	0 2 3 prologue_end              # main.cpp:2:3
+	xorl	%eax, %eax
+	popq	%rbp
+	.cfi_def_cfa %rsp, 8
+	retq
+.Ltmp1:
+.Lfunc_end0:
+	.size	main, .Lfunc_end0-main
+	.cfi_endproc
+                                        # -- End function
+	.section	.debug_abbrev,"",@progbits
+	.byte	1                               # Abbreviation Code
+	.byte	17                              # DW_TAG_compile_unit
+	.byte	1                               # DW_CHILDREN_yes
+	.byte	37                              # DW_AT_producer
+	.byte	37                              # DW_FORM_strx1
+	.byte	19                              # DW_AT_language
+	.byte	5                               # DW_FORM_data2
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	114                             # DW_AT_str_offsets_base
+	.byte	23                              # DW_FORM_sec_offset
+	.byte	16                              # DW_AT_stmt_list
+	.byte	23                              # DW_FORM_sec_offset
+	.byte	27                              # DW_AT_comp_dir
+	.byte	37                              # DW_FORM_strx1
+	.byte	17                              # DW_AT_low_pc
+	.byte	27                              # DW_FORM_addrx
+	.byte	18                              # DW_AT_high_pc
+	.byte	6                               # DW_FORM_data4
+	.byte	115                             # DW_AT_addr_base
+	.byte	23                              # DW_FORM_sec_offset
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	2                               # Abbreviation Code
+	.byte	46                              # DW_TAG_subprogram
+	.byte	0                               # DW_CHILDREN_no
+	.byte	17                              # DW_AT_low_pc
+	.byte	27                              # DW_FORM_addrx
+	.byte	18                              # DW_AT_high_pc
+	.byte	6                               # DW_FORM_data4
+	.byte	64                              # DW_AT_frame_base
+	.byte	24                              # DW_FORM_exprloc
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	58                              # DW_AT_decl_file
+	.byte	11                              # DW_FORM_data1
+	.byte	59                              # DW_AT_decl_line
+	.byte	11                              # DW_FORM_data1
+	.byte	73                              # DW_AT_type
+	.byte	19                              # DW_FORM_ref4
+	.byte	63                              # DW_AT_external
+	.byte	25                              # DW_FORM_flag_present
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	3                               # Abbreviation Code
+	.byte	36                              # DW_TAG_base_type
+	.byte	0                               # DW_CHILDREN_no
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	62                              # DW_AT_encoding
+	.byte	11                              # DW_FORM_data1
+	.byte	11                              # DW_AT_byte_size
+	.byte	11                              # DW_FORM_data1
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	0                               # EOM(3)
+	.section	.debug_info,"",@progbits
+.Lcu_begin0:
+	.long	.Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+	.short	5                               # DWARF version number
+	.byte	1                               # DWARF Unit Type
+	.byte	8                               # Address Size (in bytes)
+	.long	.debug_abbrev                   # Offset Into Abbrev. Section
+	.byte	1                               # Abbrev [1] 0xc:0x2b DW_TAG_compile_unit
+	.byte	0                               # DW_AT_producer
+	.short	33                              # DW_AT_language
+	.byte	1                               # DW_AT_name
+	.long	.Lstr_offsets_base0             # DW_AT_str_offsets_base
+	.long	.Lline_table_start0             # DW_AT_stmt_list
+	.byte	2                               # DW_AT_comp_dir
+	.byte	0                               # DW_AT_low_pc
+	.long	.Lfunc_end0-.Lfunc_begin0       # DW_AT_high_pc
+	.long	.Laddr_table_base0              # DW_AT_addr_base
+	.byte	2                               # Abbrev [2] 0x23:0xf DW_TAG_subprogram
+	.byte	0                               # DW_AT_low_pc
+	.long	.Lfunc_end0-.Lfunc_begin0       # DW_AT_high_pc
+	.byte	1                               # DW_AT_frame_base
+	.byte	86
+	.byte	3                               # DW_AT_name
+	.byte	0                               # DW_AT_decl_file
+	.byte	1                               # DW_AT_decl_line
+	.long	50                              # DW_AT_type
+                                        # DW_AT_external
+	.byte	3                               # Abbrev [3] 0x32:0x4 DW_TAG_base_type
+	.byte	4                               # DW_AT_name
+	.byte	5                               # DW_AT_encoding
+	.byte	4                               # DW_AT_byte_size
+	.byte	0                               # End Of Children Mark
+.Ldebug_info_end0:
+	.section	.debug_str_offsets,"",@progbits
+	.long	24                              # Length of String Offsets Set
+	.short	5
+	.short	0
+.Lstr_offsets_base0:
+	.section	.debug_str,"MS",@progbits,1
+.Linfo_string0:
+	.asciz	"clang version 15.0.0" # string offset=0
+.Linfo_string1:
+	.asciz	"main.cpp"                      # string offset=134
+.Linfo_string2:
+	.asciz	"." # string offset=143
+.Linfo_string3:
+	.asciz	"main"                          # string offset=180
+.Linfo_string4:
+	.asciz	"int"                           # string offset=185
+	.section	.debug_str_offsets,"",@progbits
+	.long	.Linfo_string0
+	.long	.Linfo_string1
+	.long	.Linfo_string2
+	.long	.Linfo_string3
+	.long	.Linfo_string4
+	.section	.debug_addr,"",@progbits
+	.long	.Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution
+.Ldebug_addr_start0:
+	.short	5                               # DWARF version number
+	.byte	8                               # Address size
+	.byte	0                               # Segment selector size
+.Laddr_table_base0:
+	.quad	.Lfunc_begin0
+.Ldebug_addr_end0:
+	.ident	"clang version 15.0.0"
+	.section	".note.GNU-stack","",@progbits
+	.addrsig
+	.section	.debug_line,"",@progbits
+.Lline_table_start0:
diff --git a/bolt/test/X86/dwarf5_debug_loclists.s b/bolt/test/X86/dwarf5_debug_loclists.s
new file mode 100644
--- /dev/null
+++ b/bolt/test/X86/dwarf5_debug_loclists.s
@@ -0,0 +1,439 @@
+# REQUIRES: system-linux
+
+# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %s -o %t1.o
+# RUN: %clang %cflags -dwarf-5 %t1.o -o %t.exe -Wl,-q
+# RUN: llvm-bolt %t.exe -o %t.bolt -update-debug-sections
+# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.exe | FileCheck --check-prefix=PRECHECK %s
+# RUN: llvm-dwarfdump --show-form --verbose --debug-addr %t.bolt &> %t.txt
+# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.bolt >> %t.txt
+# RUN: cat %t.txt | FileCheck --check-prefix=POSTCHECK %s
+
+# This tests checks that re-writing of .debug_loclists is handled correctly.
+
+# PRECHECK: version = 0x0005
+# PRECHECK: DW_AT_loclists_base [DW_FORM_sec_offset] (0x0000000c)
+# PRECHECK-EMPTY:
+# PRECHECK: DW_TAG_variable
+# PRECHECK: DW_AT_location [DW_FORM_loclistx]
+# PRECHECK-SAME: indexed (0x0)
+# PRECHECK-SAME: loclist = 0x00000010
+
+# POSTCHECK: Addrs: [
+# POSTCHECK-NEXT: 0x
+# POSTCHECK-NEXT: 0x[[#%.16x,ADDR:]]
+# POSTCHECK-NEXT: 0x
+# POSTCHECK-NEXT: 0x[[#%.16x,ADDR2:]]
+# POSTCHECK: version = 0x0005
+# POSTCHECK: DW_AT_loclists_base [DW_FORM_sec_offset]	(0x0000000c)
+# POSTCHECK: DW_AT_rnglists_base [DW_FORM_sec_offset]	(0x0000000c)
+# POSTCHECK: DW_TAG_variable
+# POSTCHECK: DW_AT_location [DW_FORM_loclistx]
+# POSTCHECK-SAME: indexed (0x0)
+# POSTCHECK-SAME: loclist = 0x00000010
+# POSTCHECK-NEXT: [0x[[#ADDR]]
+# POSTCHECK-SAME: 0x[[#ADDR + 3]]
+# POSTCHECK-NEXT: [0x[[#ADDR2]]
+# POSTCHECK-SAME: 0x[[#ADDR2 + 1]]
+
+# clang++ main.cpp -g -O2 -S
+# void use(int * x) {
+# 	*x += 4;
+# }
+#
+# int  main(int argc, char *argv[]) {
+# 	int x = argc;
+# 	use(&x);
+# 	return x;
+# }
+
+	.text
+	.file	"main.cpp"
+	.globl	_Z3usePi                        # -- Begin function _Z3usePi
+	.p2align	4, 0x90
+	.type	_Z3usePi,@function
+_Z3usePi:                               # @_Z3usePi
+.Lfunc_begin0:
+	.file	0 "testLocList" "main.cpp" md5 0x95a77c95663d823a6228bf928825e8c7
+	.loc	0 1 0                           # main.cpp:1:0
+	.cfi_startproc
+# %bb.0:                                # %entry
+	#DEBUG_VALUE: use:x <- $rdi
+	.loc	0 2 4 prologue_end              # main.cpp:2:4
+	addl	$4, (%rdi)
+	.loc	0 3 1                           # main.cpp:3:1
+	retq
+.Ltmp0:
+.Lfunc_end0:
+	.size	_Z3usePi, .Lfunc_end0-_Z3usePi
+	.cfi_endproc
+                                        # -- End function
+	.globl	main                            # -- Begin function main
+	.p2align	4, 0x90
+	.type	main,@function
+main:                                   # @main
+.Lfunc_begin1:
+	.loc	0 5 0                           # main.cpp:5:0
+	.cfi_startproc
+# %bb.0:                                # %entry
+	#DEBUG_VALUE: main:argc <- $edi
+	#DEBUG_VALUE: main:argv <- $rsi
+	#DEBUG_VALUE: main:x <- $edi
+                                        # kill: def $edi killed $edi def $rdi
+	#DEBUG_VALUE: use:x <- undef
+	.loc	0 2 4 prologue_end              # main.cpp:2:4
+	leal	4(%rdi), %eax
+.Ltmp1:
+	#DEBUG_VALUE: main:x <- $eax
+	.loc	0 8 4                           # main.cpp:8:4
+	retq
+.Ltmp2:
+.Lfunc_end1:
+	.size	main, .Lfunc_end1-main
+	.cfi_endproc
+                                        # -- End function
+	.section	.debug_loclists,"",@progbits
+	.long	.Ldebug_list_header_end0-.Ldebug_list_header_start0 # Length
+.Ldebug_list_header_start0:
+	.short	5                               # Version
+	.byte	8                               # Address size
+	.byte	0                               # Segment selector size
+	.long	1                               # Offset entry count
+.Lloclists_table_base0:
+	.long	.Ldebug_loc0-.Lloclists_table_base0
+.Ldebug_loc0:
+	.byte	4                               # DW_LLE_offset_pair
+	.uleb128 .Lfunc_begin1-.Lfunc_begin0    #   starting offset
+	.uleb128 .Ltmp1-.Lfunc_begin0           #   ending offset
+	.byte	1                               # Loc expr size
+	.byte	85                              # super-register DW_OP_reg5
+	.byte	4                               # DW_LLE_offset_pair
+	.uleb128 .Ltmp1-.Lfunc_begin0           #   starting offset
+	.uleb128 .Lfunc_end1-.Lfunc_begin0      #   ending offset
+	.byte	1                               # Loc expr size
+	.byte	80                              # super-register DW_OP_reg0
+	.byte	0                               # DW_LLE_end_of_list
+.Ldebug_list_header_end0:
+	.section	.debug_abbrev,"",@progbits
+	.byte	1                               # Abbreviation Code
+	.byte	17                              # DW_TAG_compile_unit
+	.byte	1                               # DW_CHILDREN_yes
+	.byte	37                              # DW_AT_producer
+	.byte	37                              # DW_FORM_strx1
+	.byte	19                              # DW_AT_language
+	.byte	5                               # DW_FORM_data2
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	114                             # DW_AT_str_offsets_base
+	.byte	23                              # DW_FORM_sec_offset
+	.byte	16                              # DW_AT_stmt_list
+	.byte	23                              # DW_FORM_sec_offset
+	.byte	27                              # DW_AT_comp_dir
+	.byte	37                              # DW_FORM_strx1
+	.byte	17                              # DW_AT_low_pc
+	.byte	27                              # DW_FORM_addrx
+	.byte	18                              # DW_AT_high_pc
+	.byte	6                               # DW_FORM_data4
+	.byte	115                             # DW_AT_addr_base
+	.byte	23                              # DW_FORM_sec_offset
+	.ascii	"\214\001"                      # DW_AT_loclists_base
+	.byte	23                              # DW_FORM_sec_offset
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	2                               # Abbreviation Code
+	.byte	46                              # DW_TAG_subprogram
+	.byte	1                               # DW_CHILDREN_yes
+	.byte	17                              # DW_AT_low_pc
+	.byte	27                              # DW_FORM_addrx
+	.byte	18                              # DW_AT_high_pc
+	.byte	6                               # DW_FORM_data4
+	.byte	64                              # DW_AT_frame_base
+	.byte	24                              # DW_FORM_exprloc
+	.byte	122                             # DW_AT_call_all_calls
+	.byte	25                              # DW_FORM_flag_present
+	.byte	49                              # DW_AT_abstract_origin
+	.byte	19                              # DW_FORM_ref4
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	3                               # Abbreviation Code
+	.byte	5                               # DW_TAG_formal_parameter
+	.byte	0                               # DW_CHILDREN_no
+	.byte	2                               # DW_AT_location
+	.byte	24                              # DW_FORM_exprloc
+	.byte	49                              # DW_AT_abstract_origin
+	.byte	19                              # DW_FORM_ref4
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	4                               # Abbreviation Code
+	.byte	46                              # DW_TAG_subprogram
+	.byte	1                               # DW_CHILDREN_yes
+	.byte	110                             # DW_AT_linkage_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	58                              # DW_AT_decl_file
+	.byte	11                              # DW_FORM_data1
+	.byte	59                              # DW_AT_decl_line
+	.byte	11                              # DW_FORM_data1
+	.byte	63                              # DW_AT_external
+	.byte	25                              # DW_FORM_flag_present
+	.byte	32                              # DW_AT_inline
+	.byte	33                              # DW_FORM_implicit_const
+	.byte	1
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	5                               # Abbreviation Code
+	.byte	5                               # DW_TAG_formal_parameter
+	.byte	0                               # DW_CHILDREN_no
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	58                              # DW_AT_decl_file
+	.byte	11                              # DW_FORM_data1
+	.byte	59                              # DW_AT_decl_line
+	.byte	11                              # DW_FORM_data1
+	.byte	73                              # DW_AT_type
+	.byte	19                              # DW_FORM_ref4
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	6                               # Abbreviation Code
+	.byte	15                              # DW_TAG_pointer_type
+	.byte	0                               # DW_CHILDREN_no
+	.byte	73                              # DW_AT_type
+	.byte	19                              # DW_FORM_ref4
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	7                               # Abbreviation Code
+	.byte	36                              # DW_TAG_base_type
+	.byte	0                               # DW_CHILDREN_no
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	62                              # DW_AT_encoding
+	.byte	11                              # DW_FORM_data1
+	.byte	11                              # DW_AT_byte_size
+	.byte	11                              # DW_FORM_data1
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	8                               # Abbreviation Code
+	.byte	46                              # DW_TAG_subprogram
+	.byte	1                               # DW_CHILDREN_yes
+	.byte	17                              # DW_AT_low_pc
+	.byte	27                              # DW_FORM_addrx
+	.byte	18                              # DW_AT_high_pc
+	.byte	6                               # DW_FORM_data4
+	.byte	64                              # DW_AT_frame_base
+	.byte	24                              # DW_FORM_exprloc
+	.byte	122                             # DW_AT_call_all_calls
+	.byte	25                              # DW_FORM_flag_present
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	58                              # DW_AT_decl_file
+	.byte	11                              # DW_FORM_data1
+	.byte	59                              # DW_AT_decl_line
+	.byte	11                              # DW_FORM_data1
+	.byte	73                              # DW_AT_type
+	.byte	19                              # DW_FORM_ref4
+	.byte	63                              # DW_AT_external
+	.byte	25                              # DW_FORM_flag_present
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	9                               # Abbreviation Code
+	.byte	5                               # DW_TAG_formal_parameter
+	.byte	0                               # DW_CHILDREN_no
+	.byte	2                               # DW_AT_location
+	.byte	24                              # DW_FORM_exprloc
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	58                              # DW_AT_decl_file
+	.byte	11                              # DW_FORM_data1
+	.byte	59                              # DW_AT_decl_line
+	.byte	11                              # DW_FORM_data1
+	.byte	73                              # DW_AT_type
+	.byte	19                              # DW_FORM_ref4
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	10                              # Abbreviation Code
+	.byte	52                              # DW_TAG_variable
+	.byte	0                               # DW_CHILDREN_no
+	.byte	2                               # DW_AT_location
+	.byte	34                              # DW_FORM_loclistx
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	58                              # DW_AT_decl_file
+	.byte	11                              # DW_FORM_data1
+	.byte	59                              # DW_AT_decl_line
+	.byte	11                              # DW_FORM_data1
+	.byte	73                              # DW_AT_type
+	.byte	19                              # DW_FORM_ref4
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	11                              # Abbreviation Code
+	.byte	29                              # DW_TAG_inlined_subroutine
+	.byte	0                               # DW_CHILDREN_no
+	.byte	49                              # DW_AT_abstract_origin
+	.byte	19                              # DW_FORM_ref4
+	.byte	17                              # DW_AT_low_pc
+	.byte	27                              # DW_FORM_addrx
+	.byte	18                              # DW_AT_high_pc
+	.byte	6                               # DW_FORM_data4
+	.byte	88                              # DW_AT_call_file
+	.byte	11                              # DW_FORM_data1
+	.byte	89                              # DW_AT_call_line
+	.byte	11                              # DW_FORM_data1
+	.byte	87                              # DW_AT_call_column
+	.byte	11                              # DW_FORM_data1
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	0                               # EOM(3)
+	.section	.debug_info,"",@progbits
+.Lcu_begin0:
+	.long	.Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+	.short	5                               # DWARF version number
+	.byte	1                               # DWARF Unit Type
+	.byte	8                               # Address Size (in bytes)
+	.long	.debug_abbrev                   # Offset Into Abbrev. Section
+	.byte	1                               # Abbrev [1] 0xc:0x8f DW_TAG_compile_unit
+	.byte	0                               # DW_AT_producer
+	.short	33                              # DW_AT_language
+	.byte	1                               # DW_AT_name
+	.long	.Lstr_offsets_base0             # DW_AT_str_offsets_base
+	.long	.Lline_table_start0             # DW_AT_stmt_list
+	.byte	2                               # DW_AT_comp_dir
+	.byte	0                               # DW_AT_low_pc
+	.long	.Lfunc_end1-.Lfunc_begin0       # DW_AT_high_pc
+	.long	.Laddr_table_base0              # DW_AT_addr_base
+	.long	.Lloclists_table_base0          # DW_AT_loclists_base
+	.byte	2                               # Abbrev [2] 0x27:0x14 DW_TAG_subprogram
+	.byte	0                               # DW_AT_low_pc
+	.long	.Lfunc_end0-.Lfunc_begin0       # DW_AT_high_pc
+	.byte	1                               # DW_AT_frame_base
+	.byte	87
+                                        # DW_AT_call_all_calls
+	.long	59                              # DW_AT_abstract_origin
+	.byte	3                               # Abbrev [3] 0x33:0x7 DW_TAG_formal_parameter
+	.byte	1                               # DW_AT_location
+	.byte	85
+	.long	64                              # DW_AT_abstract_origin
+	.byte	0                               # End Of Children Mark
+	.byte	4                               # Abbrev [4] 0x3b:0xe DW_TAG_subprogram
+	.byte	3                               # DW_AT_linkage_name
+	.byte	4                               # DW_AT_name
+	.byte	0                               # DW_AT_decl_file
+	.byte	1                               # DW_AT_decl_line
+                                        # DW_AT_external
+                                        # DW_AT_inline
+	.byte	5                               # Abbrev [5] 0x40:0x8 DW_TAG_formal_parameter
+	.byte	5                               # DW_AT_name
+	.byte	0                               # DW_AT_decl_file
+	.byte	1                               # DW_AT_decl_line
+	.long	73                              # DW_AT_type
+	.byte	0                               # End Of Children Mark
+	.byte	6                               # Abbrev [6] 0x49:0x5 DW_TAG_pointer_type
+	.long	78                              # DW_AT_type
+	.byte	7                               # Abbrev [7] 0x4e:0x4 DW_TAG_base_type
+	.byte	6                               # DW_AT_name
+	.byte	5                               # DW_AT_encoding
+	.byte	4                               # DW_AT_byte_size
+	.byte	8                               # Abbrev [8] 0x52:0x3a DW_TAG_subprogram
+	.byte	1                               # DW_AT_low_pc
+	.long	.Lfunc_end1-.Lfunc_begin1       # DW_AT_high_pc
+	.byte	1                               # DW_AT_frame_base
+	.byte	87
+                                        # DW_AT_call_all_calls
+	.byte	7                               # DW_AT_name
+	.byte	0                               # DW_AT_decl_file
+	.byte	5                               # DW_AT_decl_line
+	.long	78                              # DW_AT_type
+                                        # DW_AT_external
+	.byte	9                               # Abbrev [9] 0x61:0xa DW_TAG_formal_parameter
+	.byte	1                               # DW_AT_location
+	.byte	85
+	.byte	8                               # DW_AT_name
+	.byte	0                               # DW_AT_decl_file
+	.byte	5                               # DW_AT_decl_line
+	.long	78                              # DW_AT_type
+	.byte	9                               # Abbrev [9] 0x6b:0xa DW_TAG_formal_parameter
+	.byte	1                               # DW_AT_location
+	.byte	84
+	.byte	9                               # DW_AT_name
+	.byte	0                               # DW_AT_decl_file
+	.byte	5                               # DW_AT_decl_line
+	.long	140                             # DW_AT_type
+	.byte	10                              # Abbrev [10] 0x75:0x9 DW_TAG_variable
+	.byte	0                               # DW_AT_location
+	.byte	5                               # DW_AT_name
+	.byte	0                               # DW_AT_decl_file
+	.byte	6                               # DW_AT_decl_line
+	.long	78                              # DW_AT_type
+	.byte	11                              # Abbrev [11] 0x7e:0xd DW_TAG_inlined_subroutine
+	.long	59                              # DW_AT_abstract_origin
+	.byte	1                               # DW_AT_low_pc
+	.long	.Ltmp1-.Lfunc_begin1            # DW_AT_high_pc
+	.byte	0                               # DW_AT_call_file
+	.byte	7                               # DW_AT_call_line
+	.byte	4                               # DW_AT_call_column
+	.byte	0                               # End Of Children Mark
+	.byte	6                               # Abbrev [6] 0x8c:0x5 DW_TAG_pointer_type
+	.long	145                             # DW_AT_type
+	.byte	6                               # Abbrev [6] 0x91:0x5 DW_TAG_pointer_type
+	.long	150                             # DW_AT_type
+	.byte	7                               # Abbrev [7] 0x96:0x4 DW_TAG_base_type
+	.byte	10                              # DW_AT_name
+	.byte	6                               # DW_AT_encoding
+	.byte	1                               # DW_AT_byte_size
+	.byte	0                               # End Of Children Mark
+.Ldebug_info_end0:
+	.section	.debug_str_offsets,"",@progbits
+	.long	48                              # Length of String Offsets Set
+	.short	5
+	.short	0
+.Lstr_offsets_base0:
+	.section	.debug_str,"MS",@progbits,1
+.Linfo_string0:
+	.asciz	"clang version 15.0.0)" # string offset=0
+.Linfo_string1:
+	.asciz	"main.cpp"                      # string offset=134
+.Linfo_string2:
+	.asciz	"/testLocList" # string offset=143
+.Linfo_string3:
+	.asciz	"_Z3usePi"                      # string offset=192
+.Linfo_string4:
+	.asciz	"use"                           # string offset=201
+.Linfo_string5:
+	.asciz	"x"                             # string offset=205
+.Linfo_string6:
+	.asciz	"int"                           # string offset=207
+.Linfo_string7:
+	.asciz	"main"                          # string offset=211
+.Linfo_string8:
+	.asciz	"argc"                          # string offset=216
+.Linfo_string9:
+	.asciz	"argv"                          # string offset=221
+.Linfo_string10:
+	.asciz	"char"                          # string offset=226
+	.section	.debug_str_offsets,"",@progbits
+	.long	.Linfo_string0
+	.long	.Linfo_string1
+	.long	.Linfo_string2
+	.long	.Linfo_string3
+	.long	.Linfo_string4
+	.long	.Linfo_string5
+	.long	.Linfo_string6
+	.long	.Linfo_string7
+	.long	.Linfo_string8
+	.long	.Linfo_string9
+	.long	.Linfo_string10
+	.section	.debug_addr,"",@progbits
+	.long	.Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution
+.Ldebug_addr_start0:
+	.short	5                               # DWARF version number
+	.byte	8                               # Address size
+	.byte	0                               # Segment selector size
+.Laddr_table_base0:
+	.quad	.Lfunc_begin0
+	.quad	.Lfunc_begin1
+.Ldebug_addr_end0:
+	.ident	"clang version 15.0.0"
+	.section	".note.GNU-stack","",@progbits
+	.addrsig
+	.section	.debug_line,"",@progbits
+.Lline_table_start0:
diff --git a/bolt/test/X86/dwarf5_label_low_pc.s b/bolt/test/X86/dwarf5_label_low_pc.s
new file mode 100644
--- /dev/null
+++ b/bolt/test/X86/dwarf5_label_low_pc.s
@@ -0,0 +1,303 @@
+
+# REQUIRES: system-linux
+
+# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %s -o %tmain.o
+# RUN: %clang %cflags -dwarf-5 %tmain.o -o %t.exe -Wl,-q
+# RUN: llvm-bolt %t.exe -o %t.bolt -update-debug-sections
+# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.exe | FileCheck --check-prefix=PRECHECK %s
+
+# RUN: llvm-dwarfdump --show-form --verbose --debug-addr %t.bolt &> %t.txt
+# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.bolt >> %t.txt
+
+# This test checks that we correctly encode new index into .debug_addr section
+# from DW_AT_location [DW_FORM_exprloc]  (DW_OP_addrx 0x#)
+
+# PRECHECK: version = 0x0005
+# PRECHECK: DW_TAG_label
+# PRECHECK-NEXT: DW_AT_name
+# PRECHECK-NEXT: DW_AT_decl_file
+# PRECHECK-NEXT: DW_AT_decl_line
+# PRECHECK-NEXT:DW_AT_low_pc [DW_FORM_addrx]  (indexed (00000001)
+# PRECHECK: DW_TAG_label
+# PRECHECK-NEXT: DW_AT_name
+# PRECHECK-NEXT: DW_AT_decl_file
+# PRECHECK-NEXT: DW_AT_decl_line
+# PRECHECK-NEXT:DW_AT_low_pc [DW_FORM_addrx]  (indexed (00000002)
+
+
+# POSTCHECK: Addrs: [
+# POSTCHECK-NEXT: 0x
+# POSTCHECK-NEXT: 0x
+# POSTCHECK-NEXT: 0x[[#%.16x,ADDR:]]
+# POSTCHECK-NEXT: 0x[[#%.16x,ADDR2:]]
+
+# POSTCHECK: version = 0x0005
+# POSTCHECK: DW_TAG_label
+# POSTCHECK-NEXT: DW_AT_name
+# POSTCHECK-NEXT: DW_AT_decl_file
+# POSTCHECK-NEXT: DW_AT_decl_line
+# POSTCHECK-NEXT:
+# POSTCHECK-NEXT:DW_AT_low_pc [DW_FORM_addrx]  (indexed (00000002)
+# POSTCHECK-SAME: [0x[[#ADDR]]
+# POSTCHECK: DW_TAG_label
+# POSTCHECK-NEXT: DW_AT_name
+# POSTCHECK-NEXT: DW_AT_decl_file
+# POSTCHECK-NEXT: DW_AT_decl_line
+# POSTCHECK-NEXT:
+# POSTCHECK-NEXT:DW_AT_low_pc [DW_FORM_addrx]  (indexed (00000003)
+# POSTCHECK-SAME: [0x[[#ADDR2]]
+
+# clang++ main.cpp -g -S
+# int main() {
+#   int a = 4;
+#   if (a == 5)
+#     goto LABEL1;
+#   else
+#     goto LABEL2;
+#   LABEL1:a++;
+#   LABEL2:a--;
+#   return 0;
+# }
+
+	.text
+	.file	"main.cpp"
+	.globl	main                            # -- Begin function main
+	.p2align	4, 0x90
+	.type	main,@function
+main:                                   # @main
+.Lfunc_begin0:
+	.file	0 "/testLabel" "main.cpp" md5 0xa0bd66020d06f1303de7008e3c542050
+	.loc	0 1 0                           # main.cpp:1:0
+	.cfi_startproc
+# %bb.0:                                # %entry
+	pushq	%rbp
+	.cfi_def_cfa_offset 16
+	.cfi_offset %rbp, -16
+	movq	%rsp, %rbp
+	.cfi_def_cfa_register %rbp
+	movl	$0, -4(%rbp)
+.Ltmp0:
+	.loc	0 2 7 prologue_end              # main.cpp:2:7
+	movl	$4, -8(%rbp)
+.Ltmp1:
+	.loc	0 3 9                           # main.cpp:3:9
+	cmpl	$5, -8(%rbp)
+.Ltmp2:
+	.loc	0 3 7 is_stmt 0                 # main.cpp:3:7
+	jne	.LBB0_2
+# %bb.1:                                # %if.then
+.Ltmp3:
+	.loc	0 4 5 is_stmt 1                 # main.cpp:4:5
+	jmp	.LBB0_3
+.LBB0_2:                                # %if.else
+	.loc	0 6 5                           # main.cpp:6:5
+	jmp	.LBB0_4
+.Ltmp4:
+.LBB0_3:                                # %LABEL1
+	#DEBUG_LABEL: main:LABEL1
+	.loc	0 7 11                          # main.cpp:7:11
+	movl	-8(%rbp), %eax
+	addl	$1, %eax
+	movl	%eax, -8(%rbp)
+.LBB0_4:                                # %LABEL2
+.Ltmp5:
+	#DEBUG_LABEL: main:LABEL2
+	.loc	0 8 11                          # main.cpp:8:11
+	movl	-8(%rbp), %eax
+	addl	$-1, %eax
+	movl	%eax, -8(%rbp)
+	.loc	0 9 3                           # main.cpp:9:3
+	xorl	%eax, %eax
+	popq	%rbp
+	.cfi_def_cfa %rsp, 8
+	retq
+.Ltmp6:
+.Lfunc_end0:
+	.size	main, .Lfunc_end0-main
+	.cfi_endproc
+                                        # -- End function
+	.section	.debug_abbrev,"",@progbits
+	.byte	1                               # Abbreviation Code
+	.byte	17                              # DW_TAG_compile_unit
+	.byte	1                               # DW_CHILDREN_yes
+	.byte	37                              # DW_AT_producer
+	.byte	37                              # DW_FORM_strx1
+	.byte	19                              # DW_AT_language
+	.byte	5                               # DW_FORM_data2
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	114                             # DW_AT_str_offsets_base
+	.byte	23                              # DW_FORM_sec_offset
+	.byte	16                              # DW_AT_stmt_list
+	.byte	23                              # DW_FORM_sec_offset
+	.byte	27                              # DW_AT_comp_dir
+	.byte	37                              # DW_FORM_strx1
+	.byte	17                              # DW_AT_low_pc
+	.byte	27                              # DW_FORM_addrx
+	.byte	18                              # DW_AT_high_pc
+	.byte	6                               # DW_FORM_data4
+	.byte	115                             # DW_AT_addr_base
+	.byte	23                              # DW_FORM_sec_offset
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	2                               # Abbreviation Code
+	.byte	46                              # DW_TAG_subprogram
+	.byte	1                               # DW_CHILDREN_yes
+	.byte	17                              # DW_AT_low_pc
+	.byte	27                              # DW_FORM_addrx
+	.byte	18                              # DW_AT_high_pc
+	.byte	6                               # DW_FORM_data4
+	.byte	64                              # DW_AT_frame_base
+	.byte	24                              # DW_FORM_exprloc
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	58                              # DW_AT_decl_file
+	.byte	11                              # DW_FORM_data1
+	.byte	59                              # DW_AT_decl_line
+	.byte	11                              # DW_FORM_data1
+	.byte	73                              # DW_AT_type
+	.byte	19                              # DW_FORM_ref4
+	.byte	63                              # DW_AT_external
+	.byte	25                              # DW_FORM_flag_present
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	3                               # Abbreviation Code
+	.byte	52                              # DW_TAG_variable
+	.byte	0                               # DW_CHILDREN_no
+	.byte	2                               # DW_AT_location
+	.byte	24                              # DW_FORM_exprloc
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	58                              # DW_AT_decl_file
+	.byte	11                              # DW_FORM_data1
+	.byte	59                              # DW_AT_decl_line
+	.byte	11                              # DW_FORM_data1
+	.byte	73                              # DW_AT_type
+	.byte	19                              # DW_FORM_ref4
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	4                               # Abbreviation Code
+	.byte	10                              # DW_TAG_label
+	.byte	0                               # DW_CHILDREN_no
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	58                              # DW_AT_decl_file
+	.byte	11                              # DW_FORM_data1
+	.byte	59                              # DW_AT_decl_line
+	.byte	11                              # DW_FORM_data1
+	.byte	17                              # DW_AT_low_pc
+	.byte	27                              # DW_FORM_addrx
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	5                               # Abbreviation Code
+	.byte	36                              # DW_TAG_base_type
+	.byte	0                               # DW_CHILDREN_no
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	62                              # DW_AT_encoding
+	.byte	11                              # DW_FORM_data1
+	.byte	11                              # DW_AT_byte_size
+	.byte	11                              # DW_FORM_data1
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	0                               # EOM(3)
+	.section	.debug_info,"",@progbits
+.Lcu_begin0:
+	.long	.Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+	.short	5                               # DWARF version number
+	.byte	1                               # DWARF Unit Type
+	.byte	8                               # Address Size (in bytes)
+	.long	.debug_abbrev                   # Offset Into Abbrev. Section
+	.byte	1                               # Abbrev [1] 0xc:0x41 DW_TAG_compile_unit
+	.byte	0                               # DW_AT_producer
+	.short	33                              # DW_AT_language
+	.byte	1                               # DW_AT_name
+	.long	.Lstr_offsets_base0             # DW_AT_str_offsets_base
+	.long	.Lline_table_start0             # DW_AT_stmt_list
+	.byte	2                               # DW_AT_comp_dir
+	.byte	0                               # DW_AT_low_pc
+	.long	.Lfunc_end0-.Lfunc_begin0       # DW_AT_high_pc
+	.long	.Laddr_table_base0              # DW_AT_addr_base
+	.byte	2                               # Abbrev [2] 0x23:0x25 DW_TAG_subprogram
+	.byte	0                               # DW_AT_low_pc
+	.long	.Lfunc_end0-.Lfunc_begin0       # DW_AT_high_pc
+	.byte	1                               # DW_AT_frame_base
+	.byte	86
+	.byte	3                               # DW_AT_name
+	.byte	0                               # DW_AT_decl_file
+	.byte	1                               # DW_AT_decl_line
+	.long	72                              # DW_AT_type
+                                        # DW_AT_external
+	.byte	3                               # Abbrev [3] 0x32:0xb DW_TAG_variable
+	.byte	2                               # DW_AT_location
+	.byte	145
+	.byte	120
+	.byte	5                               # DW_AT_name
+	.byte	0                               # DW_AT_decl_file
+	.byte	2                               # DW_AT_decl_line
+	.long	72                              # DW_AT_type
+	.byte	4                               # Abbrev [4] 0x3d:0x5 DW_TAG_label
+	.byte	6                               # DW_AT_name
+	.byte	0                               # DW_AT_decl_file
+	.byte	7                               # DW_AT_decl_line
+	.byte	1                               # DW_AT_low_pc
+	.byte	4                               # Abbrev [4] 0x42:0x5 DW_TAG_label
+	.byte	7                               # DW_AT_name
+	.byte	0                               # DW_AT_decl_file
+	.byte	8                               # DW_AT_decl_line
+	.byte	2                               # DW_AT_low_pc
+	.byte	0                               # End Of Children Mark
+	.byte	5                               # Abbrev [5] 0x48:0x4 DW_TAG_base_type
+	.byte	4                               # DW_AT_name
+	.byte	5                               # DW_AT_encoding
+	.byte	4                               # DW_AT_byte_size
+	.byte	0                               # End Of Children Mark
+.Ldebug_info_end0:
+	.section	.debug_str_offsets,"",@progbits
+	.long	36                              # Length of String Offsets Set
+	.short	5
+	.short	0
+.Lstr_offsets_base0:
+	.section	.debug_str,"MS",@progbits,1
+.Linfo_string0:
+	.asciz	"clang version 15.0.0" # string offset=0
+.Linfo_string1:
+	.asciz	"main.cpp"                      # string offset=134
+.Linfo_string2:
+	.asciz	"/testLabel" # string offset=143
+.Linfo_string3:
+	.asciz	"main"                          # string offset=190
+.Linfo_string4:
+	.asciz	"int"                           # string offset=195
+.Linfo_string5:
+	.asciz	"a"                             # string offset=199
+.Linfo_string6:
+	.asciz	"LABEL1"                        # string offset=201
+.Linfo_string7:
+	.asciz	"LABEL2"                        # string offset=208
+	.section	.debug_str_offsets,"",@progbits
+	.long	.Linfo_string0
+	.long	.Linfo_string1
+	.long	.Linfo_string2
+	.long	.Linfo_string3
+	.long	.Linfo_string4
+	.long	.Linfo_string5
+	.long	.Linfo_string6
+	.long	.Linfo_string7
+	.section	.debug_addr,"",@progbits
+	.long	.Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution
+.Ldebug_addr_start0:
+	.short	5                               # DWARF version number
+	.byte	8                               # Address size
+	.byte	0                               # Segment selector size
+.Laddr_table_base0:
+	.quad	.Lfunc_begin0
+	.quad	.Ltmp4
+	.quad	.Ltmp5
+.Ldebug_addr_end0:
+	.ident	"clang version 15.0.0"
+	.section	".note.GNU-stack","",@progbits
+	.addrsig
+	.section	.debug_line,"",@progbits
+.Lline_table_start0:
diff --git a/bolt/test/X86/dwarf5_locexpr_addrx.s b/bolt/test/X86/dwarf5_locexpr_addrx.s
new file mode 100644
--- /dev/null
+++ b/bolt/test/X86/dwarf5_locexpr_addrx.s
@@ -0,0 +1,461 @@
+# REQUIRES: system-linux
+
+# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %s -o %tmain.o
+# RUN: %clang %cflags -dwarf-5 %tmain.o -o %t.exe -Wl,-q
+# RUN: llvm-bolt %t.exe -o %t.bolt -update-debug-sections
+# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.exe | FileCheck --check-prefix=PRECHECK %s
+# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.bolt | FileCheck --check-prefix=POSTCHECK %s
+
+# This test checks that we correctly encode new index into .debug_addr section
+# from DW_AT_location [DW_FORM_exprloc]  (DW_OP_addrx 0x#)
+
+# PRECHECK: version = 0x0005
+# PRECHECK: DW_TAG_variable
+# PRECHECK: DW_AT_location [DW_FORM_exprloc]  (DW_OP_addrx 0x0)
+# PRECHECK: DW_TAG_variable
+# PRECHECK: DW_AT_location [DW_FORM_exprloc]  (DW_OP_addrx 0x1)
+# PRECHECK-EMPTY:
+
+# POSTCHECK: version = 0x0005
+# POSTCHECK: DW_TAG_variable
+# POSTCHECK: DW_AT_location [DW_FORM_exprloc]  (DW_OP_addrx 0x3)
+# POSTCHECK-EMPTY:
+# POSTCHECK: DW_TAG_variable
+# POSTCHECK: DW_AT_location [DW_FORM_exprloc]  (DW_OP_addrx 0x4)
+# POSTCHECK-EMPTY:
+
+# clang++ main.cpp -g -O2
+# void use(int * x, int * y) {
+# *x += 4;
+# *y -= 2;
+# }
+#
+# int x = 0;
+# int y = 1;
+# int  main(int argc, char *argv[]) {
+#    x = argc;
+#    y = argc + 3;
+#    use(&x, &y);
+#    return x + y;
+# }
+
+	.text
+	.file	"main.cpp"
+	.file	0 "/testLocExprLoc" "main.cpp" md5 0xd4fd79ce0087c4cefd089752bf2182c6
+	.globl	_Z3usePiS_                      # -- Begin function _Z3usePiS_
+	.p2align	4, 0x90
+	.type	_Z3usePiS_,@function
+_Z3usePiS_:                             # @_Z3usePiS_
+.Lfunc_begin0:
+	.loc	0 1 0                           # main.cpp:1:0
+	.cfi_startproc
+# %bb.0:                                # %entry
+	#DEBUG_VALUE: use:x <- $rdi
+	#DEBUG_VALUE: use:y <- $rsi
+	.loc	0 2 4 prologue_end              # main.cpp:2:4
+	addl	$4, (%rdi)
+	.loc	0 3 4                           # main.cpp:3:4
+	addl	$-2, (%rsi)
+	.loc	0 4 1                           # main.cpp:4:1
+	retq
+.Ltmp0:
+.Lfunc_end0:
+	.size	_Z3usePiS_, .Lfunc_end0-_Z3usePiS_
+	.cfi_endproc
+                                        # -- End function
+	.globl	main                            # -- Begin function main
+	.p2align	4, 0x90
+	.type	main,@function
+main:                                   # @main
+.Lfunc_begin1:
+	.loc	0 8 0                           # main.cpp:8:0
+	.cfi_startproc
+# %bb.0:                                # %entry
+	#DEBUG_VALUE: main:argc <- $edi
+	#DEBUG_VALUE: main:argv <- $rsi
+                                        # kill: def $edi killed $edi def $rdi
+	.loc	0 2 4 prologue_end              # main.cpp:2:4
+	leal	4(%rdi), %eax
+	movl	%eax, x(%rip)
+.Ltmp1:
+	#DEBUG_VALUE: use:x <- undef
+	.loc	0 3 4                           # main.cpp:3:4
+	leal	1(%rdi), %eax
+	movl	%eax, y(%rip)
+.Ltmp2:
+	#DEBUG_VALUE: use:y <- undef
+	.loc	0 12 13                         # main.cpp:12:13
+	leal	(%rdi,%rdi), %eax
+	addl	$5, %eax
+	.loc	0 12 4 is_stmt 0                # main.cpp:12:4
+	retq
+.Ltmp3:
+.Lfunc_end1:
+	.size	main, .Lfunc_end1-main
+	.cfi_endproc
+                                        # -- End function
+	.type	x,@object                       # @x
+	.bss
+	.globl	x
+	.p2align	2
+x:
+	.long	0                               # 0x0
+	.size	x, 4
+
+	.type	y,@object                       # @y
+	.data
+	.globl	y
+	.p2align	2
+y:
+	.long	1                               # 0x1
+	.size	y, 4
+
+	.section	.debug_abbrev,"",@progbits
+	.byte	1                               # Abbreviation Code
+	.byte	17                              # DW_TAG_compile_unit
+	.byte	1                               # DW_CHILDREN_yes
+	.byte	37                              # DW_AT_producer
+	.byte	37                              # DW_FORM_strx1
+	.byte	19                              # DW_AT_language
+	.byte	5                               # DW_FORM_data2
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	114                             # DW_AT_str_offsets_base
+	.byte	23                              # DW_FORM_sec_offset
+	.byte	16                              # DW_AT_stmt_list
+	.byte	23                              # DW_FORM_sec_offset
+	.byte	27                              # DW_AT_comp_dir
+	.byte	37                              # DW_FORM_strx1
+	.byte	17                              # DW_AT_low_pc
+	.byte	27                              # DW_FORM_addrx
+	.byte	18                              # DW_AT_high_pc
+	.byte	6                               # DW_FORM_data4
+	.byte	115                             # DW_AT_addr_base
+	.byte	23                              # DW_FORM_sec_offset
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	2                               # Abbreviation Code
+	.byte	52                              # DW_TAG_variable
+	.byte	0                               # DW_CHILDREN_no
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	73                              # DW_AT_type
+	.byte	19                              # DW_FORM_ref4
+	.byte	63                              # DW_AT_external
+	.byte	25                              # DW_FORM_flag_present
+	.byte	58                              # DW_AT_decl_file
+	.byte	11                              # DW_FORM_data1
+	.byte	59                              # DW_AT_decl_line
+	.byte	11                              # DW_FORM_data1
+	.byte	2                               # DW_AT_location
+	.byte	24                              # DW_FORM_exprloc
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	3                               # Abbreviation Code
+	.byte	36                              # DW_TAG_base_type
+	.byte	0                               # DW_CHILDREN_no
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	62                              # DW_AT_encoding
+	.byte	11                              # DW_FORM_data1
+	.byte	11                              # DW_AT_byte_size
+	.byte	11                              # DW_FORM_data1
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	4                               # Abbreviation Code
+	.byte	46                              # DW_TAG_subprogram
+	.byte	1                               # DW_CHILDREN_yes
+	.byte	17                              # DW_AT_low_pc
+	.byte	27                              # DW_FORM_addrx
+	.byte	18                              # DW_AT_high_pc
+	.byte	6                               # DW_FORM_data4
+	.byte	64                              # DW_AT_frame_base
+	.byte	24                              # DW_FORM_exprloc
+	.byte	122                             # DW_AT_call_all_calls
+	.byte	25                              # DW_FORM_flag_present
+	.byte	49                              # DW_AT_abstract_origin
+	.byte	19                              # DW_FORM_ref4
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	5                               # Abbreviation Code
+	.byte	5                               # DW_TAG_formal_parameter
+	.byte	0                               # DW_CHILDREN_no
+	.byte	2                               # DW_AT_location
+	.byte	24                              # DW_FORM_exprloc
+	.byte	49                              # DW_AT_abstract_origin
+	.byte	19                              # DW_FORM_ref4
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	6                               # Abbreviation Code
+	.byte	46                              # DW_TAG_subprogram
+	.byte	1                               # DW_CHILDREN_yes
+	.byte	110                             # DW_AT_linkage_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	58                              # DW_AT_decl_file
+	.byte	11                              # DW_FORM_data1
+	.byte	59                              # DW_AT_decl_line
+	.byte	11                              # DW_FORM_data1
+	.byte	63                              # DW_AT_external
+	.byte	25                              # DW_FORM_flag_present
+	.byte	32                              # DW_AT_inline
+	.byte	33                              # DW_FORM_implicit_const
+	.byte	1
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	7                               # Abbreviation Code
+	.byte	5                               # DW_TAG_formal_parameter
+	.byte	0                               # DW_CHILDREN_no
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	58                              # DW_AT_decl_file
+	.byte	11                              # DW_FORM_data1
+	.byte	59                              # DW_AT_decl_line
+	.byte	11                              # DW_FORM_data1
+	.byte	73                              # DW_AT_type
+	.byte	19                              # DW_FORM_ref4
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	8                               # Abbreviation Code
+	.byte	15                              # DW_TAG_pointer_type
+	.byte	0                               # DW_CHILDREN_no
+	.byte	73                              # DW_AT_type
+	.byte	19                              # DW_FORM_ref4
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	9                               # Abbreviation Code
+	.byte	46                              # DW_TAG_subprogram
+	.byte	1                               # DW_CHILDREN_yes
+	.byte	17                              # DW_AT_low_pc
+	.byte	27                              # DW_FORM_addrx
+	.byte	18                              # DW_AT_high_pc
+	.byte	6                               # DW_FORM_data4
+	.byte	64                              # DW_AT_frame_base
+	.byte	24                              # DW_FORM_exprloc
+	.byte	122                             # DW_AT_call_all_calls
+	.byte	25                              # DW_FORM_flag_present
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	58                              # DW_AT_decl_file
+	.byte	11                              # DW_FORM_data1
+	.byte	59                              # DW_AT_decl_line
+	.byte	11                              # DW_FORM_data1
+	.byte	73                              # DW_AT_type
+	.byte	19                              # DW_FORM_ref4
+	.byte	63                              # DW_AT_external
+	.byte	25                              # DW_FORM_flag_present
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	10                              # Abbreviation Code
+	.byte	5                               # DW_TAG_formal_parameter
+	.byte	0                               # DW_CHILDREN_no
+	.byte	2                               # DW_AT_location
+	.byte	24                              # DW_FORM_exprloc
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	58                              # DW_AT_decl_file
+	.byte	11                              # DW_FORM_data1
+	.byte	59                              # DW_AT_decl_line
+	.byte	11                              # DW_FORM_data1
+	.byte	73                              # DW_AT_type
+	.byte	19                              # DW_FORM_ref4
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	11                              # Abbreviation Code
+	.byte	29                              # DW_TAG_inlined_subroutine
+	.byte	0                               # DW_CHILDREN_no
+	.byte	49                              # DW_AT_abstract_origin
+	.byte	19                              # DW_FORM_ref4
+	.byte	17                              # DW_AT_low_pc
+	.byte	27                              # DW_FORM_addrx
+	.byte	18                              # DW_AT_high_pc
+	.byte	6                               # DW_FORM_data4
+	.byte	88                              # DW_AT_call_file
+	.byte	11                              # DW_FORM_data1
+	.byte	89                              # DW_AT_call_line
+	.byte	11                              # DW_FORM_data1
+	.byte	87                              # DW_AT_call_column
+	.byte	11                              # DW_FORM_data1
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	0                               # EOM(3)
+	.section	.debug_info,"",@progbits
+.Lcu_begin0:
+	.long	.Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+	.short	5                               # DWARF version number
+	.byte	1                               # DWARF Unit Type
+	.byte	8                               # Address Size (in bytes)
+	.long	.debug_abbrev                   # Offset Into Abbrev. Section
+	.byte	1                               # Abbrev [1] 0xc:0xa7 DW_TAG_compile_unit
+	.byte	0                               # DW_AT_producer
+	.short	33                              # DW_AT_language
+	.byte	1                               # DW_AT_name
+	.long	.Lstr_offsets_base0             # DW_AT_str_offsets_base
+	.long	.Lline_table_start0             # DW_AT_stmt_list
+	.byte	2                               # DW_AT_comp_dir
+	.byte	2                               # DW_AT_low_pc
+	.long	.Lfunc_end1-.Lfunc_begin0       # DW_AT_high_pc
+	.long	.Laddr_table_base0              # DW_AT_addr_base
+	.byte	2                               # Abbrev [2] 0x23:0xb DW_TAG_variable
+	.byte	3                               # DW_AT_name
+	.long	46                              # DW_AT_type
+                                        # DW_AT_external
+	.byte	0                               # DW_AT_decl_file
+	.byte	6                               # DW_AT_decl_line
+	.byte	2                               # DW_AT_location
+	.byte	161
+	.byte	0
+	.byte	3                               # Abbrev [3] 0x2e:0x4 DW_TAG_base_type
+	.byte	4                               # DW_AT_name
+	.byte	5                               # DW_AT_encoding
+	.byte	4                               # DW_AT_byte_size
+	.byte	2                               # Abbrev [2] 0x32:0xb DW_TAG_variable
+	.byte	5                               # DW_AT_name
+	.long	46                              # DW_AT_type
+                                        # DW_AT_external
+	.byte	0                               # DW_AT_decl_file
+	.byte	7                               # DW_AT_decl_line
+	.byte	2                               # DW_AT_location
+	.byte	161
+	.byte	1
+	.byte	4                               # Abbrev [4] 0x3d:0x1b DW_TAG_subprogram
+	.byte	2                               # DW_AT_low_pc
+	.long	.Lfunc_end0-.Lfunc_begin0       # DW_AT_high_pc
+	.byte	1                               # DW_AT_frame_base
+	.byte	87
+                                        # DW_AT_call_all_calls
+	.long	88                              # DW_AT_abstract_origin
+	.byte	5                               # Abbrev [5] 0x49:0x7 DW_TAG_formal_parameter
+	.byte	1                               # DW_AT_location
+	.byte	85
+	.long	93                              # DW_AT_abstract_origin
+	.byte	5                               # Abbrev [5] 0x50:0x7 DW_TAG_formal_parameter
+	.byte	1                               # DW_AT_location
+	.byte	84
+	.long	101                             # DW_AT_abstract_origin
+	.byte	0                               # End Of Children Mark
+	.byte	6                               # Abbrev [6] 0x58:0x16 DW_TAG_subprogram
+	.byte	6                               # DW_AT_linkage_name
+	.byte	7                               # DW_AT_name
+	.byte	0                               # DW_AT_decl_file
+	.byte	1                               # DW_AT_decl_line
+                                        # DW_AT_external
+                                        # DW_AT_inline
+	.byte	7                               # Abbrev [7] 0x5d:0x8 DW_TAG_formal_parameter
+	.byte	3                               # DW_AT_name
+	.byte	0                               # DW_AT_decl_file
+	.byte	1                               # DW_AT_decl_line
+	.long	110                             # DW_AT_type
+	.byte	7                               # Abbrev [7] 0x65:0x8 DW_TAG_formal_parameter
+	.byte	5                               # DW_AT_name
+	.byte	0                               # DW_AT_decl_file
+	.byte	1                               # DW_AT_decl_line
+	.long	110                             # DW_AT_type
+	.byte	0                               # End Of Children Mark
+	.byte	8                               # Abbrev [8] 0x6e:0x5 DW_TAG_pointer_type
+	.long	46                              # DW_AT_type
+	.byte	9                               # Abbrev [9] 0x73:0x31 DW_TAG_subprogram
+	.byte	3                               # DW_AT_low_pc
+	.long	.Lfunc_end1-.Lfunc_begin1       # DW_AT_high_pc
+	.byte	1                               # DW_AT_frame_base
+	.byte	87
+                                        # DW_AT_call_all_calls
+	.byte	8                               # DW_AT_name
+	.byte	0                               # DW_AT_decl_file
+	.byte	8                               # DW_AT_decl_line
+	.long	46                              # DW_AT_type
+                                        # DW_AT_external
+	.byte	10                              # Abbrev [10] 0x82:0xa DW_TAG_formal_parameter
+	.byte	1                               # DW_AT_location
+	.byte	85
+	.byte	9                               # DW_AT_name
+	.byte	0                               # DW_AT_decl_file
+	.byte	8                               # DW_AT_decl_line
+	.long	46                              # DW_AT_type
+	.byte	10                              # Abbrev [10] 0x8c:0xa DW_TAG_formal_parameter
+	.byte	1                               # DW_AT_location
+	.byte	84
+	.byte	10                              # DW_AT_name
+	.byte	0                               # DW_AT_decl_file
+	.byte	8                               # DW_AT_decl_line
+	.long	164                             # DW_AT_type
+	.byte	11                              # Abbrev [11] 0x96:0xd DW_TAG_inlined_subroutine
+	.long	88                              # DW_AT_abstract_origin
+	.byte	3                               # DW_AT_low_pc
+	.long	.Ltmp2-.Lfunc_begin1            # DW_AT_high_pc
+	.byte	0                               # DW_AT_call_file
+	.byte	11                              # DW_AT_call_line
+	.byte	4                               # DW_AT_call_column
+	.byte	0                               # End Of Children Mark
+	.byte	8                               # Abbrev [8] 0xa4:0x5 DW_TAG_pointer_type
+	.long	169                             # DW_AT_type
+	.byte	8                               # Abbrev [8] 0xa9:0x5 DW_TAG_pointer_type
+	.long	174                             # DW_AT_type
+	.byte	3                               # Abbrev [3] 0xae:0x4 DW_TAG_base_type
+	.byte	11                              # DW_AT_name
+	.byte	6                               # DW_AT_encoding
+	.byte	1                               # DW_AT_byte_size
+	.byte	0                               # End Of Children Mark
+.Ldebug_info_end0:
+	.section	.debug_str_offsets,"",@progbits
+	.long	52                              # Length of String Offsets Set
+	.short	5
+	.short	0
+.Lstr_offsets_base0:
+	.section	.debug_str,"MS",@progbits,1
+.Linfo_string0:
+	.asciz	"clang version 15.0.0" # string offset=0
+.Linfo_string1:
+	.asciz	"main.cpp"                      # string offset=134
+.Linfo_string2:
+	.asciz	"/testLocExprLoc" # string offset=143
+.Linfo_string3:
+	.asciz	"x"                             # string offset=195
+.Linfo_string4:
+	.asciz	"int"                           # string offset=197
+.Linfo_string5:
+	.asciz	"y"                             # string offset=201
+.Linfo_string6:
+	.asciz	"_Z3usePiS_"                    # string offset=203
+.Linfo_string7:
+	.asciz	"use"                           # string offset=214
+.Linfo_string8:
+	.asciz	"main"                          # string offset=218
+.Linfo_string9:
+	.asciz	"argc"                          # string offset=223
+.Linfo_string10:
+	.asciz	"argv"                          # string offset=228
+.Linfo_string11:
+	.asciz	"char"                          # string offset=233
+	.section	.debug_str_offsets,"",@progbits
+	.long	.Linfo_string0
+	.long	.Linfo_string1
+	.long	.Linfo_string2
+	.long	.Linfo_string3
+	.long	.Linfo_string4
+	.long	.Linfo_string5
+	.long	.Linfo_string6
+	.long	.Linfo_string7
+	.long	.Linfo_string8
+	.long	.Linfo_string9
+	.long	.Linfo_string10
+	.long	.Linfo_string11
+	.section	.debug_addr,"",@progbits
+	.long	.Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution
+.Ldebug_addr_start0:
+	.short	5                               # DWARF version number
+	.byte	8                               # Address size
+	.byte	0                               # Segment selector size
+.Laddr_table_base0:
+	.quad	x
+	.quad	y
+	.quad	.Lfunc_begin0
+	.quad	.Lfunc_begin1
+.Ldebug_addr_end0:
+	.ident	"clang version 15.0.0"
+	.section	".note.GNU-stack","",@progbits
+	.addrsig
+	.section	.debug_line,"",@progbits
+.Lline_table_start0:
diff --git a/bolt/test/X86/dwarf5_lowpc_highpc_convert.s b/bolt/test/X86/dwarf5_lowpc_highpc_convert.s
new file mode 100644
--- /dev/null
+++ b/bolt/test/X86/dwarf5_lowpc_highpc_convert.s
@@ -0,0 +1,196 @@
+# REQUIRES: system-linux
+
+# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %s -o %t1.o
+# RUN: %clang %cflags -dwarf-5 %t1.o -o %t.exe -Wl,-q
+# RUN: llvm-bolt %t.exe -o %t.bolt -update-debug-sections
+# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.exe | FileCheck --check-prefix=PRECHECK %s
+# RUN: llvm-dwarfdump --show-form --verbose --debug-addr %t.bolt &> %t.txt
+# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.bolt >> %t.txt
+# RUN: cat %t.txt | FileCheck --check-prefix=POSTCHECK %s
+
+# This tests checks that DW_AT_low_pc/DW_AT_high_pc is converted to DW_AT_low_pc/DW_AT_ranges.
+# Checks that DW_AT_rnglists_base is inserted, and that correct address is used.
+
+# PRECHECK: version = 0x0005
+# PRECHECK: DW_AT_low_pc
+# PRECHECK-SAME: DW_FORM_addrx
+# PRECHECK-SAME: (00000000)
+# PRECHECK-NEXT: DW_AT_high_pc [DW_FORM_data4]	(0x0000000f)
+# PRECHECK-NEXT: DW_AT_addr_base [DW_FORM_sec_offset]	(0x00000008)
+
+# POSTCHECK: Addrs: [
+# POSTCHECK-NEXT: 0x[[#%.16x,ADDR:]]
+# POSTCHECK: version = 0x0005
+# POSTCHECK: DW_AT_low_pc
+# POSTCHECK-SAME: DW_FORM_addrx
+# POSTCHECK-SAME: (00000001)
+# POSTCHECK-SAME: address = 0x0000000000000000
+# POSTCHECK-NEXT: DW_AT_ranges
+# POSTCHECK-SAME: DW_FORM_rnglistx
+# POSTCHECK-SAME: (0x0)
+# POSTCHECK-SAME: rangelist = 0x00000014
+# POSTCHECK-NEXT: [
+# POSTCHECK-SAME: 0x[[#ADDR]]
+# POSTCHECK-SAME: 0x[[#ADDR + 15]]
+# POSTCHECK-NEXT: DW_AT_addr_base [DW_FORM_sec_offset]  (0x00000008)
+# POSTCHECK-NEXT: DW_AT_rnglists_base [DW_FORM_sec_offset]  (0x0000000c)
+
+# int main() {
+#    return 0;
+# }
+
+	.text
+	.file	"main.cpp"
+	.globl	main                            # -- Begin function main
+	.p2align	4, 0x90
+	.type	main,@function
+main:                                   # @main
+.Lfunc_begin0:
+	.file	0 "." "main.cpp" md5 0xbb12fec8d002b1f0e06f7dee4604c6cc
+	.loc	0 1 0                           # main.cpp:1:0
+	.cfi_startproc
+# %bb.0:                                # %entry
+	pushq	%rbp
+	.cfi_def_cfa_offset 16
+	.cfi_offset %rbp, -16
+	movq	%rsp, %rbp
+	.cfi_def_cfa_register %rbp
+	movl	$0, -4(%rbp)
+.Ltmp0:
+	.loc	0 2 3 prologue_end              # main.cpp:2:3
+	xorl	%eax, %eax
+	popq	%rbp
+	.cfi_def_cfa %rsp, 8
+	retq
+.Ltmp1:
+.Lfunc_end0:
+	.size	main, .Lfunc_end0-main
+	.cfi_endproc
+                                        # -- End function
+	.section	.debug_abbrev,"",@progbits
+	.byte	1                               # Abbreviation Code
+	.byte	17                              # DW_TAG_compile_unit
+	.byte	1                               # DW_CHILDREN_yes
+	.byte	37                              # DW_AT_producer
+	.byte	37                              # DW_FORM_strx1
+	.byte	19                              # DW_AT_language
+	.byte	5                               # DW_FORM_data2
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	114                             # DW_AT_str_offsets_base
+	.byte	23                              # DW_FORM_sec_offset
+	.byte	16                              # DW_AT_stmt_list
+	.byte	23                              # DW_FORM_sec_offset
+	.byte	27                              # DW_AT_comp_dir
+	.byte	37                              # DW_FORM_strx1
+	.byte	17                              # DW_AT_low_pc
+	.byte	27                              # DW_FORM_addrx
+	.byte	18                              # DW_AT_high_pc
+	.byte	6                               # DW_FORM_data4
+	.byte	115                             # DW_AT_addr_base
+	.byte	23                              # DW_FORM_sec_offset
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	2                               # Abbreviation Code
+	.byte	46                              # DW_TAG_subprogram
+	.byte	0                               # DW_CHILDREN_no
+	.byte	17                              # DW_AT_low_pc
+	.byte	27                              # DW_FORM_addrx
+	.byte	18                              # DW_AT_high_pc
+	.byte	6                               # DW_FORM_data4
+	.byte	64                              # DW_AT_frame_base
+	.byte	24                              # DW_FORM_exprloc
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	58                              # DW_AT_decl_file
+	.byte	11                              # DW_FORM_data1
+	.byte	59                              # DW_AT_decl_line
+	.byte	11                              # DW_FORM_data1
+	.byte	73                              # DW_AT_type
+	.byte	19                              # DW_FORM_ref4
+	.byte	63                              # DW_AT_external
+	.byte	25                              # DW_FORM_flag_present
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	3                               # Abbreviation Code
+	.byte	36                              # DW_TAG_base_type
+	.byte	0                               # DW_CHILDREN_no
+	.byte	3                               # DW_AT_name
+	.byte	37                              # DW_FORM_strx1
+	.byte	62                              # DW_AT_encoding
+	.byte	11                              # DW_FORM_data1
+	.byte	11                              # DW_AT_byte_size
+	.byte	11                              # DW_FORM_data1
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	0                               # EOM(3)
+	.section	.debug_info,"",@progbits
+.Lcu_begin0:
+	.long	.Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+	.short	5                               # DWARF version number
+	.byte	1                               # DWARF Unit Type
+	.byte	8                               # Address Size (in bytes)
+	.long	.debug_abbrev                   # Offset Into Abbrev. Section
+	.byte	1                               # Abbrev [1] 0xc:0x2b DW_TAG_compile_unit
+	.byte	0                               # DW_AT_producer
+	.short	33                              # DW_AT_language
+	.byte	1                               # DW_AT_name
+	.long	.Lstr_offsets_base0             # DW_AT_str_offsets_base
+	.long	.Lline_table_start0             # DW_AT_stmt_list
+	.byte	2                               # DW_AT_comp_dir
+	.byte	0                               # DW_AT_low_pc
+	.long	.Lfunc_end0-.Lfunc_begin0       # DW_AT_high_pc
+	.long	.Laddr_table_base0              # DW_AT_addr_base
+	.byte	2                               # Abbrev [2] 0x23:0xf DW_TAG_subprogram
+	.byte	0                               # DW_AT_low_pc
+	.long	.Lfunc_end0-.Lfunc_begin0       # DW_AT_high_pc
+	.byte	1                               # DW_AT_frame_base
+	.byte	86
+	.byte	3                               # DW_AT_name
+	.byte	0                               # DW_AT_decl_file
+	.byte	1                               # DW_AT_decl_line
+	.long	50                              # DW_AT_type
+                                        # DW_AT_external
+	.byte	3                               # Abbrev [3] 0x32:0x4 DW_TAG_base_type
+	.byte	4                               # DW_AT_name
+	.byte	5                               # DW_AT_encoding
+	.byte	4                               # DW_AT_byte_size
+	.byte	0                               # End Of Children Mark
+.Ldebug_info_end0:
+	.section	.debug_str_offsets,"",@progbits
+	.long	24                              # Length of String Offsets Set
+	.short	5
+	.short	0
+.Lstr_offsets_base0:
+	.section	.debug_str,"MS",@progbits,1
+.Linfo_string0:
+	.asciz	"clang version 15.0.0" # string offset=0
+.Linfo_string1:
+	.asciz	"main.cpp"                      # string offset=134
+.Linfo_string2:
+	.asciz	"." # string offset=143
+.Linfo_string3:
+	.asciz	"main"                          # string offset=180
+.Linfo_string4:
+	.asciz	"int"                           # string offset=185
+	.section	.debug_str_offsets,"",@progbits
+	.long	.Linfo_string0
+	.long	.Linfo_string1
+	.long	.Linfo_string2
+	.long	.Linfo_string3
+	.long	.Linfo_string4
+	.section	.debug_addr,"",@progbits
+	.long	.Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution
+.Ldebug_addr_start0:
+	.short	5                               # DWARF version number
+	.byte	8                               # Address size
+	.byte	0                               # Segment selector size
+.Laddr_table_base0:
+	.quad	.Lfunc_begin0
+.Ldebug_addr_end0:
+	.ident	"clang version 15.0.0"
+	.section	".note.GNU-stack","",@progbits
+	.addrsig
+	.section	.debug_line,"",@progbits
+.Lline_table_start0:
diff --git a/bolt/test/X86/dwarf5_rangeoffset_to_rangeindex.s b/bolt/test/X86/dwarf5_rangeoffset_to_rangeindex.s
new file mode 100644
--- /dev/null
+++ b/bolt/test/X86/dwarf5_rangeoffset_to_rangeindex.s
@@ -0,0 +1,256 @@
+# REQUIRES: system-linux
+
+# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %s -o %t1.o
+# RUN: %clang %cflags -dwarf-5 %t1.o -o %t.exe -Wl,-q
+# RUN: llvm-bolt %t.exe -o %t.bolt -update-debug-sections
+# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.exe | FileCheck --check-prefix=PRECHECK %s
+# RUN: llvm-dwarfdump --show-form --verbose --debug-addr %t.bolt &> %t.txt
+# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.bolt >> %t.txt
+# RUN: cat %t.txt | FileCheck --check-prefix=POSTCHECK %s
+
+# This tests conversion for DWARF5 ranges DW_AT_ranges [DW_FORM_sec_offset] to DW_AT_ranges [DW_FORM_rnglistx]
+
+# PRECHECK: version = 0x0005
+# PRECHECK: DW_AT_ranges [DW_FORM_sec_offset]
+
+# POSTCHECK: Addrs: [
+# POSTCHECK-NEXT: 0x[[#%.16x,ADDR:]]
+# POSTCHECK-NEXT: 0x[[#%.16x,ADDR1:]]
+# POSTCHECK: version = 0x0005
+# POSTCHECK: DW_AT_ranges [DW_FORM_rnglistx]
+# POSTCHECK-SAME: (indexed (0x0) rangelist = 0x00000018
+# POSTCHECK-NEXT: [0x[[#ADDR]], 0x[[#ADDR + 11]]
+# POSTCHECK-NEXT: [0x[[#ADDR1]], 0x[[#ADDR1 + 11]]
+
+# int foo() {
+#   return 3;
+# }
+#
+# int main() {
+#   return foo();
+# }
+
+	.file	"main.cpp"
+	.text
+.Ltext0:
+	.file 0 "/testRangeOffsetToRangeX" "main.cpp"
+	.section	.text._Z3foov,"ax",@progbits
+	.globl	_Z3foov
+	.type	_Z3foov, @function
+_Z3foov:
+.LFB0:
+	.file 1 "main.cpp"
+	.loc 0 1 11
+	.cfi_startproc
+	pushq	%rbp
+	.cfi_def_cfa_offset 16
+	.cfi_offset 6, -16
+	movq	%rsp, %rbp
+	.cfi_def_cfa_register 6
+	.loc 0 2 10
+	movl	$3, %eax
+	.loc 0 3 1
+	popq	%rbp
+	.cfi_def_cfa 7, 8
+	ret
+	.cfi_endproc
+.LFE0:
+	.size	_Z3foov, .-_Z3foov
+	.section	.text.main,"ax",@progbits
+	.globl	main
+	.type	main, @function
+main:
+.LFB1:
+	.loc 0 5 12
+	.cfi_startproc
+	pushq	%rbp
+	.cfi_def_cfa_offset 16
+	.cfi_offset 6, -16
+	movq	%rsp, %rbp
+	.cfi_def_cfa_register 6
+	.loc 0 6 13
+	call	_Z3foov
+	.loc 0 6 14
+	nop
+	.loc 0 7 1
+	popq	%rbp
+	.cfi_def_cfa 7, 8
+	ret
+	.cfi_endproc
+.LFE1:
+	.size	main, .-main
+	.text
+.Letext0:
+	.section	.debug_info,"",@progbits
+.Ldebug_info0:
+	.long	0x6e
+	.value	0x5
+	.byte	0x1
+	.byte	0x8
+	.long	.Ldebug_abbrev0
+	.uleb128 0x1
+	.long	.LASF2
+	.byte	0x21
+	.long	.LASF0
+	.long	.LASF1
+	.long	.LLRL0
+	.quad	0
+	.long	.Ldebug_line0
+	.uleb128 0x2
+	.long	.LASF3
+	.byte	0x1
+	.byte	0x5
+	.byte	0x5
+	.long	0x48
+	.quad	.LFB1
+	.quad	.LFE1-.LFB1
+	.uleb128 0x1
+	.byte	0x9c
+	.uleb128 0x3
+	.byte	0x4
+	.byte	0x5
+	.string	"int"
+	.uleb128 0x4
+	.string	"foo"
+	.byte	0x1
+	.byte	0x1
+	.byte	0x5
+	.long	.LASF4
+	.long	0x48
+	.quad	.LFB0
+	.quad	.LFE0-.LFB0
+	.uleb128 0x1
+	.byte	0x9c
+	.byte	0
+	.section	.debug_abbrev,"",@progbits
+.Ldebug_abbrev0:
+	.uleb128 0x1
+	.uleb128 0x11
+	.byte	0x1
+	.uleb128 0x25
+	.uleb128 0xe
+	.uleb128 0x13
+	.uleb128 0xb
+	.uleb128 0x3
+	.uleb128 0x1f
+	.uleb128 0x1b
+	.uleb128 0x1f
+	.uleb128 0x55
+	.uleb128 0x17
+	.uleb128 0x11
+	.uleb128 0x1
+	.uleb128 0x10
+	.uleb128 0x17
+	.byte	0
+	.byte	0
+	.uleb128 0x2
+	.uleb128 0x2e
+	.byte	0
+	.uleb128 0x3f
+	.uleb128 0x19
+	.uleb128 0x3
+	.uleb128 0xe
+	.uleb128 0x3a
+	.uleb128 0xb
+	.uleb128 0x3b
+	.uleb128 0xb
+	.uleb128 0x39
+	.uleb128 0xb
+	.uleb128 0x49
+	.uleb128 0x13
+	.uleb128 0x11
+	.uleb128 0x1
+	.uleb128 0x12
+	.uleb128 0x7
+	.uleb128 0x40
+	.uleb128 0x18
+	.uleb128 0x7c
+	.uleb128 0x19
+	.byte	0
+	.byte	0
+	.uleb128 0x3
+	.uleb128 0x24
+	.byte	0
+	.uleb128 0xb
+	.uleb128 0xb
+	.uleb128 0x3e
+	.uleb128 0xb
+	.uleb128 0x3
+	.uleb128 0x8
+	.byte	0
+	.byte	0
+	.uleb128 0x4
+	.uleb128 0x2e
+	.byte	0
+	.uleb128 0x3f
+	.uleb128 0x19
+	.uleb128 0x3
+	.uleb128 0x8
+	.uleb128 0x3a
+	.uleb128 0xb
+	.uleb128 0x3b
+	.uleb128 0xb
+	.uleb128 0x39
+	.uleb128 0xb
+	.uleb128 0x6e
+	.uleb128 0xe
+	.uleb128 0x49
+	.uleb128 0x13
+	.uleb128 0x11
+	.uleb128 0x1
+	.uleb128 0x12
+	.uleb128 0x7
+	.uleb128 0x40
+	.uleb128 0x18
+	.uleb128 0x7a
+	.uleb128 0x19
+	.byte	0
+	.byte	0
+	.byte	0
+	.section	.debug_aranges,"",@progbits
+	.long	0x3c
+	.value	0x2
+	.long	.Ldebug_info0
+	.byte	0x8
+	.byte	0
+	.value	0
+	.value	0
+	.quad	.LFB0
+	.quad	.LFE0-.LFB0
+	.quad	.LFB1
+	.quad	.LFE1-.LFB1
+	.quad	0
+	.quad	0
+	.section	.debug_rnglists,"",@progbits
+.Ldebug_ranges0:
+	.long	.Ldebug_ranges3-.Ldebug_ranges2
+.Ldebug_ranges2:
+	.value	0x5
+	.byte	0x8
+	.byte	0
+	.long	0
+.LLRL0:
+	.byte	0x7
+	.quad	.LFB0
+	.uleb128 .LFE0-.LFB0
+	.byte	0x7
+	.quad	.LFB1
+	.uleb128 .LFE1-.LFB1
+	.byte	0
+.Ldebug_ranges3:
+	.section	.debug_line,"",@progbits
+.Ldebug_line0:
+	.section	.debug_str,"MS",@progbits,1
+.LASF4:
+	.string	"_Z3foov"
+.LASF3:
+	.string	"main"
+.LASF2:
+	.string	"GNU C++17 11.x"
+	.section	.debug_line_str,"MS",@progbits,1
+.LASF0:
+	.string	"main.cpp"
+.LASF1:
+	.string	"/testRangeOffsetToRangeX"
+	.ident	"GCC: (GNU) 11.x"
+	.section	.note.GNU-stack,"",@progbits
diff --git a/bolt/test/X86/dwarf5_two_loclists.test b/bolt/test/X86/dwarf5_two_loclists.test
new file mode 100644
--- /dev/null
+++ b/bolt/test/X86/dwarf5_two_loclists.test
@@ -0,0 +1,78 @@
+# REQUIRES: system-linux
+
+# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5_main.s -o %tmain.o
+# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5_helper.s -o %thelper.o
+# RUN: %clang %cflags -dwarf-5 %tmain.o %thelper.o -o %t.exe -Wl,-q
+# RUN: llvm-bolt %t.exe -o %t.bolt -update-debug-sections
+# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.exe | FileCheck --check-prefix=PRECHECK %s
+# RUN: llvm-dwarfdump --show-form --verbose --debug-addr %t.bolt &> %t.txt
+# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.bolt >> %t.txt
+# RUN: cat %t.txt | FileCheck --check-prefix=POSTCHECK %s
+
+# This tests checks that re-writing of .debug_loclists is handled correctly for two CUs,
+# and two loclist entries.
+
+# PRECHECK: version = 0x0005
+# PRECHECK: DW_AT_loclists_base [DW_FORM_sec_offset] (0x0000000c)
+# PRECHECK-EMPTY:
+# PRECHECK: DW_TAG_variable
+# PRECHECK: DW_AT_location [DW_FORM_loclistx]
+# PRECHECK-SAME: indexed (0x0)
+# PRECHECK-SAME: loclist = 0x00000014
+# PRECHECK: DW_AT_location [DW_FORM_loclistx]
+# PRECHECK-SAME: indexed (0x1)
+# PRECHECK-SAME: loclist = 0x00000028
+# PRECHECK: DW_AT_loclists_base [DW_FORM_sec_offset]  (0x00000043)
+# PRECHECK-EMPTY:
+# PRECHECK: DW_TAG_variable
+# PRECHECK: DW_TAG_variable
+# PRECHECK: DW_AT_location [DW_FORM_loclistx]
+# PRECHECK-SAME: indexed (0x0)
+# PRECHECK-SAME: loclist = 0x00000047
+
+# POSTCHECK: Addrs: [
+# POSTCHECK-NEXT: 0x
+# POSTCHECK-NEXT: 0x[[#%.16x,ADDR:]]
+# POSTCHECK-NEXT: 0x
+# POSTCHECK-NEXT: 0x[[#%.16x,ADDR2:]]
+# For second CU.
+# POSTCHECK: Addrs: [
+# POSTCHECK-NEXT: 0x
+# POSTCHECK-NEXT: 0x[[#%.16x,ADDR3:]]
+# POSTCHECK-NEXT: 0x
+# POSTCHECK-NEXT: 0x
+# POSTCHECK-NEXT: 0x[[#%.16x,ADDR4:]]
+
+# POSTCHECK: version = 0x0005
+# POSTCHECK: DW_AT_loclists_base [DW_FORM_sec_offset]	(0x0000000c)
+# POSTCHECK: DW_AT_rnglists_base [DW_FORM_sec_offset]	(0x0000000c)
+# POSTCHECK-EMPTY
+# POSTCHECK: DW_TAG_variable
+# POSTCHECK: DW_AT_location [DW_FORM_loclistx]
+# POSTCHECK-SAME: indexed (0x0)
+# POSTCHECK-SAME: loclist = 0x00000014
+# POSTCHECK-NEXT: [0x[[#ADDR]]
+# POSTCHECK-SAME: 0x[[#ADDR + 6]]
+# POSTCHECK-NEXT: [0x[[#ADDR2]]
+# POSTCHECK-SAME: 0x[[#ADDR2 + 6]]
+# POSTCHECK: DW_TAG_variable
+# POSTCHECK: DW_AT_location [DW_FORM_loclistx]
+# POSTCHECK-SAME: indexed (0x1)
+# POSTCHECK-SAME: loclist = 0x00000028
+# POSTCHECK-NEXT: [0x[[#ADDR2]]
+# POSTCHECK-SAME: 0x[[#ADDR2 + 2]]
+
+# Checking second CU
+# POSTCHECK: version = 0x0005
+# POSTCHECK: DW_AT_loclists_base [DW_FORM_sec_offset]	(0x00000043)
+# POSTCHECK: DW_AT_rnglists_base [DW_FORM_sec_offset]	(0x00000033)
+# POSTCHECK-EMPTY:
+# POSTCHECK: DW_TAG_variable
+# POSTCHECK: DW_TAG_variable
+# POSTCHECK: DW_AT_location [DW_FORM_loclistx]
+# POSTCHECK-SAME: indexed (0x0)
+# POSTCHECK-SAME: loclist = 0x00000047
+# POSTCHECK-NEXT: [0x[[#ADDR3]]
+# POSTCHECK-SAME: 0x[[#ADDR3 + 3]]
+# POSTCHECK-NEXT: [0x[[#ADDR4]]
+# POSTCHECK-SAME: 0x[[#ADDR4 + 1]]
diff --git a/bolt/test/X86/dwarf5_two_rnglists.test b/bolt/test/X86/dwarf5_two_rnglists.test
new file mode 100644
--- /dev/null
+++ b/bolt/test/X86/dwarf5_two_rnglists.test
@@ -0,0 +1,110 @@
+# REQUIRES: system-linux
+
+# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5_main.s -o %tmain.o
+# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5_helper.s -o %thelper.o
+# RUN: %clang %cflags -dwarf-5 %tmain.o %thelper.o -o %t.exe -Wl,-q
+# RUN: llvm-bolt %t.exe -o %t.bolt -update-debug-sections
+# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.exe | FileCheck --check-prefix=PRECHECK %s
+# RUN: llvm-dwarfdump --show-form --verbose --debug-addr %t.bolt &> %t.txt
+# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.bolt >> %t.txt
+# RUN: cat %t.txt | FileCheck --check-prefix=POSTCHECK %s
+
+# This tests checks that re-writing of .debug_rnglists is handled correctly for two CUs,
+# and DW_AT_low_pc/DW_AT_high_pc conversion is handled correctly.
+
+# PRECHECK: version = 0x0005
+# PRECHECK: DW_AT_low_pc [DW_FORM_addrx]
+# PRECHECK: DW_AT_high_pc [DW_FORM_data4]
+# PRECHECK: DW_AT_loclists_base [DW_FORM_sec_offset] (0x0000000c)
+# PRECHECK-EMPTY:
+# PRECHECK: version = 0x0005
+# PRECHECK: DW_AT_low_pc [DW_FORM_addrx]
+# PRECHECK: DW_AT_high_pc [DW_FORM_data4]
+# PRECHECK: DW_AT_loclists_base [DW_FORM_sec_offset]  (0x00000043)
+
+# PRECHECK: DW_TAG_inlined_subroutine
+# PRECHECK-NEXT: DW_AT_abstract_origin
+# PRECHECK-NEXT: DW_AT_low_pc [DW_FORM_addrx]
+# PRECHECK-NEXT: DW_AT_high_pc [DW_FORM_data4] (0x00000003)
+
+# POSTCHECK: Addrs: [
+# POSTCHECK-NEXT: 0x[[#%.16x,ADDR:]]
+# POSTCHECK-NEXT: 0x[[#%.16x,ADDR1:]]
+# POSTCHECK-NEXT: 0x
+# POSTCHECK-NEXT: 0x[[#%.16x,ADDR2:]]
+# For second CU.
+# POSTCHECK: Addrs: [
+# POSTCHECK-NEXT: 0x[[#%.16x,ADDR3:]]
+# POSTCHECK-NEXT: 0x[[#%.16x,ADDR4:]]
+
+# POSTCHECK: version = 0x0005
+# POSTCHECK: DW_AT_ranges [DW_FORM_rnglistx]
+# POSTCHECK-SAME: (indexed (0x0)
+# POSTCHECK-SAME: rangelist = 0x00000018
+# POSTCHECK-NEXT: [
+# POSTCHECK-SAME: 0x[[#ADDR]]
+# POSTCHECK-SAME: 0x[[#ADDR + 7]]
+# POSTCHECK-NEXT: [
+# POSTCHECK-SAME: 0x[[#ADDR1]]
+# POSTCHECK-SAME: 0x[[#ADDR1 + 12]]
+# POSTCHECK-NEXT: DW_AT_addr_base [DW_FORM_sec_offset]  (0x00000008)
+# POSTCHECK-NEXT: DW_AT_loclists_base [DW_FORM_sec_offset]	(0x0000000c)
+# POSTCHECK-NEXT: DW_AT_rnglists_base [DW_FORM_sec_offset]	(0x0000000c)
+# POSTCHECK-EMPTY
+# POSTCHECK: DW_TAG_subprogram
+# POSTCHECK-NEXT: DW_AT_low_pc [DW_FORM_addrx]
+# POSTCHECK-SAME: indexed (00000002)
+# POSTCHECK-SAME: address = 0x0000000000000000
+# POSTCHECK-NEXT: DW_AT_ranges [DW_FORM_rnglistx]
+# POSTCHECK-SAME: indexed (0x1)
+# POSTCHECK-SAME: rangelist = 0x0000001f
+# POSTCHECK-NEXT: [0x[[#ADDR]], 0x[[#ADDR + 7]])
+
+# POSTCHECK: DW_TAG_subprogram
+# POSTCHECK-NEXT: DW_AT_low_pc [DW_FORM_addrx]
+# POSTCHECK-SAME: indexed (00000002)
+# POSTCHECK-SAME: address = 0x0000000000000000
+# POSTCHECK-NEXT: DW_AT_ranges [DW_FORM_rnglistx]
+# POSTCHECK-SAME: indexed (0x2)
+# POSTCHECK-SAME: rangelist = 0x00000023
+# POSTCHECK-NEXT: [0x[[#ADDR1]], 0x[[#ADDR1 + 12]])
+
+# Checking second CU
+# POSTCHECK: version = 0x0005
+# POSTCHECK: DW_AT_ranges [DW_FORM_rnglistx]
+# POSTCHECK-SAME: (indexed (0x0)
+# POSTCHECK-SAME: rangelist = 0x00000043
+# POSTCHECK-NEXT: [0x[[#ADDR3]], 0x[[#ADDR3 + 4]])
+# POSTCHECK-NEXT: [0x[[#ADDR4]], 0x[[#ADDR4 + 4]])
+# POSTCHECK-NEXT: DW_AT_addr_base [DW_FORM_sec_offset]  (0x00000030)
+# POSTCHECK-NEXT: DW_AT_loclists_base [DW_FORM_sec_offset]	(0x00000043)
+# POSTCHECK-NEXT: DW_AT_rnglists_base [DW_FORM_sec_offset]	(0x00000033)
+# POSTCHECK-EMPTY
+
+# POSTCHECK: DW_TAG_subprogram
+# POSTCHECK-NEXT: DW_AT_low_pc [DW_FORM_addrx]
+# POSTCHECK-SAME: indexed (00000002)
+# POSTCHECK-SAME: address = 0x0000000000000000
+# POSTCHECK-NEXT: DW_AT_ranges [DW_FORM_rnglistx]
+# POSTCHECK-SAME: indexed (0x1)
+# POSTCHECK-SAME: rangelist = 0x0000004a
+# POSTCHECK-NEXT: [0x[[#ADDR3]], 0x[[#ADDR3 + 4]])
+# POSTCHECK: DW_TAG_subprogram
+# POSTCHECK: DW_TAG_subprogram
+# POSTCHECK-NEXT: DW_AT_low_pc [DW_FORM_addrx]
+# POSTCHECK-SAME: indexed (00000002)
+# POSTCHECK-SAME: address = 0x0000000000000000
+# POSTCHECK-NEXT: DW_AT_ranges [DW_FORM_rnglistx]
+# POSTCHECK-SAME: indexed (0x2)
+# POSTCHECK-SAME: rangelist = 0x0000004e
+# POSTCHECK-NEXT: [0x[[#ADDR4]], 0x[[#ADDR4 + 4]])
+
+# POSTCHECK: DW_TAG_inlined_subroutine
+# POSTCHECK-NEXT: DW_AT_abstract_origin
+# POSTCHECK-NEXT: DW_AT_low_pc [DW_FORM_addrx]
+# POSTCHECK-SAME: indexed (00000002)
+# POSTCHECK-SAME: address = 0x0000000000000000
+# POSTCHECK-NEXT: DW_AT_ranges [DW_FORM_rnglistx]
+# POSTCHECK-SAME: indexed (0x3)
+# POSTCHECK-SAME: rangelist = 0x00000052
+# POSTCHECK-NEXT: [0x[[#ADDR4]], 0x[[#ADDR4 + 3]])
diff --git a/bolt/test/X86/insert_addr_rnglists_base.s b/bolt/test/X86/insert_addr_rnglists_base.s
new file mode 100644
--- /dev/null
+++ b/bolt/test/X86/insert_addr_rnglists_base.s
@@ -0,0 +1,157 @@
+# REQUIRES: system-linux
+
+# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %s -o %t1.o
+# RUN: %clang %cflags -dwarf-5 %t1.o -o %t.exe -Wl,-q
+# RUN: llvm-bolt %t.exe -o %t.bolt -update-debug-sections
+# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.exe | FileCheck --check-prefix=PRECHECK %s
+# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.bolt | FileCheck --check-prefix=POSTCHECK %s
+
+# PRECHECK-NOT: DW_AT_addr_base
+
+# POSTCHECK: DW_AT_ranges [DW_FORM_rnglistx]
+# POSTCHECK: DW_AT_rnglists_base [DW_FORM_sec_offset]	(0x0000000c)
+# POSTCHECK-NEXT: DW_AT_addr_base [DW_FORM_sec_offset]	(0x00000008)
+
+# int main() {
+#    return 0;
+# }
+
+
+	.file	"main.cpp"
+	.text
+.Ltext0:
+	.globl	main
+	.type	main, @function
+main:
+.LFB0:
+	.file 1 "main.cpp"
+	.loc 1 1 12
+	.cfi_startproc
+	pushq	%rbp
+	.cfi_def_cfa_offset 16
+	.cfi_offset 6, -16
+	movq	%rsp, %rbp
+	.cfi_def_cfa_register 6
+	.loc 1 2 10
+	movl	$0, %eax
+	.loc 1 3 1
+	popq	%rbp
+	.cfi_def_cfa 7, 8
+	ret
+	.cfi_endproc
+.LFE0:
+	.size	main, .-main
+.Letext0:
+	.section	.debug_info,"",@progbits
+.Ldebug_info0:
+	.long	0x50
+	.value	0x5
+	.byte	0x1
+	.byte	0x8
+	.long	.Ldebug_abbrev0
+	.uleb128 0x1
+	.long	.LASF0
+	.byte	0x21
+	.long	.LASF1
+	.long	.LASF2
+	.quad	.Ltext0
+	.quad	.Letext0-.Ltext0
+	.long	.Ldebug_line0
+	.uleb128 0x2
+	.long	.LASF3
+	.byte	0x1
+	.byte	0x1
+	.byte	0x5
+	.long	0x4c
+	.quad	.LFB0
+	.quad	.LFE0-.LFB0
+	.uleb128 0x1
+	.byte	0x9c
+	.uleb128 0x3
+	.byte	0x4
+	.byte	0x5
+	.string	"int"
+	.byte	0
+	.section	.debug_abbrev,"",@progbits
+.Ldebug_abbrev0:
+	.uleb128 0x1
+	.uleb128 0x11
+	.byte	0x1
+	.uleb128 0x25
+	.uleb128 0xe
+	.uleb128 0x13
+	.uleb128 0xb
+	.uleb128 0x3
+	.uleb128 0xe
+	.uleb128 0x1b
+	.uleb128 0xe
+	.uleb128 0x11
+	.uleb128 0x1
+	.uleb128 0x12
+	.uleb128 0x7
+	.uleb128 0x10
+	.uleb128 0x17
+	.byte	0
+	.byte	0
+	.uleb128 0x2
+	.uleb128 0x2e
+	.byte	0
+	.uleb128 0x3f
+	.uleb128 0x19
+	.uleb128 0x3
+	.uleb128 0xe
+	.uleb128 0x3a
+	.uleb128 0xb
+	.uleb128 0x3b
+	.uleb128 0xb
+	.uleb128 0x39
+	.uleb128 0xb
+	.uleb128 0x49
+	.uleb128 0x13
+	.uleb128 0x11
+	.uleb128 0x1
+	.uleb128 0x12
+	.uleb128 0x7
+	.uleb128 0x40
+	.uleb128 0x18
+	.uleb128 0x7a
+	.uleb128 0x19
+	.byte	0
+	.byte	0
+	.uleb128 0x3
+	.uleb128 0x24
+	.byte	0
+	.uleb128 0xb
+	.uleb128 0xb
+	.uleb128 0x3e
+	.uleb128 0xb
+	.uleb128 0x3
+	.uleb128 0x8
+	.byte	0
+	.byte	0
+	.byte	0
+	.section	.debug_aranges,"",@progbits
+	.long	0x2c
+	.value	0x2
+	.long	.Ldebug_info0
+	.byte	0x8
+	.byte	0
+	.value	0
+	.value	0
+	.quad	.Ltext0
+	.quad	.Letext0-.Ltext0
+	.quad	0
+	.quad	0
+	.section	.debug_line,"",@progbits
+.Ldebug_line0:
+	.section	.debug_str,"MS",@progbits,1
+.LASF0:
+	.string	"GNU C++14 8.5.0 20210514 (Red Hat 8.5.0-3) -mtune=generic -march=x86-64 -g2 -gdwarf-5"
+.LASF1:
+	.string	"main.cpp"
+.LASF3:
+	.string	"main"
+.LASF2:
+	.string	"."
+	.ident	"GCC: (GNU) 8.5.0 20210514 (Red Hat 8.5.0-3)"
+	.section	.note.GNU-stack,"",@progbits