10b57cec5SDimitry Andric //===- DWARFDebugPubTable.cpp ---------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h" 100b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" 110b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 120b57cec5SDimitry Andric #include "llvm/BinaryFormat/Dwarf.h" 130b57cec5SDimitry Andric #include "llvm/Support/DataExtractor.h" 14*5ffd83dbSDimitry Andric #include "llvm/Support/Errc.h" 150b57cec5SDimitry Andric #include "llvm/Support/Format.h" 160b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 170b57cec5SDimitry Andric #include <cstdint> 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric using namespace llvm; 200b57cec5SDimitry Andric using namespace dwarf; 210b57cec5SDimitry Andric 22*5ffd83dbSDimitry Andric void DWARFDebugPubTable::extract( 23*5ffd83dbSDimitry Andric DWARFDataExtractor Data, bool GnuStyle, 24*5ffd83dbSDimitry Andric function_ref<void(Error)> RecoverableErrorHandler) { 25*5ffd83dbSDimitry Andric this->GnuStyle = GnuStyle; 26*5ffd83dbSDimitry Andric Sets.clear(); 278bcb0991SDimitry Andric uint64_t Offset = 0; 28*5ffd83dbSDimitry Andric while (Data.isValidOffset(Offset)) { 29*5ffd83dbSDimitry Andric uint64_t SetOffset = Offset; 300b57cec5SDimitry Andric Sets.push_back({}); 31*5ffd83dbSDimitry Andric Set &NewSet = Sets.back(); 320b57cec5SDimitry Andric 33*5ffd83dbSDimitry Andric DataExtractor::Cursor C(Offset); 34*5ffd83dbSDimitry Andric std::tie(NewSet.Length, NewSet.Format) = Data.getInitialLength(C); 35*5ffd83dbSDimitry Andric if (!C) { 36*5ffd83dbSDimitry Andric // Drop the newly added set because it does not contain anything useful 37*5ffd83dbSDimitry Andric // to dump. 38*5ffd83dbSDimitry Andric Sets.pop_back(); 39*5ffd83dbSDimitry Andric RecoverableErrorHandler(createStringError( 40*5ffd83dbSDimitry Andric errc::invalid_argument, 41*5ffd83dbSDimitry Andric "name lookup table at offset 0x%" PRIx64 " parsing failed: %s", 42*5ffd83dbSDimitry Andric SetOffset, toString(C.takeError()).c_str())); 43*5ffd83dbSDimitry Andric return; 44*5ffd83dbSDimitry Andric } 450b57cec5SDimitry Andric 46*5ffd83dbSDimitry Andric Offset = C.tell() + NewSet.Length; 47*5ffd83dbSDimitry Andric DWARFDataExtractor SetData(Data, Offset); 48*5ffd83dbSDimitry Andric const unsigned OffsetSize = dwarf::getDwarfOffsetByteSize(NewSet.Format); 49*5ffd83dbSDimitry Andric 50*5ffd83dbSDimitry Andric NewSet.Version = SetData.getU16(C); 51*5ffd83dbSDimitry Andric NewSet.Offset = SetData.getRelocatedValue(C, OffsetSize); 52*5ffd83dbSDimitry Andric NewSet.Size = SetData.getUnsigned(C, OffsetSize); 53*5ffd83dbSDimitry Andric 54*5ffd83dbSDimitry Andric if (!C) { 55*5ffd83dbSDimitry Andric // Preserve the newly added set because at least some fields of the header 56*5ffd83dbSDimitry Andric // are read and can be dumped. 57*5ffd83dbSDimitry Andric RecoverableErrorHandler( 58*5ffd83dbSDimitry Andric createStringError(errc::invalid_argument, 59*5ffd83dbSDimitry Andric "name lookup table at offset 0x%" PRIx64 60*5ffd83dbSDimitry Andric " does not have a complete header: %s", 61*5ffd83dbSDimitry Andric SetOffset, toString(C.takeError()).c_str())); 62*5ffd83dbSDimitry Andric continue; 63*5ffd83dbSDimitry Andric } 64*5ffd83dbSDimitry Andric 65*5ffd83dbSDimitry Andric while (C) { 66*5ffd83dbSDimitry Andric uint64_t DieRef = SetData.getUnsigned(C, OffsetSize); 670b57cec5SDimitry Andric if (DieRef == 0) 680b57cec5SDimitry Andric break; 69*5ffd83dbSDimitry Andric uint8_t IndexEntryValue = GnuStyle ? SetData.getU8(C) : 0; 70*5ffd83dbSDimitry Andric StringRef Name = SetData.getCStrRef(C); 71*5ffd83dbSDimitry Andric if (C) 72*5ffd83dbSDimitry Andric NewSet.Entries.push_back( 730b57cec5SDimitry Andric {DieRef, PubIndexEntryDescriptor(IndexEntryValue), Name}); 740b57cec5SDimitry Andric } 75*5ffd83dbSDimitry Andric 76*5ffd83dbSDimitry Andric if (!C) { 77*5ffd83dbSDimitry Andric RecoverableErrorHandler(createStringError( 78*5ffd83dbSDimitry Andric errc::invalid_argument, 79*5ffd83dbSDimitry Andric "name lookup table at offset 0x%" PRIx64 " parsing failed: %s", 80*5ffd83dbSDimitry Andric SetOffset, toString(C.takeError()).c_str())); 81*5ffd83dbSDimitry Andric continue; 82*5ffd83dbSDimitry Andric } 83*5ffd83dbSDimitry Andric if (C.tell() != Offset) 84*5ffd83dbSDimitry Andric RecoverableErrorHandler(createStringError( 85*5ffd83dbSDimitry Andric errc::invalid_argument, 86*5ffd83dbSDimitry Andric "name lookup table at offset 0x%" PRIx64 87*5ffd83dbSDimitry Andric " has a terminator at offset 0x%" PRIx64 88*5ffd83dbSDimitry Andric " before the expected end at 0x%" PRIx64, 89*5ffd83dbSDimitry Andric SetOffset, C.tell() - OffsetSize, Offset - OffsetSize)); 900b57cec5SDimitry Andric } 910b57cec5SDimitry Andric } 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric void DWARFDebugPubTable::dump(raw_ostream &OS) const { 940b57cec5SDimitry Andric for (const Set &S : Sets) { 95*5ffd83dbSDimitry Andric int OffsetDumpWidth = 2 * dwarf::getDwarfOffsetByteSize(S.Format); 96*5ffd83dbSDimitry Andric OS << "length = " << format("0x%0*" PRIx64, OffsetDumpWidth, S.Length); 97*5ffd83dbSDimitry Andric OS << ", format = " << dwarf::FormatString(S.Format); 98*5ffd83dbSDimitry Andric OS << ", version = " << format("0x%04x", S.Version); 99*5ffd83dbSDimitry Andric OS << ", unit_offset = " 100*5ffd83dbSDimitry Andric << format("0x%0*" PRIx64, OffsetDumpWidth, S.Offset); 101*5ffd83dbSDimitry Andric OS << ", unit_size = " << format("0x%0*" PRIx64, OffsetDumpWidth, S.Size) 102*5ffd83dbSDimitry Andric << '\n'; 1030b57cec5SDimitry Andric OS << (GnuStyle ? "Offset Linkage Kind Name\n" 1040b57cec5SDimitry Andric : "Offset Name\n"); 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andric for (const Entry &E : S.Entries) { 107*5ffd83dbSDimitry Andric OS << format("0x%0*" PRIx64 " ", OffsetDumpWidth, E.SecOffset); 1080b57cec5SDimitry Andric if (GnuStyle) { 1090b57cec5SDimitry Andric StringRef EntryLinkage = 1100b57cec5SDimitry Andric GDBIndexEntryLinkageString(E.Descriptor.Linkage); 1110b57cec5SDimitry Andric StringRef EntryKind = dwarf::GDBIndexEntryKindString(E.Descriptor.Kind); 1120b57cec5SDimitry Andric OS << format("%-8s", EntryLinkage.data()) << ' ' 1130b57cec5SDimitry Andric << format("%-8s", EntryKind.data()) << ' '; 1140b57cec5SDimitry Andric } 1150b57cec5SDimitry Andric OS << '\"' << E.Name << "\"\n"; 1160b57cec5SDimitry Andric } 1170b57cec5SDimitry Andric } 1180b57cec5SDimitry Andric } 119