Refactor Symbol visitor code.

Type visitor code had already been refactored previously to
decouple the visitor and the visitor callback interface.  This
was necessary for having the flexibility to visit in different
ways (for example, dumping to yaml, reading from yaml, dumping
to ScopedPrinter, etc).

This patch merely implements the same visitation pattern for
symbol records that has already been implemented for type records.

llvm-svn: 283609
This commit is contained in:
Zachary Turner 2016-10-07 21:34:46 +00:00
parent 78550e3991
commit 0d8407447d
11 changed files with 468 additions and 179 deletions

View File

@ -18,85 +18,17 @@
namespace llvm {
namespace codeview {
class SymbolVisitorCallbacks;
template <typename Derived> class CVSymbolVisitor {
class CVSymbolVisitor {
public:
CVSymbolVisitor(SymbolVisitorDelegate *Delegate) : Delegate(Delegate) {}
CVSymbolVisitor(SymbolVisitorCallbacks &Callbacks);
bool hadError() const { return HadError; }
template <typename T>
bool consumeObject(ArrayRef<uint8_t> &Data, const T *&Res) {
if (Data.size() < sizeof(*Res)) {
HadError = true;
return false;
}
Res = reinterpret_cast<const T *>(Data.data());
Data = Data.drop_front(sizeof(*Res));
return true;
}
/// Actions to take on known symbols. By default, they do nothing. Visit methods
/// for member records take the FieldData by non-const reference and are
/// expected to consume the trailing bytes used by the field.
/// FIXME: Make the visitor interpret the trailing bytes so that clients don't
/// need to.
#define SYMBOL_RECORD(EnumName, EnumVal, Name) \
void visit##Name(SymbolRecordKind Kind, Name &Record) {}
#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "CVSymbolTypes.def"
void visitSymbolRecord(const CVRecord<SymbolKind> &Record) {
ArrayRef<uint8_t> Data = Record.content();
auto *DerivedThis = static_cast<Derived *>(this);
DerivedThis->visitSymbolBegin(Record.Type, Data);
uint32_t RecordOffset = Delegate ? Delegate->getRecordOffset(Data) : 0;
switch (Record.Type) {
default:
DerivedThis->visitUnknownSymbol(Record.Type, Data);
break;
#define SYMBOL_RECORD(EnumName, EnumVal, Name) \
case EnumName: { \
SymbolRecordKind RK = static_cast<SymbolRecordKind>(EnumName); \
auto ExpectedResult = Name::deserialize(RK, RecordOffset, Data); \
if (!ExpectedResult) { \
consumeError(ExpectedResult.takeError()); \
return parseError(); \
} \
DerivedThis->visit##Name(Record.Type, *ExpectedResult); \
break; \
}
#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
SYMBOL_RECORD(EnumVal, EnumVal, AliasName)
#include "CVSymbolTypes.def"
}
DerivedThis->visitSymbolEnd(Record.Type, Record.content());
}
/// Visits the symbol records in Data. Sets the error flag on parse failures.
void visitSymbolStream(const CVSymbolArray &Symbols) {
for (const auto &I : Symbols) {
visitSymbolRecord(I);
if (hadError())
break;
}
}
/// Action to take on unknown symbols. By default, they are ignored.
void visitUnknownSymbol(SymbolKind Kind, ArrayRef<uint8_t> Data) {}
/// Paired begin/end actions for all symbols. Receives all record data,
/// including the fixed-length record prefix.
void visitSymbolBegin(SymbolKind Leaf, ArrayRef<uint8_t> RecordData) {}
void visitSymbolEnd(SymbolKind Leaf, ArrayRef<uint8_t> OriginalSymData) {}
/// Helper for returning from a void function when the stream is corrupted.
void parseError() { HadError = true; }
Error visitSymbolRecord(CVSymbol &Record);
Error visitSymbolStream(const CVSymbolArray &Symbols);
private:
SymbolVisitorDelegate *Delegate;
/// Whether a symbol stream parsing error was encountered.
bool HadError = false;
SymbolVisitorCallbacks &Callbacks;
};
} // end namespace codeview

View File

@ -0,0 +1,60 @@
//===- SymbolDeserializer.h -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_CODEVIEW_SYMBOLDESERIALIZER_H
#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLDESERIALIZER_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
#include "llvm/Support/Error.h"
namespace llvm {
namespace codeview {
class SymbolVisitorDelegate;
class SymbolDeserializer : public SymbolVisitorCallbacks {
public:
explicit SymbolDeserializer(SymbolVisitorDelegate *Delegate)
: Delegate(Delegate) {}
#define SYMBOL_RECORD(EnumName, EnumVal, Name) \
Error visitKnownRecord(CVSymbol &CVR, Name &Record) override { \
return defaultVisitKnownRecord(CVR, Record); \
}
#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "CVSymbolTypes.def"
protected:
template <typename T>
Error deserializeRecord(ArrayRef<uint8_t> &Data, SymbolKind Kind,
T &Record) const {
uint32_t RecordOffset = Delegate ? Delegate->getRecordOffset(Data) : 0;
SymbolRecordKind RK = static_cast<SymbolRecordKind>(Kind);
auto ExpectedRecord = T::deserialize(RK, RecordOffset, Data);
if (!ExpectedRecord)
return ExpectedRecord.takeError();
Record = std::move(*ExpectedRecord);
return Error::success();
}
private:
template <typename T>
Error defaultVisitKnownRecord(CVSymbol &CVR, T &Record) {
ArrayRef<uint8_t> RD = CVR.content();
if (auto EC = deserializeRecord(RD, CVR.Type, Record))
return EC;
return Error::success();
}
SymbolVisitorDelegate *Delegate;
};
}
}
#endif

View File

@ -35,11 +35,11 @@ public:
/// and true otherwise. This should be called in order, since the dumper
/// maintains state about previous records which are necessary for cross
/// type references.
bool dump(const CVRecord<SymbolKind> &Record);
Error dump(CVRecord<SymbolKind> &Record);
/// Dumps the type records in Data. Returns false if there was a type stream
/// parse error, and true otherwise.
bool dump(const CVSymbolArray &Symbols);
Error dump(const CVSymbolArray &Symbols);
private:
ScopedPrinter &W;

View File

@ -56,6 +56,7 @@ public:
// Name: The null-terminated name follows.
};
explicit ProcSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
ProcSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H,
StringRef Name)
: SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H), Name(Name) {
@ -95,6 +96,7 @@ public:
// Variant portion of thunk
};
explicit Thunk32Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
Thunk32Sym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H,
StringRef Name, ArrayRef<uint8_t> VariantData)
: SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H), Name(Name),
@ -130,6 +132,7 @@ public:
ulittle16_t TargetSection;
};
explicit TrampolineSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
TrampolineSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H)
: SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H) {}
@ -160,6 +163,7 @@ public:
// Name: The null-terminated name follows.
};
explicit SectionSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
SectionSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H,
StringRef Name)
: SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H), Name(Name) {
@ -192,6 +196,7 @@ public:
// Name: The null-terminated name follows.
};
explicit CoffGroupSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
CoffGroupSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H,
StringRef Name)
: SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H), Name(Name) {
@ -215,6 +220,7 @@ public:
class ScopeEndSym : public SymbolRecord {
public:
explicit ScopeEndSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
ScopeEndSym(SymbolRecordKind Kind, uint32_t RecordOffset)
: SymbolRecord(Kind), RecordOffset(RecordOffset) {}
@ -232,6 +238,7 @@ public:
ulittle32_t Count;
};
explicit CallerSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
CallerSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *Header,
ArrayRef<TypeIndex> Indices)
: SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*Header),
@ -441,6 +448,7 @@ public:
// BinaryAnnotations
};
explicit InlineSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
InlineSiteSym(uint32_t RecordOffset, const Hdr *H,
ArrayRef<uint8_t> Annotations)
: SymbolRecord(SymbolRecordKind::InlineSiteSym),
@ -478,6 +486,7 @@ public:
// Name: The null-terminated name follows.
};
explicit PublicSym32(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
PublicSym32(uint32_t RecordOffset, const Hdr *H, StringRef Name)
: SymbolRecord(SymbolRecordKind::PublicSym32), RecordOffset(RecordOffset),
Header(*H), Name(Name) {}
@ -506,6 +515,7 @@ public:
// Name: The null-terminated name follows.
};
explicit RegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
RegisterSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
: SymbolRecord(SymbolRecordKind::RegisterSym), RecordOffset(RecordOffset),
Header(*H), Name(Name) {}
@ -535,6 +545,7 @@ public:
// Name: The null-terminated name follows.
};
explicit ProcRefSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
ProcRefSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
: SymbolRecord(SymbolRecordKind::ProcRefSym), RecordOffset(RecordOffset),
Header(*H), Name(Name) {}
@ -563,6 +574,7 @@ public:
// Name: The null-terminated name follows.
};
explicit LocalSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
LocalSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
: SymbolRecord(SymbolRecordKind::LocalSym), RecordOffset(RecordOffset),
Header(*H), Name(Name) {}
@ -604,6 +616,7 @@ public:
// LocalVariableAddrGap Gaps[];
};
explicit DefRangeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
DefRangeSym(uint32_t RecordOffset, const Hdr *H,
ArrayRef<LocalVariableAddrGap> Gaps)
: SymbolRecord(SymbolRecordKind::DefRangeSym), RecordOffset(RecordOffset),
@ -637,6 +650,7 @@ public:
LocalVariableAddrRange Range;
// LocalVariableAddrGap Gaps[];
};
explicit DefRangeSubfieldSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
DefRangeSubfieldSym(uint32_t RecordOffset, const Hdr *H,
ArrayRef<LocalVariableAddrGap> Gaps)
: SymbolRecord(SymbolRecordKind::DefRangeSubfieldSym),
@ -671,6 +685,7 @@ public:
// LocalVariableAddrGap Gaps[];
};
explicit DefRangeRegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
DefRangeRegisterSym(uint32_t RecordOffset, const Hdr *H,
ArrayRef<LocalVariableAddrGap> Gaps)
: SymbolRecord(SymbolRecordKind::DefRangeRegisterSym),
@ -715,6 +730,8 @@ public:
// LocalVariableAddrGap Gaps[];
};
explicit DefRangeSubfieldRegisterSym(SymbolRecordKind Kind)
: SymbolRecord(Kind) {}
DefRangeSubfieldRegisterSym(uint32_t RecordOffset, const Hdr *H,
ArrayRef<LocalVariableAddrGap> Gaps)
: SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym),
@ -759,6 +776,8 @@ public:
// LocalVariableAddrGap Gaps[];
};
explicit DefRangeFramePointerRelSym(SymbolRecordKind Kind)
: SymbolRecord(Kind) {}
DefRangeFramePointerRelSym(uint32_t RecordOffset, const Hdr *H,
ArrayRef<LocalVariableAddrGap> Gaps)
: SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelSym),
@ -794,6 +813,7 @@ public:
// LocalVariableAddrGap Gaps[];
};
explicit DefRangeRegisterRelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
DefRangeRegisterRelSym(uint32_t RecordOffset, const Hdr *H,
ArrayRef<LocalVariableAddrGap> Gaps)
: SymbolRecord(SymbolRecordKind::DefRangeRegisterRelSym),
@ -848,6 +868,8 @@ public:
little32_t Offset; // Offset from the frame pointer register
};
explicit DefRangeFramePointerRelFullScopeSym(SymbolRecordKind Kind)
: SymbolRecord(Kind) {}
DefRangeFramePointerRelFullScopeSym(uint32_t RecordOffset, const Hdr *H)
: SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelFullScopeSym),
RecordOffset(RecordOffset), Header(*H) {}
@ -877,6 +899,7 @@ public:
// Name: The null-terminated name follows.
};
explicit BlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
BlockSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
: SymbolRecord(SymbolRecordKind::BlockSym), RecordOffset(RecordOffset),
Header(*H), Name(Name) {}
@ -910,6 +933,7 @@ public:
// Name: The null-terminated name follows.
};
explicit LabelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
LabelSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
: SymbolRecord(SymbolRecordKind::LabelSym), RecordOffset(RecordOffset),
Header(*H), Name(Name) {}
@ -941,6 +965,7 @@ public:
// Name: The null-terminated name follows.
};
explicit ObjNameSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
ObjNameSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
: SymbolRecord(SymbolRecordKind::ObjNameSym), RecordOffset(RecordOffset),
Header(*H), Name(Name) {}
@ -968,6 +993,7 @@ public:
// Sequence of zero terminated strings.
};
explicit EnvBlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
EnvBlockSym(uint32_t RecordOffset, const Hdr *H,
const std::vector<StringRef> &Fields)
: SymbolRecord(SymbolRecordKind::EnvBlockSym), RecordOffset(RecordOffset),
@ -997,6 +1023,7 @@ public:
// Name: The null-terminated name follows.
};
explicit ExportSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
ExportSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
: SymbolRecord(SymbolRecordKind::ExportSym), RecordOffset(RecordOffset),
Header(*H), Name(Name) {}
@ -1026,6 +1053,7 @@ public:
// Name: The null-terminated name follows.
};
explicit FileStaticSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
FileStaticSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
: SymbolRecord(SymbolRecordKind::FileStaticSym),
RecordOffset(RecordOffset), Header(*H), Name(Name) {}
@ -1062,6 +1090,7 @@ public:
// Optional block of zero terminated strings terminated with a double zero.
};
explicit Compile2Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
Compile2Sym(uint32_t RecordOffset, const Hdr *H, StringRef Version)
: SymbolRecord(SymbolRecordKind::Compile2Sym), RecordOffset(RecordOffset),
Header(*H), Version(Version) {}
@ -1099,6 +1128,7 @@ public:
// VersionString: The null-terminated version string follows.
};
explicit Compile3Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
Compile3Sym(uint32_t RecordOffset, const Hdr *H, StringRef Version)
: SymbolRecord(SymbolRecordKind::Compile3Sym), RecordOffset(RecordOffset),
Header(*H), Version(Version) {}
@ -1131,6 +1161,7 @@ public:
ulittle32_t Flags;
};
explicit FrameProcSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
FrameProcSym(uint32_t RecordOffset, const Hdr *H)
: SymbolRecord(SymbolRecordKind::FrameProcSym),
RecordOffset(RecordOffset), Header(*H) {}
@ -1158,6 +1189,7 @@ public:
TypeIndex Type;
};
explicit CallSiteInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
CallSiteInfoSym(uint32_t RecordOffset, const Hdr *H)
: SymbolRecord(SymbolRecordKind::CallSiteInfoSym),
RecordOffset(RecordOffset), Header(*H) {}
@ -1189,6 +1221,7 @@ public:
TypeIndex Type;
};
explicit HeapAllocationSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
HeapAllocationSiteSym(uint32_t RecordOffset, const Hdr *H)
: SymbolRecord(SymbolRecordKind::HeapAllocationSiteSym),
RecordOffset(RecordOffset), Header(*H) {}
@ -1220,6 +1253,7 @@ public:
uint8_t Flags;
};
explicit FrameCookieSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
FrameCookieSym(uint32_t RecordOffset, const Hdr *H)
: SymbolRecord(SymbolRecordKind::FrameCookieSym),
RecordOffset(RecordOffset), Header(*H) {}
@ -1249,6 +1283,7 @@ public:
// Name: The null-terminated name follows.
};
explicit UDTSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
UDTSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
: SymbolRecord(SymbolRecordKind::UDTSym), RecordOffset(RecordOffset),
Header(*H), Name(Name) {}
@ -1275,6 +1310,7 @@ public:
ulittle32_t BuildId;
};
explicit BuildInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
BuildInfoSym(uint32_t RecordOffset, const Hdr *H)
: SymbolRecord(SymbolRecordKind::BuildInfoSym),
RecordOffset(RecordOffset), Header(*H) {}
@ -1301,6 +1337,7 @@ public:
// Name: The null-terminated name follows.
};
explicit BPRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
BPRelativeSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
: SymbolRecord(SymbolRecordKind::BPRelativeSym),
RecordOffset(RecordOffset), Header(*H), Name(Name) {}
@ -1330,6 +1367,7 @@ public:
// Name: The null-terminated name follows.
};
explicit RegRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
RegRelativeSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
: SymbolRecord(SymbolRecordKind::RegRelativeSym),
RecordOffset(RecordOffset), Header(*H), Name(Name) {}
@ -1358,6 +1396,7 @@ public:
// Name: The null-terminated name follows.
};
explicit ConstantSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
ConstantSym(uint32_t RecordOffset, const Hdr *H, const APSInt &Value,
StringRef Name)
: SymbolRecord(SymbolRecordKind::ConstantSym), RecordOffset(RecordOffset),
@ -1390,6 +1429,7 @@ public:
// Name: The null-terminated name follows.
};
explicit DataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
DataSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
: SymbolRecord(SymbolRecordKind::DataSym), RecordOffset(RecordOffset),
Header(*H), Name(Name) {}
@ -1423,6 +1463,7 @@ public:
// Name: The null-terminated name follows.
};
explicit ThreadLocalDataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
ThreadLocalDataSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
: SymbolRecord(SymbolRecordKind::ThreadLocalDataSym),
RecordOffset(RecordOffset), Header(*H), Name(Name) {}

