xref: /freebsd/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===- DWARFDebugArangeSet.cpp --------------------------------------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric 
9*0b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h"
10*0b57cec5SDimitry Andric #include "llvm/Support/Format.h"
11*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
12*0b57cec5SDimitry Andric #include <cassert>
13*0b57cec5SDimitry Andric #include <cinttypes>
14*0b57cec5SDimitry Andric #include <cstdint>
15*0b57cec5SDimitry Andric #include <cstring>
16*0b57cec5SDimitry Andric 
17*0b57cec5SDimitry Andric using namespace llvm;
18*0b57cec5SDimitry Andric 
19*0b57cec5SDimitry Andric void DWARFDebugArangeSet::Descriptor::dump(raw_ostream &OS,
20*0b57cec5SDimitry Andric                                            uint32_t AddressSize) const {
21*0b57cec5SDimitry Andric   OS << format("[0x%*.*" PRIx64 ", ", AddressSize * 2, AddressSize * 2, Address)
22*0b57cec5SDimitry Andric      << format(" 0x%*.*" PRIx64 ")", AddressSize * 2, AddressSize * 2,
23*0b57cec5SDimitry Andric                getEndAddress());
24*0b57cec5SDimitry Andric }
25*0b57cec5SDimitry Andric 
26*0b57cec5SDimitry Andric void DWARFDebugArangeSet::clear() {
27*0b57cec5SDimitry Andric   Offset = -1U;
28*0b57cec5SDimitry Andric   std::memset(&HeaderData, 0, sizeof(Header));
29*0b57cec5SDimitry Andric   ArangeDescriptors.clear();
30*0b57cec5SDimitry Andric }
31*0b57cec5SDimitry Andric 
32*0b57cec5SDimitry Andric bool
33*0b57cec5SDimitry Andric DWARFDebugArangeSet::extract(DataExtractor data, uint32_t *offset_ptr) {
34*0b57cec5SDimitry Andric   if (data.isValidOffset(*offset_ptr)) {
35*0b57cec5SDimitry Andric     ArangeDescriptors.clear();
36*0b57cec5SDimitry Andric     Offset = *offset_ptr;
37*0b57cec5SDimitry Andric 
38*0b57cec5SDimitry Andric     // 7.20 Address Range Table
39*0b57cec5SDimitry Andric     //
40*0b57cec5SDimitry Andric     // Each set of entries in the table of address ranges contained in
41*0b57cec5SDimitry Andric     // the .debug_aranges section begins with a header consisting of: a
42*0b57cec5SDimitry Andric     // 4-byte length containing the length of the set of entries for this
43*0b57cec5SDimitry Andric     // compilation unit, not including the length field itself; a 2-byte
44*0b57cec5SDimitry Andric     // version identifier containing the value 2 for DWARF Version 2; a
45*0b57cec5SDimitry Andric     // 4-byte offset into the.debug_infosection; a 1-byte unsigned integer
46*0b57cec5SDimitry Andric     // containing the size in bytes of an address (or the offset portion of
47*0b57cec5SDimitry Andric     // an address for segmented addressing) on the target system; and a
48*0b57cec5SDimitry Andric     // 1-byte unsigned integer containing the size in bytes of a segment
49*0b57cec5SDimitry Andric     // descriptor on the target system. This header is followed by a series
50*0b57cec5SDimitry Andric     // of tuples. Each tuple consists of an address and a length, each in
51*0b57cec5SDimitry Andric     // the size appropriate for an address on the target architecture.
52*0b57cec5SDimitry Andric     HeaderData.Length = data.getU32(offset_ptr);
53*0b57cec5SDimitry Andric     HeaderData.Version = data.getU16(offset_ptr);
54*0b57cec5SDimitry Andric     HeaderData.CuOffset = data.getU32(offset_ptr);
55*0b57cec5SDimitry Andric     HeaderData.AddrSize = data.getU8(offset_ptr);
56*0b57cec5SDimitry Andric     HeaderData.SegSize = data.getU8(offset_ptr);
57*0b57cec5SDimitry Andric 
58*0b57cec5SDimitry Andric     // Perform basic validation of the header fields.
59*0b57cec5SDimitry Andric     if (!data.isValidOffsetForDataOfSize(Offset, HeaderData.Length) ||
60*0b57cec5SDimitry Andric         (HeaderData.AddrSize != 4 && HeaderData.AddrSize != 8)) {
61*0b57cec5SDimitry Andric       clear();
62*0b57cec5SDimitry Andric       return false;
63*0b57cec5SDimitry Andric     }
64*0b57cec5SDimitry Andric 
65*0b57cec5SDimitry Andric     // The first tuple following the header in each set begins at an offset
66*0b57cec5SDimitry Andric     // that is a multiple of the size of a single tuple (that is, twice the
67*0b57cec5SDimitry Andric     // size of an address). The header is padded, if necessary, to the
68*0b57cec5SDimitry Andric     // appropriate boundary.
69*0b57cec5SDimitry Andric     const uint32_t header_size = *offset_ptr - Offset;
70*0b57cec5SDimitry Andric     const uint32_t tuple_size = HeaderData.AddrSize * 2;
71*0b57cec5SDimitry Andric     uint32_t first_tuple_offset = 0;
72*0b57cec5SDimitry Andric     while (first_tuple_offset < header_size)
73*0b57cec5SDimitry Andric       first_tuple_offset += tuple_size;
74*0b57cec5SDimitry Andric 
75*0b57cec5SDimitry Andric     *offset_ptr = Offset + first_tuple_offset;
76*0b57cec5SDimitry Andric 
77*0b57cec5SDimitry Andric     Descriptor arangeDescriptor;
78*0b57cec5SDimitry Andric 
79*0b57cec5SDimitry Andric     static_assert(sizeof(arangeDescriptor.Address) ==
80*0b57cec5SDimitry Andric                       sizeof(arangeDescriptor.Length),
81*0b57cec5SDimitry Andric                   "Different datatypes for addresses and sizes!");
82*0b57cec5SDimitry Andric     assert(sizeof(arangeDescriptor.Address) >= HeaderData.AddrSize);
83*0b57cec5SDimitry Andric 
84*0b57cec5SDimitry Andric     while (data.isValidOffset(*offset_ptr)) {
85*0b57cec5SDimitry Andric       arangeDescriptor.Address = data.getUnsigned(offset_ptr, HeaderData.AddrSize);
86*0b57cec5SDimitry Andric       arangeDescriptor.Length = data.getUnsigned(offset_ptr, HeaderData.AddrSize);
87*0b57cec5SDimitry Andric 
88*0b57cec5SDimitry Andric       // Each set of tuples is terminated by a 0 for the address and 0
89*0b57cec5SDimitry Andric       // for the length.
90*0b57cec5SDimitry Andric       if (arangeDescriptor.Address || arangeDescriptor.Length)
91*0b57cec5SDimitry Andric         ArangeDescriptors.push_back(arangeDescriptor);
92*0b57cec5SDimitry Andric       else
93*0b57cec5SDimitry Andric         break; // We are done if we get a zero address and length
94*0b57cec5SDimitry Andric     }
95*0b57cec5SDimitry Andric 
96*0b57cec5SDimitry Andric     return !ArangeDescriptors.empty();
97*0b57cec5SDimitry Andric   }
98*0b57cec5SDimitry Andric   return false;
99*0b57cec5SDimitry Andric }
100*0b57cec5SDimitry Andric 
101*0b57cec5SDimitry Andric void DWARFDebugArangeSet::dump(raw_ostream &OS) const {
102*0b57cec5SDimitry Andric   OS << format("Address Range Header: length = 0x%8.8x, version = 0x%4.4x, ",
103*0b57cec5SDimitry Andric                HeaderData.Length, HeaderData.Version)
104*0b57cec5SDimitry Andric      << format("cu_offset = 0x%8.8x, addr_size = 0x%2.2x, seg_size = 0x%2.2x\n",
105*0b57cec5SDimitry Andric                HeaderData.CuOffset, HeaderData.AddrSize, HeaderData.SegSize);
106*0b57cec5SDimitry Andric 
107*0b57cec5SDimitry Andric   for (const auto &Desc : ArangeDescriptors) {
108*0b57cec5SDimitry Andric     Desc.dump(OS, HeaderData.AddrSize);
109*0b57cec5SDimitry Andric     OS << '\n';
110*0b57cec5SDimitry Andric   }
111*0b57cec5SDimitry Andric }
112