1 //===- DWARFDebugRangesList.cpp -------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" 10 #include "llvm/DebugInfo/DWARF/DWARFContext.h" 11 #include "llvm/Support/Errc.h" 12 #include "llvm/Support/Format.h" 13 #include "llvm/Support/raw_ostream.h" 14 #include <cinttypes> 15 #include <cstdint> 16 17 using namespace llvm; 18 19 void DWARFDebugRangeList::clear() { 20 Offset = -1ULL; 21 AddressSize = 0; 22 Entries.clear(); 23 } 24 25 Error DWARFDebugRangeList::extract(const DWARFDataExtractor &data, 26 uint64_t *offset_ptr) { 27 clear(); 28 if (!data.isValidOffset(*offset_ptr)) 29 return createStringError(errc::invalid_argument, 30 "invalid range list offset 0x%" PRIx64, *offset_ptr); 31 32 AddressSize = data.getAddressSize(); 33 if (AddressSize != 4 && AddressSize != 8) 34 return createStringError(errc::invalid_argument, 35 "invalid address size: %" PRIu8, AddressSize); 36 Offset = *offset_ptr; 37 while (true) { 38 RangeListEntry Entry; 39 Entry.SectionIndex = -1ULL; 40 41 uint64_t prev_offset = *offset_ptr; 42 Entry.StartAddress = data.getRelocatedAddress(offset_ptr); 43 Entry.EndAddress = 44 data.getRelocatedAddress(offset_ptr, &Entry.SectionIndex); 45 46 // Check that both values were extracted correctly. 47 if (*offset_ptr != prev_offset + 2 * AddressSize) { 48 clear(); 49 return createStringError(errc::invalid_argument, 50 "invalid range list entry at offset 0x%" PRIx64, 51 prev_offset); 52 } 53 if (Entry.isEndOfListEntry()) 54 break; 55 Entries.push_back(Entry); 56 } 57 return Error::success(); 58 } 59 60 void DWARFDebugRangeList::dump(raw_ostream &OS) const { 61 for (const RangeListEntry &RLE : Entries) { 62 const char *format_str = 63 (AddressSize == 4 ? "%08" PRIx64 " %08" PRIx64 " %08" PRIx64 "\n" 64 : "%08" PRIx64 " %016" PRIx64 " %016" PRIx64 "\n"); 65 OS << format(format_str, Offset, RLE.StartAddress, RLE.EndAddress); 66 } 67 OS << format("%08" PRIx64 " <End of list>\n", Offset); 68 } 69 70 DWARFAddressRangesVector DWARFDebugRangeList::getAbsoluteRanges( 71 llvm::Optional<object::SectionedAddress> BaseAddr) const { 72 DWARFAddressRangesVector Res; 73 // debug_addr can't use the max integer tombstone because that's used for the 74 // base address specifier entry - so use max-1. 75 uint64_t Tombstone = dwarf::computeTombstoneAddress(AddressSize) - 1; 76 for (const RangeListEntry &RLE : Entries) { 77 if (RLE.isBaseAddressSelectionEntry(AddressSize)) { 78 BaseAddr = {RLE.EndAddress, RLE.SectionIndex}; 79 continue; 80 } 81 82 DWARFAddressRange E; 83 E.LowPC = RLE.StartAddress; 84 if (E.LowPC == Tombstone) 85 continue; 86 E.HighPC = RLE.EndAddress; 87 E.SectionIndex = RLE.SectionIndex; 88 // Base address of a range list entry is determined by the closest preceding 89 // base address selection entry in the same range list. It defaults to the 90 // base address of the compilation unit if there is no such entry. 91 if (BaseAddr) { 92 if (BaseAddr->Address == Tombstone) 93 continue; 94 E.LowPC += BaseAddr->Address; 95 E.HighPC += BaseAddr->Address; 96 if (E.SectionIndex == -1ULL) 97 E.SectionIndex = BaseAddr->SectionIndex; 98 } 99 Res.push_back(E); 100 } 101 return Res; 102 } 103