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