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