1c2dfd502SJames Henderson //===- DWARFDebugRnglists.cpp ---------------------------------------------===// 2c2dfd502SJames Henderson // 3c2dfd502SJames Henderson // The LLVM Compiler Infrastructure 4c2dfd502SJames Henderson // 5c2dfd502SJames Henderson // This file is distributed under the University of Illinois Open Source 6c2dfd502SJames Henderson // License. See LICENSE.TXT for details. 7c2dfd502SJames Henderson // 8c2dfd502SJames Henderson //===----------------------------------------------------------------------===// 9c2dfd502SJames Henderson 10c2dfd502SJames Henderson #include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h" 11c2dfd502SJames Henderson #include "llvm/BinaryFormat/Dwarf.h" 12ad60559bSWolfgang Pieb #include "llvm/DebugInfo/DWARF/DWARFUnit.h" 13cba595daSVictor Leschuk #include "llvm/Support/Errc.h" 14c2dfd502SJames Henderson #include "llvm/Support/Error.h" 15c2dfd502SJames Henderson #include "llvm/Support/Format.h" 16c2dfd502SJames Henderson #include "llvm/Support/raw_ostream.h" 17c2dfd502SJames Henderson 18c2dfd502SJames Henderson using namespace llvm; 19c2dfd502SJames Henderson 20439801baSWolfgang Pieb Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End, 21e74e0f11SAlexander Kornienko uint32_t *OffsetPtr) { 223fb9e3f3SWolfgang Pieb Offset = *OffsetPtr; 23ad60559bSWolfgang Pieb SectionIndex = -1ULL; 243fb9e3f3SWolfgang Pieb // The caller should guarantee that we have at least 1 byte available, so 253fb9e3f3SWolfgang Pieb // we just assert instead of revalidate. 263fb9e3f3SWolfgang Pieb assert(*OffsetPtr < End && 273fb9e3f3SWolfgang Pieb "not enough space to extract a rangelist encoding"); 28e74e0f11SAlexander Kornienko uint8_t Encoding = Data.getU8(OffsetPtr); 293fb9e3f3SWolfgang Pieb 30c2dfd502SJames Henderson switch (Encoding) { 31c2dfd502SJames Henderson case dwarf::DW_RLE_end_of_list: 323fb9e3f3SWolfgang Pieb Value0 = Value1 = 0; 33c2dfd502SJames Henderson break; 34c2dfd502SJames Henderson // TODO: Support other encodings. 35*59ac2064SDavid Blaikie case dwarf::DW_RLE_base_addressx: { 36*59ac2064SDavid Blaikie uint32_t PreviousOffset = *OffsetPtr - 1; 37*59ac2064SDavid Blaikie Value0 = Data.getULEB128(OffsetPtr); 38*59ac2064SDavid Blaikie if (End < *OffsetPtr) 39*59ac2064SDavid Blaikie return createStringError( 40*59ac2064SDavid Blaikie errc::invalid_argument, 41*59ac2064SDavid Blaikie "read past end of table when reading " 42*59ac2064SDavid Blaikie "DW_RLE_base_addressx encoding at offset 0x%" PRIx32, 43*59ac2064SDavid Blaikie PreviousOffset); 44*59ac2064SDavid Blaikie break; 45*59ac2064SDavid Blaikie } 46c2dfd502SJames Henderson case dwarf::DW_RLE_startx_endx: 47cba595daSVictor Leschuk return createStringError(errc::not_supported, 48cba595daSVictor Leschuk "unsupported rnglists encoding DW_RLE_startx_endx at " 49c2dfd502SJames Henderson "offset 0x%" PRIx32, 50c2dfd502SJames Henderson *OffsetPtr - 1); 51*59ac2064SDavid Blaikie case dwarf::DW_RLE_startx_length: { 52*59ac2064SDavid Blaikie uint32_t PreviousOffset = *OffsetPtr - 1; 53*59ac2064SDavid Blaikie Value0 = Data.getULEB128(OffsetPtr); 54*59ac2064SDavid Blaikie Value1 = Data.getULEB128(OffsetPtr); 55*59ac2064SDavid Blaikie if (End < *OffsetPtr) 56*59ac2064SDavid Blaikie return createStringError( 57*59ac2064SDavid Blaikie errc::invalid_argument, 58*59ac2064SDavid Blaikie "read past end of table when reading " 59*59ac2064SDavid Blaikie "DW_RLE_startx_length encoding at offset 0x%" PRIx32, 60*59ac2064SDavid Blaikie PreviousOffset); 61*59ac2064SDavid Blaikie break; 62*59ac2064SDavid Blaikie } 63ab068eaaSWolfgang Pieb case dwarf::DW_RLE_offset_pair: { 64ab068eaaSWolfgang Pieb uint32_t PreviousOffset = *OffsetPtr - 1; 653fb9e3f3SWolfgang Pieb Value0 = Data.getULEB128(OffsetPtr); 663fb9e3f3SWolfgang Pieb Value1 = Data.getULEB128(OffsetPtr); 67ab068eaaSWolfgang Pieb if (End < *OffsetPtr) 68cba595daSVictor Leschuk return createStringError(errc::invalid_argument, 69cba595daSVictor Leschuk "read past end of table when reading " 70ab068eaaSWolfgang Pieb "DW_RLE_offset_pair encoding at offset 0x%" PRIx32, 71ab068eaaSWolfgang Pieb PreviousOffset); 72ab068eaaSWolfgang Pieb break; 73ab068eaaSWolfgang Pieb } 74e74e0f11SAlexander Kornienko case dwarf::DW_RLE_base_address: { 753fb9e3f3SWolfgang Pieb if ((End - *OffsetPtr) < Data.getAddressSize()) 76cba595daSVictor Leschuk return createStringError(errc::invalid_argument, 77cba595daSVictor Leschuk "insufficient space remaining in table for " 78ab068eaaSWolfgang Pieb "DW_RLE_base_address encoding at offset 0x%" PRIx32, 79c2dfd502SJames Henderson *OffsetPtr - 1); 80ad60559bSWolfgang Pieb Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex); 81ab068eaaSWolfgang Pieb break; 82e74e0f11SAlexander Kornienko } 83e74e0f11SAlexander Kornienko case dwarf::DW_RLE_start_end: { 843fb9e3f3SWolfgang Pieb if ((End - *OffsetPtr) < unsigned(Data.getAddressSize() * 2)) 85cba595daSVictor Leschuk return createStringError(errc::invalid_argument, 86cba595daSVictor Leschuk "insufficient space remaining in table for " 87c2dfd502SJames Henderson "DW_RLE_start_end encoding " 88c2dfd502SJames Henderson "at offset 0x%" PRIx32, 89c2dfd502SJames Henderson *OffsetPtr - 1); 90e74e0f11SAlexander Kornienko Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex); 91e74e0f11SAlexander Kornienko Value1 = Data.getRelocatedAddress(OffsetPtr); 92c2dfd502SJames Henderson break; 93e74e0f11SAlexander Kornienko } 94c2dfd502SJames Henderson case dwarf::DW_RLE_start_length: { 95c2dfd502SJames Henderson uint32_t PreviousOffset = *OffsetPtr - 1; 96ad60559bSWolfgang Pieb Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex); 973fb9e3f3SWolfgang Pieb Value1 = Data.getULEB128(OffsetPtr); 98c2dfd502SJames Henderson if (End < *OffsetPtr) 99cba595daSVictor Leschuk return createStringError(errc::invalid_argument, 100cba595daSVictor Leschuk "read past end of table when reading " 101c2dfd502SJames Henderson "DW_RLE_start_length encoding at offset 0x%" PRIx32, 102c2dfd502SJames Henderson PreviousOffset); 103c2dfd502SJames Henderson break; 104c2dfd502SJames Henderson } 105c2dfd502SJames Henderson default: 106cba595daSVictor Leschuk return createStringError(errc::not_supported, 107cba595daSVictor Leschuk "unknown rnglists encoding 0x%" PRIx32 108c2dfd502SJames Henderson " at offset 0x%" PRIx32, 109c2dfd502SJames Henderson uint32_t(Encoding), *OffsetPtr - 1); 110c2dfd502SJames Henderson } 1113fb9e3f3SWolfgang Pieb 1123fb9e3f3SWolfgang Pieb EntryKind = Encoding; 1133fb9e3f3SWolfgang Pieb return Error::success(); 114c2dfd502SJames Henderson } 115c2dfd502SJames Henderson 116*59ac2064SDavid Blaikie DWARFAddressRangesVector 117*59ac2064SDavid Blaikie DWARFDebugRnglist::getAbsoluteRanges(llvm::Optional<SectionedAddress> BaseAddr, 118*59ac2064SDavid Blaikie DWARFUnit &U) const { 119ad60559bSWolfgang Pieb DWARFAddressRangesVector Res; 120ad60559bSWolfgang Pieb for (const RangeListEntry &RLE : Entries) { 121ad60559bSWolfgang Pieb if (RLE.EntryKind == dwarf::DW_RLE_end_of_list) 122ad60559bSWolfgang Pieb break; 123*59ac2064SDavid Blaikie if (RLE.EntryKind == dwarf::DW_RLE_base_addressx) { 124*59ac2064SDavid Blaikie BaseAddr = U.getAddrOffsetSectionItem(RLE.Value0); 125*59ac2064SDavid Blaikie if (!BaseAddr) 126*59ac2064SDavid Blaikie BaseAddr = {RLE.Value0, 0}; 127*59ac2064SDavid Blaikie continue; 128*59ac2064SDavid Blaikie } 129ad60559bSWolfgang Pieb if (RLE.EntryKind == dwarf::DW_RLE_base_address) { 130ad60559bSWolfgang Pieb BaseAddr = {RLE.Value0, RLE.SectionIndex}; 131ad60559bSWolfgang Pieb continue; 132ad60559bSWolfgang Pieb } 133ad60559bSWolfgang Pieb 134ad60559bSWolfgang Pieb DWARFAddressRange E; 135ad60559bSWolfgang Pieb E.SectionIndex = RLE.SectionIndex; 136ad60559bSWolfgang Pieb if (BaseAddr && E.SectionIndex == -1ULL) 137ad60559bSWolfgang Pieb E.SectionIndex = BaseAddr->SectionIndex; 138ad60559bSWolfgang Pieb 139ad60559bSWolfgang Pieb switch (RLE.EntryKind) { 140ad60559bSWolfgang Pieb case dwarf::DW_RLE_offset_pair: 141ad60559bSWolfgang Pieb E.LowPC = RLE.Value0; 142ad60559bSWolfgang Pieb E.HighPC = RLE.Value1; 143ad60559bSWolfgang Pieb if (BaseAddr) { 144ad60559bSWolfgang Pieb E.LowPC += BaseAddr->Address; 145ad60559bSWolfgang Pieb E.HighPC += BaseAddr->Address; 146ad60559bSWolfgang Pieb } 147ad60559bSWolfgang Pieb break; 148ad60559bSWolfgang Pieb case dwarf::DW_RLE_start_end: 149ad60559bSWolfgang Pieb E.LowPC = RLE.Value0; 150ad60559bSWolfgang Pieb E.HighPC = RLE.Value1; 151ad60559bSWolfgang Pieb break; 152ad60559bSWolfgang Pieb case dwarf::DW_RLE_start_length: 153ad60559bSWolfgang Pieb E.LowPC = RLE.Value0; 154ad60559bSWolfgang Pieb E.HighPC = E.LowPC + RLE.Value1; 155ad60559bSWolfgang Pieb break; 156*59ac2064SDavid Blaikie case dwarf::DW_RLE_startx_length: { 157*59ac2064SDavid Blaikie auto Start = U.getAddrOffsetSectionItem(RLE.Value0); 158*59ac2064SDavid Blaikie if (!Start) 159*59ac2064SDavid Blaikie Start = {0, 0}; 160*59ac2064SDavid Blaikie E.SectionIndex = Start->SectionIndex; 161*59ac2064SDavid Blaikie E.LowPC = Start->Address; 162*59ac2064SDavid Blaikie E.HighPC = E.LowPC + RLE.Value1; 163*59ac2064SDavid Blaikie break; 164*59ac2064SDavid Blaikie } 165ad60559bSWolfgang Pieb default: 166ad60559bSWolfgang Pieb // Unsupported encodings should have been reported during extraction, 167ad60559bSWolfgang Pieb // so we should not run into any here. 168ad60559bSWolfgang Pieb llvm_unreachable("Unsupported range list encoding"); 169ad60559bSWolfgang Pieb } 170ad60559bSWolfgang Pieb Res.push_back(E); 171ad60559bSWolfgang Pieb } 172ad60559bSWolfgang Pieb return Res; 173ad60559bSWolfgang Pieb } 174ad60559bSWolfgang Pieb 175*59ac2064SDavid Blaikie void RangeListEntry::dump( 176*59ac2064SDavid Blaikie raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength, 177*59ac2064SDavid Blaikie uint64_t &CurrentBase, DIDumpOptions DumpOpts, 178*59ac2064SDavid Blaikie llvm::function_ref<Optional<SectionedAddress>(uint32_t)> 179*59ac2064SDavid Blaikie LookupPooledAddress) const { 180439801baSWolfgang Pieb auto PrintRawEntry = [](raw_ostream &OS, const RangeListEntry &Entry, 181ab068eaaSWolfgang Pieb uint8_t AddrSize, DIDumpOptions DumpOpts) { 182ab068eaaSWolfgang Pieb if (DumpOpts.Verbose) { 183ab068eaaSWolfgang Pieb DumpOpts.DisplayRawContents = true; 184ab068eaaSWolfgang Pieb DWARFAddressRange(Entry.Value0, Entry.Value1) 185ab068eaaSWolfgang Pieb .dump(OS, AddrSize, DumpOpts); 186ab068eaaSWolfgang Pieb OS << " => "; 187ab068eaaSWolfgang Pieb } 188ab068eaaSWolfgang Pieb }; 189ab068eaaSWolfgang Pieb 190a0729d41SWolfgang Pieb if (DumpOpts.Verbose) { 191a0729d41SWolfgang Pieb // Print the section offset in verbose mode. 192439801baSWolfgang Pieb OS << format("0x%8.8" PRIx32 ":", Offset); 193439801baSWolfgang Pieb auto EncodingString = dwarf::RangeListEncodingString(EntryKind); 194a0729d41SWolfgang Pieb // Unsupported encodings should have been reported during parsing. 195a0729d41SWolfgang Pieb assert(!EncodingString.empty() && "Unknown range entry encoding"); 196a0729d41SWolfgang Pieb OS << format(" [%s%*c", EncodingString.data(), 197a0729d41SWolfgang Pieb MaxEncodingStringLength - EncodingString.size() + 1, ']'); 198e74e0f11SAlexander Kornienko if (EntryKind != dwarf::DW_RLE_end_of_list) 199a0729d41SWolfgang Pieb OS << ": "; 200a0729d41SWolfgang Pieb } 201a0729d41SWolfgang Pieb 202439801baSWolfgang Pieb switch (EntryKind) { 203a0729d41SWolfgang Pieb case dwarf::DW_RLE_end_of_list: 204e74e0f11SAlexander Kornienko OS << (DumpOpts.Verbose ? "" : "<End of list>"); 205a0729d41SWolfgang Pieb break; 206*59ac2064SDavid Blaikie // case dwarf::DW_RLE_base_addressx: 207*59ac2064SDavid Blaikie case dwarf::DW_RLE_base_addressx: { 208*59ac2064SDavid Blaikie if (auto SA = LookupPooledAddress(Value0)) 209*59ac2064SDavid Blaikie CurrentBase = SA->Address; 210*59ac2064SDavid Blaikie else 211*59ac2064SDavid Blaikie CurrentBase = Value0; 212*59ac2064SDavid Blaikie if (!DumpOpts.Verbose) 213*59ac2064SDavid Blaikie return; 214*59ac2064SDavid Blaikie OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0); 215*59ac2064SDavid Blaikie break; 216*59ac2064SDavid Blaikie } 217ab068eaaSWolfgang Pieb case dwarf::DW_RLE_base_address: 218e74e0f11SAlexander Kornienko // In non-verbose mode we do not print anything for this entry. 219439801baSWolfgang Pieb CurrentBase = Value0; 220ab068eaaSWolfgang Pieb if (!DumpOpts.Verbose) 221ab068eaaSWolfgang Pieb return; 222439801baSWolfgang Pieb OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0); 223ab068eaaSWolfgang Pieb break; 224a0729d41SWolfgang Pieb case dwarf::DW_RLE_start_length: 225439801baSWolfgang Pieb PrintRawEntry(OS, *this, AddrSize, DumpOpts); 226439801baSWolfgang Pieb DWARFAddressRange(Value0, Value0 + Value1).dump(OS, AddrSize, DumpOpts); 227a0729d41SWolfgang Pieb break; 228ab068eaaSWolfgang Pieb case dwarf::DW_RLE_offset_pair: 229439801baSWolfgang Pieb PrintRawEntry(OS, *this, AddrSize, DumpOpts); 230439801baSWolfgang Pieb DWARFAddressRange(Value0 + CurrentBase, Value1 + CurrentBase) 231ab068eaaSWolfgang Pieb .dump(OS, AddrSize, DumpOpts); 232ab068eaaSWolfgang Pieb break; 233a0729d41SWolfgang Pieb case dwarf::DW_RLE_start_end: 234439801baSWolfgang Pieb DWARFAddressRange(Value0, Value1).dump(OS, AddrSize, DumpOpts); 235a0729d41SWolfgang Pieb break; 236*59ac2064SDavid Blaikie case dwarf::DW_RLE_startx_length: { 237*59ac2064SDavid Blaikie PrintRawEntry(OS, *this, AddrSize, DumpOpts); 238*59ac2064SDavid Blaikie uint64_t Start = 0; 239*59ac2064SDavid Blaikie if (auto SA = LookupPooledAddress(Value0)) 240*59ac2064SDavid Blaikie Start = SA->Address; 241*59ac2064SDavid Blaikie DWARFAddressRange(Start, Start + Value1).dump(OS, AddrSize, DumpOpts); 242*59ac2064SDavid Blaikie break; 243*59ac2064SDavid Blaikie } break; 244a0729d41SWolfgang Pieb default: 245a0729d41SWolfgang Pieb llvm_unreachable("Unsupported range list encoding"); 246a0729d41SWolfgang Pieb } 247a0729d41SWolfgang Pieb OS << "\n"; 248a0729d41SWolfgang Pieb } 249