View File

@ -0,0 +1,69 @@
//===- SymbolVisitorCallbackPipeline.h ------------------------ *- C++ --*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_CODEVIEW_SYMBOLVISITORCALLBACKPIPELINE_H
#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLVISITORCALLBACKPIPELINE_H
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
#include <vector>
namespace llvm {
namespace codeview {
class SymbolVisitorCallbackPipeline : public SymbolVisitorCallbacks {
public:
SymbolVisitorCallbackPipeline() {}
virtual Error visitUnknownSymbol(CVSymbol &Record) override {
for (auto Visitor : Pipeline) {
if (auto EC = Visitor->visitUnknownSymbol(Record))
return EC;
}
return Error::success();
}
virtual Error visitSymbolBegin(CVSymbol &Record) override {
for (auto Visitor : Pipeline) {
if (auto EC = Visitor->visitSymbolBegin(Record))
return EC;
}
return Error::success();
}
virtual Error visitSymbolEnd(CVSymbol &Record) override {
for (auto Visitor : Pipeline) {
if (auto EC = Visitor->visitSymbolEnd(Record))
return EC;
}
return Error::success();
}
void addCallbackToPipeline(SymbolVisitorCallbacks &Callbacks) {
Pipeline.push_back(&Callbacks);
}
#define SYMBOL_RECORD(EnumName, EnumVal, Name) \
Error visitKnownRecord(CVSymbol &CVR, Name &Record) override { \
for (auto Visitor : Pipeline) { \
if (auto EC = Visitor->visitKnownRecord(CVR, Record)) \
return EC; \
} \
return Error::success(); \
}
#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "llvm/DebugInfo/CodeView/CVSymbolTypes.def"
private:
std::vector<SymbolVisitorCallbacks *> Pipeline;
};
}
}
#endif

