10b57cec5SDimitry Andric //===- DWARFDebugArangeSet.cpp --------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h" 100b57cec5SDimitry Andric #include "llvm/Support/Format.h" 110b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 120b57cec5SDimitry Andric #include <cassert> 130b57cec5SDimitry Andric #include <cinttypes> 140b57cec5SDimitry Andric #include <cstdint> 150b57cec5SDimitry Andric #include <cstring> 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric using namespace llvm; 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric void DWARFDebugArangeSet::Descriptor::dump(raw_ostream &OS, 200b57cec5SDimitry Andric uint32_t AddressSize) const { 210b57cec5SDimitry Andric OS << format("[0x%*.*" PRIx64 ", ", AddressSize * 2, AddressSize * 2, Address) 220b57cec5SDimitry Andric << format(" 0x%*.*" PRIx64 ")", AddressSize * 2, AddressSize * 2, 230b57cec5SDimitry Andric getEndAddress()); 240b57cec5SDimitry Andric } 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric void DWARFDebugArangeSet::clear() { 27*8bcb0991SDimitry Andric Offset = -1ULL; 280b57cec5SDimitry Andric std::memset(&HeaderData, 0, sizeof(Header)); 290b57cec5SDimitry Andric ArangeDescriptors.clear(); 300b57cec5SDimitry Andric } 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric bool 33*8bcb0991SDimitry Andric DWARFDebugArangeSet::extract(DataExtractor data, uint64_t *offset_ptr) { 340b57cec5SDimitry Andric if (data.isValidOffset(*offset_ptr)) { 350b57cec5SDimitry Andric ArangeDescriptors.clear(); 360b57cec5SDimitry Andric Offset = *offset_ptr; 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric // 7.20 Address Range Table 390b57cec5SDimitry Andric // 400b57cec5SDimitry Andric // Each set of entries in the table of address ranges contained in 410b57cec5SDimitry Andric // the .debug_aranges section begins with a header consisting of: a 420b57cec5SDimitry Andric // 4-byte length containing the length of the set of entries for this 430b57cec5SDimitry Andric // compilation unit, not including the length field itself; a 2-byte 440b57cec5SDimitry Andric // version identifier containing the value 2 for DWARF Version 2; a 450b57cec5SDimitry Andric // 4-byte offset into the.debug_infosection; a 1-byte unsigned integer 460b57cec5SDimitry Andric // containing the size in bytes of an address (or the offset portion of 470b57cec5SDimitry Andric // an address for segmented addressing) on the target system; and a 480b57cec5SDimitry Andric // 1-byte unsigned integer containing the size in bytes of a segment 490b57cec5SDimitry Andric // descriptor on the target system. This header is followed by a series 500b57cec5SDimitry Andric // of tuples. Each tuple consists of an address and a length, each in 510b57cec5SDimitry Andric // the size appropriate for an address on the target architecture. 520b57cec5SDimitry Andric HeaderData.Length = data.getU32(offset_ptr); 530b57cec5SDimitry Andric HeaderData.Version = data.getU16(offset_ptr); 540b57cec5SDimitry Andric HeaderData.CuOffset = data.getU32(offset_ptr); 550b57cec5SDimitry Andric HeaderData.AddrSize = data.getU8(offset_ptr); 560b57cec5SDimitry Andric HeaderData.SegSize = data.getU8(offset_ptr); 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric // Perform basic validation of the header fields. 590b57cec5SDimitry Andric if (!data.isValidOffsetForDataOfSize(Offset, HeaderData.Length) || 600b57cec5SDimitry Andric (HeaderData.AddrSize != 4 && HeaderData.AddrSize != 8)) { 610b57cec5SDimitry Andric clear(); 620b57cec5SDimitry Andric return false; 630b57cec5SDimitry Andric } 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric // The first tuple following the header in each set begins at an offset 660b57cec5SDimitry Andric // that is a multiple of the size of a single tuple (that is, twice the 670b57cec5SDimitry Andric // size of an address). The header is padded, if necessary, to the 680b57cec5SDimitry Andric // appropriate boundary. 690b57cec5SDimitry Andric const uint32_t header_size = *offset_ptr - Offset; 700b57cec5SDimitry Andric const uint32_t tuple_size = HeaderData.AddrSize * 2; 710b57cec5SDimitry Andric uint32_t first_tuple_offset = 0; 720b57cec5SDimitry Andric while (first_tuple_offset < header_size) 730b57cec5SDimitry Andric first_tuple_offset += tuple_size; 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric *offset_ptr = Offset + first_tuple_offset; 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric Descriptor arangeDescriptor; 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric static_assert(sizeof(arangeDescriptor.Address) == 800b57cec5SDimitry Andric sizeof(arangeDescriptor.Length), 810b57cec5SDimitry Andric "Different datatypes for addresses and sizes!"); 820b57cec5SDimitry Andric assert(sizeof(arangeDescriptor.Address) >= HeaderData.AddrSize); 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric while (data.isValidOffset(*offset_ptr)) { 850b57cec5SDimitry Andric arangeDescriptor.Address = data.getUnsigned(offset_ptr, HeaderData.AddrSize); 860b57cec5SDimitry Andric arangeDescriptor.Length = data.getUnsigned(offset_ptr, HeaderData.AddrSize); 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric // Each set of tuples is terminated by a 0 for the address and 0 890b57cec5SDimitry Andric // for the length. 900b57cec5SDimitry Andric if (arangeDescriptor.Address || arangeDescriptor.Length) 910b57cec5SDimitry Andric ArangeDescriptors.push_back(arangeDescriptor); 920b57cec5SDimitry Andric else 930b57cec5SDimitry Andric break; // We are done if we get a zero address and length 940b57cec5SDimitry Andric } 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric return !ArangeDescriptors.empty(); 970b57cec5SDimitry Andric } 980b57cec5SDimitry Andric return false; 990b57cec5SDimitry Andric } 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric void DWARFDebugArangeSet::dump(raw_ostream &OS) const { 1020b57cec5SDimitry Andric OS << format("Address Range Header: length = 0x%8.8x, version = 0x%4.4x, ", 1030b57cec5SDimitry Andric HeaderData.Length, HeaderData.Version) 1040b57cec5SDimitry Andric << format("cu_offset = 0x%8.8x, addr_size = 0x%2.2x, seg_size = 0x%2.2x\n", 1050b57cec5SDimitry Andric HeaderData.CuOffset, HeaderData.AddrSize, HeaderData.SegSize); 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric for (const auto &Desc : ArangeDescriptors) { 1080b57cec5SDimitry Andric Desc.dump(OS, HeaderData.AddrSize); 1090b57cec5SDimitry Andric OS << '\n'; 1100b57cec5SDimitry Andric } 1110b57cec5SDimitry Andric } 112