[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