1 //===- DWARFAcceleratorTable.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/ADT/SmallVector.h" 11 #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h" 12 #include "llvm/DebugInfo/DWARF/DWARFContext.h" 13 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" 14 #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" 15 #include "llvm/Support/Dwarf.h" 16 #include "llvm/Support/Compiler.h" 17 #include "llvm/Support/Format.h" 18 #include "llvm/Support/raw_ostream.h" 19 #include <cstddef> 20 #include <cstdint> 21 #include <utility> 22 23 using namespace llvm; 24 25 bool DWARFAcceleratorTable::extract() { 26 uint32_t Offset = 0; 27 28 // Check that we can at least read the header. 29 if (!AccelSection.isValidOffset(offsetof(Header, HeaderDataLength)+4)) 30 return false; 31 32 Hdr.Magic = AccelSection.getU32(&Offset); 33 Hdr.Version = AccelSection.getU16(&Offset); 34 Hdr.HashFunction = AccelSection.getU16(&Offset); 35 Hdr.NumBuckets = AccelSection.getU32(&Offset); 36 Hdr.NumHashes = AccelSection.getU32(&Offset); 37 Hdr.HeaderDataLength = AccelSection.getU32(&Offset); 38 39 // Check that we can read all the hashes and offsets from the 40 // section (see SourceLevelDebugging.rst for the structure of the index). 41 if (!AccelSection.isValidOffset(sizeof(Hdr) + Hdr.HeaderDataLength + 42 Hdr.NumBuckets*4 + Hdr.NumHashes*8)) 43 return false; 44 45 HdrData.DIEOffsetBase = AccelSection.getU32(&Offset); 46 uint32_t NumAtoms = AccelSection.getU32(&Offset); 47 48 for (unsigned i = 0; i < NumAtoms; ++i) { 49 uint16_t AtomType = AccelSection.getU16(&Offset); 50 auto AtomForm = static_cast<dwarf::Form>(AccelSection.getU16(&Offset)); 51 HdrData.Atoms.push_back(std::make_pair(AtomType, AtomForm)); 52 } 53 54 return true; 55 } 56 57 LLVM_DUMP_METHOD void DWARFAcceleratorTable::dump(raw_ostream &OS) const { 58 // Dump the header. 59 OS << "Magic = " << format("0x%08x", Hdr.Magic) << '\n' 60 << "Version = " << format("0x%04x", Hdr.Version) << '\n' 61 << "Hash function = " << format("0x%08x", Hdr.HashFunction) << '\n' 62 << "Bucket count = " << Hdr.NumBuckets << '\n' 63 << "Hashes count = " << Hdr.NumHashes << '\n' 64 << "HeaderData length = " << Hdr.HeaderDataLength << '\n' 65 << "DIE offset base = " << HdrData.DIEOffsetBase << '\n' 66 << "Number of atoms = " << HdrData.Atoms.size() << '\n'; 67 68 unsigned i = 0; 69 SmallVector<DWARFFormValue, 3> AtomForms; 70 for (const auto &Atom: HdrData.Atoms) { 71 OS << format("Atom[%d] Type: ", i++); 72 auto TypeString = dwarf::AtomTypeString(Atom.first); 73 if (!TypeString.empty()) 74 OS << TypeString; 75 else 76 OS << format("DW_ATOM_Unknown_0x%x", Atom.first); 77 OS << " Form: "; 78 auto FormString = dwarf::FormEncodingString(Atom.second); 79 if (!FormString.empty()) 80 OS << FormString; 81 else 82 OS << format("DW_FORM_Unknown_0x%x", Atom.second); 83 OS << '\n'; 84 AtomForms.push_back(DWARFFormValue(Atom.second)); 85 } 86 87 // Now go through the actual tables and dump them. 88 uint32_t Offset = sizeof(Hdr) + Hdr.HeaderDataLength; 89 unsigned HashesBase = Offset + Hdr.NumBuckets * 4; 90 unsigned OffsetsBase = HashesBase + Hdr.NumHashes * 4; 91 92 for (unsigned Bucket = 0; Bucket < Hdr.NumBuckets; ++Bucket) { 93 unsigned Index = AccelSection.getU32(&Offset); 94 95 OS << format("Bucket[%d]\n", Bucket); 96 if (Index == UINT32_MAX) { 97 OS << " EMPTY\n"; 98 continue; 99 } 100 101 for (unsigned HashIdx = Index; HashIdx < Hdr.NumHashes; ++HashIdx) { 102 unsigned HashOffset = HashesBase + HashIdx*4; 103 unsigned OffsetsOffset = OffsetsBase + HashIdx*4; 104 uint32_t Hash = AccelSection.getU32(&HashOffset); 105 106 if (Hash % Hdr.NumBuckets != Bucket) 107 break; 108 109 unsigned DataOffset = AccelSection.getU32(&OffsetsOffset); 110 OS << format(" Hash = 0x%08x Offset = 0x%08x\n", Hash, DataOffset); 111 if (!AccelSection.isValidOffset(DataOffset)) { 112 OS << " Invalid section offset\n"; 113 continue; 114 } 115 while (AccelSection.isValidOffsetForDataOfSize(DataOffset, 4)) { 116 unsigned StringOffset = 117 getRelocatedValue(AccelSection, 4, &DataOffset, &Relocs); 118 if (!StringOffset) 119 break; 120 OS << format(" Name: %08x \"%s\"\n", StringOffset, 121 StringSection.getCStr(&StringOffset)); 122 unsigned NumData = AccelSection.getU32(&DataOffset); 123 for (unsigned Data = 0; Data < NumData; ++Data) { 124 OS << format(" Data[%d] => ", Data); 125 unsigned i = 0; 126 for (auto &Atom : AtomForms) { 127 OS << format("{Atom[%d]: ", i++); 128 if (Atom.extractValue(AccelSection, &DataOffset, nullptr)) 129 Atom.dump(OS); 130 else 131 OS << "Error extracting the value"; 132 OS << "} "; 133 } 134 OS << '\n'; 135 } 136 } 137 } 138 } 139 } 140