1 //===- DWARFDebugRnglists.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/DWARFDebugRnglists.h" 11 #include "llvm/BinaryFormat/Dwarf.h" 12 #include "llvm/DebugInfo/DWARF/DWARFUnit.h" 13 #include "llvm/Support/Errc.h" 14 #include "llvm/Support/Error.h" 15 #include "llvm/Support/Format.h" 16 #include "llvm/Support/raw_ostream.h" 17 18 using namespace llvm; 19 20 Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End, 21 uint32_t *OffsetPtr) { 22 Offset = *OffsetPtr; 23 SectionIndex = -1ULL; 24 // The caller should guarantee that we have at least 1 byte available, so 25 // we just assert instead of revalidate. 26 assert(*OffsetPtr < End && 27 "not enough space to extract a rangelist encoding"); 28 uint8_t Encoding = Data.getU8(OffsetPtr); 29 30 switch (Encoding) { 31 case dwarf::DW_RLE_end_of_list: 32 Value0 = Value1 = 0; 33 break; 34 // TODO: Support other encodings. 35 case dwarf::DW_RLE_base_addressx: 36 return createStringError(errc::not_supported, 37 "unsupported rnglists encoding DW_RLE_base_addressx " 38 "at offset 0x%" PRIx32, 39 *OffsetPtr - 1); 40 case dwarf::DW_RLE_startx_endx: 41 return createStringError(errc::not_supported, 42 "unsupported rnglists encoding DW_RLE_startx_endx at " 43 "offset 0x%" PRIx32, 44 *OffsetPtr - 1); 45 case dwarf::DW_RLE_startx_length: 46 return createStringError(errc::not_supported, 47 "unsupported rnglists encoding DW_RLE_startx_length " 48 "at offset 0x%" PRIx32, 49 *OffsetPtr - 1); 50 case dwarf::DW_RLE_offset_pair: { 51 uint32_t PreviousOffset = *OffsetPtr - 1; 52 Value0 = Data.getULEB128(OffsetPtr); 53 Value1 = Data.getULEB128(OffsetPtr); 54 if (End < *OffsetPtr) 55 return createStringError(errc::invalid_argument, 56 "read past end of table when reading " 57 "DW_RLE_offset_pair encoding at offset 0x%" PRIx32, 58 PreviousOffset); 59 break; 60 } 61 case dwarf::DW_RLE_base_address: { 62 if ((End - *OffsetPtr) < Data.getAddressSize()) 63 return createStringError(errc::invalid_argument, 64 "insufficient space remaining in table for " 65 "DW_RLE_base_address encoding at offset 0x%" PRIx32, 66 *OffsetPtr - 1); 67 Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex); 68 break; 69 } 70 case dwarf::DW_RLE_start_end: { 71 if ((End - *OffsetPtr) < unsigned(Data.getAddressSize() * 2)) 72 return createStringError(errc::invalid_argument, 73 "insufficient space remaining in table for " 74 "DW_RLE_start_end encoding " 75 "at offset 0x%" PRIx32, 76 *OffsetPtr - 1); 77 Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex); 78 Value1 = Data.getRelocatedAddress(OffsetPtr); 79 break; 80 } 81 case dwarf::DW_RLE_start_length: { 82 uint32_t PreviousOffset = *OffsetPtr - 1; 83 Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex); 84 Value1 = Data.getULEB128(OffsetPtr); 85 if (End < *OffsetPtr) 86 return createStringError(errc::invalid_argument, 87 "read past end of table when reading " 88 "DW_RLE_start_length encoding at offset 0x%" PRIx32, 89 PreviousOffset); 90 break; 91 } 92 default: 93 return createStringError(errc::not_supported, 94 "unknown rnglists encoding 0x%" PRIx32 95 " at offset 0x%" PRIx32, 96 uint32_t(Encoding), *OffsetPtr - 1); 97 } 98 99 EntryKind = Encoding; 100 return Error::success(); 101 } 102 103 DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges( 104 llvm::Optional<BaseAddress> BaseAddr) const { 105 DWARFAddressRangesVector Res; 106 for (const RangeListEntry &RLE : Entries) { 107 if (RLE.EntryKind == dwarf::DW_RLE_end_of_list) 108 break; 109 if (RLE.EntryKind == dwarf::DW_RLE_base_address) { 110 BaseAddr = {RLE.Value0, RLE.SectionIndex}; 111 continue; 112 } 113 114 DWARFAddressRange E; 115 E.SectionIndex = RLE.SectionIndex; 116 if (BaseAddr && E.SectionIndex == -1ULL) 117 E.SectionIndex = BaseAddr->SectionIndex; 118 119 switch (RLE.EntryKind) { 120 case dwarf::DW_RLE_offset_pair: 121 E.LowPC = RLE.Value0; 122 E.HighPC = RLE.Value1; 123 if (BaseAddr) { 124 E.LowPC += BaseAddr->Address; 125 E.HighPC += BaseAddr->Address; 126 } 127 break; 128 case dwarf::DW_RLE_start_end: 129 E.LowPC = RLE.Value0; 130 E.HighPC = RLE.Value1; 131 break; 132 case dwarf::DW_RLE_start_length: 133 E.LowPC = RLE.Value0; 134 E.HighPC = E.LowPC + RLE.Value1; 135 break; 136 default: 137 // Unsupported encodings should have been reported during extraction, 138 // so we should not run into any here. 139 llvm_unreachable("Unsupported range list encoding"); 140 } 141 Res.push_back(E); 142 } 143 return Res; 144 } 145 146 void RangeListEntry::dump(raw_ostream &OS, uint8_t AddrSize, 147 uint8_t MaxEncodingStringLength, 148 uint64_t &CurrentBase, DIDumpOptions DumpOpts) const { 149 auto PrintRawEntry = [](raw_ostream &OS, const RangeListEntry &Entry, 150 uint8_t AddrSize, DIDumpOptions DumpOpts) { 151 if (DumpOpts.Verbose) { 152 DumpOpts.DisplayRawContents = true; 153 DWARFAddressRange(Entry.Value0, Entry.Value1) 154 .dump(OS, AddrSize, DumpOpts); 155 OS << " => "; 156 } 157 }; 158 159 if (DumpOpts.Verbose) { 160 // Print the section offset in verbose mode. 161 OS << format("0x%8.8" PRIx32 ":", Offset); 162 auto EncodingString = dwarf::RangeListEncodingString(EntryKind); 163 // Unsupported encodings should have been reported during parsing. 164 assert(!EncodingString.empty() && "Unknown range entry encoding"); 165 OS << format(" [%s%*c", EncodingString.data(), 166 MaxEncodingStringLength - EncodingString.size() + 1, ']'); 167 if (EntryKind != dwarf::DW_RLE_end_of_list) 168 OS << ": "; 169 } 170 171 switch (EntryKind) { 172 case dwarf::DW_RLE_end_of_list: 173 OS << (DumpOpts.Verbose ? "" : "<End of list>"); 174 break; 175 case dwarf::DW_RLE_base_address: 176 // In non-verbose mode we do not print anything for this entry. 177 CurrentBase = Value0; 178 if (!DumpOpts.Verbose) 179 return; 180 OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0); 181 break; 182 case dwarf::DW_RLE_start_length: 183 PrintRawEntry(OS, *this, AddrSize, DumpOpts); 184 DWARFAddressRange(Value0, Value0 + Value1).dump(OS, AddrSize, DumpOpts); 185 break; 186 case dwarf::DW_RLE_offset_pair: 187 PrintRawEntry(OS, *this, AddrSize, DumpOpts); 188 DWARFAddressRange(Value0 + CurrentBase, Value1 + CurrentBase) 189 .dump(OS, AddrSize, DumpOpts); 190 break; 191 case dwarf::DW_RLE_start_end: 192 DWARFAddressRange(Value0, Value1).dump(OS, AddrSize, DumpOpts); 193 break; 194 default: 195 llvm_unreachable("Unsupported range list encoding"); 196 } 197 OS << "\n"; 198 } 199