1//===- DWARFDebugRangesList.cpp -------------------------------------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
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/FormatVariadic.h"
14#include "llvm/Support/raw_ostream.h"
15#include <cinttypes>
16#include <cstdint>
17
18using namespace llvm;
19
20bool DWARFDebugRangeList::RangeListEntry::isBaseAddressSelectionEntry(
21 uint8_t AddressSize) const {
22 assert(DWARFContext::isAddressSizeSupported(AddressSize));
23 return StartAddress == dwarf::computeTombstoneAddress(AddressByteSize: AddressSize);
24}
25
26void DWARFDebugRangeList::clear() {
27 Offset = -1ULL;
28 AddressSize = 0;
29 Entries.clear();
30}
31
32Error DWARFDebugRangeList::extract(const DWARFDataExtractor &data,
33 uint64_t *offset_ptr) {
34 clear();
35 if (!data.isValidOffset(offset: *offset_ptr))
36 return createStringError(EC: errc::invalid_argument,
37 Fmt: "invalid range list offset 0x%" PRIx64, Vals: *offset_ptr);
38
39 AddressSize = data.getAddressSize();
40 if (Error SizeErr = DWARFContext::checkAddressSizeSupported(
41 AddressSize, EC: errc::invalid_argument,
42 Fmt: "range list at offset 0x%" PRIx64, Vals: *offset_ptr))
43 return SizeErr;
44 Offset = *offset_ptr;
45 while (true) {
46 RangeListEntry Entry;
47 Entry.SectionIndex = -1ULL;
48
49 uint64_t prev_offset = *offset_ptr;
50 Entry.StartAddress = data.getRelocatedAddress(Off: offset_ptr);
51 Entry.EndAddress =
52 data.getRelocatedAddress(Off: offset_ptr, SecIx: &Entry.SectionIndex);
53
54 // Check that both values were extracted correctly.
55 if (*offset_ptr != prev_offset + 2 * AddressSize) {
56 clear();
57 return createStringError(EC: errc::invalid_argument,
58 Fmt: "invalid range list entry at offset 0x%" PRIx64,
59 Vals: prev_offset);
60 }
61 if (Entry.isEndOfListEntry())
62 break;
63 Entries.push_back(x: Entry);
64 }
65 return Error::success();
66}
67
68void DWARFDebugRangeList::dump(raw_ostream &OS) const {
69 const char *AddrFmt;
70 switch (AddressSize) {
71 case 2:
72 AddrFmt = "{0:x-8} {1:x-4} {2:x-4}\n";
73 break;
74 case 4:
75 AddrFmt = "{0:x-8} {1:x-8} {2:x-8}\n";
76 break;
77 case 8:
78 AddrFmt = "{0:x-8} {1:x-16} {2:x-16}\n";
79 break;
80 default:
81 llvm_unreachable("unsupported address size");
82 }
83 for (const RangeListEntry &RLE : Entries)
84 OS << formatv(Fmt: AddrFmt, Vals: Offset, Vals: RLE.StartAddress, Vals: RLE.EndAddress);
85 OS << formatv(Fmt: "{0:x-8} <End of list>\n", Vals: Offset);
86}
87
88DWARFAddressRangesVector DWARFDebugRangeList::getAbsoluteRanges(
89 std::optional<object::SectionedAddress> BaseAddr) const {
90 DWARFAddressRangesVector Res;
91 // debug_addr can't use the max integer tombstone because that's used for the
92 // base address specifier entry - so use max-1.
93 uint64_t Tombstone = dwarf::computeTombstoneAddress(AddressByteSize: AddressSize) - 1;
94 for (const RangeListEntry &RLE : Entries) {
95 if (RLE.isBaseAddressSelectionEntry(AddressSize)) {
96 BaseAddr = {.Address: RLE.EndAddress, .SectionIndex: RLE.SectionIndex};
97 continue;
98 }
99
100 DWARFAddressRange E;
101 E.LowPC = RLE.StartAddress;
102 if (E.LowPC == Tombstone)
103 continue;
104 E.HighPC = RLE.EndAddress;
105 E.SectionIndex = RLE.SectionIndex;
106 // Base address of a range list entry is determined by the closest preceding
107 // base address selection entry in the same range list. It defaults to the
108 // base address of the compilation unit if there is no such entry.
109 if (BaseAddr) {
110 if (BaseAddr->Address == Tombstone)
111 continue;
112 E.LowPC += BaseAddr->Address;
113 E.HighPC += BaseAddr->Address;
114 if (E.SectionIndex == -1ULL)
115 E.SectionIndex = BaseAddr->SectionIndex;
116 }
117 Res.push_back(x: E);
118 }
119 return Res;
120}
121