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/MathExtras.h" 17 #include "llvm/Support/raw_ostream.h" 18 19 using namespace llvm; 20 21 Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End, 22 uint16_t Version, StringRef /* SectionName */, 23 uint32_t *OffsetPtr, bool /* isDWO */) { 24 Offset = *OffsetPtr; 25 SectionIndex = -1ULL; 26 27 assert((Data.getAddressSize() == 4 || Data.getAddressSize() == 8) && 28 "Unsupported address size"); 29 30 // We model a DWARF v4 range list entry like DWARF v5 DW_RLE_offset_pair, 31 // since it is subject to base adjustment. 32 uint8_t Encoding = dwarf::DW_RLE_offset_pair; 33 if (Version > 4) { 34 // The caller should guarantee that we have at least 1 byte available, so 35 // we just assert instead of revalidate. 36 assert(*OffsetPtr < End && 37 "not enough space to extract a rangelist encoding"); 38 Encoding = Data.getU8(OffsetPtr); 39 } 40 41 switch (Encoding) { 42 case dwarf::DW_RLE_end_of_list: 43 Value0 = Value1 = 0; 44 break; 45 // TODO: Support other encodings. 46 case dwarf::DW_RLE_base_addressx: { 47 uint32_t PreviousOffset = *OffsetPtr - 1; 48 Value0 = Data.getULEB128(OffsetPtr); 49 if (End < *OffsetPtr) 50 return createStringError( 51 errc::invalid_argument, 52 "read past end of table when reading " 53 "DW_RLE_base_addressx encoding at offset 0x%" PRIx32, 54 PreviousOffset); 55 break; 56 } 57 case dwarf::DW_RLE_startx_endx: 58 return createStringError(errc::not_supported, 59 "unsupported rnglists encoding DW_RLE_startx_endx at " 60 "offset 0x%" PRIx32, 61 *OffsetPtr - 1); 62 case dwarf::DW_RLE_startx_length: { 63 uint32_t PreviousOffset = *OffsetPtr - 1; 64 Value0 = Data.getULEB128(OffsetPtr); 65 Value1 = Data.getULEB128(OffsetPtr); 66 if (End < *OffsetPtr) 67 return createStringError( 68 errc::invalid_argument, 69 "read past end of table when reading " 70 "DW_RLE_startx_length encoding at offset 0x%" PRIx32, 71 PreviousOffset); 72 break; 73 } 74 case dwarf::DW_RLE_offset_pair: { 75 if (Version < 5) { 76 if ((End - *OffsetPtr) < unsigned(Data.getAddressSize() * 2)) 77 return createStringError( 78 errc::illegal_byte_sequence, 79 "invalid range list entry at offset 0x%" PRIx32, *OffsetPtr); 80 Value0 = Data.getRelocatedAddress(OffsetPtr); 81 Value1 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex); 82 // Adjust the EntryKind for end-of-list and base_address based on the 83 // contents. 84 if (Value0 == maxUIntN(Data.getAddressSize() * 8)) { 85 Encoding = dwarf::DW_RLE_base_address; 86 Value0 = Value1; 87 Value1 = 0; 88 } else if (Value0 == 0 && Value1 == 0) 89 Encoding = dwarf::DW_RLE_end_of_list; 90 break; 91 } 92 uint32_t PreviousOffset = *OffsetPtr - 1; 93 Value0 = Data.getULEB128(OffsetPtr); 94 Value1 = Data.getULEB128(OffsetPtr); 95 if (End < *OffsetPtr) 96 return createStringError(errc::invalid_argument, 97 "read past end of table when reading " 98 "DW_RLE_offset_pair encoding at offset 0x%" PRIx32, 99 PreviousOffset); 100 break; 101 } 102 case dwarf::DW_RLE_base_address: 103 if ((End - *OffsetPtr) < Data.getAddressSize()) 104 return createStringError(errc::invalid_argument, 105 "insufficient space remaining in table for " 106 "DW_RLE_base_address encoding at offset 0x%" PRIx32, 107 *OffsetPtr - 1); 108 Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex); 109 break; 110 case dwarf::DW_RLE_start_end: 111 if ((End - *OffsetPtr) < unsigned(Data.getAddressSize() * 2)) 112 return createStringError(errc::invalid_argument, 113 "insufficient space remaining in table for " 114 "DW_RLE_start_end encoding " 115 "at offset 0x%" PRIx32, 116 *OffsetPtr - 1); 117 Value0 = Data.getRelocatedAddress(OffsetPtr); 118 Value1 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex); 119 break; 120 case dwarf::DW_RLE_start_length: { 121 uint32_t PreviousOffset = *OffsetPtr - 1; 122 Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex); 123 Value1 = Data.getULEB128(OffsetPtr); 124 if (End < *OffsetPtr) 125 return createStringError(errc::invalid_argument, 126 "read past end of table when reading " 127 "DW_RLE_start_length encoding at offset 0x%" PRIx32, 128 PreviousOffset); 129 break; 130 } 131 default: 132 return createStringError(errc::not_supported, 133 "unknown rnglists encoding 0x%" PRIx32 134 " at offset 0x%" PRIx32, 135 uint32_t(Encoding), *OffsetPtr - 1); 136 } 137 138 EntryKind = Encoding; 139 return Error::success(); 140 } 141 142 DWARFAddressRangesVector 143 DWARFDebugRnglist::getAbsoluteRanges(llvm::Optional<SectionedAddress> BaseAddr, 144 DWARFUnit &U) const { 145 DWARFAddressRangesVector Res; 146 for (const RangeListEntry &RLE : Entries) { 147 if (RLE.EntryKind == dwarf::DW_RLE_end_of_list) 148 break; 149 if (RLE.EntryKind == dwarf::DW_RLE_base_addressx) { 150 BaseAddr = U.getAddrOffsetSectionItem(RLE.Value0); 151 if (!BaseAddr) 152 BaseAddr = {RLE.Value0, 0}; 153 continue; 154 } 155 if (RLE.EntryKind == dwarf::DW_RLE_base_address) { 156 BaseAddr = {RLE.Value0, RLE.SectionIndex}; 157 continue; 158 } 159 160 DWARFAddressRange E; 161 E.SectionIndex = RLE.SectionIndex; 162 if (BaseAddr && E.SectionIndex == -1ULL) 163 E.SectionIndex = BaseAddr->SectionIndex; 164 165 switch (RLE.EntryKind) { 166 case dwarf::DW_RLE_offset_pair: 167 E.LowPC = RLE.Value0; 168 E.HighPC = RLE.Value1; 169 if (BaseAddr) { 170 E.LowPC += BaseAddr->Address; 171 E.HighPC += BaseAddr->Address; 172 } 173 break; 174 case dwarf::DW_RLE_start_end: 175 E.LowPC = RLE.Value0; 176 E.HighPC = RLE.Value1; 177 break; 178 case dwarf::DW_RLE_start_length: 179 E.LowPC = RLE.Value0; 180 E.HighPC = E.LowPC + RLE.Value1; 181 break; 182 case dwarf::DW_RLE_startx_length: { 183 auto Start = U.getAddrOffsetSectionItem(RLE.Value0); 184 if (!Start) 185 Start = {0, 0}; 186 E.SectionIndex = Start->SectionIndex; 187 E.LowPC = Start->Address; 188 E.HighPC = E.LowPC + RLE.Value1; 189 break; 190 } 191 default: 192 // Unsupported encodings should have been reported during extraction, 193 // so we should not run into any here. 194 llvm_unreachable("Unsupported range list encoding"); 195 } 196 Res.push_back(E); 197 } 198 return Res; 199 } 200 201 void RangeListEntry::dump( 202 raw_ostream &OS, DWARFContext *, uint8_t AddrSize, uint64_t &CurrentBase, 203 unsigned Indent, uint16_t Version, uint8_t MaxEncodingStringLength, 204 DIDumpOptions DumpOpts, 205 llvm::function_ref<Optional<SectionedAddress>(uint32_t)> 206 LookupPooledAddress) const { 207 auto PrintRawEntry = [](raw_ostream &OS, const RangeListEntry &Entry, 208 uint8_t AddrSize, DIDumpOptions DumpOpts) { 209 if (DumpOpts.Verbose) { 210 DumpOpts.DisplayRawContents = true; 211 DWARFAddressRange(Entry.Value0, Entry.Value1) 212 .dump(OS, AddrSize, DumpOpts); 213 OS << " => "; 214 } 215 }; 216 217 // Output indentations before we print the actual entry. We only print 218 // anything for DW_RLE_base_address when we are in verbose mode. 219 if (Version < 5 || DumpOpts.Verbose || !isBaseAddressSelectionEntry()) 220 OS.indent(Indent); 221 222 // Always print the section offset in DWARF v4 and earlier. 223 if (Version < 5) { 224 OS << format("%08x", Offset); 225 DumpOpts.Verbose = false; 226 } 227 228 if (DumpOpts.Verbose) { 229 // Print the section offset in verbose mode. 230 OS << format("0x%8.8" PRIx32 ":", Offset); 231 if (Version > 4) { 232 auto EncodingString = dwarf::RangeListEncodingString(EntryKind); 233 // Unsupported encodings should have been reported during parsing. 234 assert(!EncodingString.empty() && "Unknown range entry encoding"); 235 OS << format(" [%s%*c", EncodingString.data(), 236 MaxEncodingStringLength - EncodingString.size() + 1, ']'); 237 if (!isEndOfList()) 238 OS << ": "; 239 } 240 } 241 242 switch (EntryKind) { 243 case dwarf::DW_RLE_end_of_list: 244 OS << (DumpOpts.Verbose ? "" : " <End of list>"); 245 break; 246 // case dwarf::DW_RLE_base_addressx: 247 case dwarf::DW_RLE_base_addressx: { 248 if (auto SA = LookupPooledAddress(Value0)) 249 CurrentBase = SA->Address; 250 else 251 CurrentBase = Value0; 252 if (!DumpOpts.Verbose) 253 return; 254 OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0); 255 break; 256 } 257 case dwarf::DW_RLE_base_address: 258 // In non-verbose mode we do not print anything for this entry. 259 CurrentBase = Value0; 260 if (Version < 5) { 261 // Dump the entry in pre-DWARF v5 format, i.e. with a -1 as Value0. 262 uint64_t allOnes = maxUIntN(AddrSize * 8); 263 OS << format(" %*.*" PRIx64, AddrSize * 2, AddrSize * 2, allOnes); 264 OS << format(" %*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0); 265 break; 266 } 267 if (!DumpOpts.Verbose) 268 return; 269 OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0); 270 break; 271 case dwarf::DW_RLE_start_length: 272 PrintRawEntry(OS, *this, AddrSize, DumpOpts); 273 DWARFAddressRange(Value0, Value0 + Value1).dump(OS, AddrSize, DumpOpts); 274 break; 275 case dwarf::DW_RLE_offset_pair: 276 if (Version < 5) { 277 OS << format(" %*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0); 278 OS << format(" %*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value1); 279 break; 280 } 281 PrintRawEntry(OS, *this, AddrSize, DumpOpts); 282 DWARFAddressRange(Value0 + CurrentBase, Value1 + CurrentBase) 283 .dump(OS, AddrSize, DumpOpts); 284 break; 285 case dwarf::DW_RLE_start_end: 286 DWARFAddressRange(Value0, Value1).dump(OS, AddrSize, DumpOpts); 287 break; 288 case dwarf::DW_RLE_startx_length: { 289 PrintRawEntry(OS, *this, AddrSize, DumpOpts); 290 uint64_t Start = 0; 291 if (auto SA = LookupPooledAddress(Value0)) 292 Start = SA->Address; 293 DWARFAddressRange(Start, Start + Value1).dump(OS, AddrSize, DumpOpts); 294 break; 295 } break; 296 default: 297 llvm_unreachable("Unsupported range list encoding"); 298 } 299 OS << "\n"; 300 } 301