[llvm] 3aad490 - Revert "[DebugInfo][llvm-dwarfutil] Combine overlapped address ranges."

Alexey Lapshin via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 21 03:40:56 PDT 2022


Author: Alexey Lapshin
Date: 2022-07-21T13:40:20+03:00
New Revision: 3aad49082cc1da70f52441e7fd689efd54d1a0a9

URL: https://github.com/llvm/llvm-project/commit/3aad49082cc1da70f52441e7fd689efd54d1a0a9
DIFF: https://github.com/llvm/llvm-project/commit/3aad49082cc1da70f52441e7fd689efd54d1a0a9.diff

LOG: Revert "[DebugInfo][llvm-dwarfutil] Combine overlapped address ranges."

This reverts commit d2a4d6bf9c52861f3d418bf7bb7d05f6e74dfead.

Added: 
    

Modified: 
    llvm/include/llvm/ADT/AddressRanges.h
    llvm/include/llvm/DWARFLinker/DWARFLinker.h
    llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h
    llvm/include/llvm/DWARFLinker/DWARFStreamer.h
    llvm/lib/DWARFLinker/DWARFLinker.cpp
    llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp
    llvm/lib/DWARFLinker/DWARFStreamer.cpp
    llvm/lib/Support/AddressRanges.cpp
    llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
    llvm/tools/dsymutil/DwarfLinkerForBinary.h
    llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
    llvm/unittests/Support/AddressRangeTest.cpp

Removed: 
    llvm/test/tools/llvm-dwarfutil/ELF/gc-func-overlapping-address-ranges.test
    llvm/test/tools/llvm-dwarfutil/ELF/gc-unit-overlapping-address-ranges.test


################################################################################
diff  --git a/llvm/include/llvm/ADT/AddressRanges.h b/llvm/include/llvm/ADT/AddressRanges.h
index c02844a095d1c..1953680d52223 100644
--- a/llvm/include/llvm/ADT/AddressRanges.h
+++ b/llvm/include/llvm/ADT/AddressRanges.h
@@ -10,10 +10,9 @@
 #define LLVM_ADT_ADDRESSRANGES_H
 
 #include "llvm/ADT/Optional.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallVector.h"
 #include <cassert>
 #include <stdint.h>
