xref: /llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp (revision 89fab98e884f05076bbd420d95b5de3596f5452c)
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