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