1 //===- DWARFDebugRangesList.cpp -------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
10 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
11 #include "llvm/Support/Errc.h"
12 #include "llvm/Support/Format.h"
13 #include "llvm/Support/raw_ostream.h"
19 bool DWARFDebugRangeList::RangeListEntry::isBaseAddressSelectionEntry(
20 uint8_t AddressSize
) const {
21 assert(DWARFContext::isAddressSizeSupported(AddressSize
));
22 return StartAddress
== dwarf::computeTombstoneAddress(AddressSize
);
25 void DWARFDebugRangeList::clear() {
31 Error
DWARFDebugRangeList::extract(const DWARFDataExtractor
&data
,
32 uint64_t *offset_ptr
) {
34 if (!data
.isValidOffset(*offset_ptr
))
35 return createStringError(errc::invalid_argument
,
36 "invalid range list offset 0x%" PRIx64
, *offset_ptr
);
38 AddressSize
= data
.getAddressSize();
39 if (Error SizeErr
= DWARFContext::checkAddressSizeSupported(
40 AddressSize
, errc::invalid_argument
,
41 "range list at offset 0x%" PRIx64
, *offset_ptr
))
46 Entry
.SectionIndex
= -1ULL;
48 uint64_t prev_offset
= *offset_ptr
;
49 Entry
.StartAddress
= data
.getRelocatedAddress(offset_ptr
);
51 data
.getRelocatedAddress(offset_ptr
, &Entry
.SectionIndex
);
53 // Check that both values were extracted correctly.
54 if (*offset_ptr
!= prev_offset
+ 2 * AddressSize
) {
56 return createStringError(errc::invalid_argument
,
57 "invalid range list entry at offset 0x%" PRIx64
,
60 if (Entry
.isEndOfListEntry())
62 Entries
.push_back(Entry
);
64 return Error::success();
67 void DWARFDebugRangeList::dump(raw_ostream
&OS
) const {
69 switch (AddressSize
) {
71 AddrFmt
= "%08" PRIx64
" %04" PRIx64
" %04" PRIx64
"\n";
74 AddrFmt
= "%08" PRIx64
" %08" PRIx64
" %08" PRIx64
"\n";
77 AddrFmt
= "%08" PRIx64
" %016" PRIx64
" %016" PRIx64
"\n";
80 llvm_unreachable("unsupported address size");
82 for (const RangeListEntry
&RLE
: Entries
)
83 OS
<< format(AddrFmt
, Offset
, RLE
.StartAddress
, RLE
.EndAddress
);
84 OS
<< format("%08" PRIx64
" <End of list>\n", Offset
);
87 DWARFAddressRangesVector
DWARFDebugRangeList::getAbsoluteRanges(
88 std::optional
<object::SectionedAddress
> BaseAddr
) const {
89 DWARFAddressRangesVector Res
;
90 // debug_addr can't use the max integer tombstone because that's used for the
91 // base address specifier entry - so use max-1.
92 uint64_t Tombstone
= dwarf::computeTombstoneAddress(AddressSize
) - 1;
93 for (const RangeListEntry
&RLE
: Entries
) {
94 if (RLE
.isBaseAddressSelectionEntry(AddressSize
)) {
95 BaseAddr
= {RLE
.EndAddress
, RLE
.SectionIndex
};
100 E
.LowPC
= RLE
.StartAddress
;
101 if (E
.LowPC
== Tombstone
)
103 E
.HighPC
= RLE
.EndAddress
;
104 E
.SectionIndex
= RLE
.SectionIndex
;
105 // Base address of a range list entry is determined by the closest preceding
106 // base address selection entry in the same range list. It defaults to the
107 // base address of the compilation unit if there is no such entry.
109 if (BaseAddr
->Address
== Tombstone
)
111 E
.LowPC
+= BaseAddr
->Address
;
112 E
.HighPC
+= BaseAddr
->Address
;
113 if (E
.SectionIndex
== -1ULL)
114 E
.SectionIndex
= BaseAddr
->SectionIndex
;