+#include <vector>
 
 namespace llvm {
 
@@ -48,29 +47,20 @@ class AddressRange {
 /// The AddressRanges class helps normalize address range collections.
 /// This class keeps a sorted vector of AddressRange objects and can perform
 /// insertions and searches efficiently. The address ranges are always sorted
-/// and never contain any invalid or empty address ranges.
-/// Intersecting([100,200), [150,300)) and adjacent([100,200), [200,300))
+/// and never contain any invalid or empty address ranges. Intersecting
 /// address ranges are combined during insertion.
 class AddressRanges {
 protected:
-  using Collection = SmallVector<AddressRange>;
+  using Collection = std::vector<AddressRange>;
   Collection Ranges;
 
 public:
   void clear() { Ranges.clear(); }
   bool empty() const { return Ranges.empty(); }
-  bool contains(uint64_t Addr) const { return find(Addr) != Ranges.end(); }
-  bool contains(AddressRange Range) const {
-    return find(Range) != Ranges.end();
-  }
-  Optional<AddressRange> getRangeThatContains(uint64_t Addr) const {
-    Collection::const_iterator It = find(Addr);
-    if (It == Ranges.end())
-      return None;
-
-    return *It;
-  }
-  Collection::const_iterator insert(AddressRange Range);
+  bool contains(uint64_t Addr) const;
+  bool contains(AddressRange Range) const;
+  Optional<AddressRange> getRangeThatContains(uint64_t Addr) const;
+  void insert(AddressRange Range);
   void reserve(size_t Capacity) { Ranges.reserve(Capacity); }
   size_t size() const { return Ranges.size(); }
   bool operator==(const AddressRanges &RHS) const {
@@ -82,64 +72,6 @@ class AddressRanges {
   }
   Collection::const_iterator begin() const { return Ranges.begin(); }
   Collection::const_iterator end() const { return Ranges.end(); }
-
-protected:
-  Collection::const_iterator find(uint64_t Addr) const;
-  Collection::const_iterator find(AddressRange Range) const;
-};
-
-/// AddressRangesMap class maps values to the address ranges.
-/// It keeps address ranges and corresponding values. If ranges
-/// are combined during insertion, then combined range keeps
-/// newly inserted value.
-template <typename T> class AddressRangesMap : protected AddressRanges {
-public:
-  void clear() {
-    Ranges.clear();
-    Values.clear();
-  }
-  bool empty() const { return AddressRanges::empty(); }
-  bool contains(uint64_t Addr) const { return AddressRanges::contains(Addr); }
-  bool contains(AddressRange Range) const {
-    return AddressRanges::contains(Range);
-  }
-  void insert(AddressRange Range, T Value) {
-    size_t InputSize = Ranges.size();
-    Collection::const_iterator RangesIt = AddressRanges::insert(Range);
-    if (RangesIt == Ranges.end())
-      return;
-
-    // make Values match to Ranges.
-    size_t Idx = RangesIt - Ranges.begin();
-    typename ValuesCollection::iterator ValuesIt = Values.begin() + Idx;
-    if (InputSize < Ranges.size())
-      Values.insert(ValuesIt, T());
-    else if (InputSize > Ranges.size())
-      Values.erase(ValuesIt, ValuesIt + InputSize - Ranges.size());
-    assert(Ranges.size() == Values.size());
-
-    // set value to the inserted or combined range.
-    Values[Idx] = Value;
-  }
-  size_t size() const {
-    assert(Ranges.size() == Values.size());
-    return AddressRanges::size();
-  }
-  Optional<std::pair<AddressRange, T>>
-  getRangeValueThatContains(uint64_t Addr) const {
-    Collection::const_iterator It = find(Addr);
-    if (It == Ranges.end())
-      return None;
-
-    return std::make_pair(*It, Values[It - Ranges.begin()]);
-  }
-  std::pair<AddressRange, T> operator[](size_t Idx) const {
-    return std::make_pair(Ranges[Idx], Values[Idx]);
-  }
-
-protected:
-  using ValuesCollection = SmallVector<T>;
-  ValuesCollection Values;
 };
 
 } // namespace llvm

diff  --git a/llvm/include/llvm/DWARFLinker/DWARFLinker.h b/llvm/include/llvm/DWARFLinker/DWARFLinker.h
index 3961100e00e13..b2b2e2e873be2 100644
--- a/llvm/include/llvm/DWARFLinker/DWARFLinker.h
+++ b/llvm/include/llvm/DWARFLinker/DWARFLinker.h
@@ -9,7 +9,6 @@
 #ifndef LLVM_DWARFLINKER_DWARFLINKER_H
 #define LLVM_DWARFLINKER_DWARFLINKER_H
 
-#include "llvm/ADT/AddressRanges.h"
 #include "llvm/CodeGen/AccelTable.h"
 #include "llvm/CodeGen/NonRelocatableStringpool.h"
 #include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
@@ -38,6 +37,25 @@ enum class DwarfLinkerAccelTableKind : uint8_t {
   Pub,     ///< .debug_pubnames, .debug_pubtypes
 };
 
+/// Partial address range. Besides an offset, only the
+/// HighPC is stored. The structure is stored in a map where the LowPC is the
+/// key.
+struct ObjFileAddressRange {
+  /// Function HighPC.
+  uint64_t HighPC;
+  /// Offset to apply to the linked address.
+  /// should be 0 for not-linked object file.
+  int64_t Offset;
+
+  ObjFileAddressRange(uint64_t EndPC, int64_t Offset)
+      : HighPC(EndPC), Offset(Offset) {}
+
+  ObjFileAddressRange() : HighPC(0), Offset(0) {}
+};
+
+/// Map LowPC to ObjFileAddressRange.
+using RangesTy = std::map<uint64_t, ObjFileAddressRange>;
+
 /// AddressesMap represents information about valid addresses used
 /// by debug information. Valid addresses are those which points to
 /// live code sections. i.e. relocations for these addresses point
@@ -124,7 +142,7 @@ class DwarfEmitter {
   /// original \p Entries.
   virtual void emitRangesEntries(
       int64_t UnitPcOffset, uint64_t OrigLowPc,
-      Optional<std::pair<AddressRange, int64_t>> FuncRange,
+      const FunctionIntervals::const_iterator &FuncRange,
       const std::vector<DWARFDebugRangeList::RangeListEntry> &Entries,
       unsigned AddressSize) = 0;
 

diff  --git a/llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h b/llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h
index 05e291c051329..930db0913226a 100644
--- a/llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h
+++ b/llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h
@@ -9,8 +9,8 @@
 #ifndef LLVM_DWARFLINKER_DWARFLINKERCOMPILEUNIT_H
 #define LLVM_DWARFLINKER_DWARFLINKERCOMPILEUNIT_H
 
-#include "llvm/ADT/AddressRanges.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/IntervalMap.h"
 #include "llvm/CodeGen/DIE.h"
 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
 
@@ -18,9 +18,12 @@ namespace llvm {
 
 class DeclContext;
 
-/// Mapped value in the address map is the offset to apply to the
-/// linked address.
-using RangesTy = AddressRangesMap<int64_t>;
+template <typename KeyT, typename ValT>
+using HalfOpenIntervalMap =
+    IntervalMap<KeyT, ValT, IntervalMapImpl::NodeSizer<KeyT, ValT>::LeafSize,
+                IntervalMapHalfOpenInfo<KeyT>>;
+
+using FunctionIntervals = HalfOpenIntervalMap<uint64_t, int64_t>;
 
 // FIXME: Delete this structure.
 struct PatchLocation {
@@ -81,7 +84,8 @@ class CompileUnit {
 
   CompileUnit(DWARFUnit &OrigUnit, unsigned ID, bool CanUseODR,
               StringRef ClangModuleName)
-      : OrigUnit(OrigUnit), ID(ID), ClangModuleName(ClangModuleName) {
+      : OrigUnit(OrigUnit), ID(ID), Ranges(RangeAlloc),
+        ClangModuleName(ClangModuleName) {
     Info.resize(OrigUnit.getNumDIEs());
 
     auto CUDie = OrigUnit.getUnitDIE(false);
@@ -139,7 +143,7 @@ class CompileUnit {
     return UnitRangeAttribute;
   }
 
-  const RangesTy &getFunctionRanges() const { return Ranges; }
+  const FunctionIntervals &getFunctionRanges() const { return Ranges; }
 
   const std::vector<PatchLocation> &getRangesAttributes() const {
     return RangeAttributes;
@@ -178,6 +182,10 @@ class CompileUnit {
   /// offset \p PCOffset.
   void addFunctionRange(uint64_t LowPC, uint64_t HighPC, int64_t PCOffset);
 
+  /// Check whether specified address range \p LowPC \p HighPC
+  /// overlaps with existing function ranges.
+  bool overlapsWithFunctionRanges(uint64_t LowPC, uint64_t HighPC);
+
   /// Keep track of a DW_AT_range attribute that we will need to patch up later.
   void noteRangeAttribute(const DIE &Die, PatchLocation Attr);
 
@@ -262,10 +270,12 @@ class CompileUnit {
       std::tuple<DIE *, const CompileUnit *, DeclContext *, PatchLocation>>
       ForwardDIEReferences;
 
-  /// The ranges in that map are the PC ranges for functions in this unit,
-  /// associated with the PC offset to apply to the addresses to get
-  /// the linked address.
-  RangesTy Ranges;
+  FunctionIntervals::Allocator RangeAlloc;
+
+  /// The ranges in that interval map are the PC ranges for
+  /// functions in this unit, associated with the PC offset to apply
+  /// to the addresses to get the linked address.
+  FunctionIntervals Ranges;
 
   /// The DW_AT_low_pc of each DW_TAG_label.
   SmallDenseMap<uint64_t, uint64_t, 1> Labels;

diff  --git a/llvm/include/llvm/DWARFLinker/DWARFStreamer.h b/llvm/include/llvm/DWARFLinker/DWARFStreamer.h
index 0ccab0efa8f41..003fe548252ae 100644
--- a/llvm/include/llvm/DWARFLinker/DWARFStreamer.h
+++ b/llvm/include/llvm/DWARFLinker/DWARFStreamer.h
@@ -96,7 +96,7 @@ class DwarfStreamer : public DwarfEmitter {
   /// original \p Entries.
   void emitRangesEntries(
       int64_t UnitPcOffset, uint64_t OrigLowPc,
-      Optional<std::pair<AddressRange, int64_t>> FuncRange,
+      const FunctionIntervals::const_iterator &FuncRange,
       const std::vector<DWARFDebugRangeList::RangeListEntry> &Entries,
       unsigned AddressSize) override;
 

diff  --git a/llvm/lib/DWARFLinker/DWARFLinker.cpp b/llvm/lib/DWARFLinker/DWARFLinker.cpp
index 62b7f629f4033..47cce9ed67778 100644
--- a/llvm/lib/DWARFLinker/DWARFLinker.cpp
+++ b/llvm/lib/DWARFLinker/DWARFLinker.cpp
@@ -504,14 +504,22 @@ unsigned DWARFLinker::shouldKeepSubprogramDIE(
                   &DIE);
     return Flags;
   }
-  if (*LowPc > *HighPc) {
-    reportWarning("low_pc greater than high_pc. Range will be discarded.\n",
-                  File, &DIE);
+
+  // TODO: Following check is a workaround for overlapping address ranges.
+  //       ELF binaries built with LTO might contain overlapping address
+  //       ranges. The better fix would be to combine such ranges. Following
+  //       is a workaround that should be removed when a good fix is done.
+  if (Unit.overlapsWithFunctionRanges(*LowPc, *HighPc)) {
+    reportWarning(
+        formatv("Overlapping address range [{0:X}, {1:X}]. Range will "
+                "be discarded.\n",
+                *LowPc, *HighPc),
+        File, &DIE);
     return Flags;
   }
 
   // Replace the debug map range with a more accurate one.
-  Ranges.insert({*LowPc, *HighPc}, MyInfo.AddrAdjust);
+  Ranges[*LowPc] = ObjFileAddressRange(*HighPc, MyInfo.AddrAdjust);
   Unit.addFunctionRange(*LowPc, *HighPc, MyInfo.AddrAdjust);
   return Flags;
 }
@@ -1580,7 +1588,7 @@ void DWARFLinker::patchRangesForUnit(const CompileUnit &Unit,
   DWARFDataExtractor RangeExtractor(OrigDwarf.getDWARFObj(),
                                     OrigDwarf.getDWARFObj().getRangesSection(),
                                     OrigDwarf.isLittleEndian(), AddressSize);
-  Optional<std::pair<AddressRange, int64_t>> CurrRange;
+  auto InvalidRange = FunctionRanges.end(), CurrRange = InvalidRange;
   DWARFUnit &OrigUnit = Unit.getOrigUnit();
   auto OrigUnitDie = OrigUnit.getUnitDIE(false);
   uint64_t OrigLowPc =
@@ -1603,11 +1611,12 @@ void DWARFLinker::patchRangesForUnit(const CompileUnit &Unit,
     if (!Entries.empty()) {
       const DWARFDebugRangeList::RangeListEntry &First = Entries.front();
 
-      if (!CurrRange ||
-          !CurrRange->first.contains(First.StartAddress + OrigLowPc)) {
-        CurrRange = FunctionRanges.getRangeValueThatContains(
-            First.StartAddress + OrigLowPc);
-        if (!CurrRange) {
+      if (CurrRange == InvalidRange ||
+          First.StartAddress + OrigLowPc < CurrRange.start() ||
+          First.StartAddress + OrigLowPc >= CurrRange.stop()) {
+        CurrRange = FunctionRanges.find(First.StartAddress + OrigLowPc);
+        if (CurrRange == InvalidRange ||
+            CurrRange.start() > First.StartAddress + OrigLowPc) {
           reportWarning("no mapping for range.", File);
           continue;
         }
@@ -1714,7 +1723,7 @@ void DWARFLinker::patchLineTableForUnit(CompileUnit &Unit,
   // in NewRows.
   std::vector<DWARFDebugLine::Row> Seq;
   const auto &FunctionRanges = Unit.getFunctionRanges();
-  Optional<std::pair<AddressRange, int64_t>> CurrRange;
+  auto InvalidRange = FunctionRanges.end(), CurrRange = InvalidRange;
 
   // FIXME: This logic is meant to generate exactly the same output as
   // Darwin's classic dsymutil. There is a nicer way to implement this
@@ -1733,14 +1742,19 @@ void DWARFLinker::patchLineTableForUnit(CompileUnit &Unit,
     // it is marked as end_sequence in the input (because in that
     // case, the relocation offset is accurate and that entry won't
     // serve as the start of another function).
-    if (!CurrRange || !CurrRange->first.contains(Row.Address.Address) ||
-        (Row.Address.Address == CurrRange->first.end() && !Row.EndSequence)) {
+    if (CurrRange == InvalidRange || Row.Address.Address < CurrRange.start() ||
+        Row.Address.Address > CurrRange.stop() ||
+        (Row.Address.Address == CurrRange.stop() && !Row.EndSequence)) {
       // We just stepped out of a known range. Insert a end_sequence
       // corresponding to the end of the range.
-      uint64_t StopAddress =
-          CurrRange ? CurrRange->first.end() + CurrRange->second : -1ULL;
-      CurrRange = FunctionRanges.getRangeValueThatContains(Row.Address.Address);
-      if (!CurrRange) {
+      uint64_t StopAddress = CurrRange != InvalidRange
+                                 ? CurrRange.stop() + CurrRange.value()
+                                 : -1ULL;
+      CurrRange = FunctionRanges.find(Row.Address.Address);
+      bool CurrRangeValid =
+          CurrRange != InvalidRange && CurrRange.start() <= Row.Address.Address;
+      if (!CurrRangeValid) {
+        CurrRange = InvalidRange;
         if (StopAddress != -1ULL) {
           // Try harder by looking in the Address ranges map.
           // There are corner cases where this finds a
@@ -1748,9 +1762,14 @@ void DWARFLinker::patchLineTableForUnit(CompileUnit &Unit,
           // for now do as dsymutil.
           // FIXME: Understand exactly what cases this addresses and
           // potentially remove it along with the Ranges map.
-          if (Optional<std::pair<AddressRange, int64_t>> Range =
-                  Ranges.getRangeValueThatContains(Row.Address.Address))
-            StopAddress = Row.Address.Address + (*Range).second;
+          auto Range = Ranges.lower_bound(Row.Address.Address);
+          if (Range != Ranges.begin() && Range != Ranges.end())
+            --Range;
+
+          if (Range != Ranges.end() && Range->first <= Row.Address.Address &&
+              Range->second.HighPC >= Row.Address.Address) {
+            StopAddress = Row.Address.Address + Range->second.Offset;
+          }
         }
       }
       if (StopAddress != -1ULL && !Seq.empty()) {
@@ -1766,7 +1785,7 @@ void DWARFLinker::patchLineTableForUnit(CompileUnit &Unit,
         insertLineSequence(Seq, NewRows);
       }
 
-      if (!CurrRange)
+      if (!CurrRangeValid)
         continue;
     }
 
@@ -1775,7 +1794,7 @@ void DWARFLinker::patchLineTableForUnit(CompileUnit &Unit,
       continue;
 
     // Relocate row address and add it to the current sequence.
-    Row.Address.Address += CurrRange->second;
+    Row.Address.Address += CurrRange.value();
     Seq.emplace_back(Row);
 
     if (Row.EndSequence)
@@ -1915,9 +1934,11 @@ void DWARFLinker::patchFrameInfoForObject(const DWARFFile &File,
     // the function entry point, thus we can't just lookup the address
     // in the debug map. Use the AddressInfo's range map to see if the FDE
     // describes something that we can relocate.
-    Optional<std::pair<AddressRange, int64_t>> Range =
-        Ranges.getRangeValueThatContains(Loc);
-    if (!Range) {
+    auto Range = Ranges.upper_bound(Loc);
+    if (Range != Ranges.begin())
+      --Range;
+    if (Range == Ranges.end() || Range->first > Loc ||
+        Range->second.HighPC <= Loc) {
       // The +4 is to account for the size of the InitialLength field itself.
       InputOffset = EntryOffset + InitialLength + 4;
       continue;
@@ -1945,7 +1966,7 @@ void DWARFLinker::patchFrameInfoForObject(const DWARFFile &File,
     // fields that will get reconstructed by emitFDE().
     unsigned FDERemainingBytes = InitialLength - (4 + AddrSize);
     TheDwarfEmitter->emitFDE(IteratorInserted.first->getValue(), AddrSize,
-                             Loc + Range->second,
+                             Loc + Range->second.Offset,
                              FrameData.substr(InputOffset, FDERemainingBytes));
     InputOffset += FDERemainingBytes;
   }

diff  --git a/llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp b/llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp
index 1cb20c0bb948d..ebb1106521cc6 100644
--- a/llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp
+++ b/llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp
@@ -105,11 +105,19 @@ void CompileUnit::addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset) {
 
 void CompileUnit::addFunctionRange(uint64_t FuncLowPc, uint64_t FuncHighPc,
                                    int64_t PcOffset) {
-  Ranges.insert({FuncLowPc, FuncHighPc}, PcOffset);
+  //  Don't add empty ranges to the interval map.  They are a problem because
+  //  the interval map expects half open intervals. This is safe because they
+  //  are empty anyway.
+  if (FuncHighPc != FuncLowPc)
+    Ranges.insert(FuncLowPc, FuncHighPc, PcOffset);
   this->LowPc = std::min(LowPc, FuncLowPc + PcOffset);
   this->HighPc = std::max(HighPc, FuncHighPc + PcOffset);
 }
 
+bool CompileUnit::overlapsWithFunctionRanges(uint64_t LowPC, uint64_t HighPC) {
+  return Ranges.overlaps(LowPC, HighPC);
+}
+
 void CompileUnit::noteRangeAttribute(const DIE &Die, PatchLocation Attr) {
   if (Die.getTag() != dwarf::DW_TAG_compile_unit)
     RangeAttributes.push_back(Attr);

diff  --git a/llvm/lib/DWARFLinker/DWARFStreamer.cpp b/llvm/lib/DWARFLinker/DWARFStreamer.cpp
index a00e51fcf135f..55ff6b14f9451 100644
--- a/llvm/lib/DWARFLinker/DWARFStreamer.cpp
+++ b/llvm/lib/DWARFLinker/DWARFStreamer.cpp
@@ -321,14 +321,13 @@ void DwarfStreamer::emitSwiftReflectionSection(
 /// sized addresses describing the ranges.
 void DwarfStreamer::emitRangesEntries(
     int64_t UnitPcOffset, uint64_t OrigLowPc,
-    Optional<std::pair<AddressRange, int64_t>> FuncRange,
+    const FunctionIntervals::const_iterator &FuncRange,
     const std::vector<DWARFDebugRangeList::RangeListEntry> &Entries,
     unsigned AddressSize) {
   MS->switchSection(MC->getObjectFileInfo()->getDwarfRangesSection());
 
   // Offset each range by the right amount.
-  int64_t PcOffset =
-      (Entries.empty() || !FuncRange) ? 0 : FuncRange->second + UnitPcOffset;
+  int64_t PcOffset = Entries.empty() ? 0 : FuncRange.value() + UnitPcOffset;
   for (const auto &Range : Entries) {
     if (Range.isBaseAddressSelectionEntry(AddressSize)) {
       warn("unsupported base address selection operation",
@@ -340,7 +339,8 @@ void DwarfStreamer::emitRangesEntries(
       continue;
 
     // All range entries should lie in the function range.
-    if (!FuncRange->first.contains(Range.StartAddress + OrigLowPc))
+    if (!(Range.StartAddress + OrigLowPc >= FuncRange.start() &&
+          Range.EndAddress + OrigLowPc <= FuncRange.stop()))
       warn("inconsistent range data.", "emitting debug_ranges");
     MS->emitIntValue(Range.StartAddress + PcOffset, AddressSize);
     MS->emitIntValue(Range.EndAddress + PcOffset, AddressSize);
@@ -365,13 +365,11 @@ void DwarfStreamer::emitUnitRangesEntries(CompileUnit &Unit,
   // IntervalMap will have coalesced the non-linked ranges, but here
   // we want to coalesce the linked addresses.
   std::vector<std::pair<uint64_t, uint64_t>> Ranges;
-  const RangesTy &FunctionRanges = Unit.getFunctionRanges();
-  for (size_t Idx = 0; Idx < FunctionRanges.size(); Idx++) {
-    std::pair<AddressRange, int64_t> CurRange = FunctionRanges[Idx];
-
-    Ranges.push_back(std::make_pair(CurRange.first.start() + CurRange.second,
-                                    CurRange.first.end() + CurRange.second));
-  }
+  const auto &FunctionRanges = Unit.getFunctionRanges();
+  for (auto Range = FunctionRanges.begin(), End = FunctionRanges.end();
+       Range != End; ++Range)
+    Ranges.push_back(std::make_pair(Range.start() + Range.value(),
+                                    Range.stop() + Range.value()));
 
   // The object addresses where sorted, but again, the linked
   // addresses might end up in a 
diff erent order.

diff  --git a/llvm/lib/Support/AddressRanges.cpp b/llvm/lib/Support/AddressRanges.cpp
index 187d5be00daed..5ba011bac4e99 100644
--- a/llvm/lib/Support/AddressRanges.cpp
+++ b/llvm/lib/Support/AddressRanges.cpp
@@ -12,59 +12,48 @@
 
 using namespace llvm;
 
-AddressRanges::Collection::const_iterator
-AddressRanges::insert(AddressRange Range) {
+void AddressRanges::insert(AddressRange Range) {
   if (Range.size() == 0)
-    return Ranges.end();
+    return;
 
   auto It = llvm::upper_bound(Ranges, Range);
   auto It2 = It;
-  while (It2 != Ranges.end() && It2->start() <= Range.end())
+  while (It2 != Ranges.end() && It2->start() < Range.end())
     ++It2;
   if (It != It2) {
-    Range = {Range.start(), std::max(Range.end(), std::prev(It2)->end())};
+    Range = {Range.start(), std::max(Range.end(), It2[-1].end())};
     It = Ranges.erase(It, It2);
   }
-  if (It != Ranges.begin() && Range.start() <= std::prev(It)->end()) {
-    --It;
-    *It = {It->start(), std::max(It->end(), Range.end())};
-    return It;
-  }
-
-  return Ranges.insert(It, Range);
+  if (It != Ranges.begin() && Range.start() < It[-1].end())
+    It[-1] = {It[-1].start(), std::max(It[-1].end(), Range.end())};
+  else
+    Ranges.insert(It, Range);
 }
 
-AddressRanges::Collection::const_iterator
-AddressRanges::find(uint64_t Addr) const {
+bool AddressRanges::contains(uint64_t Addr) const {
   auto It = std::partition_point(
       Ranges.begin(), Ranges.end(),
       [=](const AddressRange &R) { return R.start() <= Addr; });
-
-  if (It == Ranges.begin())
-    return Ranges.end();
-
-  --It;
-  if (Addr >= It->end())
-    return Ranges.end();
-
-  return It;
+  return It != Ranges.begin() && Addr < It[-1].end();
 }
 
-AddressRanges::Collection::const_iterator
-AddressRanges::find(AddressRange Range) const {
+bool AddressRanges::contains(AddressRange Range) const {
   if (Range.size() == 0)
-    return Ranges.end();
-
+    return false;
   auto It = std::partition_point(
       Ranges.begin(), Ranges.end(),
       [=](const AddressRange &R) { return R.start() <= Range.start(); });
-
   if (It == Ranges.begin())
-    return Ranges.end();
-
-  --It;
-  if (Range.end() > It->end())
-    return Ranges.end();
+    return false;
+  return Range.end() <= It[-1].end();
+}
 
-  return It;
+Optional<AddressRange>
+AddressRanges::getRangeThatContains(uint64_t Addr) const {
+  auto It = std::partition_point(
+      Ranges.begin(), Ranges.end(),
+      [=](const AddressRange &R) { return R.start() <= Addr; });
+  if (It != Ranges.begin() && Addr < It[-1].end())
+    return It[-1];
+  return llvm::None;
 }

diff  --git a/llvm/test/tools/llvm-dwarfutil/ELF/gc-func-overlapping-address-ranges.test b/llvm/test/tools/llvm-dwarfutil/ELF/gc-func-overlapping-address-ranges.test
deleted file mode 100644
index cfbb7cb105586..0000000000000
--- a/llvm/test/tools/llvm-dwarfutil/ELF/gc-func-overlapping-address-ranges.test
+++ /dev/null
@@ -1,254 +0,0 @@
-## This test checks that overlapping function address ranges
-## are combined during --garbage-collection optimisation.
-
-# RUN: yaml2obj %s -o %t.o
-# RUN: llvm-dwarfutil --garbage-collection %t.o %t1
-# RUN: llvm-dwarfdump -a %t1 | FileCheck %s
-
-# CHECK: DW_TAG_compile_unit
-# CHECK: DW_AT_name{{.*}}"CU1"
-# CHECK: DW_AT_low_pc{{.*}}0000000000001000
-# CHECK: DW_AT_ranges
-# CHECK: [0x0000000000001000, 0x000000000000102d)
-# CHECK: [0x0000000000002002, 0x000000000000200d)
-# CHECK: [0x000000000000201b, 0x000000000000202a)
-# CHECK: [0x0000000000003002, 0x0000000000003007)
-# CHECK: [0x0000000000003012, 0x0000000000003017)
-# CHECK: [0x0000000000003018, 0x000000000000301a)
-# CHECK: [0x0000000000003022, 0x0000000000003027
-# CHECK: DW_TAG_class_type
-# CHECK: DW_AT_name{{.*}}"class1"
-# CHECK: DW_TAG_class_type
-# CHECK: "class2"
-# CHECK: DW_TAG_subprogram
-# CHECK: DW_AT_name{{.*}}"foo1"
-# CHECK: DW_AT_low_pc{{.*}}0x0000000000001000
-# CHECK: DW_AT_high_pc{{.*}}0x0000000000001010
-# CHECK: DW_AT_type{{.*}}"class1"
-# CHECK: DW_TAG_subprogram
-# CHECK: "foo2"
-# CHECK: DW_AT_low_pc{{.*}}0x0000000000001004
-# CHECK: DW_AT_high_pc{{.*}}0x0000000000001007
-# CHECK: DW_AT_type{{.*}}"class2"
-# CHECK: DW_TAG_subprogram
-# CHECK: "foo3"
-# CHECK: DW_AT_low_pc{{.*}}0x000000000000100d
-# CHECK: DW_AT_high_pc{{.*}}0x000000000000102d
-# CHECK: DW_TAG_subprogram
-# CHECK: "foo4"
-# CHECK: DW_AT_low_pc{{.*}}0x0000000000002002
-# CHECK: DW_AT_high_pc{{.*}}0x000000000000200d
-# CHECK: DW_TAG_subprogram
-# CHECK: "foo5"
-# CHECK: DW_AT_low_pc{{.*}}0x000000000000201b
-# CHECK: DW_AT_high_pc{{.*}}0x000000000000202a
-# CHECK: DW_TAG_subprogram
-# CHECK: "foo6"
-# CHECK: DW_AT_low_pc{{.*}}0x0000000000003002
-# CHECK: DW_AT_high_pc{{.*}}0x0000000000003007
-# CHECK: DW_TAG_subprogram
-# CHECK: "foo7"
-# CHECK: DW_AT_low_pc{{.*}}0x0000000000003012
-# CHECK: DW_AT_high_pc{{.*}}0x0000000000003017
-# CHECK: DW_TAG_subprogram
-# CHECK: "foo8"
-# CHECK: DW_AT_low_pc{{.*}}0x0000000000003022
-# CHECK: DW_AT_high_pc{{.*}}0x0000000000003027
-# CHECK: DW_TAG_subprogram
-# CHECK: "foo9"
-# CHECK: DW_AT_low_pc{{.*}}0x0000000000003012
-# CHECK: DW_AT_high_pc{{.*}}0x0000000000003017
-# CHECK: "foo10"
-# CHECK: DW_AT_low_pc{{.*}}0x0000000000003018
-# CHECK: DW_AT_high_pc{{.*}}0x000000000000301a
-
---- !ELF
-FileHeader:
-  Class:    ELFCLASS64
-  Data:     ELFDATA2LSB
-  Type:     ET_REL
-  Machine:  EM_X86_64
-Sections:
-  - Name:            .text
-    Type:            SHT_PROGBITS
-    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
-    Address:         0x1000
-    AddressAlign:    0x0000000000000010
-    Content:        "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
-  - Name:            .text2
-    Type:            SHT_PROGBITS
-    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
-    Address:         0x2000
-    AddressAlign:    0x0000000000000010
-    Content:        "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
-  - Name:            .text3
-    Type:            SHT_PROGBITS
-    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
-    Address:         0x3000
-    AddressAlign:    0x0000000000000010
-    Content:        "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
-DWARF:
-  debug_abbrev:
-    - Table:
-      - Tag:      DW_TAG_compile_unit
-        Children: DW_CHILDREN_yes
-        Attributes:
-          - Attribute: DW_AT_producer
-            Form:      DW_FORM_string
-          - Attribute: DW_AT_language
-            Form:      DW_FORM_data2
-          - Attribute: DW_AT_name
-            Form:      DW_FORM_string
-          - Attribute: DW_AT_low_pc
-            Form:      DW_FORM_addr
-          - Attribute: DW_AT_ranges
-            Form:      DW_FORM_sec_offset
-      - Tag:      DW_TAG_subprogram
-        Children: DW_CHILDREN_no
-        Attributes:
-          - Attribute: DW_AT_name
-            Form:      DW_FORM_string
-          - Attribute: DW_AT_low_pc
-            Form:      DW_FORM_addr
-          - Attribute: DW_AT_high_pc
-            Form:      DW_FORM_data8
-          - Attribute: DW_AT_type
-            Form:      DW_FORM_ref4
-      - Tag:      DW_TAG_class_type
-        Children: DW_CHILDREN_yes
-        Attributes:
-          - Attribute: DW_AT_name
-            Form:      DW_FORM_string
-      - Tag:      DW_TAG_member
-        Children: DW_CHILDREN_no
-        Attributes:
-          - Attribute: DW_AT_type
-            Form:      DW_FORM_ref4
-          - Attribute: DW_AT_name
-            Form:      DW_FORM_string
-      - Tag:      DW_TAG_class_type
-        Children: DW_CHILDREN_no
-        Attributes:
-          - Attribute: DW_AT_name
-            Form:      DW_FORM_string
-          - Attribute: DW_AT_declaration
-            Form:      DW_FORM_flag_present
-      - Tag:      DW_TAG_class_type
-        Children: DW_CHILDREN_yes
-        Attributes:
-          - Attribute: DW_AT_name
-            Form:      DW_FORM_string
-          - Attribute: DW_AT_declaration
-            Form:      DW_FORM_flag_present
-      - Tag:      DW_TAG_template_type_parameter
-        Children: DW_CHILDREN_no
-        Attributes:
-          - Attribute: DW_AT_type
-            Form:      DW_FORM_ref4
-      - Tag:      DW_TAG_base_type
-        Children: DW_CHILDREN_no
-        Attributes:
-          - Attribute: DW_AT_name
-            Form:      DW_FORM_string
-  debug_info:
-    - Version: 4
-      Entries:
-        - AbbrCode: 1
-          Values:
-            - CStr: by_hand
-            - Value:  0x04
-            - CStr: CU1
-            - Value:  0x00
-            - Value:  0x00
-        - AbbrCode: 3
-          Values:
-            - CStr: class1
-        - AbbrCode: 4
-          Values:
-            - Value:  0x00000052
-            - CStr: member1
-        - AbbrCode: 0
-        - AbbrCode: 3
-          Values:
-            - CStr: class2
-        - AbbrCode: 4
-          Values:
-            - Value:  0x00000052
-            - CStr: member1
-        - AbbrCode: 0
-        - AbbrCode: 8
-          Values:
-            - CStr: int
-        - AbbrCode: 2
-          Values:
-            - CStr: foo1
-            - Value:  0x1000
-            - Value:  0x10
-            - Value:  0x00000026
-        - AbbrCode: 2
-          Values:
-            - CStr: foo2
-            - Value:  0x1004
-            - Value:  0x3
-            - Value:  0x0000003c
-        - AbbrCode: 2
-          Values:
-            - CStr: foo3
-            - Value:  0x100d
-            - Value:  0x20
-            - Value:  0x0000003c
-        - AbbrCode: 2
-          Values:
-            - CStr: foo4
-            - Value:  0x2002
-            - Value:  0xb
-            - Value:  0x0000003c
-        - AbbrCode: 2
-          Values:
-            - CStr: foo5
-            - Value:  0x201b
-            - Value:  0xf
-            - Value:  0x0000003c
-        - AbbrCode: 2
-          Values:
-            - CStr: foo6
-            - Value:  0x3002
-            - Value:  0x5
-            - Value:  0x0000003c
-        - AbbrCode: 2
-          Values:
-            - CStr: foo7
-            - Value:  0x3012
-            - Value:  0x5
-            - Value:  0x0000003c
-        - AbbrCode: 2
-          Values:
-            - CStr: foo8
-            - Value:  0x3022
-            - Value:  0x5
-            - Value:  0x0000003c
-        - AbbrCode: 2
-          Values:
-            - CStr: foo9
-            - Value:  0x3012
-            - Value:  0x5
-            - Value:  0x0000003c
-        - AbbrCode: 2
-          Values:
-            - CStr: foo10
-            - Value:  0x3018
-            - Value:  0x2
-            - Value:  0x0000003c
-        - AbbrCode: 0
-
-  debug_ranges:
-    - Offset:          0x00000000
-      AddrSize:        0x08
-      Entries:
-        - LowOffset:       0x0000000000001000
-          HighOffset:      0x000000000000102d
-        - LowOffset:       0x0000000000002000
-          HighOffset:      0x000000000000202d
-        - LowOffset:       0x0000000000000000
-          HighOffset:      0x0000000000000000
-...

diff  --git a/llvm/test/tools/llvm-dwarfutil/ELF/gc-unit-overlapping-address-ranges.test b/llvm/test/tools/llvm-dwarfutil/ELF/gc-unit-overlapping-address-ranges.test
deleted file mode 100644
index f9d42c28d4209..0000000000000
--- a/llvm/test/tools/llvm-dwarfutil/ELF/gc-unit-overlapping-address-ranges.test
+++ /dev/null
@@ -1,247 +0,0 @@
-## This test checks that overlapping compile unit address ranges
-## are ignored (i.e. left unchanged) by --garbage-collection
-## optimisation.
-
-# RUN: yaml2obj %s -o %t.o
-# RUN: llvm-dwarfutil --garbage-collection %t.o %t1
-# RUN: llvm-dwarfdump -a %t1 | FileCheck %s
-
-# CHECK: DW_TAG_compile_unit
-# CHECK: DW_AT_name{{.*}}"CU1"
-# CHECK: DW_TAG_class_type
-# CHECK: DW_AT_name{{.*}}"class1"
-# CHECK: DW_TAG_subprogram
-# CHECK: DW_AT_name{{.*}}"foo1"
-# CHECK: DW_AT_low_pc{{.*}}0x0000000000001000
-# CHECK: DW_AT_high_pc{{.*}}0x0000000000001010
-# CHECK: DW_TAG_subprogram
-# CHECK: DW_AT_name{{.*}}"foo2"
-# CHECK: DW_AT_low_pc{{.*}}0x0000000000001000
-# CHECK: DW_AT_high_pc{{.*}}0x0000000000001010
-# CHECK: DW_AT_type{{.*}}"class2"
-
---- !ELF
-FileHeader:
-  Class:    ELFCLASS64
-  Data:     ELFDATA2LSB
-  Type:     ET_REL
-  Machine:  EM_X86_64
-Sections:
-  - Name:            .text
-    Type:            SHT_PROGBITS
-    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
-    Address:         0x1000
-    AddressAlign:    0x0000000000000010
-    Content:        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
-DWARF:
-  debug_abbrev:
-    - Table:
-      - Tag:      DW_TAG_compile_unit
-        Children: DW_CHILDREN_yes
-        Attributes:
-          - Attribute: DW_AT_producer
-            Form:      DW_FORM_string
-          - Attribute: DW_AT_language
-            Form:      DW_FORM_data2
-          - Attribute: DW_AT_name
-            Form:      DW_FORM_string
-          - Attribute: DW_AT_low_pc
-            Form:      DW_FORM_addr
-          - Attribute: DW_AT_high_pc
-            Form:      DW_FORM_data8
-      - Tag:      DW_TAG_subprogram
-        Children: DW_CHILDREN_no
-        Attributes:
-          - Attribute: DW_AT_name
-            Form:      DW_FORM_string
-          - Attribute: DW_AT_low_pc
-            Form:      DW_FORM_addr
-          - Attribute: DW_AT_high_pc
-            Form:      DW_FORM_data8
-          - Attribute: DW_AT_type
-            Form:      DW_FORM_ref4
-      - Tag:      DW_TAG_class_type
-        Children: DW_CHILDREN_yes
-        Attributes:
-          - Attribute: DW_AT_name
-            Form:      DW_FORM_string
-      - Tag:      DW_TAG_member
-        Children: DW_CHILDREN_no
-        Attributes:
-          - Attribute: DW_AT_type
-            Form:      DW_FORM_ref4
-          - Attribute: DW_AT_name
-            Form:      DW_FORM_string
-      - Tag:      DW_TAG_class_type
-        Children: DW_CHILDREN_no
-        Attributes:
-          - Attribute: DW_AT_name
-            Form:      DW_FORM_string
-          - Attribute: DW_AT_declaration
-            Form:      DW_FORM_flag_present
-      - Tag:      DW_TAG_class_type
-        Children: DW_CHILDREN_yes
-        Attributes:
-          - Attribute: DW_AT_name
-            Form:      DW_FORM_string
-          - Attribute: DW_AT_declaration
-            Form:      DW_FORM_flag_present
-      - Tag:      DW_TAG_template_type_parameter
-        Children: DW_CHILDREN_no
-        Attributes:
-          - Attribute: DW_AT_type
-            Form:      DW_FORM_ref4
-      - Tag:      DW_TAG_base_type
-        Children: DW_CHILDREN_no
-        Attributes:
-          - Attribute: DW_AT_name
-            Form:      DW_FORM_string
-    - Table:
-      - Tag:      DW_TAG_compile_unit
-        Children: DW_CHILDREN_yes
-        Attributes:
-          - Attribute: DW_AT_producer
-            Form:      DW_FORM_string
-          - Attribute: DW_AT_language
-            Form:      DW_FORM_data2
-          - Attribute: DW_AT_name
-            Form:      DW_FORM_string
-          - Attribute: DW_AT_low_pc
-            Form:      DW_FORM_addr
-          - Attribute: DW_AT_high_pc
-            Form:      DW_FORM_data8
-      - Tag:      DW_TAG_subprogram
-        Children: DW_CHILDREN_no
-        Attributes:
-          - Attribute: DW_AT_name
-            Form:      DW_FORM_string
-          - Attribute: DW_AT_low_pc
-            Form:      DW_FORM_addr
-          - Attribute: DW_AT_high_pc
-            Form:      DW_FORM_data8
-          - Attribute: DW_AT_type
-            Form:      DW_FORM_ref4
-      - Tag:      DW_TAG_class_type
-        Children: DW_CHILDREN_yes
-        Attributes:
-          - Attribute: DW_AT_name
-            Form:      DW_FORM_string
-      - Tag:      DW_TAG_member
-        Children: DW_CHILDREN_no
-        Attributes:
-          - Attribute: DW_AT_type
-            Form:      DW_FORM_ref4
-          - Attribute: DW_AT_name
-            Form:      DW_FORM_string
-      - Tag:      DW_TAG_class_type
-        Children: DW_CHILDREN_no
-        Attributes:
-          - Attribute: DW_AT_name
-            Form:      DW_FORM_string
-          - Attribute: DW_AT_declaration
-            Form:      DW_FORM_flag_present
-      - Tag:      DW_TAG_class_type
-        Children: DW_CHILDREN_yes
-        Attributes:
-          - Attribute: DW_AT_name
-            Form:      DW_FORM_string
-          - Attribute: DW_AT_declaration
-            Form:      DW_FORM_flag_present
-      - Tag:      DW_TAG_template_type_parameter
-        Children: DW_CHILDREN_no
-        Attributes:
-          - Attribute: DW_AT_type
-            Form:      DW_FORM_ref4
-      - Tag:      DW_TAG_base_type
-        Children: DW_CHILDREN_no
-        Attributes:
-          - Attribute: DW_AT_name
-            Form:      DW_FORM_string
-  debug_info:
-    - Version: 4
-      Entries:
-        - AbbrCode: 1
-          Values:
-            - CStr: by_hand
-            - Value:  0x04
-            - CStr: CU1
-            - Value:  0x1000
-            - Value:  0x1b
-        - AbbrCode: 3
-          Values:
-            - CStr: class1
-        - AbbrCode: 4
-          Values:
-            - Value:  0x0000006c
-            - CStr: member1
-        - AbbrCode: 0
-        - AbbrCode: 3
-          Values:
-            - CStr: class2
-        - AbbrCode: 4
-          Values:
-            - Value:  0x0000006c
-            - CStr: member1
-        - AbbrCode: 0
-        - AbbrCode: 3
-          Values:
-            - CStr: class3
-        - AbbrCode: 4
-          Values:
-            - Value:  0x0000006c
-            - CStr: member1
-        - AbbrCode: 0
-        - AbbrCode: 8
-          Values:
-            - CStr: int
-        - AbbrCode: 2
-          Values:
-            - CStr: foo1
-            - Value:  0x1000
-            - Value:  0x10
-            - Value:  0x0000002a
-        - AbbrCode: 0
-    - Version: 4
-      Entries:
-        - AbbrCode: 1
-          Values:
-            - CStr: by_hand
-            - Value:  0x04
-            - CStr: CU1
-            - Value:  0x1000
-            - Value:  0x1b
-        - AbbrCode: 3
-          Values:
-            - CStr: class1
-        - AbbrCode: 4
-          Values:
-            - Value:  0x0000006c
-            - CStr: member1
-        - AbbrCode: 0
-        - AbbrCode: 3
-          Values:
-            - CStr: class2
-        - AbbrCode: 4
-          Values:
-            - Value:  0x0000006c
-            - CStr: member1
-        - AbbrCode: 0
-        - AbbrCode: 3
-          Values:
-            - CStr: class3
-        - AbbrCode: 4
-          Values:
-            - Value:  0x0000006c
-            - CStr: member1
-        - AbbrCode: 0
-        - AbbrCode: 8
-          Values:
-            - CStr: int
-        - AbbrCode: 2
-          Values:
-            - CStr: foo2
-            - Value:  0x1000
-            - Value:  0x10
-            - Value:  0x00000040
-        - AbbrCode: 0
-...

diff  --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
index d5e6f82e17780..12d5af24e6e4d 100644
--- a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
+++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
@@ -18,6 +18,7 @@
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/FoldingSet.h"
 #include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/IntervalMap.h"
 #include "llvm/ADT/None.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/PointerIntPair.h"

diff  --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.h b/llvm/tools/dsymutil/DwarfLinkerForBinary.h
index f6aa7295379b7..bb9e3c1be45fc 100644
--- a/llvm/tools/dsymutil/DwarfLinkerForBinary.h
+++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.h
@@ -132,8 +132,8 @@ class DwarfLinkerForBinary {
       for (const auto &Entry : DMO.symbols()) {
         const auto &Mapping = Entry.getValue();
         if (Mapping.Size && Mapping.ObjectAddress)
-          AddressRanges.insert(
-              {*Mapping.ObjectAddress, *Mapping.ObjectAddress + Mapping.Size},
+          AddressRanges[*Mapping.ObjectAddress] = ObjFileAddressRange(
+              *Mapping.ObjectAddress + Mapping.Size,
               int64_t(Mapping.BinaryAddress) - *Mapping.ObjectAddress);
       }
     }

diff  --git a/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp b/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
index 844ecddc55c55..ee6bf4fa78120 100644
--- a/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
+++ b/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
@@ -48,7 +48,7 @@ class ObjFileAddressMap : public AddressesMap {
       if (Size == 0)
         continue;
       const uint64_t StartAddr = Sect.getAddress();
-      TextAddressRanges.insert({StartAddr, StartAddr + Size});
+      TextAddressRanges[{StartAddr}] = {StartAddr + Size, 0};
     }
 
     // Check CU address ranges for tombstone value.
@@ -59,7 +59,7 @@ class ObjFileAddressMap : public AddressesMap {
         for (auto &Range : *ARanges) {
           if (!isDeadAddressRange(Range.LowPC, Range.HighPC, CU->getVersion(),
                                   Options.Tombstone, CU->getAddressByteSize()))
-            DWARFAddressRanges.insert({Range.LowPC, Range.HighPC}, 0);
+            DWARFAddressRanges[{Range.LowPC}] = {Range.HighPC, 0};
         }
       }
     }
@@ -146,13 +146,17 @@ class ObjFileAddressMap : public AddressesMap {
   // of executable sections.
   bool isInsideExecutableSectionsAddressRange(uint64_t LowPC,
                                               Optional<uint64_t> HighPC) {
-    Optional<AddressRange> Range =
-        TextAddressRanges.getRangeThatContains(LowPC);
-
-    if (HighPC)
-      return Range.hasValue() && Range->end() >= *HighPC;
+    auto Range = TextAddressRanges.lower_bound(LowPC);
+    if ((Range == TextAddressRanges.end() || Range->first != LowPC) &&
+        Range != TextAddressRanges.begin())
+      --Range;
+
+    if (Range != TextAddressRanges.end() && Range->first <= LowPC &&
+        (HighPC ? Range->second.HighPC >= HighPC
+                : Range->second.HighPC >= LowPC))
+      return true;
 
-    return Range.hasValue();
+    return false;
   }
 
   uint64_t isBFDDeadAddressRange(uint64_t LowPC, Optional<uint64_t> HighPC,
@@ -206,7 +210,7 @@ class ObjFileAddressMap : public AddressesMap {
 
 private:
   RangesTy DWARFAddressRanges;
-  AddressRanges TextAddressRanges;
+  RangesTy TextAddressRanges;
   const Options &Opts;
 };
 

diff  --git a/llvm/unittests/Support/AddressRangeTest.cpp b/llvm/unittests/Support/AddressRangeTest.cpp
index 468f1e22ffa88..95943ad0365a8 100644
--- a/llvm/unittests/Support/AddressRangeTest.cpp
+++ b/llvm/unittests/Support/AddressRangeTest.cpp
@@ -100,7 +100,7 @@ TEST(AddressRangeTest, TestRanges) {
   EXPECT_FALSE(Ranges.contains(AddressRange(0x1000, 0x1000)));
   EXPECT_TRUE(Ranges.contains(AddressRange(0x1000, 0x1000 + 1)));
   EXPECT_TRUE(Ranges.contains(AddressRange(0x1000, 0x2000)));
-  EXPECT_TRUE(Ranges.contains(AddressRange(0x1000, 0x2001)));
+  EXPECT_FALSE(Ranges.contains(AddressRange(0x1000, 0x2001)));
   EXPECT_TRUE(Ranges.contains(AddressRange(0x2000, 0x3000)));
   EXPECT_FALSE(Ranges.contains(AddressRange(0x2000, 0x3001)));
   EXPECT_FALSE(Ranges.contains(AddressRange(0x3000, 0x3001)));
@@ -125,22 +125,16 @@ TEST(AddressRangeTest, TestRanges) {
   EXPECT_EQ(Ranges.size(), 1u);
   EXPECT_EQ(Ranges[0], AddressRange(0x1000, 0x2000));
 
-  // Verify that adjacent ranges get combined
-  Ranges.insert(AddressRange(0x2000, 0x2fff));
-  EXPECT_EQ(Ranges.size(), 1u);
-  EXPECT_EQ(Ranges[0], AddressRange(0x1000, 0x2fff));
-
-  // Verify that ranges having 1 byte gap do not get combined
-  Ranges.insert(AddressRange(0x3000, 0x4000));
+  // Verify that adjacent ranges don't get combined
+  Ranges.insert(AddressRange(0x2000, 0x3000));
   EXPECT_EQ(Ranges.size(), 2u);
-  EXPECT_EQ(Ranges[0], AddressRange(0x1000, 0x2fff));
-  EXPECT_EQ(Ranges[1], AddressRange(0x3000, 0x4000));
-
+  EXPECT_EQ(Ranges[0], AddressRange(0x1000, 0x2000));
+  EXPECT_EQ(Ranges[1], AddressRange(0x2000, 0x3000));
   // Verify if we add an address range that intersects two ranges
   // that they get combined
   Ranges.insert(AddressRange(Ranges[0].end() - 1, Ranges[1].start() + 1));
   EXPECT_EQ(Ranges.size(), 1u);
-  EXPECT_EQ(Ranges[0], AddressRange(0x1000, 0x4000));
+  EXPECT_EQ(Ranges[0], AddressRange(0x1000, 0x3000));
 
   Ranges.insert(AddressRange(0x3000, 0x4000));
   Ranges.insert(AddressRange(0x4000, 0x5000));
@@ -148,87 +142,3 @@ TEST(AddressRangeTest, TestRanges) {
   EXPECT_EQ(Ranges.size(), 1u);
   EXPECT_EQ(Ranges[0], AddressRange(0x1000, 0x5000));
 }
-
-TEST(AddressRangeTest, TestRangesMap) {
-  AddressRangesMap<int> Ranges;
-
-  EXPECT_EQ(Ranges.size(), 0u);
-  EXPECT_TRUE(Ranges.empty());
-
-  // Add single range.
-  Ranges.insert(AddressRange(0x1000, 0x2000), 0xfe);
-  EXPECT_EQ(Ranges.size(), 1u);
-  EXPECT_FALSE(Ranges.empty());
-  EXPECT_TRUE(Ranges.contains(0x1500));
-  EXPECT_TRUE(Ranges.contains(AddressRange(0x1000, 0x2000)));
-
-  // Clear ranges.
-  Ranges.clear();
-  EXPECT_EQ(Ranges.size(), 0u);
-  EXPECT_TRUE(Ranges.empty());
-
-  // Add range and check value.
-  Ranges.insert(AddressRange(0x1000, 0x2000), 0xfe);
-  EXPECT_EQ(Ranges.size(), 1u);
-  EXPECT_EQ(Ranges.getRangeValueThatContains(0x1000)->second, 0xfe);
-
-  // Add adjacent range and check value.
-  Ranges.insert(AddressRange(0x2000, 0x3000), 0xfc);
-  EXPECT_EQ(Ranges.size(), 1u);
-  EXPECT_EQ(Ranges.getRangeValueThatContains(0x1000)->second, 0xfc);
-  EXPECT_EQ(Ranges.getRangeValueThatContains(0x2000)->second, 0xfc);
-  EXPECT_EQ(Ranges.getRangeValueThatContains(0x2900)->second, 0xfc);
-  EXPECT_FALSE(Ranges.getRangeValueThatContains(0x3000));
-
-  // Add intersecting range and check value.
-  Ranges.insert(AddressRange(0x2000, 0x3000), 0xff);
-  EXPECT_EQ(Ranges.size(), 1u);
-  EXPECT_EQ(Ranges.getRangeValueThatContains(0x1000)->second, 0xff);
-
-  // Add second range and check values.
-  Ranges.insert(AddressRange(0x4000, 0x5000), 0x0);
-  EXPECT_EQ(Ranges.size(), 2u);
-  EXPECT_EQ(Ranges[0].second, 0xff);
-  EXPECT_EQ(Ranges[1].second, 0x0);
-  EXPECT_EQ(Ranges.getRangeValueThatContains(0x1000)->second, 0xff);
-  EXPECT_EQ(Ranges.getRangeValueThatContains(0x4000)->second, 0x0);
-
-  // Add intersecting range and check value.
-  Ranges.insert(AddressRange(0x0, 0x6000), 0x1);
-  EXPECT_EQ(Ranges.size(), 1u);
-  EXPECT_EQ(Ranges.getRangeValueThatContains(0x1000)->second, 0x1);
-
-  // Check that values are correctly preserved for combined ranges.
-  Ranges.clear();
-  Ranges.insert(AddressRange(0x0, 0xff), 0x1);
-  Ranges.insert(AddressRange(0x100, 0x1ff), 0x2);
-  Ranges.insert(AddressRange(0x200, 0x2ff), 0x3);
-  Ranges.insert(AddressRange(0x300, 0x3ff), 0x4);
-  Ranges.insert(AddressRange(0x400, 0x4ff), 0x5);
-  Ranges.insert(AddressRange(0x500, 0x5ff), 0x6);
-  Ranges.insert(AddressRange(0x600, 0x6ff), 0x7);
-
-  Ranges.insert(AddressRange(0x150, 0x350), 0xff);
-  EXPECT_EQ(Ranges.size(), 5u);
-  EXPECT_EQ(Ranges[0].first, AddressRange(0x0, 0xff));
-  EXPECT_EQ(Ranges[0].second, 0x1);
-  EXPECT_EQ(Ranges[1].first, AddressRange(0x100, 0x3ff));
-  EXPECT_EQ(Ranges[1].second, 0xff);
-  EXPECT_EQ(Ranges[2].first, AddressRange(0x400, 0x4ff));
-  EXPECT_EQ(Ranges[2].second, 0x5);
-  EXPECT_EQ(Ranges[3].first, AddressRange(0x500, 0x5ff));
-  EXPECT_EQ(Ranges[3].second, 0x6);
-  EXPECT_EQ(Ranges[4].first, AddressRange(0x600, 0x6ff));
-  EXPECT_EQ(Ranges[4].second, 0x7);
-
-  Ranges.insert(AddressRange(0x3ff, 0x400), 0x5);
-  EXPECT_EQ(Ranges.size(), 4u);
-  EXPECT_EQ(Ranges[0].first, AddressRange(0x0, 0xff));
-  EXPECT_EQ(Ranges[0].second, 0x1);
-  EXPECT_EQ(Ranges[1].first, AddressRange(0x100, 0x4ff));
-  EXPECT_EQ(Ranges[1].second, 0x5);
-  EXPECT_EQ(Ranges[2].first, AddressRange(0x500, 0x5ff));
-  EXPECT_EQ(Ranges[2].second, 0x6);
-  EXPECT_EQ(Ranges[3].first, AddressRange(0x600, 0x6ff));
-  EXPECT_EQ(Ranges[3].second, 0x7);
-}


        


More information about the llvm-commits mailing list