Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- DWARFUnitIndex.cpp -------------------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
10
#include "llvm/ADT/STLExtras.h"
11
#include "llvm/ADT/StringRef.h"
12
#include "llvm/Support/ErrorHandling.h"
13
#include "llvm/Support/Format.h"
14
#include "llvm/Support/raw_ostream.h"
15
#include <cinttypes>
16
#include <cstdint>
17
18
using namespace llvm;
19
20
bool DWARFUnitIndex::Header::parse(DataExtractor IndexData,
21
77
                                   uint32_t *OffsetPtr) {
22
77
  if (!IndexData.isValidOffsetForDataOfSize(*OffsetPtr, 16))
23
50
    return false;
24
27
  Version = IndexData.getU32(OffsetPtr);
25
27
  NumColumns = IndexData.getU32(OffsetPtr);
26
27
  NumUnits = IndexData.getU32(OffsetPtr);
27
27
  NumBuckets = IndexData.getU32(OffsetPtr);
28
27
  return Version <= 2;
29
27
}
30
31
17
void DWARFUnitIndex::Header::dump(raw_ostream &OS) const {
32
17
  OS << format("version = %u slots = %u\n\n", Version, NumBuckets);
33
17
}
34
35
77
bool DWARFUnitIndex::parse(DataExtractor IndexData) {
36
77
  bool b = parseImpl(IndexData);
37
77
  if (!b) {
38
50
    // Make sure we don't try to dump anything
39
50
    Header.NumBuckets = 0;
40
50
    // Release any partially initialized data.
41
50
    ColumnKinds.reset();
42
50
    Rows.reset();
43
50
  }
44
77
  return b;
45
77
}
46
47
77
bool DWARFUnitIndex::parseImpl(DataExtractor IndexData) {
48
77
  uint32_t Offset = 0;
49
77
  if (!Header.parse(IndexData, &Offset))
50
50
    return false;
51
27
52
27
  if (!IndexData.isValidOffsetForDataOfSize(
53
27
          Offset, Header.NumBuckets * (8 + 4) +
54
27
                      (2 * Header.NumUnits + 1) * 4 * Header.NumColumns))
55
0
    return false;
56
27
57
27
  Rows = llvm::make_unique<Entry[]>(Header.NumBuckets);
58
27
  auto Contribs =
59
27
      llvm::make_unique<Entry::SectionContribution *[]>(Header.NumUnits);
60
27
  ColumnKinds = llvm::make_unique<DWARFSectionKind[]>(Header.NumColumns);
61
27
62
27
  // Read Hash Table of Signatures
63
162
  for (unsigned i = 0; i != Header.NumBuckets; 
++i135
)
64
135
    Rows[i].Signature = IndexData.getU64(&Offset);
65
27
66
27
  // Read Parallel Table of Indexes
67
162
  for (unsigned i = 0; i != Header.NumBuckets; 
++i135
) {
68
135
    auto Index = IndexData.getU32(&Offset);
69
135
    if (!Index)
70
79
      continue;
71
56
    Rows[i].Index = this;
72
56
    Rows[i].Contributions =
73
56
        llvm::make_unique<Entry::SectionContribution[]>(Header.NumColumns);
74
56
    Contribs[Index - 1] = Rows[i].Contributions.get();
75
56
  }
76
27
77
27
  // Read the Column Headers
78
131
  for (unsigned i = 0; i != Header.NumColumns; 
++i104
) {
79
104
    ColumnKinds[i] = static_cast<DWARFSectionKind>(IndexData.getU32(&Offset));
80
104
    if (ColumnKinds[i] == InfoColumnKind) {
81
27
      if (InfoColumn != -1)
82
0
        return false;
83
27
      InfoColumn = i;
84
27
    }
85
104
  }
86
27
87
27
  if (InfoColumn == -1)
88
0
    return false;
89
27
90
27
  // Read Table of Section Offsets
91
83
  
for (unsigned i = 0; 27
i != Header.NumUnits;
++i56
) {
92
56
    auto *Contrib = Contribs[i];
93
272
    for (unsigned i = 0; i != Header.NumColumns; 
++i216
)
94
216
      Contrib[i].Offset = IndexData.getU32(&Offset);
95
56
  }
96
27
97
27
  // Read Table of Section Sizes
98
83
  for (unsigned i = 0; i != Header.NumUnits; 
++i56
) {
99
56
    auto *Contrib = Contribs[i];
100
272
    for (unsigned i = 0; i != Header.NumColumns; 
++i216
)
101
216
      Contrib[i].Length = IndexData.getU32(&Offset);
102
56
  }
103
27
104
27
  return true;
105
27
}
106
107
64
StringRef DWARFUnitIndex::getColumnHeader(DWARFSectionKind DS) {
108
64
#define CASE(DS)                                                               \
109
64
  case DW_SECT_##DS:                                                           \
110
64
    return #DS;
111
64
  switch (DS) {
112
64
    
CASE11
(INFO);
113
6
    CASE
(TYPES)0
;
114
17
    CASE
(ABBREV)0
;
115
14
    CASE
(LINE)0
;
116
1
    CASE
(LOC)0
;
117
15
    CASE
(STR_OFFSETS)0
;
118
0
    CASE(MACINFO);
119
0
    CASE(MACRO);
120
64
  }
121
64
  
llvm_unreachable0
("unknown DWARFSectionKind");
122
64
}
123
124
17
void DWARFUnitIndex::dump(raw_ostream &OS) const {
125
17
  if (!*this)
126
0
    return;
127
17
128
17
  Header.dump(OS);
129
17
  OS << "Index Signature         ";
130
81
  for (unsigned i = 0; i != Header.NumColumns; 
++i64
)
131
64
    OS << ' ' << left_justify(getColumnHeader(ColumnKinds[i]), 24);
132
17
  OS << "\n----- ------------------";
133
81
  for (unsigned i = 0; i != Header.NumColumns; 
++i64
)
134
64
    OS << " ------------------------";
135
17
  OS << '\n';
136
118
  for (unsigned i = 0; i != Header.NumBuckets; 
++i101
) {
137
101
    auto &Row = Rows[i];
138
101
    if (auto *Contribs = Row.Contributions.get()) {
139
39
      OS << format("%5u 0x%016" PRIx64 " ", i + 1, Row.Signature);
140
187
      for (unsigned i = 0; i != Header.NumColumns; 
++i148
) {
141
148
        auto &Contrib = Contribs[i];
142
148
        OS << format("[0x%08x, 0x%08x) ", Contrib.Offset,
143
148
                     Contrib.Offset + Contrib.Length);
144
148
      }
145
39
      OS << '\n';
146
39
    }
147
101
  }
148
17
}
149
150
const DWARFUnitIndex::Entry::SectionContribution *
151
166
DWARFUnitIndex::Entry::getOffset(DWARFSectionKind Sec) const {
152
166
  uint32_t i = 0;
153
537
  for (; i != Index->Header.NumColumns; 
++i371
)
154
496
    if (Index->ColumnKinds[i] == Sec)
155
125
      return &Contributions[i];
156
166
  
return nullptr41
;
157
166
}
158
159
const DWARFUnitIndex::Entry::SectionContribution *
160
40
DWARFUnitIndex::Entry::getOffset() const {
161
40
  return &Contributions[Index->InfoColumn];
162
40
}
163
164
const DWARFUnitIndex::Entry *
165
105
DWARFUnitIndex::getFromOffset(uint32_t Offset) const {
166
105
  if (OffsetLookup.empty()) {
167
184
    for (uint32_t i = 0; i != Header.NumBuckets; 
++i101
)
168
101
      if (Rows[i].Contributions)
169
39
        OffsetLookup.push_back(&Rows[i]);
170
83
    llvm::sort(OffsetLookup, [&](Entry *E1, Entry *E2) {
171
29
      return E1->Contributions[InfoColumn].Offset <
172
29
             E2->Contributions[InfoColumn].Offset;
173
29
    });
174
83
  }
175
105
  auto I = partition_point(OffsetLookup, [&](Entry *E2) {
176
69
    return E2->Contributions[InfoColumn].Offset <= Offset;
177
69
  });
178
105
  if (I == OffsetLookup.begin())
179
66
    return nullptr;
180
39
  --I;
181
39
  const auto *E = *I;
182
39
  const auto &InfoContrib = E->Contributions[InfoColumn];
183
39
  if ((InfoContrib.Offset + InfoContrib.Length) <= Offset)
184
0
    return nullptr;
185
39
  return E;
186
39
}
187
188
1
const DWARFUnitIndex::Entry *DWARFUnitIndex::getFromHash(uint64_t S) const {
189
1
  uint64_t Mask = Header.NumBuckets - 1;
190
1
191
1
  auto H = S & Mask;
192
1
  auto HP = ((S >> 32) & Mask) | 1;
193
1
  while (Rows[H].getSignature() != S && 
Rows[H].getSignature() != 00
)
194
0
    H = (H + HP) & Mask;
195
1
196
1
  if (Rows[H].getSignature() != S)
197
0
    return nullptr;
198
1
199
1
  return &Rows[H];
200
1
}