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
@@ -110,6 +110,13 @@
 /// Common buffer vector used for debug info handling.
 using DebugBufferVector = SmallVector<char, 16>;
 
+/// Map of old CU offset to new offset and length.
+struct CUInfo {
+  uint32_t Offset;
+  uint32_t Length;
+};
+using CUOffsetMap = std::map<uint32_t, CUInfo>;
+
 /// Serializes the .debug_ranges DWARF section.
 class DebugRangesSectionWriter {
 public:
@@ -158,9 +165,8 @@
   /// Writes .debug_aranges with the added ranges to the MCObjectWriter.
   /// Takes in \p RangesStream to write into, and \p CUMap which maps CU
   /// original offsets to new ones.
-  void
-  writeARangesSection(raw_svector_ostream &RangesStream,
-                      const std::unordered_map<uint32_t, uint32_t> CUMap) const;
+  void writeARangesSection(raw_svector_ostream &RangesStream,
+                           const CUOffsetMap &CUMap) const;
 
   /// Resets the writer to a clear state.
   void reset() { CUAddressRanges.clear(); }
@@ -650,8 +656,8 @@
   void setDWPOffset(uint64_t DWPOffset) { DWPUnitOffset = DWPOffset; }
 
   /// When this function is invoked all of the DebugInfo Patches must be done.
-  /// Returns a map of old CU offsets to new ones.
-  std::unordered_map<uint32_t, uint32_t> computeNewOffsets();
+  /// Returns a map of old CU offsets to new offsets and new sizes.
+  CUOffsetMap computeNewOffsets(DWARFContext &DWCtx, bool IsDWOContext);
 
 private:
   struct PatchDeleter {
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
@@ -94,14 +94,14 @@
   makeFinalLocListsSection(SimpleBinaryPatcher &DebugInfoPatcher);
 
   /// Finalize debug sections in the main binary.
-  void finalizeDebugSections(DebugInfoBinaryPatcher &DebugInfoPatcher);
+  CUOffsetMap finalizeDebugSections(DebugInfoBinaryPatcher &DebugInfoPatcher);
 
   /// Patches the binary for DWARF address ranges (e.g. in functions and lexical
   /// blocks) to be updated.
   void updateDebugAddressRanges();
 
   /// Rewrite .gdb_index section if present.
-  void updateGdbIndexSection();
+  void updateGdbIndexSection(CUOffsetMap &CUMap);
 
   /// Output .dwo files.
   void writeDWOFiles(std::unordered_map<uint64_t, std::string> &DWOIdToName);
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
@@ -120,8 +120,7 @@
 }
 
 void DebugARangesSectionWriter::writeARangesSection(
-    raw_svector_ostream &RangesStream,
-    const std::unordered_map<uint32_t, uint32_t> CUMap) const {
+    raw_svector_ostream &RangesStream, const CUOffsetMap &CUMap) const {
   // For reference on the format of the .debug_aranges section, see the DWARF4
   // specification, section 6.1.4 Lookup by Address
   // http://www.dwarfstd.org/doc/DWARF4.pdf
@@ -147,9 +146,9 @@
 
     assert(CUMap.count(Offset) && "Original CU offset is not found in CU Map");
     // Header field #3: debug info offset of the correspondent compile unit.
-    support::endian::write(RangesStream,
-                           static_cast<uint32_t>(CUMap.find(Offset)->second),
-                           support::little);
+    support::endian::write(
+        RangesStream, static_cast<uint32_t>(CUMap.find(Offset)->second.Offset),
+        support::little);
 
     // Header field #4: address size.
     // 8 since we only write ELF64 binaries for now.
@@ -472,23 +471,32 @@
   return BinaryContentsStr;
 }
 
-std::unordered_map<uint32_t, uint32_t>
-DebugInfoBinaryPatcher::computeNewOffsets() {
-  std::unordered_map<uint32_t, uint32_t> CUMap;
+CUOffsetMap DebugInfoBinaryPatcher::computeNewOffsets(DWARFContext &DWCtx,
+                                                      bool IsDWOContext) {
+  CUOffsetMap CUMap;
   std::sort(DebugPatches.begin(), DebugPatches.end(),
             [](const UniquePatchPtrType &V1, const UniquePatchPtrType &V2) {
               return V1.get()->Offset < V2.get()->Offset;
             });
 
+  DWARFUnitVector::compile_unit_range CompileUnits =
+      IsDWOContext ? DWCtx.dwo_compile_units() : DWCtx.compile_units();
+
+  for (const std::unique_ptr<DWARFUnit> &CU : CompileUnits)
+    CUMap[CU->getOffset()] = {static_cast<uint32_t>(CU->getOffset()),
+                              static_cast<uint32_t>(CU->getLength())};
+
   // Calculating changes in .debug_info size from Patches to build a map of old
   // to updated reference destination offsets.
+  uint32_t PreviousOffset = 0;
+  uint32_t PreviousChangeInSize = 0;
   for (UniquePatchPtrType &PatchBase : DebugPatches) {
     Patch *P = PatchBase.get();
     switch (P->Kind) {
     default:
       continue;
     case DebugPatchKind::PatchValue64to32: {
-      ChangeInSize -= 4;
+      PreviousChangeInSize -= 4;
       break;
     }
     case DebugPatchKind::PatchValueVariable: {
@@ -497,13 +505,14 @@
       std::string Temp;
       raw_string_ostream OS(Temp);
       encodeULEB128(DPV->Value, OS);
-      ChangeInSize += Temp.size() - DPV->OldValueSize;
+      PreviousChangeInSize += Temp.size() - DPV->OldValueSize;
       break;
     }
     case DebugPatchKind::DestinationReferenceLabel: {
       DestinationReferenceLabel *DRL =
           reinterpret_cast<DestinationReferenceLabel *>(P);
-      OldToNewOffset[DRL->Offset] = DRL->Offset + ChangeInSize;
+      OldToNewOffset[DRL->Offset] =
+          DRL->Offset + ChangeInSize + PreviousChangeInSize;
       break;
     }
     case DebugPatchKind::ReferencePatchValue: {
@@ -511,7 +520,7 @@
       // to reduce algorithmic complexity.
       DebugPatchReference *RDP = reinterpret_cast<DebugPatchReference *>(P);
       if (RDP->PatchInfo.IndirectRelative) {
-        ChangeInSize += 4 - RDP->PatchInfo.OldValueSize;
+        PreviousChangeInSize += 4 - RDP->PatchInfo.OldValueSize;
         assert(RDP->PatchInfo.OldValueSize <= 4 &&
                "Variable encoding reference greater than 4 bytes.");
       }
@@ -521,11 +530,16 @@
       DWARFUnitOffsetBaseLabel *BaseLabel =
           reinterpret_cast<DWARFUnitOffsetBaseLabel *>(P);
       uint32_t CUOffset = BaseLabel->Offset;
+      ChangeInSize += PreviousChangeInSize;
       uint32_t CUOffsetUpdate = CUOffset + ChangeInSize;
-      CUMap[CUOffset] = CUOffsetUpdate;
+      CUMap[CUOffset].Offset = CUOffsetUpdate;
+      CUMap[PreviousOffset].Length -= PreviousChangeInSize;
+      PreviousChangeInSize = 0;
+      PreviousOffset = CUOffset;
     }
     }
   }
+  CUMap[PreviousOffset].Length -= PreviousChangeInSize;
   return CUMap;
 }
 
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
@@ -325,14 +325,14 @@
   DebugInfoPatcher->clearDestinationLabels();
   flushPendingRanges(*DebugInfoPatcher);
 
-  finalizeDebugSections(*DebugInfoPatcher);
+  CUOffsetMap OffsetMap = finalizeDebugSections(*DebugInfoPatcher);
 
   if (opts::WriteDWP)
     writeDWP(DWOIdToName);
   else
     writeDWOFiles(DWOIdToName);
 
-  updateGdbIndexSection();
+  updateGdbIndexSection(OffsetMap);
 }
 
 void DWARFRewriter::updateUnitDebugInfo(
@@ -822,8 +822,8 @@
     TypeInfoSection->setIsFinalized();
 }
 
-void DWARFRewriter::finalizeDebugSections(
-    DebugInfoBinaryPatcher &DebugInfoPatcher) {
+CUOffsetMap
+DWARFRewriter::finalizeDebugSections(DebugInfoBinaryPatcher &DebugInfoPatcher) {
   if (StrWriter->isInitialized()) {
     RewriteInstance::addToDebugSectionsToOverwrite(".debug_str");
     std::unique_ptr<DebugStrBufferVector> DebugStrSectionContents =
@@ -900,8 +900,8 @@
   }
 
   // No more creating new DebugInfoPatches.
-  std::unordered_map<uint32_t, uint32_t> CUMap =
-      DebugInfoPatcher.computeNewOffsets();
+  CUOffsetMap CUMap =
+      DebugInfoPatcher.computeNewOffsets(*BC.DwCtx.get(), false);
 
   // Skip .debug_aranges if we are re-generating .gdb_index.
   if (opts::KeepARanges || !BC.getGdbIndexSection()) {
@@ -918,6 +918,7 @@
                                    copyByteArray(ARangesContents),
                                    ARangesContents.size());
   }
+  return CUMap;
 }
 
 // Creates all the data structures necessary for creating MCStreamer.
@@ -960,15 +961,14 @@
 
 // Exctracts an appropriate slice if input is DWP.
 // Applies patches or overwrites the section.
-Optional<StringRef>
-updateDebugData(std::string &Storage, const SectionRef &Section,
-                const StringMap<KnownSectionsEntry> &KnownSections,
-                MCStreamer &Streamer, DWARFRewriter &Writer,
-                const DWARFUnitIndex::Entry *DWOEntry, uint64_t DWOId,
-                std::unique_ptr<DebugBufferVector> &OutputBuffer) {
+Optional<StringRef> updateDebugData(
+    DWARFContext &DWCtx, std::string &Storage, const SectionRef &Section,
+    const StringMap<KnownSectionsEntry> &KnownSections, MCStreamer &Streamer,
+    DWARFRewriter &Writer, const DWARFUnitIndex::Entry *DWOEntry,
+    uint64_t DWOId, std::unique_ptr<DebugBufferVector> &OutputBuffer) {
   auto applyPatch = [&](DebugInfoBinaryPatcher *Patcher,
                         StringRef Data) -> StringRef {
-    Patcher->computeNewOffsets();
+    Patcher->computeNewOffsets(DWCtx, true);
     Storage = Patcher->patchBinary(Data);
     return StringRef(Storage.c_str(), Storage.size());
   };
@@ -1129,9 +1129,9 @@
     for (const SectionRef &Section : DWOFile->sections()) {
       std::string Storage = "";
       std::unique_ptr<DebugBufferVector> OutputData;
-      Optional<StringRef> TOutData =
-          updateDebugData(Storage, Section, KnownSections, *Streamer, *this,
-                          DWOEntry, *DWOId, OutputData);
+      Optional<StringRef> TOutData = updateDebugData(
+          (*DWOCU)->getContext(), Storage, Section, KnownSections, *Streamer,
+          *this, DWOEntry, *DWOId, OutputData);
       if (!TOutData)
         continue;
 
@@ -1229,9 +1229,9 @@
     for (const SectionRef &Section : File->sections()) {
       std::string Storage = "";
       std::unique_ptr<DebugBufferVector> OutputData;
-      if (Optional<StringRef> OutData =
-              updateDebugData(Storage, Section, KnownSections, *Streamer, *this,
-                              DWOEntry, *DWOId, OutputData))
+      if (Optional<StringRef> OutData = updateDebugData(
+              (*DWOCU)->getContext(), Storage, Section, KnownSections,
+              *Streamer, *this, DWOEntry, *DWOId, OutputData))
         Streamer->emitBytes(*OutData);
     }
     Streamer->Finish();
@@ -1239,7 +1239,7 @@
   }
 }
 
-void DWARFRewriter::updateGdbIndexSection() {
+void DWARFRewriter::updateGdbIndexSection(CUOffsetMap &CUMap) {
   if (!BC.getGdbIndexSection())
     return;
 
@@ -1316,10 +1316,23 @@
   write32le(Buffer + 20, ConstantPoolOffset + Delta);
   Buffer += 24;
 
-  // Copy over CU list and types CU list.
-  memcpy(Buffer, GdbIndexContents.data() + 24,
-         AddressTableOffset - CUListOffset);
-  Buffer += AddressTableOffset - CUListOffset;
+  // Writing out CU List <Offset, Size>
+  for (auto &CUInfo : CUMap) {
+    write64le(Buffer, CUInfo.second.Offset);
+    // Length encoded in CU doesn't contain first 4 bytes that encode length.
+    write64le(Buffer + 8, CUInfo.second.Length + 4);
+    Buffer += 16;
+  }
+
+  // Copy over types CU list
+  // Spec says " triplet, the first value is the CU offset, the second value is
+  // the type offset in the CU, and the third value is the type signature"
+  // Looking at what is being generated by gdb-add-index. The first entry is TU
+  // offset, second entry is offset from it, and third entry is the type
+  // signature.
+  memcpy(Buffer, GdbIndexContents.data() + CUTypesOffset,
+         AddressTableOffset - CUTypesOffset);
+  Buffer += AddressTableOffset - CUTypesOffset;
 
   // Generate new address table.
   for (const std::pair<const uint64_t, DebugAddressRangesVector> &CURangesPair :