mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
[PDB] Fix linking of function symbols and local variables.
The compiler outputs PROC32_ID symbols into the object files for functions, and these symbols have an embedded type index which, when copied to the PDB, refer to the IPI stream. However, the symbols themselves are also converted into regular symbols (e.g. S_GPROC32_ID -> S_GPROC32), and type indices in the regular symbol records refer to the TPI stream. So this patch applies two fixes to function records. 1. It converts ID symbols to the proper non-ID record type. 2. After remapping the type index from the object file's index space to the PDB file/IPI stream's index space, it then remaps that index to the TPI stream's index space by. Besides functions, during the remapping process we were also discarding symbol record types which we did not recognize. In particular, we were discarding S_BPREL32 records, which is what MSVC uses to describe local variables on the stack. So this patch fixes that as well by copying them to the PDB. Differential Revision: https://reviews.llvm.org/D36426 llvm-svn: 310394
This commit is contained in:
parent
7e72c09914
commit
ae9d9f3bb3
@ -52,6 +52,21 @@ public:
|
|||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static Expected<T> deserializeAs(ArrayRef<uint8_t> Data) {
|
||||||
|
CVType CVT;
|
||||||
|
CVT.RecordData = Data;
|
||||||
|
MappingInfo I(CVT.content());
|
||||||
|
const RecordPrefix *Prefix =
|
||||||
|
reinterpret_cast<const RecordPrefix *>(Data.data());
|
||||||
|
TypeRecordKind K =
|
||||||
|
static_cast<TypeRecordKind>(uint16_t(Prefix->RecordKind));
|
||||||
|
T Record(K);
|
||||||
|
if (auto EC = deserializeAs<T>(CVT, Record))
|
||||||
|
return std::move(EC);
|
||||||
|
return Record;
|
||||||
|
}
|
||||||
|
|
||||||
Error visitTypeBegin(CVType &Record) override {
|
Error visitTypeBegin(CVType &Record) override {
|
||||||
assert(!Mapping && "Already in a type mapping!");
|
assert(!Mapping && "Already in a type mapping!");
|
||||||
Mapping = llvm::make_unique<MappingInfo>(Record.content());
|
Mapping = llvm::make_unique<MappingInfo>(Record.content());
|
||||||
|
@ -30,11 +30,17 @@ void discoverTypeIndices(const CVType &Type,
|
|||||||
SmallVectorImpl<TiReference> &Refs);
|
SmallVectorImpl<TiReference> &Refs);
|
||||||
void discoverTypeIndices(const CVType &Type,
|
void discoverTypeIndices(const CVType &Type,
|
||||||
SmallVectorImpl<TypeIndex> &Indices);
|
SmallVectorImpl<TypeIndex> &Indices);
|
||||||
|
void discoverTypeIndices(ArrayRef<uint8_t> RecordData,
|
||||||
|
SmallVectorImpl<TypeIndex> &Indices);
|
||||||
|
|
||||||
/// Discover type indices in symbol records. Returns false if this is an unknown
|
/// Discover type indices in symbol records. Returns false if this is an unknown
|
||||||
/// record.
|
/// record.
|
||||||
bool discoverTypeIndices(const CVSymbol &Symbol,
|
bool discoverTypeIndicesInSymbol(const CVSymbol &Symbol,
|
||||||
SmallVectorImpl<TiReference> &Refs);
|
SmallVectorImpl<TiReference> &Refs);
|
||||||
|
bool discoverTypeIndicesInSymbol(ArrayRef<uint8_t> RecordData,
|
||||||
|
SmallVectorImpl<TiReference> &Refs);
|
||||||
|
bool discoverTypeIndicesInSymbol(ArrayRef<uint8_t> RecordData,
|
||||||
|
SmallVectorImpl<TypeIndex> &Indices);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,6 +395,7 @@ static bool discoverTypeIndices(ArrayRef<uint8_t> Content, SymbolKind Kind,
|
|||||||
case SymbolKind::S_CONSTANT:
|
case SymbolKind::S_CONSTANT:
|
||||||
Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type
|
Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type
|
||||||
break;
|
break;
|
||||||
|
case SymbolKind::S_BPREL32:
|
||||||
case SymbolKind::S_REGREL32:
|
case SymbolKind::S_REGREL32:
|
||||||
Refs.push_back({TiRefKind::TypeRef, 4, 1}); // Type
|
Refs.push_back({TiRefKind::TypeRef, 4, 1}); // Type
|
||||||
break;
|
break;
|
||||||
@ -450,17 +451,17 @@ void llvm::codeview::discoverTypeIndices(const CVType &Type,
|
|||||||
::discoverTypeIndices(Type.content(), Type.kind(), Refs);
|
::discoverTypeIndices(Type.content(), Type.kind(), Refs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void llvm::codeview::discoverTypeIndices(const CVType &Type,
|
static void resolveTypeIndexReferences(ArrayRef<uint8_t> RecordData,
|
||||||
SmallVectorImpl<TypeIndex> &Indices) {
|
ArrayRef<TiReference> Refs,
|
||||||
|
SmallVectorImpl<TypeIndex> &Indices) {
|
||||||
Indices.clear();
|
Indices.clear();
|
||||||
|
|
||||||
SmallVector<TiReference, 4> Refs;
|
|
||||||
discoverTypeIndices(Type, Refs);
|
|
||||||
if (Refs.empty())
|
if (Refs.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
BinaryStreamReader Reader(Type.content(), support::little);
|
RecordData = RecordData.drop_front(sizeof(RecordPrefix));
|
||||||
|
|
||||||
|
BinaryStreamReader Reader(RecordData, support::little);
|
||||||
for (const auto &Ref : Refs) {
|
for (const auto &Ref : Refs) {
|
||||||
Reader.setOffset(Ref.Offset);
|
Reader.setOffset(Ref.Offset);
|
||||||
FixedStreamArray<TypeIndex> Run;
|
FixedStreamArray<TypeIndex> Run;
|
||||||
@ -469,6 +470,18 @@ void llvm::codeview::discoverTypeIndices(const CVType &Type,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void llvm::codeview::discoverTypeIndices(const CVType &Type,
|
||||||
|
SmallVectorImpl<TypeIndex> &Indices) {
|
||||||
|
return discoverTypeIndices(Type.RecordData, Indices);
|
||||||
|
}
|
||||||
|
|
||||||
|
void llvm::codeview::discoverTypeIndices(ArrayRef<uint8_t> RecordData,
|
||||||
|
SmallVectorImpl<TypeIndex> &Indices) {
|
||||||
|
SmallVector<TiReference, 4> Refs;
|
||||||
|
discoverTypeIndices(RecordData, Refs);
|
||||||
|
resolveTypeIndexReferences(RecordData, Refs, Indices);
|
||||||
|
}
|
||||||
|
|
||||||
void llvm::codeview::discoverTypeIndices(ArrayRef<uint8_t> RecordData,
|
void llvm::codeview::discoverTypeIndices(ArrayRef<uint8_t> RecordData,
|
||||||
SmallVectorImpl<TiReference> &Refs) {
|
SmallVectorImpl<TiReference> &Refs) {
|
||||||
const RecordPrefix *P =
|
const RecordPrefix *P =
|
||||||
@ -477,8 +490,26 @@ void llvm::codeview::discoverTypeIndices(ArrayRef<uint8_t> RecordData,
|
|||||||
::discoverTypeIndices(RecordData.drop_front(sizeof(RecordPrefix)), K, Refs);
|
::discoverTypeIndices(RecordData.drop_front(sizeof(RecordPrefix)), K, Refs);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool llvm::codeview::discoverTypeIndices(const CVSymbol &Sym,
|
bool llvm::codeview::discoverTypeIndicesInSymbol(
|
||||||
SmallVectorImpl<TiReference> &Refs) {
|
const CVSymbol &Sym, SmallVectorImpl<TiReference> &Refs) {
|
||||||
SymbolKind K = Sym.kind();
|
SymbolKind K = Sym.kind();
|
||||||
return ::discoverTypeIndices(Sym.content(), K, Refs);
|
return ::discoverTypeIndices(Sym.content(), K, Refs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool llvm::codeview::discoverTypeIndicesInSymbol(
|
||||||
|
ArrayRef<uint8_t> RecordData, SmallVectorImpl<TiReference> &Refs) {
|
||||||
|
const RecordPrefix *P =
|
||||||
|
reinterpret_cast<const RecordPrefix *>(RecordData.data());
|
||||||
|
SymbolKind K = static_cast<SymbolKind>(uint16_t(P->RecordKind));
|
||||||
|
return ::discoverTypeIndices(RecordData.drop_front(sizeof(RecordPrefix)), K,
|
||||||
|
Refs);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool llvm::codeview::discoverTypeIndicesInSymbol(
|
||||||
|
ArrayRef<uint8_t> RecordData, SmallVectorImpl<TypeIndex> &Indices) {
|
||||||
|
SmallVector<TiReference, 2> Refs;
|
||||||
|
if (!discoverTypeIndicesInSymbol(RecordData, Refs))
|
||||||
|
return false;
|
||||||
|
resolveTypeIndexReferences(RecordData, Refs, Indices);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@ -837,6 +837,7 @@ Error DumpOutputStyle::dumpModuleSyms() {
|
|||||||
|
|
||||||
ExitOnError Err("Unexpected error processing symbols: ");
|
ExitOnError Err("Unexpected error processing symbols: ");
|
||||||
|
|
||||||
|
auto &Ids = Err(initializeTypes(StreamIPI));
|
||||||
auto &Types = Err(initializeTypes(StreamTPI));
|
auto &Types = Err(initializeTypes(StreamTPI));
|
||||||
|
|
||||||
iterateModules(
|
iterateModules(
|
||||||
@ -852,7 +853,8 @@ Error DumpOutputStyle::dumpModuleSyms() {
|
|||||||
|
|
||||||
SymbolVisitorCallbackPipeline Pipeline;
|
SymbolVisitorCallbackPipeline Pipeline;
|
||||||
SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
|
SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
|
||||||
MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, Types);
|
MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, Ids,
|
||||||
|
Types);
|
||||||
|
|
||||||
Pipeline.addCallbackToPipeline(Deserializer);
|
Pipeline.addCallbackToPipeline(Deserializer);
|
||||||
Pipeline.addCallbackToPipeline(Dumper);
|
Pipeline.addCallbackToPipeline(Dumper);
|
||||||
@ -936,9 +938,13 @@ Error DumpOutputStyle::dumpSymbolsFromGSI(const GSIHashTable &Table,
|
|||||||
auto ExpectedTypes = initializeTypes(StreamTPI);
|
auto ExpectedTypes = initializeTypes(StreamTPI);
|
||||||
if (!ExpectedTypes)
|
if (!ExpectedTypes)
|
||||||
return ExpectedTypes.takeError();
|
return ExpectedTypes.takeError();
|
||||||
|
auto ExpectedIds = initializeTypes(StreamIPI);
|
||||||
|
if (!ExpectedIds)
|
||||||
|
return ExpectedIds.takeError();
|
||||||
SymbolVisitorCallbackPipeline Pipeline;
|
SymbolVisitorCallbackPipeline Pipeline;
|
||||||
SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
|
SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
|
||||||
MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, *ExpectedTypes);
|
MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, *ExpectedIds,
|
||||||
|
*ExpectedTypes);
|
||||||
|
|
||||||
Pipeline.addCallbackToPipeline(Deserializer);
|
Pipeline.addCallbackToPipeline(Deserializer);
|
||||||
Pipeline.addCallbackToPipeline(Dumper);
|
Pipeline.addCallbackToPipeline(Dumper);
|
||||||
|
@ -389,10 +389,12 @@ Error MinimalSymbolDumper::visitSymbolEnd(CVSymbol &Record) {
|
|||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string MinimalSymbolDumper::typeIndex(TypeIndex TI) const {
|
std::string MinimalSymbolDumper::typeOrIdIndex(codeview::TypeIndex TI,
|
||||||
|
bool IsType) const {
|
||||||
if (TI.isSimple())
|
if (TI.isSimple())
|
||||||
return formatv("{0}", TI).str();
|
return formatv("{0}", TI).str();
|
||||||
StringRef Name = Types.getTypeName(TI);
|
auto &Container = IsType ? Types : Ids;
|
||||||
|
StringRef Name = Container.getTypeName(TI);
|
||||||
if (Name.size() > 32) {
|
if (Name.size() > 32) {
|
||||||
Name = Name.take_front(32);
|
Name = Name.take_front(32);
|
||||||
return formatv("{0} ({1}...)", TI, Name);
|
return formatv("{0} ({1}...)", TI, Name);
|
||||||
@ -400,6 +402,14 @@ std::string MinimalSymbolDumper::typeIndex(TypeIndex TI) const {
|
|||||||
return formatv("{0} ({1})", TI, Name);
|
return formatv("{0} ({1})", TI, Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string MinimalSymbolDumper::idIndex(codeview::TypeIndex TI) const {
|
||||||
|
return typeOrIdIndex(TI, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string MinimalSymbolDumper::typeIndex(TypeIndex TI) const {
|
||||||
|
return typeOrIdIndex(TI, true);
|
||||||
|
}
|
||||||
|
|
||||||
Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, BlockSym &Block) {
|
Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, BlockSym &Block) {
|
||||||
P.format(" `{0}`", Block.Name);
|
P.format(" `{0}`", Block.Name);
|
||||||
AutoIndent Indent(P, 7);
|
AutoIndent Indent(P, 7);
|
||||||
@ -727,9 +737,19 @@ Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, ProcSym &Proc) {
|
|||||||
Proc.Parent, Proc.End,
|
Proc.Parent, Proc.End,
|
||||||
formatSegmentOffset(Proc.Segment, Proc.CodeOffset),
|
formatSegmentOffset(Proc.Segment, Proc.CodeOffset),
|
||||||
Proc.CodeSize);
|
Proc.CodeSize);
|
||||||
// FIXME: It seems FunctionType is sometimes an id and sometimes a type.
|
bool IsType = true;
|
||||||
|
switch (Proc.getKind()) {
|
||||||
|
case SymbolRecordKind::GlobalProcIdSym:
|
||||||
|
case SymbolRecordKind::ProcIdSym:
|
||||||
|
case SymbolRecordKind::DPCProcIdSym:
|
||||||
|
IsType = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
P.formatLine("type = `{0}`, debug start = {1}, debug end = {2}, flags = {3}",
|
P.formatLine("type = `{0}`, debug start = {1}, debug end = {2}, flags = {3}",
|
||||||
typeIndex(Proc.FunctionType), Proc.DbgStart, Proc.DbgEnd,
|
typeOrIdIndex(Proc.FunctionType, IsType), Proc.DbgStart,
|
||||||
|
Proc.DbgEnd,
|
||||||
formatProcSymFlags(P.getIndentLevel() + 9, Proc.Flags));
|
formatProcSymFlags(P.getIndentLevel() + 9, Proc.Flags));
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
@ -23,8 +23,9 @@ class LinePrinter;
|
|||||||
class MinimalSymbolDumper : public codeview::SymbolVisitorCallbacks {
|
class MinimalSymbolDumper : public codeview::SymbolVisitorCallbacks {
|
||||||
public:
|
public:
|
||||||
MinimalSymbolDumper(LinePrinter &P, bool RecordBytes,
|
MinimalSymbolDumper(LinePrinter &P, bool RecordBytes,
|
||||||
|
codeview::LazyRandomTypeCollection &Ids,
|
||||||
codeview::LazyRandomTypeCollection &Types)
|
codeview::LazyRandomTypeCollection &Types)
|
||||||
: P(P), Types(Types) {}
|
: P(P), Ids(Ids), Types(Types) {}
|
||||||
|
|
||||||
Error visitSymbolBegin(codeview::CVSymbol &Record) override;
|
Error visitSymbolBegin(codeview::CVSymbol &Record) override;
|
||||||
Error visitSymbolBegin(codeview::CVSymbol &Record, uint32_t Offset) override;
|
Error visitSymbolBegin(codeview::CVSymbol &Record, uint32_t Offset) override;
|
||||||
@ -37,9 +38,13 @@ public:
|
|||||||
#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
|
#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::string typeOrIdIndex(codeview::TypeIndex TI, bool IsType) const;
|
||||||
|
|
||||||
std::string typeIndex(codeview::TypeIndex TI) const;
|
std::string typeIndex(codeview::TypeIndex TI) const;
|
||||||
|
std::string idIndex(codeview::TypeIndex TI) const;
|
||||||
|
|
||||||
LinePrinter &P;
|
LinePrinter &P;
|
||||||
|
codeview::LazyRandomTypeCollection &Ids;
|
||||||
codeview::LazyRandomTypeCollection &Types;
|
codeview::LazyRandomTypeCollection &Types;
|
||||||
};
|
};
|
||||||
} // namespace pdb
|
} // namespace pdb
|
||||||
|
@ -131,7 +131,7 @@ private:
|
|||||||
void discoverTypeIndicesInSymbols() {
|
void discoverTypeIndicesInSymbols() {
|
||||||
Refs.resize(Symbols.size());
|
Refs.resize(Symbols.size());
|
||||||
for (uint32_t I = 0; I < Symbols.size(); ++I)
|
for (uint32_t I = 0; I < Symbols.size(); ++I)
|
||||||
discoverTypeIndices(Symbols[I], Refs[I]);
|
discoverTypeIndicesInSymbol(Symbols[I], Refs[I]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to write out a field list record with the given list
|
// Helper function to write out a field list record with the given list
|
||||||
|
Loading…
Reference in New Issue
Block a user