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/Format.h" 13 #include "llvm/Support/raw_ostream.h" 14 #include <cinttypes> 15 #include <cstdint> 16 17 using namespace llvm; 18 19 // FIXME: There are several versions of this. Consolidate them. 20 template <typename... Ts> 21 static Error createError(char const *Fmt, const Ts &... Vals) { 22 std::string Buffer; 23 raw_string_ostream Stream(Buffer); 24 Stream << format(Fmt, Vals...); 25 return make_error<StringError>(Stream.str(), inconvertibleErrorCode()); 26 } 27 28 void DWARFDebugRangeList::clear() { 29 Offset = -1U; 30 AddressSize = 0; 31 Entries.clear(); 32 } 33 34 Error DWARFDebugRangeList::extract(const DWARFDataExtractor &data, 35 uint32_t *offset_ptr) { 36 clear(); 37 if (!data.isValidOffset(*offset_ptr)) 38 return createError("invalid range list offset 0x%" PRIx32, *offset_ptr); 39 40 AddressSize = data.getAddressSize(); 41 if (AddressSize != 4 && AddressSize != 8) 42 return createError("invalid address size: %d", AddressSize); 43 Offset = *offset_ptr; 44 while (true) { 45 RangeListEntry Entry; 46 Entry.SectionIndex = -1ULL; 47 48 uint32_t prev_offset = *offset_ptr; 49 Entry.StartAddress = data.getRelocatedAddress(offset_ptr); 50 Entry.EndAddress = 51 data.getRelocatedAddress(offset_ptr, &Entry.SectionIndex); 52 53 // Check that both values were extracted correctly. 54 if (*offset_ptr != prev_offset + 2 * AddressSize) { 55 clear(); 56 return createError("invalid range list entry at offset 0x%" PRIx32, 57 prev_offset); 58 } 59 if (Entry.isEndOfListEntry()) 60 break; 61 Entries.push_back(Entry); 62 } 63 return Error::success(); 64 } 65 66 void DWARFDebugRangeList::dump(raw_ostream &OS) const { 67 for (const RangeListEntry &RLE : Entries) { 68 const char *format_str = (AddressSize == 4 69 ? "%08x %08" PRIx64 " %08" PRIx64 "\n" 70 : "%08x %016" PRIx64 " %016" PRIx64 "\n"); 71 OS << format(format_str, Offset, RLE.StartAddress, RLE.EndAddress); 72 } 73 OS << format("%08x <End of list>\n", Offset); 74 } 75 76 DWARFAddressRangesVector DWARFDebugRangeList::getAbsoluteRanges( 77 llvm::Optional<BaseAddress> BaseAddr) const { 78 DWARFAddressRangesVector Res; 79 for (const RangeListEntry &RLE : Entries) { 80 if (RLE.isBaseAddressSelectionEntry(AddressSize)) { 81 BaseAddr = {RLE.EndAddress, RLE.SectionIndex}; 82 continue; 83 } 84 85 DWARFAddressRange E; 86 E.LowPC = RLE.StartAddress; 87 E.HighPC = RLE.EndAddress; 88 E.SectionIndex = RLE.SectionIndex; 89 // Base address of a range list entry is determined by the closest preceding 90 // base address selection entry in the same range list. It defaults to the 91 // base address of the compilation unit if there is no such entry. 92 if (BaseAddr) { 93 E.LowPC += BaseAddr->Address; 94 E.HighPC += BaseAddr->Address; 95 if (E.SectionIndex == -1ULL) 96 E.SectionIndex = BaseAddr->SectionIndex; 97 } 98 Res.push_back(E); 99 } 100 return Res; 101 } 102