Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/DebugInfo/CodeView/RecordName.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- RecordName.cpp ----------------------------------------- *- C++ --*-===//
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/CodeView/RecordName.h"
10
11
#include "llvm/ADT/SmallString.h"
12
#include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
13
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
14
#include "llvm/DebugInfo/CodeView/SymbolRecordMapping.h"
15
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
16
#include "llvm/Support/FormatVariadic.h"
17
18
using namespace llvm;
19
using namespace llvm::codeview;
20
21
namespace {
22
class TypeNameComputer : public TypeVisitorCallbacks {
23
  /// The type collection.  Used to calculate names of nested types.
24
  TypeCollection &Types;
25
  TypeIndex CurrentTypeIndex = TypeIndex::None();
26
27
  /// Name of the current type. Only valid before visitTypeEnd.
28
  SmallString<256> Name;
29
30
public:
31
5.49k
  explicit TypeNameComputer(TypeCollection &Types) : Types(Types) {}
32
33
5.49k
  StringRef name() const { return Name; }
34
35
  /// Paired begin/end actions for all types. Receives all record data,
36
  /// including the fixed-length record prefix.
37
  Error visitTypeBegin(CVType &Record) override;
38
  Error visitTypeBegin(CVType &Record, TypeIndex Index) override;
39
  Error visitTypeEnd(CVType &Record) override;
40
41
#define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
42
  Error visitKnownRecord(CVType &CVR, Name##Record &Record) override;
43
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
44
#define MEMBER_RECORD(EnumName, EnumVal, Name)
45
#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
46
};
47
} // namespace
48
49
0
Error TypeNameComputer::visitTypeBegin(CVType &Record) {
50
0
  llvm_unreachable("Must call visitTypeBegin with a TypeIndex!");
51
0
  return Error::success();
52
0
}
53
54
5.49k
Error TypeNameComputer::visitTypeBegin(CVType &Record, TypeIndex Index) {
55
5.49k
  // Reset Name to the empty string. If the visitor sets it, we know it.
56
5.49k
  Name = "";
57
5.49k
  CurrentTypeIndex = Index;
58
5.49k
  return Error::success();
59
5.49k
}
60
61
5.49k
Error TypeNameComputer::visitTypeEnd(CVType &CVR) { return Error::success(); }
62
63
Error TypeNameComputer::visitKnownRecord(CVType &CVR,
64
601
                                         FieldListRecord &FieldList) {
65
601
  Name = "<field list>";
66
601
  return Error::success();
67
601
}
68
69
Error TypeNameComputer::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
70
770
                                         StringIdRecord &String) {
71
770
  Name = String.getString();
72
770
  return Error::success();
73
770
}
74
75
494
Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArgListRecord &Args) {
76
494
  auto Indices = Args.getIndices();
77
494
  uint32_t Size = Indices.size();
78
494
  Name = "(";
79
1.01k
  for (uint32_t I = 0; I < Size; 
++I517
) {
80
517
    assert(Indices[I] < CurrentTypeIndex);
81
517
82
517
    Name.append(Types.getTypeName(Indices[I]));
83
517
    if (I + 1 != Size)
84
221
      Name.append(", ");
85
517
  }
86
494
  Name.push_back(')');
87
494
  return Error::success();
88
494
}
89
90
Error TypeNameComputer::visitKnownRecord(CVType &CVR,
91
20
                                         StringListRecord &Strings) {
92
20
  auto Indices = Strings.getIndices();
93
20
  uint32_t Size = Indices.size();
94
20
  Name = "\"";
95
41
  for (uint32_t I = 0; I < Size; 
++I21
) {
96
21
    Name.append(Types.getTypeName(Indices[I]));
97
21
    if (I + 1 != Size)
98
1
      Name.append("\" \"");
99
21
  }
100
20
  Name.push_back('\"');
101
20
  return Error::success();
102
20
}
103
104
979
Error TypeNameComputer::visitKnownRecord(CVType &CVR, ClassRecord &Class) {
105
979
  Name = Class.getName();
106
979
  return Error::success();
107
979
}
108
109
57
Error TypeNameComputer::visitKnownRecord(CVType &CVR, UnionRecord &Union) {
110
57
  Name = Union.getName();
111
57
  return Error::success();
112
57
}
113
114
146
Error TypeNameComputer::visitKnownRecord(CVType &CVR, EnumRecord &Enum) {
115
146
  Name = Enum.getName();
116
146
  return Error::success();
117
146
}
118
119
44
Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArrayRecord &AT) {
120
44
  Name = AT.getName();
121
44
  return Error::success();
122
44
}
123
124
4
Error TypeNameComputer::visitKnownRecord(CVType &CVR, VFTableRecord &VFT) {
125
4
  Name = VFT.getName();
126
4
  return Error::success();
127
4
}
128
129
62
Error TypeNameComputer::visitKnownRecord(CVType &CVR, MemberFuncIdRecord &Id) {
130
62
  Name = Id.getName();
131
62
  return Error::success();
132
62
}
133
134
369
Error TypeNameComputer::visitKnownRecord(CVType &CVR, ProcedureRecord &Proc) {
135
369
  StringRef Ret = Types.getTypeName(Proc.getReturnType());
136
369
  StringRef Params = Types.getTypeName(Proc.getArgumentList());
137
369
  Name = formatv("{0} {1}", Ret, Params).sstr<256>();
138
369
  return Error::success();
139
369
}
140
141
Error TypeNameComputer::visitKnownRecord(CVType &CVR,
142
545
                                         MemberFunctionRecord &MF) {
143
545
  StringRef Ret = Types.getTypeName(MF.getReturnType());
144
545
  StringRef Class = Types.getTypeName(MF.getClassType());
145
545
  StringRef Params = Types.getTypeName(MF.getArgumentList());
146
545
  Name = formatv("{0} {1}::{2}", Ret, Class, Params).sstr<256>();
147
545
  return Error::success();
148
545
}
149
150
271
Error TypeNameComputer::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) {
151
271
  Name = Func.getName();
152
271
  return Error::success();
153
271
}
154
155
0
Error TypeNameComputer::visitKnownRecord(CVType &CVR, TypeServer2Record &TS) {
156
0
  Name = TS.getName();
157
0
  return Error::success();
158
0
}
159
160
727
Error TypeNameComputer::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) {
161
727
162
727
  if (Ptr.isPointerToMember()) {
163
31
    const MemberPointerInfo &MI = Ptr.getMemberInfo();
164
31
165
31
    StringRef Pointee = Types.getTypeName(Ptr.getReferentType());
166
31
    StringRef Class = Types.getTypeName(MI.getContainingType());
167
31
    Name = formatv("{0} {1}::*", Pointee, Class);
168
696
  } else {
169
696
    Name.append(Types.getTypeName(Ptr.getReferentType()));
170
696
171
696
    if (Ptr.getMode() == PointerMode::LValueReference)
172
120
      Name.append("&");
173
576
    else if (Ptr.getMode() == PointerMode::RValueReference)
174
9
      Name.append("&&");
175
567
    else if (Ptr.getMode() == PointerMode::Pointer)
176
567
      Name.append("*");
177
696
178
696
    // Qualifiers in pointer records apply to the pointer, not the pointee, so
179
696
    // they go on the right.
180
696
    if (Ptr.isConst())
181
355
      Name.append(" const");
182
696
    if (Ptr.isVolatile())
183
3
      Name.append(" volatile");
184
696
    if (Ptr.isUnaligned())
185
0
      Name.append(" __unaligned");
186
696
    if (Ptr.isRestrict())
187
15
      Name.append(" __restrict");
188
696
  }
189
727
  return Error::success();
190
727
}
191
192
131
Error TypeNameComputer::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) {
193
131
  uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers());
