1f39a9bbeSWolfgang Pieb //===- DWARFDebugRangesList.cpp -------------------------------------------===//
2f39a9bbeSWolfgang Pieb //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f39a9bbeSWolfgang Pieb //
7f39a9bbeSWolfgang Pieb //===----------------------------------------------------------------------===//
8f39a9bbeSWolfgang Pieb
9f39a9bbeSWolfgang Pieb #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
10f39a9bbeSWolfgang Pieb #include "llvm/DebugInfo/DWARF/DWARFContext.h"
11f39a9bbeSWolfgang Pieb #include "llvm/Support/Errc.h"
12f39a9bbeSWolfgang Pieb #include "llvm/Support/Format.h"
13f39a9bbeSWolfgang Pieb #include "llvm/Support/raw_ostream.h"
14f39a9bbeSWolfgang Pieb #include <cinttypes>
15f39a9bbeSWolfgang Pieb #include <cstdint>
16f39a9bbeSWolfgang Pieb
17f39a9bbeSWolfgang Pieb using namespace llvm;
18f39a9bbeSWolfgang Pieb
isBaseAddressSelectionEntry(uint8_t AddressSize) const19d7733f84SJack Anderson bool DWARFDebugRangeList::RangeListEntry::isBaseAddressSelectionEntry(
20d7733f84SJack Anderson uint8_t AddressSize) const {
21d7733f84SJack Anderson assert(DWARFContext::isAddressSizeSupported(AddressSize));
22d7733f84SJack Anderson return StartAddress == dwarf::computeTombstoneAddress(AddressSize);
23d7733f84SJack Anderson }
24d7733f84SJack Anderson
clear()25f39a9bbeSWolfgang Pieb void DWARFDebugRangeList::clear() {
26f26a70a5SIgor Kudrin Offset = -1ULL;
27f39a9bbeSWolfgang Pieb AddressSize = 0;
28f39a9bbeSWolfgang Pieb Entries.clear();
29f39a9bbeSWolfgang Pieb }
30f39a9bbeSWolfgang Pieb
extract(const DWARFDataExtractor & data,uint64_t * offset_ptr)31f39a9bbeSWolfgang Pieb Error DWARFDebugRangeList::extract(const DWARFDataExtractor &data,
32f26a70a5SIgor Kudrin uint64_t *offset_ptr) {
33f39a9bbeSWolfgang Pieb clear();
34f39a9bbeSWolfgang Pieb if (!data.isValidOffset(*offset_ptr))
35f39a9bbeSWolfgang Pieb return createStringError(errc::invalid_argument,
36f26a70a5SIgor Kudrin "invalid range list offset 0x%" PRIx64, *offset_ptr);
37f39a9bbeSWolfgang Pieb
38f39a9bbeSWolfgang Pieb AddressSize = data.getAddressSize();
39d7733f84SJack Anderson if (Error SizeErr = DWARFContext::checkAddressSizeSupported(
40d7733f84SJack Anderson AddressSize, errc::invalid_argument,
41d7733f84SJack Anderson "range list at offset 0x%" PRIx64, *offset_ptr))
42d7733f84SJack Anderson return SizeErr;
43f39a9bbeSWolfgang Pieb Offset = *offset_ptr;
44f39a9bbeSWolfgang Pieb while (true) {
45f39a9bbeSWolfgang Pieb RangeListEntry Entry;
46f39a9bbeSWolfgang Pieb Entry.SectionIndex = -1ULL;
47f39a9bbeSWolfgang Pieb
48f26a70a5SIgor Kudrin uint64_t prev_offset = *offset_ptr;
49f39a9bbeSWolfgang Pieb Entry.StartAddress = data.getRelocatedAddress(offset_ptr);
50f39a9bbeSWolfgang Pieb Entry.EndAddress =
51f39a9bbeSWolfgang Pieb data.getRelocatedAddress(offset_ptr, &Entry.SectionIndex);
52f39a9bbeSWolfgang Pieb
53f39a9bbeSWolfgang Pieb // Check that both values were extracted correctly.
54f39a9bbeSWolfgang Pieb if (*offset_ptr != prev_offset + 2 * AddressSize) {
55f39a9bbeSWolfgang Pieb clear();
56f39a9bbeSWolfgang Pieb return createStringError(errc::invalid_argument,
57f26a70a5SIgor Kudrin "invalid range list entry at offset 0x%" PRIx64,
58f39a9bbeSWolfgang Pieb prev_offset);
59f39a9bbeSWolfgang Pieb }
60f39a9bbeSWolfgang Pieb if (Entry.isEndOfListEntry())
61f39a9bbeSWolfgang Pieb break;
62f39a9bbeSWolfgang Pieb Entries.push_back(Entry);
63f39a9bbeSWolfgang Pieb }
64f39a9bbeSWolfgang Pieb return Error::success();
65f39a9bbeSWolfgang Pieb }
66f39a9bbeSWolfgang Pieb
dump(raw_ostream & OS) const67f39a9bbeSWolfgang Pieb void DWARFDebugRangeList::dump(raw_ostream &OS) const {
68d7733f84SJack Anderson const char *AddrFmt;
69d7733f84SJack Anderson switch (AddressSize) {
70d7733f84SJack Anderson case 2:
71d7733f84SJack Anderson AddrFmt = "%08" PRIx64 " %04" PRIx64 " %04" PRIx64 "\n";
72d7733f84SJack Anderson break;
73d7733f84SJack Anderson case 4:
74d7733f84SJack Anderson AddrFmt = "%08" PRIx64 " %08" PRIx64 " %08" PRIx64 "\n";
75d7733f84SJack Anderson break;
76d7733f84SJack Anderson case 8:
77d7733f84SJack Anderson AddrFmt = "%08" PRIx64 " %016" PRIx64 " %016" PRIx64 "\n";
78d7733f84SJack Anderson break;
79d7733f84SJack Anderson default:
80d7733f84SJack Anderson llvm_unreachable("unsupported address size");
81f39a9bbeSWolfgang Pieb }
82d7733f84SJack Anderson for (const RangeListEntry &RLE : Entries)
83d7733f84SJack Anderson OS << format(AddrFmt, Offset, RLE.StartAddress, RLE.EndAddress);
84f26a70a5SIgor Kudrin OS << format("%08" PRIx64 " <End of list>\n", Offset);
85f39a9bbeSWolfgang Pieb }
86f39a9bbeSWolfgang Pieb
getAbsoluteRanges(std::optional<object::SectionedAddress> BaseAddr) const87f39a9bbeSWolfgang Pieb DWARFAddressRangesVector DWARFDebugRangeList::getAbsoluteRanges(
88*89fab98eSFangrui Song std::optional<object::SectionedAddress> BaseAddr) const {
89f39a9bbeSWolfgang Pieb DWARFAddressRangesVector Res;
908036cf7fSDavid Blaikie // debug_addr can't use the max integer tombstone because that's used for the
918036cf7fSDavid Blaikie // base address specifier entry - so use max-1.
928036cf7fSDavid Blaikie uint64_t Tombstone = dwarf::computeTombstoneAddress(AddressSize) - 1;
93f39a9bbeSWolfgang Pieb for (const RangeListEntry &RLE : Entries) {
94f39a9bbeSWolfgang Pieb if (RLE.isBaseAddressSelectionEntry(AddressSize)) {
95f39a9bbeSWolfgang Pieb BaseAddr = {RLE.EndAddress, RLE.SectionIndex};
96f39a9bbeSWolfgang Pieb continue;
97f39a9bbeSWolfgang Pieb }
98f39a9bbeSWolfgang Pieb
99f39a9bbeSWolfgang Pieb DWARFAddressRange E;
100f39a9bbeSWolfgang Pieb E.LowPC = RLE.StartAddress;
1018036cf7fSDavid Blaikie if (E.LowPC == Tombstone)
1028036cf7fSDavid Blaikie continue;
103f39a9bbeSWolfgang Pieb E.HighPC = RLE.EndAddress;
104f39a9bbeSWolfgang Pieb E.SectionIndex = RLE.SectionIndex;
105f39a9bbeSWolfgang Pieb // Base address of a range list entry is determined by the closest preceding
106f39a9bbeSWolfgang Pieb // base address selection entry in the same range list. It defaults to the
107f39a9bbeSWolfgang Pieb // base address of the compilation unit if there is no such entry.
108f39a9bbeSWolfgang Pieb if (BaseAddr) {
1098036cf7fSDavid Blaikie if (BaseAddr->Address == Tombstone)
1108036cf7fSDavid Blaikie continue;
111f39a9bbeSWolfgang Pieb E.LowPC += BaseAddr->Address;
112f39a9bbeSWolfgang Pieb E.HighPC += BaseAddr->Address;
113f39a9bbeSWolfgang Pieb if (E.SectionIndex == -1ULL)
114f39a9bbeSWolfgang Pieb E.SectionIndex = BaseAddr->SectionIndex;
115f39a9bbeSWolfgang Pieb }
116f39a9bbeSWolfgang Pieb Res.push_back(E);
117f39a9bbeSWolfgang Pieb }
118f39a9bbeSWolfgang Pieb return Res;
119f39a9bbeSWolfgang Pieb }
120