1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 10:42:39 +01:00

[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

llvm-svn: 305933
This commit is contained in:
Reid Kleckner 2017-06-21 17:25:56 +00:00
parent e88badc692
commit d394a5b7a6
3 changed files with 167 additions and 8 deletions

View File

@ -11,6 +11,7 @@
#define LLVM_DEBUGINFO_CODEVIEW_TYPEINDEXDISCOVERY_H
#include "llvm/ADT/SmallVector.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/Support/Error.h"
@ -27,6 +28,11 @@ void discoverTypeIndices(ArrayRef<uint8_t> RecordData,
SmallVectorImpl<TiReference> &Refs);
void discoverTypeIndices(const CVType &Type,
SmallVectorImpl<TiReference> &Refs);
/// Discover type indices in symbol records. Returns false if this is an unknown
/// record.
bool discoverTypeIndices(const CVSymbol &Symbol,
SmallVectorImpl<TiReference> &Refs);
}
}

View File

@ -357,6 +357,82 @@ static void discoverTypeIndices(ArrayRef<uint8_t> Content, TypeLeafKind Kind,
}
}
static bool discoverTypeIndices(ArrayRef<uint8_t> Content, SymbolKind Kind,
SmallVectorImpl<TiReference> &Refs) {
uint32_t Count;
// FIXME: In the future it would be nice if we could avoid hardcoding these
// values. One idea is to define some structures representing these types
// that would allow the use of offsetof().
switch (Kind) {
case SymbolKind::S_GPROC32:
case SymbolKind::S_LPROC32:
case SymbolKind::S_GPROC32_ID:
case SymbolKind::S_LPROC32_ID:
case SymbolKind::S_LPROC32_DPC:
case SymbolKind::S_LPROC32_DPC_ID:
Refs.push_back({TiRefKind::IndexRef, 24, 1}); // LF_FUNC_ID
break;
case SymbolKind::S_UDT:
Refs.push_back({TiRefKind::TypeRef, 0, 1}); // UDT
break;
case SymbolKind::S_GDATA32:
case SymbolKind::S_LDATA32:
Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type
break;
case SymbolKind::S_BUILDINFO:
Refs.push_back({TiRefKind::IndexRef, 0, 1}); // Compile flags
break;
case SymbolKind::S_LOCAL:
Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type
break;
case SymbolKind::S_CONSTANT:
Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type
break;
case SymbolKind::S_REGREL32:
Refs.push_back({TiRefKind::TypeRef, 4, 1}); // Type
break;
case SymbolKind::S_CALLSITEINFO:
Refs.push_back({TiRefKind::TypeRef, 8, 1}); // Call signature
break;
case SymbolKind::S_CALLERS:
case SymbolKind::S_CALLEES:
// The record is a count followed by an array of type indices.
Count = *reinterpret_cast<const ulittle32_t *>(Content.data());
Refs.push_back({TiRefKind::IndexRef, 4, Count}); // Callees
break;
case SymbolKind::S_INLINESITE:
Refs.push_back({TiRefKind::IndexRef, 8, 1}); // ID of inlinee
break;
// Defranges don't have types, just registers and code offsets.
case SymbolKind::S_DEFRANGE_REGISTER:
case SymbolKind::S_DEFRANGE_REGISTER_REL:
case SymbolKind::S_DEFRANGE_FRAMEPOINTER_REL:
case SymbolKind::S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE:
case SymbolKind::S_DEFRANGE_SUBFIELD_REGISTER:
case SymbolKind::S_DEFRANGE_SUBFIELD:
break;
// No type refernces.
case SymbolKind::S_LABEL32:
case SymbolKind::S_OBJNAME:
case SymbolKind::S_COMPILE:
case SymbolKind::S_COMPILE2:
case SymbolKind::S_COMPILE3:
case SymbolKind::S_BLOCK32:
case SymbolKind::S_FRAMEPROC:
break;
// Scope ending symbols.
case SymbolKind::S_END:
case SymbolKind::S_INLINESITE_END:
case SymbolKind::S_PROC_ID_END:
break;
default:
return false; // Unknown symbol.
}
return true;
}
void llvm::codeview::discoverTypeIndices(const CVType &Type,
SmallVectorImpl<TiReference> &Refs) {
::discoverTypeIndices(Type.content(), Type.kind(), Refs);
@ -369,3 +445,9 @@ void llvm::codeview::discoverTypeIndices(ArrayRef<uint8_t> RecordData,
TypeLeafKind K = static_cast<TypeLeafKind>(uint16_t(P->RecordKind));
::discoverTypeIndices(RecordData.drop_front(sizeof(RecordPrefix)), K, Refs);
}
bool llvm::codeview::discoverTypeIndices(const CVSymbol &Sym,
SmallVectorImpl<TiReference> &Refs) {
SymbolKind K = Sym.kind();
return ::discoverTypeIndices(Sym.content(), K, Refs);
}

View File

@ -10,6 +10,7 @@
#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
#include "llvm/DebugInfo/CodeView/SymbolSerializer.h"
#include "llvm/Support/Allocator.h"
#include "gmock/gmock.h"
@ -26,6 +27,7 @@ public:
Refs.clear();
TTB = make_unique<TypeTableBuilder>(Storage);
FLRB = make_unique<FieldListRecordBuilder>(*TTB);
Symbols.clear();
}
void TearDown() override {
@ -37,7 +39,19 @@ protected:
template <typename... Indices>
bool checkTypeReferences(uint32_t RecordIndex, Indices &&... TIs) const {
EXPECT_EQ(sizeof...(Indices), countRefs(RecordIndex));
return checkTypeReferencesImpl(RecordIndex, std::forward<Indices>(TIs)...);
// Choose between type or symbol records. The checking code doesn't care
// which we have.
std::vector<ArrayRef<uint8_t>> CVRecords;
if (Symbols.empty()) {
CVRecords = TTB->records();
} else {
for (const CVSymbol &S : Symbols)
CVRecords.push_back(S.data());
}
return checkTypeReferencesImpl(RecordIndex, CVRecords,
std::forward<Indices>(TIs)...);
}
template <typename... T> void writeFieldList(T &&... MemberRecords) {
@ -54,6 +68,13 @@ protected:
discoverAllTypeIndices();
}
template <typename... T> void writeSymbolRecords(T &&... Records) {
writeSymbolRecordsImpl(std::forward<T>(Records)...);
ASSERT_EQ(sizeof...(T), Symbols.size());
discoverTypeIndicesInSymbols();
}
std::unique_ptr<TypeTableBuilder> TTB;
private:
@ -83,18 +104,20 @@ private:
}
template <typename... Indices>
bool checkTypeReferencesImpl(uint32_t RecordIndex) const {
bool checkTypeReferencesImpl(uint32_t RecordIndex,
ArrayRef<ArrayRef<uint8_t>> CVRecords) const {
return true;
}
template <typename... Indices>
bool checkTypeReferencesImpl(uint32_t RecordIndex, TypeIndex TI,
Indices &&... Rest) const {
ArrayRef<uint8_t> Record = TTB->records()[RecordIndex];
bool checkTypeReferencesImpl(uint32_t RecordIndex,
ArrayRef<ArrayRef<uint8_t>> CVRecords,
TypeIndex TI, Indices &&... Rest) const {
ArrayRef<uint8_t> Record = CVRecords[RecordIndex];
bool Success = checkOneTypeReference(RecordIndex, Record, TI);
EXPECT_TRUE(Success);
return Success &
checkTypeReferencesImpl(RecordIndex, std::forward<Indices>(Rest)...);
return Success & checkTypeReferencesImpl(RecordIndex, CVRecords,
std::forward<Indices>(Rest)...);
}
void discoverAllTypeIndices() {
@ -105,6 +128,12 @@ private:
}
}
void discoverTypeIndicesInSymbols() {
Refs.resize(Symbols.size());
for (uint32_t I = 0; I < Symbols.size(); ++I)
discoverTypeIndices(Symbols[I], Refs[I]);
}
// Helper function to write out a field list record with the given list
// of member records.
void writeFieldListImpl() {}
@ -124,8 +153,19 @@ private:
writeTypeRecordsImpl(std::forward<Rest>(Records)...);
}
// Helper function to write out a list of symbol records.
void writeSymbolRecordsImpl() {}
template <typename RecType, typename... Rest>
void writeSymbolRecordsImpl(RecType &&Record, Rest &&... Records) {
Symbols.push_back(SymbolSerializer::writeOneSymbol(Record, Storage,
CodeViewContainer::Pdb));
writeSymbolRecordsImpl(std::forward<Rest>(Records)...);
}
std::vector<SmallVector<TiReference, 4>> Refs;
std::unique_ptr<FieldListRecordBuilder> FLRB;
std::vector<CVSymbol> Symbols;
BumpPtrAllocator Storage;
};
@ -493,3 +533,34 @@ TEST_F(TypeIndexIteratorTest, ManyMembers) {
StaticDataMember.Type, VirtualBaseClass.BaseType,
VirtualBaseClass.VBPtrType, VFPtr.Type, Continuation.ContinuationIndex);
}
TEST_F(TypeIndexIteratorTest, ProcSym) {
ProcSym GS(SymbolRecordKind::GlobalProcSym);
GS.FunctionType = TypeIndex(0x40);
ProcSym LS(SymbolRecordKind::ProcSym);
LS.FunctionType = TypeIndex(0x41);
writeSymbolRecords(GS, LS);
checkTypeReferences(0, GS.FunctionType);
checkTypeReferences(1, LS.FunctionType);
}
TEST_F(TypeIndexIteratorTest, DataSym) {
DataSym DS(SymbolRecordKind::GlobalData);
DS.Type = TypeIndex(0x40);
writeSymbolRecords(DS);
checkTypeReferences(0, DS.Type);
}
TEST_F(TypeIndexIteratorTest, CallerSym) {
CallerSym Callees(SymbolRecordKind::CalleeSym);
Callees.Indices.push_back(TypeIndex(1));
Callees.Indices.push_back(TypeIndex(2));
Callees.Indices.push_back(TypeIndex(3));
CallerSym Callers(SymbolRecordKind::CallerSym);
Callers.Indices.push_back(TypeIndex(4));
Callers.Indices.push_back(TypeIndex(5));
Callers.Indices.push_back(TypeIndex(6));
writeSymbolRecords(Callees, Callers);
checkTypeReferences(0, TypeIndex(1), TypeIndex(2), TypeIndex(3));
checkTypeReferences(1, TypeIndex(4), TypeIndex(5), TypeIndex(6));
}