View File

@ -0,0 +1,49 @@
//===- SymbolVisitorCallbacks.h ---------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_CODEVIEW_SYMBOLVISITORCALLBACKS_H
#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLVISITORCALLBACKS_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/DebugInfo/CodeView/CVRecord.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/Support/Error.h"
namespace llvm {
namespace codeview {
class SymbolVisitorCallbacks {
friend class CVSymbolVisitor;
public:
virtual ~SymbolVisitorCallbacks() {}
/// Action to take on unknown symbols. By default, they are ignored.
virtual Error visitUnknownSymbol(CVSymbol &Record) {
return Error::success();
}
/// Paired begin/end actions for all symbols. Receives all record data,
/// including the fixed-length record prefix. visitSymbolBegin() should
/// return
/// the type of the Symbol, or an error if it cannot be determined.
virtual Error visitSymbolBegin(CVSymbol &Record) { return Error::success(); }
virtual Error visitSymbolEnd(CVSymbol &Record) { return Error::success(); }
#define SYMBOL_RECORD(EnumName, EnumVal, Name) \
virtual Error visitKnownRecord(CVSymbol &CVR, Name &Record) { \
return Error::success(); \
}
#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "CVSymbolTypes.def"
};
}
}
#endif

View File

@ -1,5 +1,6 @@
add_llvm_library(LLVMDebugInfoCodeView
CodeViewError.cpp
CVSymbolVisitor.cpp
CVTypeVisitor.cpp
EnumTables.cpp
FieldListRecordBuilder.cpp

View File

@ -0,0 +1,73 @@
//===- CVSymbolVisitor.cpp --------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
#include "llvm/DebugInfo/CodeView/CodeViewError.h"
#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
#include "llvm/DebugInfo/MSF/ByteStream.h"
using namespace llvm;
using namespace llvm::codeview;
template <typename T>
static Error takeObject(ArrayRef<uint8_t> &Data, const T *&Res) {
if (Data.size() < sizeof(*Res))
return llvm::make_error<CodeViewError>(cv_error_code::insufficient_buffer);
Res = reinterpret_cast<const T *>(Data.data());
Data = Data.drop_front(sizeof(*Res));
return Error::success();
}
CVSymbolVisitor::CVSymbolVisitor(SymbolVisitorCallbacks &Callbacks)
: Callbacks(Callbacks) {}
template <typename T>
static Error visitKnownRecord(CVSymbol &Record,
SymbolVisitorCallbacks &Callbacks) {
SymbolRecordKind RK = static_cast<SymbolRecordKind>(Record.Type);
T KnownRecord(RK);
if (auto EC = Callbacks.visitKnownRecord(Record, KnownRecord))
return EC;
return Error::success();
}
Error CVSymbolVisitor::visitSymbolRecord(CVSymbol &Record) {
if (auto EC = Callbacks.visitSymbolBegin(Record))
return EC;
switch (Record.Type) {
default:
if (auto EC = Callbacks.visitUnknownSymbol(Record))
return EC;
break;
#define SYMBOL_RECORD(EnumName, EnumVal, Name) \
case EnumName: { \
if (auto EC = visitKnownRecord<Name>(Record, Callbacks)) \
return EC; \
break; \
}
#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
SYMBOL_RECORD(EnumVal, EnumVal, AliasName)
#include "llvm/DebugInfo/CodeView/CVSymbolTypes.def"
}
if (auto EC = Callbacks.visitSymbolEnd(Record))
return EC;
return Error::success();
}
Error CVSymbolVisitor::visitSymbolStream(const CVSymbolArray &Symbols) {
for (auto I : Symbols) {
if (auto EC = visitSymbolRecord(I))
return EC;
}
return Error::success();
}

View File

@ -12,10 +12,14 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
#include "llvm/DebugInfo/CodeView/EnumTables.h"
#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
#include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h"
#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
#include "llvm/DebugInfo/CodeView/TypeDumper.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ScopedPrinter.h"
#include <system_error>
@ -26,22 +30,22 @@ using namespace llvm::codeview;
namespace {
/// Use this private dumper implementation to keep implementation details about
/// the visitor out of SymbolDumper.h.
class CVSymbolDumperImpl : public CVSymbolVisitor<CVSymbolDumperImpl> {
class CVSymbolDumperImpl : public SymbolVisitorCallbacks {
public:
CVSymbolDumperImpl(CVTypeDumper &CVTD, SymbolDumpDelegate *ObjDelegate,
ScopedPrinter &W, bool PrintRecordBytes)
: CVSymbolVisitor(ObjDelegate), CVTD(CVTD), ObjDelegate(ObjDelegate),
W(W), PrintRecordBytes(PrintRecordBytes), InFunctionScope(false) {}
: CVTD(CVTD), ObjDelegate(ObjDelegate), W(W),
PrintRecordBytes(PrintRecordBytes), InFunctionScope(false) {}
/// CVSymbolVisitor overrides.
#define SYMBOL_RECORD(EnumName, EnumVal, Name) \
void visit##Name(SymbolKind Kind, Name &Record);
Error visitKnownRecord(CVSymbol &CVR, Name &Record) override;
#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "llvm/DebugInfo/CodeView/CVSymbolTypes.def"
void visitSymbolBegin(SymbolKind Kind, ArrayRef<uint8_t> Data);
void visitSymbolEnd(SymbolKind Kind, ArrayRef<uint8_t> OriginalSymData);
void visitUnknownSymbol(SymbolKind Kind, ArrayRef<uint8_t> Data);
Error visitSymbolBegin(CVSymbol &Record) override;
Error visitSymbolEnd(CVSymbol &Record) override;
Error visitUnknownSymbol(CVSymbol &Record) override;
private:
void printLocalVariableAddrRange(const LocalVariableAddrRange &Range,
@ -76,16 +80,17 @@ void CVSymbolDumperImpl::printLocalVariableAddrGap(
}
}
void CVSymbolDumperImpl::visitSymbolBegin(SymbolKind Kind,
ArrayRef<uint8_t> Data) {}
void CVSymbolDumperImpl::visitSymbolEnd(SymbolKind Kind,
ArrayRef<uint8_t> OriginalSymData) {
if (PrintRecordBytes && ObjDelegate)
ObjDelegate->printBinaryBlockWithRelocs("SymData", OriginalSymData);
Error CVSymbolDumperImpl::visitSymbolBegin(CVSymbol &CVR) {
return Error::success();
}
void CVSymbolDumperImpl::visitBlockSym(SymbolKind Kind, BlockSym &Block) {
Error CVSymbolDumperImpl::visitSymbolEnd(CVSymbol &CVR) {
if (PrintRecordBytes && ObjDelegate)
ObjDelegate->printBinaryBlockWithRelocs("SymData", CVR.content());
return Error::success();
}
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, BlockSym &Block) {
DictScope S(W, "BlockStart");
StringRef LinkageName;
@ -99,9 +104,10 @@ void CVSymbolDumperImpl::visitBlockSym(SymbolKind Kind, BlockSym &Block) {
W.printHex("Segment", Block.Header.Segment);
W.printString("BlockName", Block.Name);
W.printString("LinkageName", LinkageName);
return Error::success();
}
void CVSymbolDumperImpl::visitThunk32Sym(SymbolKind Kind, Thunk32Sym &Thunk) {
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, Thunk32Sym &Thunk) {
DictScope S(W, "Thunk32");
W.printNumber("Parent", Thunk.Header.Parent);
W.printNumber("End", Thunk.Header.End);
@ -110,10 +116,11 @@ void CVSymbolDumperImpl::visitThunk32Sym(SymbolKind Kind, Thunk32Sym &Thunk) {
W.printNumber("Seg", Thunk.Header.Seg);
W.printNumber("Len", Thunk.Header.Len);
W.printEnum("Ordinal", Thunk.Header.Ord, getThunkOrdinalNames());
return Error::success();
}
void CVSymbolDumperImpl::visitTrampolineSym(SymbolKind Kind,
TrampolineSym &Tramp) {
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
TrampolineSym &Tramp) {
DictScope S(W, "Trampoline");
W.printEnum("Type", Tramp.Header.Type, getTrampolineNames());
W.printNumber("Size", Tramp.Header.Size);
@ -121,9 +128,10 @@ void CVSymbolDumperImpl::visitTrampolineSym(SymbolKind Kind,
W.printNumber("TargetOff", Tramp.Header.TargetOff);
W.printNumber("ThunkSection", Tramp.Header.ThunkSection);
W.printNumber("TargetSection", Tramp.Header.TargetSection);
return Error::success();
}
void CVSymbolDumperImpl::visitSectionSym(SymbolKind Kind, SectionSym &Section) {
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, SectionSym &Section) {
DictScope S(W, "Section");
W.printNumber("SectionNumber", Section.Header.SectionNumber);
W.printNumber("Alignment", Section.Header.Alignment);
@ -135,9 +143,10 @@ void CVSymbolDumperImpl::visitSectionSym(SymbolKind Kind, SectionSym &Section) {
COFF::SectionCharacteristics(0x00F00000));
W.printString("Name", Section.Name);
return Error::success();
}
void CVSymbolDumperImpl::visitCoffGroupSym(SymbolKind Kind,
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
CoffGroupSym &CoffGroup) {
DictScope S(W, "COFF Group");
W.printNumber("Size", CoffGroup.Header.Size);
@ -147,26 +156,29 @@ void CVSymbolDumperImpl::visitCoffGroupSym(SymbolKind Kind,
W.printNumber("Offset", CoffGroup.Header.Offset);
W.printNumber("Segment", CoffGroup.Header.Segment);
W.printString("Name", CoffGroup.Name);
return Error::success();
}
void CVSymbolDumperImpl::visitBPRelativeSym(SymbolKind Kind,
BPRelativeSym &BPRel) {
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
BPRelativeSym &BPRel) {
DictScope S(W, "BPRelativeSym");
W.printNumber("Offset", BPRel.Header.Offset);
CVTD.printTypeIndex("Type", BPRel.Header.Type);
W.printString("VarName", BPRel.Name);
return Error::success();
}
void CVSymbolDumperImpl::visitBuildInfoSym(SymbolKind Kind,
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
BuildInfoSym &BuildInfo) {
DictScope S(W, "BuildInfo");
W.printNumber("BuildId", BuildInfo.Header.BuildId);
return Error::success();
}
void CVSymbolDumperImpl::visitCallSiteInfoSym(SymbolKind Kind,
CallSiteInfoSym &CallSiteInfo) {
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
CallSiteInfoSym &CallSiteInfo) {
DictScope S(W, "CallSiteInfo");
StringRef LinkageName;
@ -180,10 +192,11 @@ void CVSymbolDumperImpl::visitCallSiteInfoSym(SymbolKind Kind,
CVTD.printTypeIndex("Type", CallSiteInfo.Header.Type);
if (!LinkageName.empty())
W.printString("LinkageName", LinkageName);
return Error::success();
}
void CVSymbolDumperImpl::visitEnvBlockSym(SymbolKind Kind,
EnvBlockSym &EnvBlock) {
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
EnvBlockSym &EnvBlock) {
DictScope S(W, "EnvBlock");
W.printNumber("Reserved", EnvBlock.Header.Reserved);
@ -191,26 +204,29 @@ void CVSymbolDumperImpl::visitEnvBlockSym(SymbolKind Kind,
for (auto Entry : EnvBlock.Fields) {
W.printString(Entry);
}
return Error::success();
}
void CVSymbolDumperImpl::visitFileStaticSym(SymbolKind Kind,
FileStaticSym &FileStatic) {
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
FileStaticSym &FileStatic) {
DictScope S(W, "FileStatic");
W.printNumber("Index", FileStatic.Header.Index);
W.printNumber("ModFilenameOffset", FileStatic.Header.ModFilenameOffset);
W.printFlags("Flags", uint16_t(FileStatic.Header.Flags), getLocalFlagNames());
W.printString("Name", FileStatic.Name);
return Error::success();
}
void CVSymbolDumperImpl::visitExportSym(SymbolKind Kind, ExportSym &Export) {
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ExportSym &Export) {
DictScope S(W, "Export");
W.printNumber("Ordinal", Export.Header.Ordinal);
W.printFlags("Flags", Export.Header.Flags, getExportSymFlagNames());
W.printString("Name", Export.Name);
return Error::success();
}
void CVSymbolDumperImpl::visitCompile2Sym(SymbolKind Kind,
Compile2Sym &Compile2) {
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
Compile2Sym &Compile2) {
DictScope S(W, "CompilerFlags2");
W.printEnum("Language", Compile2.Header.getLanguage(),
@ -235,10 +251,11 @@ void CVSymbolDumperImpl::visitCompile2Sym(SymbolKind Kind,
W.printString("FrontendVersion", FrontendVersion);
W.printString("BackendVersion", BackendVersion);
W.printString("VersionName", Compile2.Version);
return Error::success();
}
void CVSymbolDumperImpl::visitCompile3Sym(SymbolKind Kind,
Compile3Sym &Compile3) {
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
Compile3Sym &Compile3) {
DictScope S(W, "CompilerFlags3");
W.printEnum("Language", Compile3.Header.getLanguage(),
@ -265,21 +282,23 @@ void CVSymbolDumperImpl::visitCompile3Sym(SymbolKind Kind,
W.printString("FrontendVersion", FrontendVersion);
W.printString("BackendVersion", BackendVersion);
W.printString("VersionName", Compile3.Version);
return Error::success();
}
void CVSymbolDumperImpl::visitConstantSym(SymbolKind Kind,
ConstantSym &Constant) {
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
ConstantSym &Constant) {
DictScope S(W, "Constant");
CVTD.printTypeIndex("Type", Constant.Header.Type);
W.printNumber("Value", Constant.Value);
W.printString("Name", Constant.Name);
return Error::success();
}
void CVSymbolDumperImpl::visitDataSym(SymbolKind Kind, DataSym &Data) {
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, DataSym &Data) {
DictScope S(W, "DataSym");
W.printEnum("Kind", uint16_t(Kind), getSymbolTypeNames());
W.printEnum("Kind", uint16_t(CVR.kind()), getSymbolTypeNames());
StringRef LinkageName;
if (ObjDelegate) {
ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(),
@ -289,27 +308,30 @@ void CVSymbolDumperImpl::visitDataSym(SymbolKind Kind, DataSym &Data) {
W.printString("DisplayName", Data.Name);
if (!LinkageName.empty())
W.printString("LinkageName", LinkageName);
return Error::success();
}
void CVSymbolDumperImpl::visitDefRangeFramePointerRelFullScopeSym(
SymbolKind Kind,
Error CVSymbolDumperImpl::visitKnownRecord(
CVSymbol &CVR,
DefRangeFramePointerRelFullScopeSym &DefRangeFramePointerRelFullScope) {
DictScope S(W, "DefRangeFramePointerRelFullScope");
W.printNumber("Offset", DefRangeFramePointerRelFullScope.Header.Offset);
return Error::success();
}
void CVSymbolDumperImpl::visitDefRangeFramePointerRelSym(
SymbolKind Kind, DefRangeFramePointerRelSym &DefRangeFramePointerRel) {
Error CVSymbolDumperImpl::visitKnownRecord(
CVSymbol &CVR, DefRangeFramePointerRelSym &DefRangeFramePointerRel) {
DictScope S(W, "DefRangeFramePointerRel");
W.printNumber("Offset", DefRangeFramePointerRel.Header.Offset);
printLocalVariableAddrRange(DefRangeFramePointerRel.Header.Range,
DefRangeFramePointerRel.getRelocationOffset());
printLocalVariableAddrGap(DefRangeFramePointerRel.Gaps);
return Error::success();
}
void CVSymbolDumperImpl::visitDefRangeRegisterRelSym(
SymbolKind Kind, DefRangeRegisterRelSym &DefRangeRegisterRel) {
Error CVSymbolDumperImpl::visitKnownRecord(
CVSymbol &CVR, DefRangeRegisterRelSym &DefRangeRegisterRel) {
DictScope S(W, "DefRangeRegisterRel");
W.printNumber("BaseRegister", DefRangeRegisterRel.Header.BaseRegister);
@ -321,10 +343,11 @@ void CVSymbolDumperImpl::visitDefRangeRegisterRelSym(
printLocalVariableAddrRange(DefRangeRegisterRel.Header.Range,
DefRangeRegisterRel.getRelocationOffset());
printLocalVariableAddrGap(DefRangeRegisterRel.Gaps);
return Error::success();
}
void CVSymbolDumperImpl::visitDefRangeRegisterSym(
SymbolKind Kind, DefRangeRegisterSym &DefRangeRegister) {
Error CVSymbolDumperImpl::visitKnownRecord(
CVSymbol &CVR, DefRangeRegisterSym &DefRangeRegister) {
DictScope S(W, "DefRangeRegister");
W.printNumber("Register", DefRangeRegister.Header.Register);
@ -332,10 +355,11 @@ void CVSymbolDumperImpl::visitDefRangeRegisterSym(
printLocalVariableAddrRange(DefRangeRegister.Header.Range,
DefRangeRegister.getRelocationOffset());
printLocalVariableAddrGap(DefRangeRegister.Gaps);
return Error::success();
}
void CVSymbolDumperImpl::visitDefRangeSubfieldRegisterSym(
SymbolKind Kind, DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) {
Error CVSymbolDumperImpl::visitKnownRecord(
CVSymbol &CVR, DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) {
DictScope S(W, "DefRangeSubfieldRegister");
W.printNumber("Register", DefRangeSubfieldRegister.Header.Register);
@ -345,17 +369,19 @@ void CVSymbolDumperImpl::visitDefRangeSubfieldRegisterSym(
printLocalVariableAddrRange(DefRangeSubfieldRegister.Header.Range,
DefRangeSubfieldRegister.getRelocationOffset());
printLocalVariableAddrGap(DefRangeSubfieldRegister.Gaps);
return Error::success();
}
void CVSymbolDumperImpl::visitDefRangeSubfieldSym(
SymbolKind Kind, DefRangeSubfieldSym &DefRangeSubfield) {
Error CVSymbolDumperImpl::visitKnownRecord(
CVSymbol &CVR, DefRangeSubfieldSym &DefRangeSubfield) {
DictScope S(W, "DefRangeSubfield");
if (ObjDelegate) {
StringRef StringTable = ObjDelegate->getStringTable();
auto ProgramStringTableOffset = DefRangeSubfield.Header.Program;
if (ProgramStringTableOffset >= StringTable.size())
return parseError();
return llvm::make_error<CodeViewError>(
"String table offset outside of bounds of String Table!");
StringRef Program =
StringTable.drop_front(ProgramStringTableOffset).split('\0').first;
W.printString("Program", Program);
@ -364,17 +390,19 @@ void CVSymbolDumperImpl::visitDefRangeSubfieldSym(
printLocalVariableAddrRange(DefRangeSubfield.Header.Range,
DefRangeSubfield.getRelocationOffset());
printLocalVariableAddrGap(DefRangeSubfield.Gaps);
return Error::success();
}
void CVSymbolDumperImpl::visitDefRangeSym(SymbolKind Kind,
DefRangeSym &DefRange) {
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
DefRangeSym &DefRange) {
DictScope S(W, "DefRange");
if (ObjDelegate) {
StringRef StringTable = ObjDelegate->getStringTable();
auto ProgramStringTableOffset = DefRange.Header.Program;
if (ProgramStringTableOffset >= StringTable.size())
return parseError();
return llvm::make_error<CodeViewError>(
"String table offset outside of bounds of String Table!");
StringRef Program =
StringTable.drop_front(ProgramStringTableOffset).split('\0').first;
W.printString("Program", Program);
@ -382,10 +410,11 @@ void CVSymbolDumperImpl::visitDefRangeSym(SymbolKind Kind,
printLocalVariableAddrRange(DefRange.Header.Range,
DefRange.getRelocationOffset());
printLocalVariableAddrGap(DefRange.Gaps);
return Error::success();
}
void CVSymbolDumperImpl::visitFrameCookieSym(SymbolKind Kind,
FrameCookieSym &FrameCookie) {
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
FrameCookieSym &FrameCookie) {
DictScope S(W, "FrameCookie");
StringRef LinkageName;
@ -398,9 +427,10 @@ void CVSymbolDumperImpl::visitFrameCookieSym(SymbolKind Kind,
W.printEnum("CookieKind", uint16_t(FrameCookie.Header.CookieKind),
getFrameCookieKindNames());
W.printHex("Flags", FrameCookie.Header.Flags);
return Error::success();
}
void CVSymbolDumperImpl::visitFrameProcSym(SymbolKind Kind,
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
FrameProcSym &FrameProc) {
DictScope S(W, "FrameProc");
@ -414,10 +444,11 @@ void CVSymbolDumperImpl::visitFrameProcSym(SymbolKind Kind,
W.printHex("SectionIdOfExceptionHandler",
FrameProc.Header.SectionIdOfExceptionHandler);
W.printFlags("Flags", FrameProc.Header.Flags, getFrameProcSymFlagNames());
return Error::success();
}
void CVSymbolDumperImpl::visitHeapAllocationSiteSym(
SymbolKind Kind, HeapAllocationSiteSym &HeapAllocSite) {
Error CVSymbolDumperImpl::visitKnownRecord(
CVSymbol &CVR, HeapAllocationSiteSym &HeapAllocSite) {
DictScope S(W, "HeapAllocationSite");
StringRef LinkageName;
@ -431,10 +462,11 @@ void CVSymbolDumperImpl::visitHeapAllocationSiteSym(
CVTD.printTypeIndex("Type", HeapAllocSite.Header.Type);
if (!LinkageName.empty())
W.printString("LinkageName", LinkageName);
return Error::success();
}
void CVSymbolDumperImpl::visitInlineSiteSym(SymbolKind Kind,
InlineSiteSym &InlineSite) {
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
InlineSiteSym &InlineSite) {
DictScope S(W, "InlineSite");
W.printHex("PtrParent", InlineSite.Header.PtrParent);
@ -445,7 +477,8 @@ void CVSymbolDumperImpl::visitInlineSiteSym(SymbolKind Kind,
for (auto &Annotation : InlineSite.annotations()) {
switch (Annotation.OpCode) {
case BinaryAnnotationsOpCode::Invalid:
return parseError();
return llvm::make_error<CodeViewError>(
"Invalid binary annotation opcode!");
case BinaryAnnotationsOpCode::CodeOffset:
case BinaryAnnotationsOpCode::ChangeCodeOffset:
case BinaryAnnotationsOpCode::ChangeCodeLength:
@ -486,34 +519,37 @@ void CVSymbolDumperImpl::visitInlineSiteSym(SymbolKind Kind,
}
}
}
return Error::success();
}
void CVSymbolDumperImpl::visitRegisterSym(SymbolKind Kind,
RegisterSym &Register) {
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
RegisterSym &Register) {
DictScope S(W, "RegisterSym");
W.printNumber("Type", Register.Header.Index);
W.printEnum("Seg", uint16_t(Register.Header.Register), getRegisterNames());
W.printString("Name", Register.Name);
return Error::success();
}
void CVSymbolDumperImpl::visitPublicSym32(SymbolKind Kind,
PublicSym32 &Public) {
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, PublicSym32 &Public) {
DictScope S(W, "PublicSym");
W.printNumber("Type", Public.Header.Index);
W.printNumber("Seg", Public.Header.Seg);
W.printNumber("Off", Public.Header.Off);
W.printString("Name", Public.Name);
return Error::success();
}
void CVSymbolDumperImpl::visitProcRefSym(SymbolKind Kind, ProcRefSym &ProcRef) {
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ProcRefSym &ProcRef) {
DictScope S(W, "ProcRef");
W.printNumber("SumName", ProcRef.Header.SumName);
W.printNumber("SymOffset", ProcRef.Header.SymOffset);
W.printNumber("Mod", ProcRef.Header.Mod);
W.printString("Name", ProcRef.Name);
return Error::success();
}
void CVSymbolDumperImpl::visitLabelSym(SymbolKind Kind, LabelSym &Label) {
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, LabelSym &Label) {
DictScope S(W, "Label");
StringRef LinkageName;
@ -527,33 +563,37 @@ void CVSymbolDumperImpl::visitLabelSym(SymbolKind Kind, LabelSym &Label) {
W.printString("DisplayName", Label.Name);
if (!LinkageName.empty())
W.printString("LinkageName", LinkageName);
return Error::success();
}
void CVSymbolDumperImpl::visitLocalSym(SymbolKind Kind, LocalSym &Local) {
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, LocalSym &Local) {
DictScope S(W, "Local");
CVTD.printTypeIndex("Type", Local.Header.Type);
W.printFlags("Flags", uint16_t(Local.Header.Flags), getLocalFlagNames());
W.printString("VarName", Local.Name);
return Error::success();
}
void CVSymbolDumperImpl::visitObjNameSym(SymbolKind Kind, ObjNameSym &ObjName) {
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ObjNameSym &ObjName) {
DictScope S(W, "ObjectName");
W.printHex("Signature", ObjName.Header.Signature);
W.printString("ObjectName", ObjName.Name);
return Error::success();
}
void CVSymbolDumperImpl::visitProcSym(SymbolKind Kind, ProcSym &Proc) {
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ProcSym &Proc) {
DictScope S(W, "ProcStart");
if (InFunctionScope)
return parseError();
return llvm::make_error<CodeViewError>(
"Visiting a ProcSym while inside function scope!");
InFunctionScope = true;
StringRef LinkageName;
W.printEnum("Kind", uint16_t(Kind), getSymbolTypeNames());
W.printEnum("Kind", uint16_t(CVR.kind()), getSymbolTypeNames());
W.printHex("PtrParent", Proc.Header.PtrParent);
W.printHex("PtrEnd", Proc.Header.PtrEnd);
W.printHex("PtrNext", Proc.Header.PtrNext);
@ -571,38 +611,42 @@ void CVSymbolDumperImpl::visitProcSym(SymbolKind Kind, ProcSym &Proc) {
W.printString("DisplayName", Proc.Name);
if (!LinkageName.empty())
W.printString("LinkageName", LinkageName);
return Error::success();
}
void CVSymbolDumperImpl::visitScopeEndSym(SymbolKind Kind,
ScopeEndSym &ScopeEnd) {
if (Kind == SymbolKind::S_END)
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
ScopeEndSym &ScopeEnd) {
if (CVR.kind() == SymbolKind::S_END)
DictScope S(W, "BlockEnd");
else if (Kind == SymbolKind::S_PROC_ID_END)
else if (CVR.kind() == SymbolKind::S_PROC_ID_END)
DictScope S(W, "ProcEnd");
else if (Kind == SymbolKind::S_INLINESITE_END)
else if (CVR.kind() == SymbolKind::S_INLINESITE_END)
DictScope S(W, "InlineSiteEnd");
InFunctionScope = false;
return Error::success();
}
void CVSymbolDumperImpl::visitCallerSym(SymbolKind Kind, CallerSym &Caller) {
ListScope S(W, Kind == S_CALLEES ? "Callees" : "Callers");
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, CallerSym &Caller) {
ListScope S(W, CVR.kind() == S_CALLEES ? "Callees" : "Callers");
for (auto FuncID : Caller.Indices)
CVTD.printTypeIndex("FuncID", FuncID);
return Error::success();
}
void CVSymbolDumperImpl::visitRegRelativeSym(SymbolKind Kind,
RegRelativeSym &RegRel) {
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
RegRelativeSym &RegRel) {
DictScope S(W, "RegRelativeSym");
W.printHex("Offset", RegRel.Header.Offset);
CVTD.printTypeIndex("Type", RegRel.Header.Type);
W.printHex("Register", RegRel.Header.Register);
W.printString("VarName", RegRel.Name);
return Error::success();
}
void CVSymbolDumperImpl::visitThreadLocalDataSym(SymbolKind Kind,
ThreadLocalDataSym &Data) {
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
ThreadLocalDataSym &Data) {
DictScope S(W, "ThreadLocalDataSym");
StringRef LinkageName;
@ -614,29 +658,41 @@ void CVSymbolDumperImpl::visitThreadLocalDataSym(SymbolKind Kind,
W.printString("DisplayName", Data.Name);
if (!LinkageName.empty())
W.printString("LinkageName", LinkageName);
return Error::success();
}
void CVSymbolDumperImpl::visitUDTSym(SymbolKind Kind, UDTSym &UDT) {
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, UDTSym &UDT) {
DictScope S(W, "UDT");
CVTD.printTypeIndex("Type", UDT.Header.Type);
W.printString("UDTName", UDT.Name);
return Error::success();
}
void CVSymbolDumperImpl::visitUnknownSymbol(SymbolKind Kind,
ArrayRef<uint8_t> Data) {
Error CVSymbolDumperImpl::visitUnknownSymbol(CVSymbol &CVR) {
DictScope S(W, "UnknownSym");
W.printEnum("Kind", uint16_t(Kind), getSymbolTypeNames());
W.printNumber("Length", uint32_t(Data.size()));
W.printEnum("Kind", uint16_t(CVR.kind()), getSymbolTypeNames());
W.printNumber("Length", CVR.length());
return Error::success();
}
bool CVSymbolDumper::dump(const CVRecord<SymbolKind> &Record) {
Error CVSymbolDumper::dump(CVRecord<SymbolKind> &Record) {
SymbolVisitorCallbackPipeline Pipeline;
SymbolDeserializer Deserializer(ObjDelegate.get());
CVSymbolDumperImpl Dumper(CVTD, ObjDelegate.get(), W, PrintRecordBytes);
Dumper.visitSymbolRecord(Record);
return !Dumper.hadError();
Pipeline.addCallbackToPipeline(Deserializer);
Pipeline.addCallbackToPipeline(Dumper);
CVSymbolVisitor Visitor(Pipeline);
return Visitor.visitSymbolRecord(Record);
}
bool CVSymbolDumper::dump(const CVSymbolArray &Symbols) {
Error CVSymbolDumper::dump(const CVSymbolArray &Symbols) {
SymbolVisitorCallbackPipeline Pipeline;
SymbolDeserializer Deserializer(ObjDelegate.get());
CVSymbolDumperImpl Dumper(CVTD, ObjDelegate.get(), W, PrintRecordBytes);
Dumper.visitSymbolStream(Symbols);
return !Dumper.hadError();
Pipeline.addCallbackToPipeline(Deserializer);
Pipeline.addCallbackToPipeline(Dumper);
CVSymbolVisitor Visitor(Pipeline);
return Visitor.visitSymbolStream(Symbols);
}

View File

@ -598,11 +598,15 @@ Error LLVMOutputStyle::dumpDbiStream() {
ListScope SS(P, "Symbols");
codeview::CVSymbolDumper SD(P, Dumper, nullptr, false);
bool HadError = false;
for (const auto &S : ModS.symbols(&HadError)) {
DictScope DD(P, "");
if (opts::raw::DumpModuleSyms)
SD.dump(S);
for (auto S : ModS.symbols(&HadError)) {
DictScope LL(P, "");
if (opts::raw::DumpModuleSyms) {
if (auto EC = SD.dump(S)) {
llvm::consumeError(std::move(EC));
HadError = true;
break;
}
}
if (opts::raw::DumpSymRecordBytes)
P.printBinaryBlock("Bytes", S.content());
}
@ -811,7 +815,10 @@ Error LLVMOutputStyle::dumpPublicsStream() {
for (auto S : Publics->getSymbols(&HadError)) {
DictScope DD(P, "");
SD.dump(S);
if (auto EC = SD.dump(S)) {
HadError = true;
break;
}
if (opts::raw::DumpSymRecordBytes)
P.printBinaryBlock("Bytes", S.content());
}

View File

@ -26,6 +26,7 @@
#include "llvm/DebugInfo/CodeView/Line.h"
#include "llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h"
#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
#include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h"
#include "llvm/DebugInfo/CodeView/SymbolDumper.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
@ -965,9 +966,9 @@ void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection,
error(object_error::parse_failed);
}
if (!CVSD.dump(Symbols)) {
if (auto EC = CVSD.dump(Symbols)) {
W.flush();
error(object_error::parse_failed);
error(std::move(EC));
}
W.flush();
}