194
131
195
131
  if (Mods & uint16_t(ModifierOptions::Const))
196
121
    Name.append("const ");
197
131
  if (Mods & uint16_t(ModifierOptions::Volatile))
198
18
    Name.append("volatile ");
199
131
  if (Mods & uint16_t(ModifierOptions::Unaligned))
200
2
    Name.append("__unaligned ");
201
131
  Name.append(Types.getTypeName(Mod.getModifiedType()));
202
131
  return Error::success();
203
131
}
204
205
Error TypeNameComputer::visitKnownRecord(CVType &CVR,
206
33
                                         VFTableShapeRecord &Shape) {
207
33
  Name = formatv("<vftable {0} methods>", Shape.getEntryCount());
208
33
  return Error::success();
209
33
}
210
211
Error TypeNameComputer::visitKnownRecord(
212
0
    CVType &CVR, UdtModSourceLineRecord &ModSourceLine) {
213
0
  return Error::success();
214
0
}
215
216
Error TypeNameComputer::visitKnownRecord(CVType &CVR,
217
0
                                         UdtSourceLineRecord &SourceLine) {
218
0
  return Error::success();
219
0
}
220
221
7
Error TypeNameComputer::visitKnownRecord(CVType &CVR, BitFieldRecord &BF) {
222
7
  return Error::success();
223
7
}
224
225
Error TypeNameComputer::visitKnownRecord(CVType &CVR,
226
97
                                         MethodOverloadListRecord &Overloads) {
227
97
  return Error::success();
228
97
}
229
230
139
Error TypeNameComputer::visitKnownRecord(CVType &CVR, BuildInfoRecord &BI) {
231
139
  return Error::success();
232
139
}
233
234
0
Error TypeNameComputer::visitKnownRecord(CVType &CVR, LabelRecord &R) {
235
0
  return Error::success();
236
0
}
237
238
Error TypeNameComputer::visitKnownRecord(CVType &CVR,
239
0
                                         PrecompRecord &Precomp) {
240
0
  return Error::success();
241
0
}
242
243
Error TypeNameComputer::visitKnownRecord(CVType &CVR,
244
0
                                         EndPrecompRecord &EndPrecomp) {
245
0
  return Error::success();
246
0
}
247
248
std::string llvm::codeview::computeTypeName(TypeCollection &Types,
249
5.49k
                                            TypeIndex Index) {
250
5.49k
  TypeNameComputer Computer(Types);
251
5.49k
  CVType Record = Types.getType(Index);
252
5.49k
  if (auto EC = visitTypeRecord(Record, Index, Computer)) {
253
0
    consumeError(std::move(EC));
254
0
    return "<unknown UDT>";
255
0
  }
256
5.49k
  return Computer.name();
257
5.49k
}
258
259
1.23k
static int getSymbolNameOffset(CVSymbol Sym) {
260
1.23k
  switch (Sym.kind()) {
261
1.23k
  // See ProcSym
262
1.23k
  case SymbolKind::S_GPROC32:
263
97
  case SymbolKind::S_LPROC32:
264
97
  case SymbolKind::S_GPROC32_ID:
265
97
  case SymbolKind::S_LPROC32_ID:
266
97
  case SymbolKind::S_LPROC32_DPC:
267
97
  case SymbolKind::S_LPROC32_DPC_ID:
268
97
    return 35;
269
97
  // See Thunk32Sym
270
97
  case SymbolKind::S_THUNK32:
271
0
    return 21;
272
97
  // See SectionSym
273
97
  case SymbolKind::S_SECTION:
274
0
    return 16;
275
97
  // See CoffGroupSym
276
97
  case SymbolKind::S_COFFGROUP:
277
0
    return 14;
278
97
  // See PublicSym32, FileStaticSym, RegRelativeSym, DataSym, ThreadLocalDataSym
279
406
  case SymbolKind::S_PUB32:
280
406
  case SymbolKind::S_FILESTATIC:
281
406
  case SymbolKind::S_REGREL32:
282
406
  case SymbolKind::S_GDATA32:
283
406
  case SymbolKind::S_LDATA32:
284
406
  case SymbolKind::S_LMANDATA:
285
406
  case SymbolKind::S_GMANDATA:
286
406
  case SymbolKind::S_LTHREAD32:
287
406
  case SymbolKind::S_GTHREAD32:
288
406
  case SymbolKind::S_PROCREF:
289
406
  case SymbolKind::S_LPROCREF:
290
406
    return 10;
291
406
  // See RegisterSym and LocalSym
292
406
  case SymbolKind::S_REGISTER:
293
0
  case SymbolKind::S_LOCAL:
294
0
    return 6;
295
0
  // See BlockSym
296
0
  case SymbolKind::S_BLOCK32:
297
0
    return 18;
298
0
  // See LabelSym
299
0
  case SymbolKind::S_LABEL32:
300
0
    return 7;
301
0
  // See ObjNameSym, ExportSym, and UDTSym
302
736
  case SymbolKind::S_OBJNAME:
303
736
  case SymbolKind::S_EXPORT:
304
736
  case SymbolKind::S_UDT:
305
736
    return 4;
306
736
  // See BPRelativeSym
307
736
  case SymbolKind::S_BPREL32:
308
0
    return 8;
309
736
  // See UsingNamespaceSym
310
736
  case SymbolKind::S_UNAMESPACE:
311
0
    return 0;
312
736
  default:
313
0
    return -1;
314
1.23k
  }
315
1.23k
}
316
317
1.24k
StringRef llvm::codeview::getSymbolName(CVSymbol Sym) {
318
1.24k
  if (Sym.kind() == SymbolKind::S_CONSTANT) {
319
3
    // S_CONSTANT is preceded by an APSInt, which has a variable length.  So we
320
3
    // have to do a full deserialization.
321
3
    BinaryStreamReader Reader(Sym.content(), llvm::support::little);
322
3
    // The container doesn't matter for single records.
323
3
    SymbolRecordMapping Mapping(Reader, CodeViewContainer::ObjectFile);
324
3
    ConstantSym Const(SymbolKind::S_CONSTANT);
325
3
    cantFail(Mapping.visitSymbolBegin(Sym));
326
3
    cantFail(Mapping.visitKnownRecord(Sym, Const));
327
3
    cantFail(Mapping.visitSymbolEnd(Sym));
328
3
    return Const.Name;
329
3
  }
330
1.23k
331
1.23k
  int Offset = getSymbolNameOffset(Sym);
332
1.23k
  if (Offset == -1)
333
0
    return StringRef();
334
1.23k
335
1.23k
  StringRef StringData = toStringRef(Sym.content()).drop_front(Offset);
336
1.23k
  return StringData.split('\0').first;
337
1.23k
}