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