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 uint32_t PreviousOffset = *OffsetPtr - 1; 37 Value0 = Data.getULEB128(OffsetPtr); 38 if (End < *OffsetPtr) 39 return createStringError( 40 errc::invalid_argument, 41 "read past end of table when reading " 42 "DW_RLE_base_addressx encoding at offset 0x%" PRIx32, 43 PreviousOffset); 44 break; 45 } 46 case dwarf::DW_RLE_startx_endx: 47 return createStringError(errc::not_supported, 48 "unsupported rnglists encoding DW_RLE_startx_endx at " 49 "offset 0x%" PRIx32, 50 *OffsetPtr - 1); 51 case dwarf::DW_RLE_startx_length: { 52 uint32_t PreviousOffset = *OffsetPtr - 1; 53 Value0 = Data.getULEB128(OffsetPtr); 54 Value1 = Data.getULEB128(OffsetPtr); 55 if (End < *OffsetPtr) 56 return createStringError( 57 errc::invalid_argument, 58 "read past end of table when reading " 59 "DW_RLE_startx_length encoding at offset 0x%" PRIx32, 60 PreviousOffset); 61 break; 62 } 63 case dwarf::DW_RLE_offset_pair: { 64 uint32_t PreviousOffset = *OffsetPtr - 1; 65 Value0 = Data.getULEB128(OffsetPtr); 66 Value1 = Data.getULEB128(OffsetPtr); 67 if (End < *OffsetPtr) 68 return createStringError(errc::invalid_argument, 69 "read past end of table when reading " 70 "DW_RLE_offset_pair encoding at offset 0x%" PRIx32, 71 PreviousOffset); 72 break; 73 } 74 case dwarf::DW_RLE_base_address: { 75 if ((End - *OffsetPtr) < Data.getAddressSize()) 76 return createStringError(errc::invalid_argument, 77 "insufficient space remaining in table for " 78 "DW_RLE_base_address encoding at offset 0x%" PRIx32, 79 *OffsetPtr - 1); 80 Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex); 81 break; 82 } 83 case dwarf::DW_RLE_start_end: { 84 if ((End - *OffsetPtr) < unsigned(Data.getAddressSize() * 2)) 85 return createStringError(errc::invalid_argument, 86 "insufficient space remaining in table for " 87 "DW_RLE_start_end encoding " 88 "at offset 0x%" PRIx32, 89 *OffsetPtr - 1); 90 Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex); 91 Value1 = Data.getRelocatedAddress(OffsetPtr); 92 break; 93 } 94 case dwarf::DW_RLE_start_length: { 95 uint32_t PreviousOffset = *OffsetPtr - 1; 96 Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex); 97 Value1 = Data.getULEB128(OffsetPtr); 98 if (End < *OffsetPtr) 99 return createStringError(errc::invalid_argument, 100 "read past end of table when reading " 101 "DW_RLE_start_length encoding at offset 0x%" PRIx32, 102 PreviousOffset); 103 break; 104 } 105 default: 106 return createStringError(errc::not_supported, 107 "unknown rnglists encoding 0x%" PRIx32 108 " at offset 0x%" PRIx32, 109 uint32_t(Encoding), *OffsetPtr - 1); 110 } 111 112 EntryKind = Encoding; 113 return Error::success(); 114 } 115 116 DWARFAddressRangesVector 117 DWARFDebugRnglist::getAbsoluteRanges(llvm::Optional<SectionedAddress> BaseAddr, 118 DWARFUnit &U) const { 119 DWARFAddressRangesVector Res; 120 for (const RangeListEntry &RLE : Entries) { 121 if (RLE.EntryKind == dwarf::DW_RLE_end_of_list) 122 break; 123 if (RLE.EntryKind == dwarf::DW_RLE_base_addressx) { 124 BaseAddr = U.getAddrOffsetSectionItem(RLE.Value0); 125 if (!BaseAddr) 126 BaseAddr = {RLE.Value0, -1ULL}; 127 continue; 128 } 129 if (RLE.EntryKind == dwarf::DW_RLE_base_address) { 130 BaseAddr = {RLE.Value0, RLE.SectionIndex}; 131 continue; 132 } 133 134 DWARFAddressRange E; 135 E.SectionIndex = RLE.SectionIndex; 136 if (BaseAddr && E.SectionIndex == -1ULL) 137 E.SectionIndex = BaseAddr->SectionIndex; 138 139 switch (RLE.EntryKind) { 140 case dwarf::DW_RLE_offset_pair: 141 E.LowPC = RLE.Value0; 142 E.HighPC = RLE.Value1; 143 if (BaseAddr) { 144 E.LowPC += BaseAddr->Address; 145 E.HighPC += BaseAddr->Address; 146 } 147 break; 148 case dwarf::DW_RLE_start_end: 149 E.LowPC = RLE.Value0; 150 E.HighPC = RLE.Value1; 151 break; 152 case dwarf::DW_RLE_start_length: 153 E.LowPC = RLE.Value0; 154 E.HighPC = E.LowPC + RLE.Value1; 155 break; 156 case dwarf::DW_RLE_startx_length: { 157 auto Start = U.getAddrOffsetSectionItem(RLE.Value0); 158 if (!Start) 159 Start = {0, -1ULL}; 160 E.SectionIndex = Start->SectionIndex; 161 E.LowPC = Start->Address; 162 E.HighPC = E.LowPC + RLE.Value1; 163 break; 164 } 165 default: 166 // Unsupported encodings should have been reported during extraction, 167 // so we should not run into any here. 168 llvm_unreachable("Unsupported range list encoding"); 169 } 170 Res.push_back(E); 171 } 172 return Res; 173 } 174 175 void RangeListEntry::dump( 176 raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength, 177 uint64_t &CurrentBase, DIDumpOptions DumpOpts, 178 llvm::function_ref<Optional<SectionedAddress>(uint32_t)> 179 LookupPooledAddress) const { 180 auto PrintRawEntry = [](raw_ostream &OS, const RangeListEntry &Entry, 181 uint8_t AddrSize, DIDumpOptions DumpOpts) { 182 if (DumpOpts.Verbose) { 183 DumpOpts.DisplayRawContents = true; 184 DWARFAddressRange(Entry.Value0, Entry.Value1) 185 .dump(OS, AddrSize, DumpOpts); 186 OS << " => "; 187 } 188 }; 189 190 if (DumpOpts.Verbose) { 191 // Print the section offset in verbose mode. 192 OS << format("0x%8.8" PRIx32 ":", Offset); 193 auto EncodingString = dwarf::RangeListEncodingString(EntryKind); 194 // Unsupported encodings should have been reported during parsing. 195 assert(!EncodingString.empty() && "Unknown range entry encoding"); 196 OS << format(" [%s%*c", EncodingString.data(), 197 MaxEncodingStringLength - EncodingString.size() + 1, ']'); 198 if (EntryKind != dwarf::DW_RLE_end_of_list) 199 OS << ": "; 200 } 201 202 switch (EntryKind) { 203 case dwarf::DW_RLE_end_of_list: 204 OS << (DumpOpts.Verbose ? "" : "<End of list>"); 205 break; 206 // case dwarf::DW_RLE_base_addressx: 207 case dwarf::DW_RLE_base_addressx: { 208 if (auto SA = LookupPooledAddress(Value0)) 209 CurrentBase = SA->Address; 210 else 211 CurrentBase = Value0; 212 if (!DumpOpts.Verbose) 213 return; 214 OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0); 215 break; 216 } 217 case dwarf::DW_RLE_base_address: 218 // In non-verbose mode we do not print anything for this entry. 219 CurrentBase = Value0; 220 if (!DumpOpts.Verbose) 221 return; 222 OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0); 223 break; 224 case dwarf::DW_RLE_start_length: 225 PrintRawEntry(OS, *this, AddrSize, DumpOpts); 226 DWARFAddressRange(Value0, Value0 + Value1).dump(OS, AddrSize, DumpOpts); 227 break; 228 case dwarf::DW_RLE_offset_pair: 229 PrintRawEntry(OS, *this, AddrSize, DumpOpts); 230 DWARFAddressRange(Value0 + CurrentBase, Value1 + CurrentBase) 231 .dump(OS, AddrSize, DumpOpts); 232 break; 233 case dwarf::DW_RLE_start_end: 234 DWARFAddressRange(Value0, Value1).dump(OS, AddrSize, DumpOpts); 235 break; 236 case dwarf::DW_RLE_startx_length: { 237 PrintRawEntry(OS, *this, AddrSize, DumpOpts); 238 uint64_t Start = 0; 239 if (auto SA = LookupPooledAddress(Value0)) 240 Start = SA->Address; 241 DWARFAddressRange(Start, Start + Value1).dump(OS, AddrSize, DumpOpts); 242 break; 243 } break; 244 default: 245 llvm_unreachable("Unsupported range list encoding"); 246 } 247 OS << "\n"; 248 } 249