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