Coverage Report

Created: 2017-10-03 07:32

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