aboutsummaryrefslogtreecommitdiffstats
path: root/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
blob: 8ae05432869a23e10d3e73ee6e7237f8a041ae7d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
//===--- DWARFAcceleratorTable.cpp ----------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"

namespace llvm {

bool DWARFAcceleratorTable::extract() {
  uint32_t Offset = 0;

  // Check that we can at least read the header.
  if (!AccelSection.isValidOffset(offsetof(Header, HeaderDataLength)+4))
    return false;

  Hdr.Magic = AccelSection.getU32(&Offset);
  Hdr.Version = AccelSection.getU16(&Offset);
  Hdr.HashFunction = AccelSection.getU16(&Offset);
  Hdr.NumBuckets = AccelSection.getU32(&Offset);
  Hdr.NumHashes = AccelSection.getU32(&Offset);
  Hdr.HeaderDataLength = AccelSection.getU32(&Offset);

  // Check that we can read all the hashes and offsets from the
  // section (see SourceLevelDebugging.rst for the structure of the index).
  if (!AccelSection.isValidOffset(sizeof(Hdr) + Hdr.HeaderDataLength +
                                  Hdr.NumBuckets*4 + Hdr.NumHashes*8))
    return false;

  HdrData.DIEOffsetBase = AccelSection.getU32(&Offset);
  uint32_t NumAtoms = AccelSection.getU32(&Offset);

  for (unsigned i = 0; i < NumAtoms; ++i) {
    uint16_t AtomType = AccelSection.getU16(&Offset);
    uint16_t AtomForm = AccelSection.getU16(&Offset);
    HdrData.Atoms.push_back(std::make_pair(AtomType, AtomForm));
  }

  return true;
}

void DWARFAcceleratorTable::dump(raw_ostream &OS) const {
  // Dump the header.
  OS << "Magic = " << format("0x%08x", Hdr.Magic) << '\n'
     << "Version = " << format("0x%04x", Hdr.Version) << '\n'
     << "Hash function = " << format("0x%08x", Hdr.HashFunction) << '\n'
     << "Bucket count = " << Hdr.NumBuckets << '\n'
     << "Hashes count = " << Hdr.NumHashes << '\n'
     << "HeaderData length = " << Hdr.HeaderDataLength << '\n'
     << "DIE offset base = " << HdrData.DIEOffsetBase << '\n'
     << "Number of atoms = " << HdrData.Atoms.size() << '\n';

  unsigned i = 0;
  SmallVector<DWARFFormValue, 3> AtomForms;
  for (const auto &Atom: HdrData.Atoms) {
    OS << format("Atom[%d] Type: ", i++);
    if (const char *TypeString = dwarf::AtomTypeString(Atom.first))
      OS << TypeString;
    else
      OS << format("DW_ATOM_Unknown_0x%x", Atom.first);
    OS << " Form: ";
    if (const char *FormString = dwarf::FormEncodingString(Atom.second))
      OS << FormString;
    else
      OS << format("DW_FORM_Unknown_0x%x", Atom.second);
    OS << '\n';
    AtomForms.push_back(DWARFFormValue(Atom.second));
  }

  // Now go through the actual tables and dump them.
  uint32_t Offset = sizeof(Hdr) + Hdr.HeaderDataLength;
  unsigned HashesBase = Offset + Hdr.NumBuckets * 4;
  unsigned OffsetsBase = HashesBase + Hdr.NumHashes * 4;

  for (unsigned Bucket = 0; Bucket < Hdr.NumBuckets; ++Bucket) {
    unsigned Index = AccelSection.getU32(&Offset);

    OS << format("Bucket[%d]\n", Bucket);
    if (Index == UINT32_MAX) {
      OS << "  EMPTY\n";
      continue;
    }

    for (unsigned HashIdx = Index; HashIdx < Hdr.NumHashes; ++HashIdx) {
      unsigned HashOffset = HashesBase + HashIdx*4;
      unsigned OffsetsOffset = OffsetsBase + HashIdx*4;
      uint32_t Hash = AccelSection.getU32(&HashOffset);

      if (Hash % Hdr.NumBuckets != Bucket)
        break;

      unsigned DataOffset = AccelSection.getU32(&OffsetsOffset);
      OS << format("  Hash = 0x%08x Offset = 0x%08x\n", Hash, DataOffset);
      if (!AccelSection.isValidOffset(DataOffset)) {
        OS << "    Invalid section offset\n";
        continue;
      }
      while (AccelSection.isValidOffsetForDataOfSize(DataOffset, 4)) {
        unsigned StringOffset = AccelSection.getU32(&DataOffset);
        RelocAddrMap::const_iterator Reloc = Relocs.find(DataOffset-4);
        if (Reloc != Relocs.end())
          StringOffset += Reloc->second.second;
        if (!StringOffset)
          break;
        OS << format("    Name: %08x \"%s\"\n", StringOffset,
                     StringSection.getCStr(&StringOffset));
        unsigned NumData = AccelSection.getU32(&DataOffset);
        for (unsigned Data = 0; Data < NumData; ++Data) {
          OS << format("    Data[%d] => ", Data);
          unsigned i = 0;
          for (auto &Atom : AtomForms) {
            OS << format("{Atom[%d]: ", i++);
            if (Atom.extractValue(AccelSection, &DataOffset, nullptr))
              Atom.dump(OS, nullptr);
            else
              OS << "Error extracting the value";
            OS << "} ";
          }
          OS << '\n';
        }
      }
    }
  }
}
}