llvm.org GIT mirror llvm / 41428eb
[PDB] Add symbols to the PDB Summary: The main complexity in adding symbol records is that we need to "relocate" all the type indices. Type indices do not have anything like relocations, an opaque data structure describing where to find existing type indices for fixups. The linker just has to "know" where the type references are in the symbol records. I added an overload of `discoverTypeIndices` that works on symbol records, and it seems to be able to link the standard library. Reviewers: zturner, ruiu Subscribers: llvm-commits, hiraditya Differential Revision: https://reviews.llvm.org/D34432 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@305933 91177308-0d34-0410-b5e6-96231b3b80d8 Reid Kleckner 2 years ago
3 changed file(s) with 167 addition(s) and 8 deletion(s). Raw diff Collapse all Expand all
1010 #define LLVM_DEBUGINFO_CODEVIEW_TYPEINDEXDISCOVERY_H
1111
1212 #include "llvm/ADT/SmallVector.h"
13 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
1314 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
1415 #include "llvm/Support/Error.h"
1516
2627 SmallVectorImpl &Refs);
2728 void discoverTypeIndices(const CVType &Type,
2829 SmallVectorImpl &Refs);
30
31 /// Discover type indices in symbol records. Returns false if this is an unknown
32 /// record.
33 bool discoverTypeIndices(const CVSymbol &Symbol,
34 SmallVectorImpl &Refs);
2935 }
3036 }
3137
356356 }
357357 }
358358
359 static bool discoverTypeIndices(ArrayRef Content, SymbolKind Kind,
360 SmallVectorImpl &Refs) {
361 uint32_t Count;
362 // FIXME: In the future it would be nice if we could avoid hardcoding these
363 // values. One idea is to define some structures representing these types
364 // that would allow the use of offsetof().
365 switch (Kind) {
366 case SymbolKind::S_GPROC32:
367 case SymbolKind::S_LPROC32:
368 case SymbolKind::S_GPROC32_ID:
369 case SymbolKind::S_LPROC32_ID:
370 case SymbolKind::S_LPROC32_DPC:
371 case SymbolKind::S_LPROC32_DPC_ID:
372 Refs.push_back({TiRefKind::IndexRef, 24, 1}); // LF_FUNC_ID
373 break;
374 case SymbolKind::S_UDT:
375 Refs.push_back({TiRefKind::TypeRef, 0, 1}); // UDT
376 break;
377 case SymbolKind::S_GDATA32:
378 case SymbolKind::S_LDATA32:
379 Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type
380 break;
381 case SymbolKind::S_BUILDINFO:
382 Refs.push_back({TiRefKind::IndexRef, 0, 1}); // Compile flags
383 break;
384 case SymbolKind::S_LOCAL:
385 Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type
386 break;
387 case SymbolKind::S_CONSTANT:
388 Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type
389 break;
390 case SymbolKind::S_REGREL32:
391 Refs.push_back({TiRefKind::TypeRef, 4, 1}); // Type
392 break;
393 case SymbolKind::S_CALLSITEINFO:
394 Refs.push_back({TiRefKind::TypeRef, 8, 1}); // Call signature
395 break;
396 case SymbolKind::S_CALLERS:
397 case SymbolKind::S_CALLEES:
398 // The record is a count followed by an array of type indices.
399 Count = *reinterpret_cast(Content.data());
400 Refs.push_back({TiRefKind::IndexRef, 4, Count}); // Callees
401 break;
402 case SymbolKind::S_INLINESITE:
403 Refs.push_back({TiRefKind::IndexRef, 8, 1}); // ID of inlinee
404 break;
405
406 // Defranges don't have types, just registers and code offsets.
407 case SymbolKind::S_DEFRANGE_REGISTER:
408 case SymbolKind::S_DEFRANGE_REGISTER_REL:
409 case SymbolKind::S_DEFRANGE_FRAMEPOINTER_REL:
410 case SymbolKind::S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE:
411 case SymbolKind::S_DEFRANGE_SUBFIELD_REGISTER:
412 case SymbolKind::S_DEFRANGE_SUBFIELD:
413 break;
414
415 // No type refernces.
416 case SymbolKind::S_LABEL32:
417 case SymbolKind::S_OBJNAME:
418 case SymbolKind::S_COMPILE:
419 case SymbolKind::S_COMPILE2:
420 case SymbolKind::S_COMPILE3:
421 case SymbolKind::S_BLOCK32:
422 case SymbolKind::S_FRAMEPROC:
423 break;
424 // Scope ending symbols.
425 case SymbolKind::S_END:
426 case SymbolKind::S_INLINESITE_END:
427 case SymbolKind::S_PROC_ID_END:
428 break;
429 default:
430 return false; // Unknown symbol.
431 }
432 return true;
433 }
434
359435 void llvm::codeview::discoverTypeIndices(const CVType &Type,
360436 SmallVectorImpl &Refs) {
361437 ::discoverTypeIndices(Type.content(), Type.kind(), Refs);
368444 TypeLeafKind K = static_cast(uint16_t(P->RecordKind));
369445 ::discoverTypeIndices(RecordData.drop_front(sizeof(RecordPrefix)), K, Refs);
370446 }
447
448 bool llvm::codeview::discoverTypeIndices(const CVSymbol &Sym,
449 SmallVectorImpl &Refs) {
450 SymbolKind K = Sym.kind();
451 return ::discoverTypeIndices(Sym.content(), K, Refs);
452 }
99 #include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
1010
1111 #include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
12 #include "llvm/DebugInfo/CodeView/SymbolSerializer.h"
1213 #include "llvm/Support/Allocator.h"
1314
1415 #include "gmock/gmock.h"
2526 Refs.clear();
2627 TTB = make_unique(Storage);
2728 FLRB = make_unique(*TTB);
29 Symbols.clear();
2830 }
2931
3032 void TearDown() override {
3638 template
3739 bool checkTypeReferences(uint32_t RecordIndex, Indices &&... TIs) const {
3840 EXPECT_EQ(sizeof...(Indices), countRefs(RecordIndex));
39 return checkTypeReferencesImpl(RecordIndex, std::forward(TIs)...);
41
42 // Choose between type or symbol records. The checking code doesn't care
43 // which we have.
44 std::vector> CVRecords;
45 if (Symbols.empty()) {
46 CVRecords = TTB->records();
47 } else {
48 for (const CVSymbol &S : Symbols)
49 CVRecords.push_back(S.data());
50 }
51
52 return checkTypeReferencesImpl(RecordIndex, CVRecords,
53 std::forward(TIs)...);
4054 }
4155
4256 template void writeFieldList(T &&... MemberRecords) {
5266 ASSERT_EQ(sizeof...(T), TTB->records().size());
5367 discoverAllTypeIndices();
5468 }
69
70 template void writeSymbolRecords(T &&... Records) {
71 writeSymbolRecordsImpl(std::forward(Records)...);
72 ASSERT_EQ(sizeof...(T), Symbols.size());
73 discoverTypeIndicesInSymbols();
74 }
75
5576
5677 std::unique_ptr TTB;
5778
82103 }
83104
84105 template
85 bool checkTypeReferencesImpl(uint32_t RecordIndex) const {
106 bool checkTypeReferencesImpl(uint32_t RecordIndex,
107 ArrayRef> CVRecords) const {
86108 return true;
87109 }
88110
89111 template
90 bool checkTypeReferencesImpl(uint32_t RecordIndex, TypeIndex TI,
91 Indices &&... Rest) const {
92 ArrayRef Record = TTB->records()[RecordIndex];
112 bool checkTypeReferencesImpl(uint32_t RecordIndex,
113 ArrayRef> CVRecords,
114 TypeIndex TI, Indices &&... Rest) const {
115 ArrayRef Record = CVRecords[RecordIndex];
93116 bool Success = checkOneTypeReference(RecordIndex, Record, TI);
94117 EXPECT_TRUE(Success);
95 return Success &
96 checkTypeReferencesImpl(RecordIndex, std::forward(Rest)...);
118 return Success & checkTypeReferencesImpl(RecordIndex, CVRecords,
119 std::forward(Rest)...);
97120 }
98121
99122 void discoverAllTypeIndices() {
104127 }
105128 }
106129
130 void discoverTypeIndicesInSymbols() {
131 Refs.resize(Symbols.size());
132 for (uint32_t I = 0; I < Symbols.size(); ++I)
133 discoverTypeIndices(Symbols[I], Refs[I]);
134 }
135
107136 // Helper function to write out a field list record with the given list
108137 // of member records.
109138 void writeFieldListImpl() {}
123152 writeTypeRecordsImpl(std::forward(Records)...);
124153 }
125154
155 // Helper function to write out a list of symbol records.
156 void writeSymbolRecordsImpl() {}
157
158 template
159 void writeSymbolRecordsImpl(RecType &&Record, Rest &&... Records) {
160 Symbols.push_back(SymbolSerializer::writeOneSymbol(Record, Storage,
161 CodeViewContainer::Pdb));
162 writeSymbolRecordsImpl(std::forward(Records)...);
163 }
164
126165 std::vector> Refs;
127166 std::unique_ptr FLRB;
167 std::vector Symbols;
128168 BumpPtrAllocator Storage;
129169 };
130170
491531 OneMethod.T1, OneMethod.T2, OneMethod.T3, OneMethod.T4, NestedType.Type,
492532 StaticDataMember.Type, VirtualBaseClass.BaseType,
493533 VirtualBaseClass.VBPtrType, VFPtr.Type, Continuation.ContinuationIndex);
494 }
534 }
535
536 TEST_F(TypeIndexIteratorTest, ProcSym) {
537 ProcSym GS(SymbolRecordKind::GlobalProcSym);
538 GS.FunctionType = TypeIndex(0x40);
539 ProcSym LS(SymbolRecordKind::ProcSym);
540 LS.FunctionType = TypeIndex(0x41);
541 writeSymbolRecords(GS, LS);
542 checkTypeReferences(0, GS.FunctionType);
543 checkTypeReferences(1, LS.FunctionType);
544 }
545
546 TEST_F(TypeIndexIteratorTest, DataSym) {
547 DataSym DS(SymbolRecordKind::GlobalData);
548 DS.Type = TypeIndex(0x40);
549 writeSymbolRecords(DS);
550 checkTypeReferences(0, DS.Type);
551 }
552
553 TEST_F(TypeIndexIteratorTest, CallerSym) {
554 CallerSym Callees(SymbolRecordKind::CalleeSym);
555 Callees.Indices.push_back(TypeIndex(1));
556 Callees.Indices.push_back(TypeIndex(2));
557 Callees.Indices.push_back(TypeIndex(3));
558 CallerSym Callers(SymbolRecordKind::CallerSym);
559 Callers.Indices.push_back(TypeIndex(4));
560 Callers.Indices.push_back(TypeIndex(5));
561 Callers.Indices.push_back(TypeIndex(6));
562 writeSymbolRecords(Callees, Callers);
563 checkTypeReferences(0, TypeIndex(1), TypeIndex(2), TypeIndex(3));
564 checkTypeReferences(1, TypeIndex(4), TypeIndex(5), TypeIndex(6));
565 }