forked from OSchip/llvm-project
Make a symbol visitor and use it to dump CV symbols.
Differential Revision: http://reviews.llvm.org/D20534 Reviewed By: rnk llvm-svn: 270511
This commit is contained in:
parent
a5690b00af
commit
aaad57440d
|
@ -30,7 +30,6 @@ CV_SYMBOL(S_REGISTER_16t , 0x0002)
|
|||
CV_SYMBOL(S_CONSTANT_16t , 0x0003)
|
||||
CV_SYMBOL(S_UDT_16t , 0x0004)
|
||||
CV_SYMBOL(S_SSEARCH , 0x0005)
|
||||
CV_SYMBOL(S_END , 0x0006)
|
||||
CV_SYMBOL(S_SKIP , 0x0007)
|
||||
CV_SYMBOL(S_CVRESERVE , 0x0008)
|
||||
CV_SYMBOL(S_OBJNAME_ST , 0x0009)
|
||||
|
@ -179,12 +178,6 @@ CV_SYMBOL(S_GPROCMIPS_ID , 0x1149)
|
|||
CV_SYMBOL(S_LPROCIA64_ID , 0x114a)
|
||||
CV_SYMBOL(S_GPROCIA64_ID , 0x114b)
|
||||
|
||||
// Inlined call site delimiters.
|
||||
CV_SYMBOL(S_INLINESITE_END , 0x114e)
|
||||
|
||||
// Procedure info end delimiter.
|
||||
CV_SYMBOL(S_PROC_ID_END , 0x114f)
|
||||
|
||||
CV_SYMBOL(S_DEFRANGE_HLSL , 0x1150)
|
||||
CV_SYMBOL(S_GDATA_HLSL , 0x1151)
|
||||
CV_SYMBOL(S_LDATA_HLSL , 0x1152)
|
||||
|
@ -193,8 +186,6 @@ CV_SYMBOL(S_LOCAL_DPC_GROUPSHARED, 0x1154)
|
|||
CV_SYMBOL(S_DEFRANGE_DPC_PTR_TAG, 0x1157)
|
||||
CV_SYMBOL(S_DPC_SYM_TAG_MAP, 0x1158)
|
||||
CV_SYMBOL(S_ARMSWITCHTABLE , 0x1159)
|
||||
CV_SYMBOL(S_CALLEES , 0x115a)
|
||||
CV_SYMBOL(S_CALLERS , 0x115b)
|
||||
CV_SYMBOL(S_POGODATA , 0x115c)
|
||||
CV_SYMBOL(S_INLINESITE2 , 0x115d)
|
||||
CV_SYMBOL(S_MOD_TYPEREF , 0x115f)
|
||||
|
@ -206,19 +197,24 @@ CV_SYMBOL(S_GDATA_HLSL32_EX, 0x1164)
|
|||
CV_SYMBOL(S_LDATA_HLSL32_EX, 0x1165)
|
||||
|
||||
// Known symbol types
|
||||
SYMBOL_RECORD(S_END , 0x0006, ScopeEndSym)
|
||||
SYMBOL_RECORD_ALIAS(S_INLINESITE_END , 0x114e, InlineSiteEnd, ScopeEndSym)
|
||||
SYMBOL_RECORD_ALIAS(S_PROC_ID_END , 0x114f, ProcEnd, ScopeEndSym)
|
||||
|
||||
SYMBOL_RECORD(S_LPROC32 , 0x110f, ProcSym)
|
||||
SYMBOL_RECORD_ALIAS(S_GPROC32 , 0x1110, GlobalProcSym, ProcSym)
|
||||
SYMBOL_RECORD_ALIAS(S_LPROC32_ID , 0x1146, ProcIdSym, ProcSym)
|
||||
SYMBOL_RECORD_ALIAS(S_GPROC32_ID , 0x1147, GlobalProcIdSym, ProcSym)
|
||||
SYMBOL_RECORD_ALIAS(S_LPROC32_DPC , 0x1155, DPCProcSym, ProcSym)
|
||||
SYMBOL_RECORD_ALIAS(S_LPROC32_DPC_ID , 0x1156, DPCProcIdSym, ProcSym)
|
||||
|
||||
SYMBOL_RECORD(S_INLINESITE , 0x114d, InlineSiteSym)
|
||||
SYMBOL_RECORD(S_LOCAL , 0x113e, LocalSym)
|
||||
SYMBOL_RECORD(S_DEFRANGE , 0x113f, DefRangeSym)
|
||||
SYMBOL_RECORD(S_DEFRANGE_SUBFIELD, 0x1140, DefRangeSubfieldSym)
|
||||
SYMBOL_RECORD(S_DEFRANGE_REGISTER, 0x1141, DefRangeRegisterSym)
|
||||
SYMBOL_RECORD(S_DEFRANGE_FRAMEPOINTER_REL, 0x1142, DefRangeSubfieldRegisterSym)
|
||||
SYMBOL_RECORD(S_DEFRANGE_SUBFIELD_REGISTER, 0x1143, DefRangeFramePointerRelSym)
|
||||
SYMBOL_RECORD(S_DEFRANGE_FRAMEPOINTER_REL, 0x1142, DefRangeFramePointerRelSym)
|
||||
SYMBOL_RECORD(S_DEFRANGE_SUBFIELD_REGISTER, 0x1143, DefRangeSubfieldRegisterSym)
|
||||
SYMBOL_RECORD(S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE, 0x1144, DefRangeFramePointerRelFullScopeSym)
|
||||
SYMBOL_RECORD(S_DEFRANGE_REGISTER_REL, 0x1145, DefRangeRegisterRelSym)
|
||||
SYMBOL_RECORD(S_BLOCK32 , 0x1103, BlockSym)
|
||||
|
@ -229,17 +225,25 @@ SYMBOL_RECORD(S_FRAMEPROC , 0x1012, FrameProcSym)
|
|||
SYMBOL_RECORD(S_CALLSITEINFO , 0x1139, CallSiteInfoSym)
|
||||
SYMBOL_RECORD(S_HEAPALLOCSITE , 0x115e, HeapAllocationSiteSym)
|
||||
SYMBOL_RECORD(S_FRAMECOOKIE , 0x113a, FrameCookieSym)
|
||||
|
||||
SYMBOL_RECORD(S_CALLEES , 0x115a, CallerSym)
|
||||
SYMBOL_RECORD_ALIAS(S_CALLERS , 0x115b, CalleeSym, CallerSym)
|
||||
|
||||
SYMBOL_RECORD(S_UDT , 0x1108, UDTSym)
|
||||
SYMBOL_RECORD_ALIAS(S_COBOLUDT , 0x1109, CobolUDT, UDTSym)
|
||||
|
||||
SYMBOL_RECORD(S_BUILDINFO , 0x114c, BuildInfoSym)
|
||||
SYMBOL_RECORD(S_BPREL32 , 0x110b, BPRelativeSym)
|
||||
SYMBOL_RECORD(S_REGREL32 , 0x1111, RegRelativeSym)
|
||||
|
||||
SYMBOL_RECORD(S_CONSTANT , 0x1107, ConstantSym)
|
||||
SYMBOL_RECORD_ALIAS(S_MANCONSTANT , 0x112d, ManagedConstant, ConstantSym)
|
||||
|
||||
SYMBOL_RECORD(S_LDATA32 , 0x110c, DataSym)
|
||||
SYMBOL_RECORD_ALIAS(S_GDATA32 , 0x110d, GlobalData, DataSym)
|
||||
SYMBOL_RECORD_ALIAS(S_LMANDATA , 0x111c, ManagedLocalData, DataSym)
|
||||
SYMBOL_RECORD_ALIAS(S_GMANDATA , 0x111d, ManagedGlobalData, DataSym)
|
||||
|
||||
SYMBOL_RECORD(S_LTHREAD32 , 0x1112, ThreadLocalDataSym)
|
||||
SYMBOL_RECORD_ALIAS(S_GTHREAD32 , 0x1113, GlobalTLS, ThreadLocalDataSym)
|
||||
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
//===- CVSymbolVisitor.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_CVSYMBOLVISITOR_H
|
||||
#define LLVM_DEBUGINFO_CODEVIEW_CVSYMBOLVISITOR_H
|
||||
|
||||
#include "llvm/DebugInfo/CodeView/CodeView.h"
|
||||
#include "llvm/DebugInfo/CodeView/RecordIterator.h"
|
||||
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
|
||||
#include "llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h"
|
||||
#include "llvm/Support/ErrorOr.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace codeview {
|
||||
|
||||
template <typename Derived> class CVSymbolVisitor {
|
||||
public:
|
||||
CVSymbolVisitor(SymbolVisitorDelegate *Delegate) : Delegate(Delegate) {}
|
||||
|
||||
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 SymbolIterator::Record &Record) {
|
||||
ArrayRef<uint8_t> Data = Record.Data;
|
||||
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 Result = Name::deserialize(RK, RecordOffset, Data); \
|
||||
if (Result.getError()) \
|
||||
return parseError(); \
|
||||
DerivedThis->visit##Name(Record.Type, *Result); \
|
||||
break; \
|
||||
}
|
||||
#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
|
||||
SYMBOL_RECORD(EnumVal, EnumVal, AliasName)
|
||||
#include "CVSymbolTypes.def"
|
||||
}
|
||||
DerivedThis->visitSymbolEnd(Record.Type, Record.Data);
|
||||
}
|
||||
|
||||
/// Visits the symbol records in Data. Sets the error flag on parse failures.
|
||||
void visitSymbolStream(ArrayRef<uint8_t> Data) {
|
||||
for (const auto &I : makeSymbolRange(Data, &HadError)) {
|
||||
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; }
|
||||
|
||||
private:
|
||||
SymbolVisitorDelegate *Delegate;
|
||||
/// Whether a symbol stream parsing error was encountered.
|
||||
bool HadError = false;
|
||||
};
|
||||
|
||||
} // end namespace codeview
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_DEBUGINFO_CODEVIEW_CVSYMBOLVISITOR_H
|
|
@ -0,0 +1,37 @@
|
|||
//===-- SymbolDumpDelegate.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_SYMBOLDUMPDELEGATE_H
|
||||
#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLDUMPDELEGATE_H
|
||||
|
||||
#include "SymbolVisitorDelegate.h"
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
namespace codeview {
|
||||
|
||||
class SymbolDumpDelegate : public SymbolVisitorDelegate {
|
||||
public:
|
||||
virtual ~SymbolDumpDelegate() {}
|
||||
|
||||
virtual void printRelocatedField(StringRef Label, uint32_t RelocOffset,
|
||||
uint32_t Offset,
|
||||
StringRef *RelocSym = nullptr) = 0;
|
||||
virtual void printBinaryBlockWithRelocs(StringRef Label,
|
||||
ArrayRef<uint8_t> Block) = 0;
|
||||
};
|
||||
} // end namespace codeview
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLDUMPDELEGATE_H
|
|
@ -0,0 +1,54 @@
|
|||
//===-- SymbolDumper.h - CodeView symbol info dumper ------------*- 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_SYMBOLDUMPER_H
|
||||
#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLDUMPER_H
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/StringSet.h"
|
||||
#include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h"
|
||||
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
|
||||
|
||||
namespace llvm {
|
||||
class ScopedPrinter;
|
||||
|
||||
namespace codeview {
|
||||
class CVTypeDumper;
|
||||
|
||||
/// Dumper for CodeView symbol streams found in COFF object files and PDB files.
|
||||
class CVSymbolDumper {
|
||||
public:
|
||||
CVSymbolDumper(ScopedPrinter &W, CVTypeDumper &CVTD,
|
||||
std::unique_ptr<SymbolDumpDelegate> ObjDelegate,
|
||||
bool PrintRecordBytes)
|
||||
: W(W), CVTD(CVTD), ObjDelegate(std::move(ObjDelegate)),
|
||||
PrintRecordBytes(PrintRecordBytes) {}
|
||||
|
||||
/// Dumps one type record. Returns false if there was a type parsing error,
|
||||
/// 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 SymbolIterator::Record &Record);
|
||||
|
||||
/// Dumps the type records in Data. Returns false if there was a type stream
|
||||
/// parse error, and true otherwise.
|
||||
bool dump(ArrayRef<uint8_t> Data);
|
||||
|
||||
private:
|
||||
ScopedPrinter &W;
|
||||
CVTypeDumper &CVTD;
|
||||
std::unique_ptr<SymbolDumpDelegate> ObjDelegate;
|
||||
|
||||
bool PrintRecordBytes;
|
||||
};
|
||||
} // end namespace codeview
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLDUMPER_H
|
|
@ -79,6 +79,46 @@ public:
|
|||
StringRef Name;
|
||||
};
|
||||
|
||||
class ScopeEndSym : public SymbolRecord {
|
||||
public:
|
||||
ScopeEndSym(SymbolRecordKind Kind, uint32_t RecordOffset)
|
||||
: SymbolRecord(Kind), RecordOffset(RecordOffset) {}
|
||||
|
||||
static ErrorOr<ScopeEndSym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
return ScopeEndSym(Kind, RecordOffset);
|
||||
}
|
||||
uint32_t RecordOffset;
|
||||
};
|
||||
|
||||
class CallerSym : public SymbolRecord {
|
||||
public:
|
||||
struct Hdr {
|
||||
uint32_t Count;
|
||||
};
|
||||
|
||||
CallerSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *Header,
|
||||
ArrayRef<TypeIndex> Indices)
|
||||
: SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*Header),
|
||||
Indices(Indices) {}
|
||||
|
||||
static ErrorOr<CallerSym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
const Hdr *Header;
|
||||
ArrayRef<TypeIndex> Indices;
|
||||
|
||||
CV_DESERIALIZE(Data, Header, CV_ARRAY_FIELD_N(Indices, Header->Count));
|
||||
|
||||
return CallerSym(Kind, RecordOffset, Header, Indices);
|
||||
}
|
||||
|
||||
Hdr Header;
|
||||
uint32_t RecordOffset;
|
||||
ArrayRef<TypeIndex> Indices;
|
||||
};
|
||||
|
||||
struct BinaryAnnotationIterator {
|
||||
struct AnnotationData {
|
||||
BinaryAnnotationsOpCode OpCode;
|
||||
|
@ -697,7 +737,7 @@ public:
|
|||
};
|
||||
|
||||
// S_COMPILE3
|
||||
class CompileSym3 : public SymbolRecord {
|
||||
class Compile3Sym : public SymbolRecord {
|
||||
public:
|
||||
struct Hdr {
|
||||
ulittle32_t flags; // CompileSym3Flags enum
|
||||
|
@ -714,18 +754,18 @@ public:
|
|||
// VersionString: The null-terminated version string follows.
|
||||
};
|
||||
|
||||
CompileSym3(uint32_t RecordOffset, const Hdr *H, StringRef Version)
|
||||
Compile3Sym(uint32_t RecordOffset, const Hdr *H, StringRef Version)
|
||||
: SymbolRecord(SymbolRecordKind::Compile3Sym), RecordOffset(RecordOffset),
|
||||
Header(*H), Version(Version) {}
|
||||
|
||||
static ErrorOr<CompileSym3> deserialize(SymbolRecordKind Kind,
|
||||
static ErrorOr<Compile3Sym> deserialize(SymbolRecordKind Kind,
|
||||
uint32_t RecordOffset,
|
||||
ArrayRef<uint8_t> &Data) {
|
||||
const Hdr *H = nullptr;
|
||||
StringRef Version;
|
||||
CV_DESERIALIZE(Data, H, Version);
|
||||
|
||||
return CompileSym3(RecordOffset, H, Version);
|
||||
return Compile3Sym(RecordOffset, H, Version);
|
||||
}
|
||||
|
||||
uint32_t RecordOffset;
|
||||
|
@ -1060,10 +1100,11 @@ public:
|
|||
StringRef Name;
|
||||
};
|
||||
|
||||
typedef RecordIterator<SymbolRecordKind> SymbolIterator;
|
||||
typedef RecordIterator<SymbolKind> SymbolIterator;
|
||||
|
||||
inline iterator_range<SymbolIterator> makeSymbolRange(ArrayRef<uint8_t> Data) {
|
||||
return make_range(SymbolIterator(Data, nullptr), SymbolIterator());
|
||||
inline iterator_range<SymbolIterator> makeSymbolRange(ArrayRef<uint8_t> Data,
|
||||
bool *HadError) {
|
||||
return make_range(SymbolIterator(Data, HadError), SymbolIterator());
|
||||
}
|
||||
|
||||
} // namespace codeview
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
//===-- SymbolVisitorDelegate.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_SYMBOLVISITORDELEGATE_H
|
||||
#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLVISITORDELEGATE_H
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
namespace codeview {
|
||||
|
||||
class SymbolVisitorDelegate {
|
||||
public:
|
||||
virtual ~SymbolVisitorDelegate() {}
|
||||
|
||||
virtual uint32_t getRecordOffset(ArrayRef<uint8_t> Record) = 0;
|
||||
virtual StringRef getFileNameForFileOffset(uint32_t FileOffset) = 0;
|
||||
virtual StringRef getStringTable() = 0;
|
||||
};
|
||||
} // end namespace codeview
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLVISITORDELEGATE_H
|
|
@ -5,6 +5,7 @@ add_llvm_library(LLVMDebugInfoCodeView
|
|||
MemoryTypeTableBuilder.cpp
|
||||
MethodListRecordBuilder.cpp
|
||||
RecordSerialization.cpp
|
||||
SymbolDumper.cpp
|
||||
TypeDumper.cpp
|
||||
TypeRecord.cpp
|
||||
TypeRecordBuilder.cpp
|
||||
|
|
|
@ -0,0 +1,670 @@
|
|||
//===-- SymbolDumper.cpp - CodeView symbol info dumper ----------*- 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/SymbolDumper.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
|
||||
#include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h"
|
||||
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeDumper.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
|
||||
#include "llvm/Support/ScopedPrinter.h"
|
||||
|
||||
#include <system_error>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::codeview;
|
||||
|
||||
static const EnumEntry<SymbolKind> SymbolTypeNames[] = {
|
||||
#define CV_SYMBOL(enum, val) {#enum, enum},
|
||||
#include "llvm/DebugInfo/CodeView/CVSymbolTypes.def"
|
||||
};
|
||||
|
||||
namespace {
|
||||
#define CV_ENUM_CLASS_ENT(enum_class, enum) \
|
||||
{ #enum, std::underlying_type < enum_class > ::type(enum_class::enum) }
|
||||
|
||||
#define CV_ENUM_ENT(ns, enum) \
|
||||
{ #enum, ns::enum }
|
||||
|
||||
static const EnumEntry<uint8_t> ProcSymFlagNames[] = {
|
||||
CV_ENUM_CLASS_ENT(ProcSymFlags, HasFP),
|
||||
CV_ENUM_CLASS_ENT(ProcSymFlags, HasIRET),
|
||||
CV_ENUM_CLASS_ENT(ProcSymFlags, HasFRET),
|
||||
CV_ENUM_CLASS_ENT(ProcSymFlags, IsNoReturn),
|
||||
CV_ENUM_CLASS_ENT(ProcSymFlags, IsUnreachable),
|
||||
CV_ENUM_CLASS_ENT(ProcSymFlags, HasCustomCallingConv),
|
||||
CV_ENUM_CLASS_ENT(ProcSymFlags, IsNoInline),
|
||||
CV_ENUM_CLASS_ENT(ProcSymFlags, HasOptimizedDebugInfo),
|
||||
};
|
||||
|
||||
static const EnumEntry<uint16_t> LocalFlags[] = {
|
||||
CV_ENUM_CLASS_ENT(LocalSymFlags, IsParameter),
|
||||
CV_ENUM_CLASS_ENT(LocalSymFlags, IsAddressTaken),
|
||||
CV_ENUM_CLASS_ENT(LocalSymFlags, IsCompilerGenerated),
|
||||
CV_ENUM_CLASS_ENT(LocalSymFlags, IsAggregate),
|
||||
CV_ENUM_CLASS_ENT(LocalSymFlags, IsAggregated),
|
||||
CV_ENUM_CLASS_ENT(LocalSymFlags, IsAliased),
|
||||
CV_ENUM_CLASS_ENT(LocalSymFlags, IsAlias),
|
||||
CV_ENUM_CLASS_ENT(LocalSymFlags, IsReturnValue),
|
||||
CV_ENUM_CLASS_ENT(LocalSymFlags, IsOptimizedOut),
|
||||
CV_ENUM_CLASS_ENT(LocalSymFlags, IsEnregisteredGlobal),
|
||||
CV_ENUM_CLASS_ENT(LocalSymFlags, IsEnregisteredStatic),
|
||||
};
|
||||
|
||||
static const EnumEntry<uint32_t> FrameCookieKinds[] = {
|
||||
CV_ENUM_CLASS_ENT(FrameCookieKind, Copy),
|
||||
CV_ENUM_CLASS_ENT(FrameCookieKind, XorStackPointer),
|
||||
CV_ENUM_CLASS_ENT(FrameCookieKind, XorFramePointer),
|
||||
CV_ENUM_CLASS_ENT(FrameCookieKind, XorR13),
|
||||
};
|
||||
|
||||
static const EnumEntry<codeview::SourceLanguage> SourceLanguages[] = {
|
||||
CV_ENUM_ENT(SourceLanguage, C), CV_ENUM_ENT(SourceLanguage, Cpp),
|
||||
CV_ENUM_ENT(SourceLanguage, Fortran), CV_ENUM_ENT(SourceLanguage, Masm),
|
||||
CV_ENUM_ENT(SourceLanguage, Pascal), CV_ENUM_ENT(SourceLanguage, Basic),
|
||||
CV_ENUM_ENT(SourceLanguage, Cobol), CV_ENUM_ENT(SourceLanguage, Link),
|
||||
CV_ENUM_ENT(SourceLanguage, Cvtres), CV_ENUM_ENT(SourceLanguage, Cvtpgd),
|
||||
CV_ENUM_ENT(SourceLanguage, CSharp), CV_ENUM_ENT(SourceLanguage, VB),
|
||||
CV_ENUM_ENT(SourceLanguage, ILAsm), CV_ENUM_ENT(SourceLanguage, Java),
|
||||
CV_ENUM_ENT(SourceLanguage, JScript), CV_ENUM_ENT(SourceLanguage, MSIL),
|
||||
CV_ENUM_ENT(SourceLanguage, HLSL),
|
||||
};
|
||||
|
||||
static const EnumEntry<uint32_t> CompileSym3FlagNames[] = {
|
||||
CV_ENUM_CLASS_ENT(CompileSym3Flags, EC),
|
||||
CV_ENUM_CLASS_ENT(CompileSym3Flags, NoDbgInfo),
|
||||
CV_ENUM_CLASS_ENT(CompileSym3Flags, LTCG),
|
||||
CV_ENUM_CLASS_ENT(CompileSym3Flags, NoDataAlign),
|
||||
CV_ENUM_CLASS_ENT(CompileSym3Flags, ManagedPresent),
|
||||
CV_ENUM_CLASS_ENT(CompileSym3Flags, SecurityChecks),
|
||||
CV_ENUM_CLASS_ENT(CompileSym3Flags, HotPatch),
|
||||
CV_ENUM_CLASS_ENT(CompileSym3Flags, CVTCIL),
|
||||
CV_ENUM_CLASS_ENT(CompileSym3Flags, MSILModule),
|
||||
CV_ENUM_CLASS_ENT(CompileSym3Flags, Sdl),
|
||||
CV_ENUM_CLASS_ENT(CompileSym3Flags, PGO),
|
||||
CV_ENUM_CLASS_ENT(CompileSym3Flags, Exp),
|
||||
};
|
||||
|
||||
static const EnumEntry<unsigned> CPUTypeNames[] = {
|
||||
CV_ENUM_CLASS_ENT(CPUType, Intel8080),
|
||||
CV_ENUM_CLASS_ENT(CPUType, Intel8086),
|
||||
CV_ENUM_CLASS_ENT(CPUType, Intel80286),
|
||||
CV_ENUM_CLASS_ENT(CPUType, Intel80386),
|
||||
CV_ENUM_CLASS_ENT(CPUType, Intel80486),
|
||||
CV_ENUM_CLASS_ENT(CPUType, Pentium),
|
||||
CV_ENUM_CLASS_ENT(CPUType, PentiumPro),
|
||||
CV_ENUM_CLASS_ENT(CPUType, Pentium3),
|
||||
CV_ENUM_CLASS_ENT(CPUType, MIPS),
|
||||
CV_ENUM_CLASS_ENT(CPUType, MIPS16),
|
||||
CV_ENUM_CLASS_ENT(CPUType, MIPS32),
|
||||
CV_ENUM_CLASS_ENT(CPUType, MIPS64),
|
||||
CV_ENUM_CLASS_ENT(CPUType, MIPSI),
|
||||
CV_ENUM_CLASS_ENT(CPUType, MIPSII),
|
||||
CV_ENUM_CLASS_ENT(CPUType, MIPSIII),
|
||||
CV_ENUM_CLASS_ENT(CPUType, MIPSIV),
|
||||
CV_ENUM_CLASS_ENT(CPUType, MIPSV),
|
||||
CV_ENUM_CLASS_ENT(CPUType, M68000),
|
||||
CV_ENUM_CLASS_ENT(CPUType, M68010),
|
||||
CV_ENUM_CLASS_ENT(CPUType, M68020),
|
||||
CV_ENUM_CLASS_ENT(CPUType, M68030),
|
||||
CV_ENUM_CLASS_ENT(CPUType, M68040),
|
||||
CV_ENUM_CLASS_ENT(CPUType, Alpha),
|
||||
CV_ENUM_CLASS_ENT(CPUType, Alpha21164),
|
||||
CV_ENUM_CLASS_ENT(CPUType, Alpha21164A),
|
||||
CV_ENUM_CLASS_ENT(CPUType, Alpha21264),
|
||||
CV_ENUM_CLASS_ENT(CPUType, Alpha21364),
|
||||
CV_ENUM_CLASS_ENT(CPUType, PPC601),
|
||||
CV_ENUM_CLASS_ENT(CPUType, PPC603),
|
||||
CV_ENUM_CLASS_ENT(CPUType, PPC604),
|
||||
CV_ENUM_CLASS_ENT(CPUType, PPC620),
|
||||
CV_ENUM_CLASS_ENT(CPUType, PPCFP),
|
||||
CV_ENUM_CLASS_ENT(CPUType, PPCBE),
|
||||
CV_ENUM_CLASS_ENT(CPUType, SH3),
|
||||
CV_ENUM_CLASS_ENT(CPUType, SH3E),
|
||||
CV_ENUM_CLASS_ENT(CPUType, SH3DSP),
|
||||
CV_ENUM_CLASS_ENT(CPUType, SH4),
|
||||
CV_ENUM_CLASS_ENT(CPUType, SHMedia),
|
||||
CV_ENUM_CLASS_ENT(CPUType, ARM3),
|
||||
CV_ENUM_CLASS_ENT(CPUType, ARM4),
|
||||
CV_ENUM_CLASS_ENT(CPUType, ARM4T),
|
||||
CV_ENUM_CLASS_ENT(CPUType, ARM5),
|
||||
CV_ENUM_CLASS_ENT(CPUType, ARM5T),
|
||||
CV_ENUM_CLASS_ENT(CPUType, ARM6),
|
||||
CV_ENUM_CLASS_ENT(CPUType, ARM_XMAC),
|
||||
CV_ENUM_CLASS_ENT(CPUType, ARM_WMMX),
|
||||
CV_ENUM_CLASS_ENT(CPUType, ARM7),
|
||||
CV_ENUM_CLASS_ENT(CPUType, Omni),
|
||||
CV_ENUM_CLASS_ENT(CPUType, Ia64),
|
||||
CV_ENUM_CLASS_ENT(CPUType, Ia64_2),
|
||||
CV_ENUM_CLASS_ENT(CPUType, CEE),
|
||||
CV_ENUM_CLASS_ENT(CPUType, AM33),
|
||||
CV_ENUM_CLASS_ENT(CPUType, M32R),
|
||||
CV_ENUM_CLASS_ENT(CPUType, TriCore),
|
||||
CV_ENUM_CLASS_ENT(CPUType, X64),
|
||||
CV_ENUM_CLASS_ENT(CPUType, EBC),
|
||||
CV_ENUM_CLASS_ENT(CPUType, Thumb),
|
||||
CV_ENUM_CLASS_ENT(CPUType, ARMNT),
|
||||
CV_ENUM_CLASS_ENT(CPUType, D3D11_Shader),
|
||||
};
|
||||
|
||||
static const EnumEntry<uint32_t> FrameProcSymFlags[] = {
|
||||
CV_ENUM_CLASS_ENT(FrameProcedureOptions, HasAlloca),
|
||||
CV_ENUM_CLASS_ENT(FrameProcedureOptions, HasSetJmp),
|
||||
CV_ENUM_CLASS_ENT(FrameProcedureOptions, HasLongJmp),
|
||||
CV_ENUM_CLASS_ENT(FrameProcedureOptions, HasInlineAssembly),
|
||||
CV_ENUM_CLASS_ENT(FrameProcedureOptions, HasExceptionHandling),
|
||||
CV_ENUM_CLASS_ENT(FrameProcedureOptions, MarkedInline),
|
||||
CV_ENUM_CLASS_ENT(FrameProcedureOptions, HasStructuredExceptionHandling),
|
||||
CV_ENUM_CLASS_ENT(FrameProcedureOptions, Naked),
|
||||
CV_ENUM_CLASS_ENT(FrameProcedureOptions, SecurityChecks),
|
||||
CV_ENUM_CLASS_ENT(FrameProcedureOptions, AsynchronousExceptionHandling),
|
||||
CV_ENUM_CLASS_ENT(FrameProcedureOptions, NoStackOrderingForSecurityChecks),
|
||||
CV_ENUM_CLASS_ENT(FrameProcedureOptions, Inlined),
|
||||
CV_ENUM_CLASS_ENT(FrameProcedureOptions, StrictSecurityChecks),
|
||||
CV_ENUM_CLASS_ENT(FrameProcedureOptions, SafeBuffers),
|
||||
CV_ENUM_CLASS_ENT(FrameProcedureOptions, ProfileGuidedOptimization),
|
||||
CV_ENUM_CLASS_ENT(FrameProcedureOptions, ValidProfileCounts),
|
||||
CV_ENUM_CLASS_ENT(FrameProcedureOptions, OptimizedForSpeed),
|
||||
CV_ENUM_CLASS_ENT(FrameProcedureOptions, GuardCfg),
|
||||
CV_ENUM_CLASS_ENT(FrameProcedureOptions, GuardCfw),
|
||||
};
|
||||
|
||||
/// Use this private dumper implementation to keep implementation details about
|
||||
/// the visitor out of SymbolDumper.h.
|
||||
class CVSymbolDumperImpl : public CVSymbolVisitor<CVSymbolDumperImpl> {
|
||||
public:
|
||||
CVSymbolDumperImpl(CVSymbolDumper &CVSD, CVTypeDumper &CVTD,
|
||||
SymbolDumpDelegate *ObjDelegate, ScopedPrinter &W,
|
||||
bool PrintRecordBytes)
|
||||
: CVSymbolVisitor(ObjDelegate), CVSD(CVSD), 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);
|
||||
#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);
|
||||
|
||||
private:
|
||||
void printLocalVariableAddrRange(const LocalVariableAddrRange &Range,
|
||||
uint32_t RelocationOffset);
|
||||
void printLocalVariableAddrGap(ArrayRef<LocalVariableAddrGap> Gaps);
|
||||
|
||||
CVSymbolDumper &CVSD;
|
||||
CVTypeDumper &CVTD;
|
||||
SymbolDumpDelegate *ObjDelegate;
|
||||
ScopedPrinter &W;
|
||||
|
||||
bool PrintRecordBytes;
|
||||
bool InFunctionScope;
|
||||
};
|
||||
}
|
||||
|
||||
void CVSymbolDumperImpl::printLocalVariableAddrRange(
|
||||
const LocalVariableAddrRange &Range, uint32_t RelocationOffset) {
|
||||
DictScope S(W, "LocalVariableAddrRange");
|
||||
if (ObjDelegate)
|
||||
ObjDelegate->printRelocatedField("OffsetStart", RelocationOffset,
|
||||
Range.OffsetStart);
|
||||
W.printHex("ISectStart", Range.ISectStart);
|
||||
W.printHex("Range", Range.Range);
|
||||
}
|
||||
|
||||
void CVSymbolDumperImpl::printLocalVariableAddrGap(
|
||||
ArrayRef<LocalVariableAddrGap> Gaps) {
|
||||
for (auto &Gap : Gaps) {
|
||||
ListScope S(W, "LocalVariableAddrGap");
|
||||
W.printHex("GapStartOffset", Gap.GapStartOffset);
|
||||
W.printHex("Range", Gap.Range);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void CVSymbolDumperImpl::visitBlockSym(SymbolKind Kind, BlockSym &Block) {
|
||||
DictScope S(W, "BlockStart");
|
||||
|
||||
StringRef LinkageName;
|
||||
W.printHex("PtrParent", Block.Header.PtrParent);
|
||||
W.printHex("PtrEnd", Block.Header.PtrEnd);
|
||||
W.printHex("CodeSize", Block.Header.CodeSize);
|
||||
if (ObjDelegate) {
|
||||
ObjDelegate->printRelocatedField("CodeOffset", Block.getRelocationOffset(),
|
||||
Block.Header.CodeOffset, &LinkageName);
|
||||
}
|
||||
W.printHex("Segment", Block.Header.Segment);
|
||||
W.printString("BlockName", Block.Name);
|
||||
W.printString("LinkageName", LinkageName);
|
||||
}
|
||||
|
||||
void CVSymbolDumperImpl::visitBPRelativeSym(SymbolKind Kind,
|
||||
BPRelativeSym &BPRel) {
|
||||
DictScope S(W, "BPRelativeSym");
|
||||
|
||||
W.printNumber("Offset", BPRel.Header.Offset);
|
||||
CVTD.printTypeIndex("Type", BPRel.Header.Type);
|
||||
W.printString("VarName", BPRel.Name);
|
||||
}
|
||||
|
||||
void CVSymbolDumperImpl::visitBuildInfoSym(SymbolKind Kind,
|
||||
BuildInfoSym &BuildInfo) {
|
||||
DictScope S(W, "BuildInfo");
|
||||
|
||||
W.printNumber("BuildId", BuildInfo.Header.BuildId);
|
||||
}
|
||||
|
||||
void CVSymbolDumperImpl::visitCallSiteInfoSym(SymbolKind Kind,
|
||||
CallSiteInfoSym &CallSiteInfo) {
|
||||
DictScope S(W, "CallSiteInfo");
|
||||
|
||||
StringRef LinkageName;
|
||||
if (ObjDelegate) {
|
||||
ObjDelegate->printRelocatedField(
|
||||
"CodeOffset", CallSiteInfo.getRelocationOffset(),
|
||||
CallSiteInfo.Header.CodeOffset, &LinkageName);
|
||||
}
|
||||
W.printHex("Segment", CallSiteInfo.Header.Segment);
|
||||
W.printHex("Reserved", CallSiteInfo.Header.Reserved);
|
||||
CVTD.printTypeIndex("Type", CallSiteInfo.Header.Type);
|
||||
if (!LinkageName.empty())
|
||||
W.printString("LinkageName", LinkageName);
|
||||
}
|
||||
|
||||
void CVSymbolDumperImpl::visitCompile3Sym(SymbolKind Kind,
|
||||
Compile3Sym &Compile3) {
|
||||
DictScope S(W, "CompilerFlags");
|
||||
|
||||
W.printEnum("Language", Compile3.Header.getLanguage(),
|
||||
makeArrayRef(SourceLanguages));
|
||||
W.printFlags("Flags", Compile3.Header.flags & ~0xff,
|
||||
makeArrayRef(CompileSym3FlagNames));
|
||||
W.printEnum("Machine", unsigned(Compile3.Header.Machine),
|
||||
makeArrayRef(CPUTypeNames));
|
||||
std::string FrontendVersion;
|
||||
{
|
||||
raw_string_ostream Out(FrontendVersion);
|
||||
Out << Compile3.Header.VersionFrontendMajor << '.'
|
||||
<< Compile3.Header.VersionFrontendMinor << '.'
|
||||
<< Compile3.Header.VersionFrontendBuild << '.'
|
||||
<< Compile3.Header.VersionFrontendQFE;
|
||||
}
|
||||
std::string BackendVersion;
|
||||
{
|
||||
raw_string_ostream Out(BackendVersion);
|
||||
Out << Compile3.Header.VersionBackendMajor << '.'
|
||||
<< Compile3.Header.VersionBackendMinor << '.'
|
||||
<< Compile3.Header.VersionBackendBuild << '.'
|
||||
<< Compile3.Header.VersionBackendQFE;
|
||||
}
|
||||
W.printString("FrontendVersion", FrontendVersion);
|
||||
W.printString("BackendVersion", BackendVersion);
|
||||
W.printString("VersionName", Compile3.Version);
|
||||
}
|
||||
|
||||
void CVSymbolDumperImpl::visitConstantSym(SymbolKind Kind,
|
||||
ConstantSym &Constant) {
|
||||
DictScope S(W, "Constant");
|
||||
|
||||
CVTD.printTypeIndex("Type", Constant.Header.Type);
|
||||
W.printNumber("Value", Constant.Value);
|
||||
W.printString("Name", Constant.Name);
|
||||
}
|
||||
|
||||
void CVSymbolDumperImpl::visitDataSym(SymbolKind Kind, DataSym &Data) {
|
||||
DictScope S(W, "DataSym");
|
||||
|
||||
StringRef LinkageName;
|
||||
if (ObjDelegate) {
|
||||
ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(),
|
||||
Data.Header.DataOffset, &LinkageName);
|
||||
}
|
||||
CVTD.printTypeIndex("Type", Data.Header.Type);
|
||||
W.printString("DisplayName", Data.Name);
|
||||
if (!LinkageName.empty())
|
||||
W.printString("LinkageName", LinkageName);
|
||||
}
|
||||
|
||||
void CVSymbolDumperImpl::visitDefRangeFramePointerRelFullScopeSym(
|
||||
SymbolKind Kind,
|
||||
DefRangeFramePointerRelFullScopeSym &DefRangeFramePointerRelFullScope) {
|
||||
DictScope S(W, "DefRangeFramePointerRelFullScope");
|
||||
W.printNumber("Offset", DefRangeFramePointerRelFullScope.Header.Offset);
|
||||
}
|
||||
|
||||
void CVSymbolDumperImpl::visitDefRangeFramePointerRelSym(
|
||||
SymbolKind Kind, DefRangeFramePointerRelSym &DefRangeFramePointerRel) {
|
||||
DictScope S(W, "DefRangeFramePointerRel");
|
||||
|
||||
W.printNumber("Offset", DefRangeFramePointerRel.Header.Offset);
|
||||
printLocalVariableAddrRange(DefRangeFramePointerRel.Header.Range,
|
||||
DefRangeFramePointerRel.getRelocationOffset());
|
||||
printLocalVariableAddrGap(DefRangeFramePointerRel.Gaps);
|
||||
}
|
||||
|
||||
void CVSymbolDumperImpl::visitDefRangeRegisterRelSym(
|
||||
SymbolKind Kind, DefRangeRegisterRelSym &DefRangeRegisterRel) {
|
||||
DictScope S(W, "DefRangeRegisterRel");
|
||||
|
||||
W.printNumber("BaseRegister", DefRangeRegisterRel.Header.BaseRegister);
|
||||
W.printBoolean("HasSpilledUDTMember",
|
||||
DefRangeRegisterRel.hasSpilledUDTMember());
|
||||
W.printNumber("OffsetInParent", DefRangeRegisterRel.offsetInParent());
|
||||
W.printNumber("BasePointerOffset",
|
||||
DefRangeRegisterRel.Header.BasePointerOffset);
|
||||
printLocalVariableAddrRange(DefRangeRegisterRel.Header.Range,
|
||||
DefRangeRegisterRel.getRelocationOffset());
|
||||
printLocalVariableAddrGap(DefRangeRegisterRel.Gaps);
|
||||
}
|
||||
|
||||
void CVSymbolDumperImpl::visitDefRangeRegisterSym(
|
||||
SymbolKind Kind, DefRangeRegisterSym &DefRangeRegister) {
|
||||
DictScope S(W, "DefRangeRegister");
|
||||
|
||||
W.printNumber("Register", DefRangeRegister.Header.Register);
|
||||
W.printNumber("MayHaveNoName", DefRangeRegister.Header.MayHaveNoName);
|
||||
printLocalVariableAddrRange(DefRangeRegister.Header.Range,
|
||||
DefRangeRegister.getRelocationOffset());
|
||||
printLocalVariableAddrGap(DefRangeRegister.Gaps);
|
||||
}
|
||||
|
||||
void CVSymbolDumperImpl::visitDefRangeSubfieldRegisterSym(
|
||||
SymbolKind Kind, DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) {
|
||||
DictScope S(W, "DefRangeSubfieldRegister");
|
||||
|
||||
W.printNumber("Register", DefRangeSubfieldRegister.Header.Register);
|
||||
W.printNumber("MayHaveNoName", DefRangeSubfieldRegister.Header.MayHaveNoName);
|
||||
W.printNumber("OffsetInParent",
|
||||
DefRangeSubfieldRegister.Header.OffsetInParent);
|
||||
printLocalVariableAddrRange(DefRangeSubfieldRegister.Header.Range,
|
||||
DefRangeSubfieldRegister.getRelocationOffset());
|
||||
printLocalVariableAddrGap(DefRangeSubfieldRegister.Gaps);
|
||||
}
|
||||
|
||||
void CVSymbolDumperImpl::visitDefRangeSubfieldSym(
|
||||
SymbolKind Kind, DefRangeSubfieldSym &DefRangeSubfield) {
|
||||
DictScope S(W, "DefRangeSubfield");
|
||||
|
||||
if (ObjDelegate) {
|
||||
StringRef StringTable = ObjDelegate->getStringTable();
|
||||
if (!StringTable.empty()) {
|
||||
W.printString("Program",
|
||||
StringTable.drop_front(DefRangeSubfield.Header.Program)
|
||||
.split('\0')
|
||||
.first);
|
||||
}
|
||||
}
|
||||
W.printNumber("OffsetInParent", DefRangeSubfield.Header.OffsetInParent);
|
||||
printLocalVariableAddrRange(DefRangeSubfield.Header.Range,
|
||||
DefRangeSubfield.getRelocationOffset());
|
||||
printLocalVariableAddrGap(DefRangeSubfield.Gaps);
|
||||
}
|
||||
|
||||
void CVSymbolDumperImpl::visitDefRangeSym(SymbolKind Kind,
|
||||
DefRangeSym &DefRange) {
|
||||
DictScope S(W, "DefRange");
|
||||
|
||||
if (ObjDelegate) {
|
||||
StringRef StringTable = ObjDelegate->getStringTable();
|
||||
if (!StringTable.empty()) {
|
||||
W.printString(
|
||||
"Program",
|
||||
StringTable.drop_front(DefRange.Header.Program).split('\0').first);
|
||||
}
|
||||
}
|
||||
printLocalVariableAddrRange(DefRange.Header.Range,
|
||||
DefRange.getRelocationOffset());
|
||||
printLocalVariableAddrGap(DefRange.Gaps);
|
||||
}
|
||||
|
||||
void CVSymbolDumperImpl::visitFrameCookieSym(SymbolKind Kind,
|
||||
FrameCookieSym &FrameCookie) {
|
||||
DictScope S(W, "FrameCookie");
|
||||
|
||||
StringRef LinkageName;
|
||||
if (ObjDelegate) {
|
||||
ObjDelegate->printRelocatedField(
|
||||
"CodeOffset", FrameCookie.getRelocationOffset(),
|
||||
FrameCookie.Header.CodeOffset, &LinkageName);
|
||||
}
|
||||
W.printHex("Register", FrameCookie.Header.Register);
|
||||
W.printEnum("CookieKind", uint16_t(FrameCookie.Header.CookieKind),
|
||||
makeArrayRef(FrameCookieKinds));
|
||||
}
|
||||
|
||||
void CVSymbolDumperImpl::visitFrameProcSym(SymbolKind Kind,
|
||||
FrameProcSym &FrameProc) {
|
||||
DictScope S(W, "FrameProc");
|
||||
|
||||
W.printHex("TotalFrameBytes", FrameProc.Header.TotalFrameBytes);
|
||||
W.printHex("PaddingFrameBytes", FrameProc.Header.PaddingFrameBytes);
|
||||
W.printHex("OffsetToPadding", FrameProc.Header.OffsetToPadding);
|
||||
W.printHex("BytesOfCalleeSavedRegisters",
|
||||
FrameProc.Header.BytesOfCalleeSavedRegisters);
|
||||
W.printHex("OffsetOfExceptionHandler",
|
||||
FrameProc.Header.OffsetOfExceptionHandler);
|
||||
W.printHex("SectionIdOfExceptionHandler",
|
||||
FrameProc.Header.SectionIdOfExceptionHandler);
|
||||
W.printFlags("Flags", FrameProc.Header.Flags,
|
||||
makeArrayRef(FrameProcSymFlags));
|
||||
}
|
||||
|
||||
void CVSymbolDumperImpl::visitHeapAllocationSiteSym(
|
||||
SymbolKind Kind, HeapAllocationSiteSym &HeapAllocSite) {
|
||||
DictScope S(W, "HeapAllocationSite");
|
||||
|
||||
StringRef LinkageName;
|
||||
if (ObjDelegate) {
|
||||
ObjDelegate->printRelocatedField(
|
||||
"CodeOffset", HeapAllocSite.getRelocationOffset(),
|
||||
HeapAllocSite.Header.CodeOffset, &LinkageName);
|
||||
}
|
||||
W.printHex("Segment", HeapAllocSite.Header.Segment);
|
||||
W.printHex("CallInstructionSize", HeapAllocSite.Header.CallInstructionSize);
|
||||
CVTD.printTypeIndex("Type", HeapAllocSite.Header.Type);
|
||||
if (!LinkageName.empty())
|
||||
W.printString("LinkageName", LinkageName);
|
||||
}
|
||||
|
||||
void CVSymbolDumperImpl::visitInlineSiteSym(SymbolKind Kind,
|
||||
InlineSiteSym &InlineSite) {
|
||||
DictScope S(W, "InlineSite");
|
||||
|
||||
W.printHex("PtrParent", InlineSite.Header.PtrParent);
|
||||
W.printHex("PtrEnd", InlineSite.Header.PtrEnd);
|
||||
CVTD.printTypeIndex("Inlinee", InlineSite.Header.Inlinee);
|
||||
|
||||
ListScope BinaryAnnotations(W, "BinaryAnnotations");
|
||||
for (auto &Annotation : InlineSite.annotations()) {
|
||||
switch (Annotation.OpCode) {
|
||||
case BinaryAnnotationsOpCode::Invalid:
|
||||
return parseError();
|
||||
case BinaryAnnotationsOpCode::CodeOffset:
|
||||
case BinaryAnnotationsOpCode::ChangeCodeOffset:
|
||||
case BinaryAnnotationsOpCode::ChangeCodeLength:
|
||||
W.printHex(Annotation.Name, Annotation.U1);
|
||||
break;
|
||||
case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
|
||||
case BinaryAnnotationsOpCode::ChangeLineEndDelta:
|
||||
case BinaryAnnotationsOpCode::ChangeRangeKind:
|
||||
case BinaryAnnotationsOpCode::ChangeColumnStart:
|
||||
case BinaryAnnotationsOpCode::ChangeColumnEnd:
|
||||
W.printNumber(Annotation.Name, Annotation.U1);
|
||||
break;
|
||||
case BinaryAnnotationsOpCode::ChangeLineOffset:
|
||||
case BinaryAnnotationsOpCode::ChangeColumnEndDelta:
|
||||
W.printNumber(Annotation.Name, Annotation.S1);
|
||||
break;
|
||||
case BinaryAnnotationsOpCode::ChangeFile:
|
||||
if (ObjDelegate) {
|
||||
W.printHex("ChangeFile",
|
||||
ObjDelegate->getFileNameForFileOffset(Annotation.U1),
|
||||
Annotation.U1);
|
||||
} else {
|
||||
W.printHex("ChangeFile", Annotation.U1);
|
||||
}
|
||||
|
||||
break;
|
||||
case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: {
|
||||
W.startLine() << "ChangeCodeOffsetAndLineOffset: {CodeOffset: "
|
||||
<< W.hex(Annotation.U1) << ", LineOffset: " << Annotation.S1
|
||||
<< "}\n";
|
||||
break;
|
||||
}
|
||||
case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: {
|
||||
W.startLine() << "ChangeCodeLengthAndCodeOffset: {CodeOffset: "
|
||||
<< W.hex(Annotation.U2)
|
||||
<< ", Length: " << W.hex(Annotation.U1) << "}\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CVSymbolDumperImpl::visitLabelSym(SymbolKind Kind, LabelSym &Label) {
|
||||
DictScope S(W, "Label");
|
||||
|
||||
StringRef LinkageName;
|
||||
if (ObjDelegate) {
|
||||
ObjDelegate->printRelocatedField("CodeOffset", Label.getRelocationOffset(),
|
||||
Label.Header.CodeOffset, &LinkageName);
|
||||
}
|
||||
W.printHex("Segment", Label.Header.Segment);
|
||||
W.printHex("Flags", Label.Header.Flags);
|
||||
W.printFlags("Flags", Label.Header.Flags, makeArrayRef(ProcSymFlagNames));
|
||||
W.printString("DisplayName", Label.Name);
|
||||
if (!LinkageName.empty())
|
||||
W.printString("LinkageName", LinkageName);
|
||||
}
|
||||
|
||||
void CVSymbolDumperImpl::visitLocalSym(SymbolKind Kind, LocalSym &Local) {
|
||||
DictScope S(W, "Local");
|
||||
|
||||
CVTD.printTypeIndex("Type", Local.Header.Type);
|
||||
W.printFlags("Flags", uint16_t(Local.Header.Flags), makeArrayRef(LocalFlags));
|
||||
W.printString("VarName", Local.Name);
|
||||
}
|
||||
|
||||
void CVSymbolDumperImpl::visitObjNameSym(SymbolKind Kind, ObjNameSym &ObjName) {
|
||||
DictScope S(W, "ObjectName");
|
||||
|
||||
W.printHex("Signature", ObjName.Header.Signature);
|
||||
W.printString("ObjectName", ObjName.Name);
|
||||
}
|
||||
|
||||
void CVSymbolDumperImpl::visitProcSym(SymbolKind Kind, ProcSym &Proc) {
|
||||
DictScope S(W, "ProcStart");
|
||||
|
||||
if (InFunctionScope)
|
||||
return parseError();
|
||||
|
||||
InFunctionScope = true;
|
||||
|
||||
StringRef LinkageName;
|
||||
W.printHex("PtrParent", Proc.Header.PtrParent);
|
||||
W.printHex("PtrEnd", Proc.Header.PtrEnd);
|
||||
W.printHex("PtrNext", Proc.Header.PtrNext);
|
||||
W.printHex("CodeSize", Proc.Header.CodeSize);
|
||||
W.printHex("DbgStart", Proc.Header.DbgStart);
|
||||
W.printHex("DbgEnd", Proc.Header.DbgEnd);
|
||||
CVTD.printTypeIndex("FunctionType", Proc.Header.FunctionType);
|
||||
if (ObjDelegate) {
|
||||
ObjDelegate->printRelocatedField("CodeOffset", Proc.getRelocationOffset(),
|
||||
Proc.Header.CodeOffset, &LinkageName);
|
||||
}
|
||||
W.printHex("Segment", Proc.Header.Segment);
|
||||
W.printFlags("Flags", static_cast<uint8_t>(Proc.Header.Flags),
|
||||
makeArrayRef(ProcSymFlagNames));
|
||||
W.printString("DisplayName", Proc.Name);
|
||||
if (!LinkageName.empty())
|
||||
W.printString("LinkageName", LinkageName);
|
||||
}
|
||||
|
||||
void CVSymbolDumperImpl::visitScopeEndSym(SymbolKind Kind,
|
||||
ScopeEndSym &ScopeEnd) {
|
||||
if (Kind == SymbolKind::S_END)
|
||||
W.startLine() << "BlockEnd\n";
|
||||
else if (Kind == SymbolKind::S_PROC_ID_END)
|
||||
W.startLine() << "ProcEnd\n";
|
||||
else if (Kind == SymbolKind::S_INLINESITE_END)
|
||||
DictScope S(W, "InlineSiteEnd");
|
||||
|
||||
InFunctionScope = false;
|
||||
}
|
||||
|
||||
void CVSymbolDumperImpl::visitCallerSym(SymbolKind Kind, CallerSym &Caller) {
|
||||
ListScope S(W, Kind == S_CALLEES ? "Callees" : "Callers");
|
||||
for (auto FuncID : Caller.Indices)
|
||||
CVTD.printTypeIndex("FuncID", FuncID);
|
||||
}
|
||||
|
||||
void CVSymbolDumperImpl::visitRegRelativeSym(SymbolKind Kind,
|
||||
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);
|
||||
}
|
||||
|
||||
void CVSymbolDumperImpl::visitThreadLocalDataSym(SymbolKind Kind,
|
||||
ThreadLocalDataSym &Data) {
|
||||
DictScope S(W, "ThreadLocalDataSym");
|
||||
|
||||
StringRef LinkageName;
|
||||
if (ObjDelegate) {
|
||||
ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(),
|
||||
Data.Header.DataOffset, &LinkageName);
|
||||
}
|
||||
CVTD.printTypeIndex("Type", Data.Header.Type);
|
||||
W.printString("DisplayName", Data.Name);
|
||||
if (!LinkageName.empty())
|
||||
W.printString("LinkageName", LinkageName);
|
||||
}
|
||||
|
||||
void CVSymbolDumperImpl::visitUDTSym(SymbolKind Kind, UDTSym &UDT) {
|
||||
DictScope S(W, "UDT");
|
||||
CVTD.printTypeIndex("Type", UDT.Header.Type);
|
||||
W.printString("UDTName", UDT.Name);
|
||||
}
|
||||
|
||||
void CVSymbolDumperImpl::visitUnknownSymbol(SymbolKind Kind,
|
||||
ArrayRef<uint8_t> Data) {
|
||||
DictScope S(W, "UnknownSym");
|
||||
W.printHex("Kind", unsigned(Kind));
|
||||
W.printHex("Size", Data.size());
|
||||
}
|
||||
|
||||
bool CVSymbolDumper::dump(const SymbolIterator::Record &Record) {
|
||||
CVSymbolDumperImpl Dumper(*this, CVTD, ObjDelegate.get(), W,
|
||||
PrintRecordBytes);
|
||||
Dumper.visitSymbolRecord(Record);
|
||||
return !Dumper.hadError();
|
||||
}
|
||||
|
||||
bool CVSymbolDumper::dump(ArrayRef<uint8_t> Data) {
|
||||
CVSymbolDumperImpl Dumper(*this, CVTD, ObjDelegate.get(), W,
|
||||
PrintRecordBytes);
|
||||
Dumper.visitSymbolStream(Data);
|
||||
return !Dumper.hadError();
|
||||
}
|
|
@ -51,5 +51,5 @@ Error ModStream::reload() {
|
|||
}
|
||||
|
||||
iterator_range<codeview::SymbolIterator> ModStream::symbols() const {
|
||||
return codeview::makeSymbolRange(SymbolsSubstream.data().slice(4));
|
||||
return codeview::makeSymbolRange(SymbolsSubstream.data().slice(4), nullptr);
|
||||
}
|
||||
|
|
|
@ -24,8 +24,10 @@
|
|||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/DebugInfo/CodeView/CodeView.h"
|
||||
#include "llvm/DebugInfo/CodeView/Line.h"
|
||||
#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
|
||||
#include "llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h"
|
||||
#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
|
||||
#include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h"
|
||||
#include "llvm/DebugInfo/CodeView/SymbolDumper.h"
|
||||
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeDumper.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
|
||||
|
@ -58,6 +60,7 @@ namespace {
|
|||
|
||||
class COFFDumper : public ObjDumper {
|
||||
public:
|
||||
friend class COFFObjectDumpDelegate;
|
||||
COFFDumper(const llvm::object::COFFObjectFile *Obj, ScopedPrinter &Writer)
|
||||
: ObjDumper(Writer), Obj(Obj),
|
||||
CVTD(Writer, opts::CodeViewSubsectionBytes) {}
|
||||
|
@ -96,10 +99,6 @@ private:
|
|||
// Forward to CVTypeDumper for simplicity.
|
||||
CVTD.printTypeIndex(FieldName, TI);
|
||||
}
|
||||
void printLocalVariableAddrRange(const LocalVariableAddrRange &Range,
|
||||
const coff_section *Sec,
|
||||
uint32_t RelocationOffset);
|
||||
void printLocalVariableAddrGap(ArrayRef<LocalVariableAddrGap> Gaps);
|
||||
|
||||
void printCodeViewSymbolsSubsection(StringRef Subsection,
|
||||
const SectionRef &Section,
|
||||
|
@ -148,6 +147,45 @@ private:
|
|||
CVTypeDumper CVTD;
|
||||
};
|
||||
|
||||
class COFFObjectDumpDelegate : public SymbolDumpDelegate {
|
||||
public:
|
||||
COFFObjectDumpDelegate(COFFDumper &CD, const SectionRef &SR,
|
||||
const COFFObjectFile *Obj, StringRef SectionContents)
|
||||
: CD(CD), SR(SR), Obj(Obj), SectionContents(SectionContents) {
|
||||
Sec = Obj->getCOFFSection(SR);
|
||||
}
|
||||
|
||||
uint32_t getRecordOffset(ArrayRef<uint8_t> Record) override {
|
||||
return Record.data() - SectionContents.bytes_begin();
|
||||
}
|
||||
|
||||
void printRelocatedField(StringRef Label, uint32_t RelocOffset,
|
||||
uint32_t Offset, StringRef *RelocSym) override {
|
||||
CD.printRelocatedField(Label, Sec, RelocOffset, Offset, RelocSym);
|
||||
}
|
||||
|
||||
void printBinaryBlockWithRelocs(StringRef Label,
|
||||
ArrayRef<uint8_t> Block) override {
|
||||
StringRef SBlock(reinterpret_cast<const char *>(Block.data()),
|
||||
Block.size());
|
||||
if (opts::CodeViewSubsectionBytes)
|
||||
CD.printBinaryBlockWithRelocs(Label, SR, SectionContents, SBlock);
|
||||
}
|
||||
|
||||
StringRef getFileNameForFileOffset(uint32_t FileOffset) override {
|
||||
return CD.getFileNameForFileOffset(FileOffset);
|
||||
}
|
||||
|
||||
StringRef getStringTable() override { return CD.CVStringTable; }
|
||||
|
||||
private:
|
||||
COFFDumper &CD;
|
||||
const SectionRef &SR;
|
||||
const COFFObjectFile *Obj;
|
||||
const coff_section *Sec;
|
||||
StringRef SectionContents;
|
||||
};
|
||||
|
||||
} // end namespace
|
||||
|
||||
namespace llvm {
|
||||
|
@ -246,6 +284,7 @@ void COFFDumper::printBinaryBlockWithRelocs(StringRef Label,
|
|||
uint64_t OffsetStart = Block.data() - SectionContents.data();
|
||||
uint64_t OffsetEnd = OffsetStart + Block.size();
|
||||
|
||||
W.flush();
|
||||
cacheRelocations();
|
||||
ListScope D(W, "BlockRelocations");
|
||||
const coff_section *Section = Obj->getCOFFSection(Sec);
|
||||
|
@ -440,41 +479,6 @@ WeakExternalCharacteristics[] = {
|
|||
{ "Alias" , COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS }
|
||||
};
|
||||
|
||||
static const EnumEntry<uint32_t> CompileSym3FlagNames[] = {
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CompileSym3Flags, EC),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CompileSym3Flags, NoDbgInfo),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CompileSym3Flags, LTCG),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CompileSym3Flags, NoDataAlign),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CompileSym3Flags, ManagedPresent),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CompileSym3Flags, SecurityChecks),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CompileSym3Flags, HotPatch),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CompileSym3Flags, CVTCIL),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CompileSym3Flags, MSILModule),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CompileSym3Flags, Sdl),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CompileSym3Flags, PGO),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CompileSym3Flags, Exp),
|
||||
};
|
||||
|
||||
static const EnumEntry<codeview::SourceLanguage> SourceLanguages[] = {
|
||||
LLVM_READOBJ_ENUM_ENT(SourceLanguage, C),
|
||||
LLVM_READOBJ_ENUM_ENT(SourceLanguage, Cpp),
|
||||
LLVM_READOBJ_ENUM_ENT(SourceLanguage, Fortran),
|
||||
LLVM_READOBJ_ENUM_ENT(SourceLanguage, Masm),
|
||||
LLVM_READOBJ_ENUM_ENT(SourceLanguage, Pascal),
|
||||
LLVM_READOBJ_ENUM_ENT(SourceLanguage, Basic),
|
||||
LLVM_READOBJ_ENUM_ENT(SourceLanguage, Cobol),
|
||||
LLVM_READOBJ_ENUM_ENT(SourceLanguage, Link),
|
||||
LLVM_READOBJ_ENUM_ENT(SourceLanguage, Cvtres),
|
||||
LLVM_READOBJ_ENUM_ENT(SourceLanguage, Cvtpgd),
|
||||
LLVM_READOBJ_ENUM_ENT(SourceLanguage, CSharp),
|
||||
LLVM_READOBJ_ENUM_ENT(SourceLanguage, VB),
|
||||
LLVM_READOBJ_ENUM_ENT(SourceLanguage, ILAsm),
|
||||
LLVM_READOBJ_ENUM_ENT(SourceLanguage, Java),
|
||||
LLVM_READOBJ_ENUM_ENT(SourceLanguage, JScript),
|
||||
LLVM_READOBJ_ENUM_ENT(SourceLanguage, MSIL),
|
||||
LLVM_READOBJ_ENUM_ENT(SourceLanguage, HLSL),
|
||||
};
|
||||
|
||||
static const EnumEntry<uint32_t> SubSectionTypes[] = {
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, Symbols),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, Lines),
|
||||
|
@ -491,68 +495,6 @@ static const EnumEntry<uint32_t> SubSectionTypes[] = {
|
|||
LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, CoffSymbolRVA),
|
||||
};
|
||||
|
||||
static const EnumEntry<unsigned> CPUTypeNames[] = {
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Intel8080),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Intel8086),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Intel80286),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Intel80386),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Intel80486),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Pentium),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, PentiumPro),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Pentium3),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, MIPS),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, MIPS16),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, MIPS32),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, MIPS64),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, MIPSI),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, MIPSII),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, MIPSIII),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, MIPSIV),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, MIPSV),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, M68000),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, M68010),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, M68020),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, M68030),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, M68040),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Alpha),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Alpha21164),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Alpha21164A),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Alpha21264),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Alpha21364),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, PPC601),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, PPC603),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, PPC604),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, PPC620),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, PPCFP),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, PPCBE),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, SH3),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, SH3E),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, SH3DSP),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, SH4),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, SHMedia),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, ARM3),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, ARM4),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, ARM4T),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, ARM5),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, ARM5T),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, ARM6),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, ARM_XMAC),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, ARM_WMMX),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, ARM7),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Omni),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Ia64),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Ia64_2),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, CEE),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, AM33),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, M32R),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, TriCore),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, X64),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, EBC),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Thumb),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, ARMNT),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, D3D11_Shader),
|
||||
};
|
||||
|
||||
static const EnumEntry<uint8_t> ProcSymFlagNames[] = {
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(ProcSymFlags, HasFP),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(ProcSymFlags, HasIRET),
|
||||
|
@ -564,59 +506,12 @@ static const EnumEntry<uint8_t> ProcSymFlagNames[] = {
|
|||
LLVM_READOBJ_ENUM_CLASS_ENT(ProcSymFlags, HasOptimizedDebugInfo),
|
||||
};
|
||||
|
||||
static const EnumEntry<uint32_t> FrameProcSymFlags[] = {
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, HasAlloca),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, HasSetJmp),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, HasLongJmp),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, HasInlineAssembly),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, HasExceptionHandling),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, MarkedInline),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions,
|
||||
HasStructuredExceptionHandling),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, Naked),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, SecurityChecks),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions,
|
||||
AsynchronousExceptionHandling),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions,
|
||||
NoStackOrderingForSecurityChecks),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, Inlined),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, StrictSecurityChecks),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, SafeBuffers),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions,
|
||||
ProfileGuidedOptimization),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, ValidProfileCounts),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, OptimizedForSpeed),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, GuardCfg),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, GuardCfw),
|
||||
};
|
||||
|
||||
static const EnumEntry<uint32_t> FrameDataFlags[] = {
|
||||
LLVM_READOBJ_ENUM_ENT(FrameData, HasSEH),
|
||||
LLVM_READOBJ_ENUM_ENT(FrameData, HasEH),
|
||||
LLVM_READOBJ_ENUM_ENT(FrameData, IsFunctionStart),
|
||||
};
|
||||
|
||||
static const EnumEntry<uint16_t> LocalFlags[] = {
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(LocalSymFlags, IsParameter),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(LocalSymFlags, IsAddressTaken),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(LocalSymFlags, IsCompilerGenerated),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(LocalSymFlags, IsAggregate),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(LocalSymFlags, IsAggregated),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(LocalSymFlags, IsAliased),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(LocalSymFlags, IsAlias),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(LocalSymFlags, IsReturnValue),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(LocalSymFlags, IsOptimizedOut),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(LocalSymFlags, IsEnregisteredGlobal),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(LocalSymFlags, IsEnregisteredStatic),
|
||||
};
|
||||
|
||||
static const EnumEntry<uint32_t> FrameCookieKinds[] = {
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(FrameCookieKind, Copy),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(FrameCookieKind, XorStackPointer),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(FrameCookieKind, XorFramePointer),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(FrameCookieKind, XorR13),
|
||||
};
|
||||
|
||||
static const EnumEntry<uint8_t> FileChecksumKindNames[] = {
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(FileChecksumKind, None),
|
||||
LLVM_READOBJ_ENUM_CLASS_ENT(FileChecksumKind, MD5),
|
||||
|
@ -1009,574 +904,16 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName,
|
|||
void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection,
|
||||
const SectionRef &Section,
|
||||
StringRef SectionContents) {
|
||||
if (Subsection.size() < sizeof(RecordPrefix))
|
||||
return error(object_error::parse_failed);
|
||||
ArrayRef<uint8_t> BinaryData(Subsection.bytes_begin(),
|
||||
Subsection.bytes_end());
|
||||
auto CODD = llvm::make_unique<COFFObjectDumpDelegate>(*this, Section, Obj,
|
||||
SectionContents);
|
||||
|
||||
const coff_section *Sec = Obj->getCOFFSection(Section);
|
||||
CVSymbolDumper CVSD(W, CVTD, std::move(CODD), opts::CodeViewSubsectionBytes);
|
||||
|
||||
// This holds the remaining data to parse.
|
||||
StringRef Data = Subsection;
|
||||
|
||||
bool InFunctionScope = false;
|
||||
while (!Data.empty()) {
|
||||
const RecordPrefix *Rec;
|
||||
error(consumeObject(Data, Rec));
|
||||
|
||||
StringRef SymData = Data.substr(0, Rec->RecordLen - 2);
|
||||
StringRef OrigSymData = SymData;
|
||||
|
||||
Data = Data.drop_front(Rec->RecordLen - 2);
|
||||
uint32_t RecordOffset = SymData.data() - SectionContents.data();
|
||||
|
||||
SymbolKind Kind = static_cast<SymbolKind>(uint16_t(Rec->RecordKind));
|
||||
switch (Kind) {
|
||||
case S_LPROC32:
|
||||
case S_GPROC32:
|
||||
case S_GPROC32_ID:
|
||||
case S_LPROC32_ID:
|
||||
case S_LPROC32_DPC:
|
||||
case S_LPROC32_DPC_ID: {
|
||||
DictScope S(W, "ProcStart");
|
||||
ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
|
||||
auto ProcOrError = ProcSym::deserialize(
|
||||
static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
|
||||
if (!ProcOrError)
|
||||
error(ProcOrError.getError());
|
||||
auto &Proc = ProcOrError.get();
|
||||
|
||||
if (InFunctionScope)
|
||||
return error(object_error::parse_failed);
|
||||
InFunctionScope = true;
|
||||
|
||||
StringRef LinkageName;
|
||||
W.printHex("PtrParent", Proc.Header.PtrParent);
|
||||
W.printHex("PtrEnd", Proc.Header.PtrEnd);
|
||||
W.printHex("PtrNext", Proc.Header.PtrNext);
|
||||
W.printHex("CodeSize", Proc.Header.CodeSize);
|
||||
W.printHex("DbgStart", Proc.Header.DbgStart);
|
||||
W.printHex("DbgEnd", Proc.Header.DbgEnd);
|
||||
printTypeIndex("FunctionType", Proc.Header.FunctionType);
|
||||
printRelocatedField("CodeOffset", Sec, Proc.getRelocationOffset(),
|
||||
Proc.Header.CodeOffset, &LinkageName);
|
||||
W.printHex("Segment", Proc.Header.Segment);
|
||||
W.printFlags("Flags", static_cast<uint8_t>(Proc.Header.Flags),
|
||||
makeArrayRef(ProcSymFlagNames));
|
||||
W.printString("DisplayName", Proc.Name);
|
||||
W.printString("LinkageName", LinkageName);
|
||||
break;
|
||||
}
|
||||
|
||||
case S_PROC_ID_END: {
|
||||
W.startLine() << "ProcEnd\n";
|
||||
InFunctionScope = false;
|
||||
break;
|
||||
}
|
||||
|
||||
case S_BLOCK32: {
|
||||
DictScope S(W, "BlockStart");
|
||||
ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
|
||||
auto BlockOrError = BlockSym::deserialize(
|
||||
static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
|
||||
if (!BlockOrError)
|
||||
error(BlockOrError.getError());
|
||||
auto &Block = BlockOrError.get();
|
||||
|
||||
StringRef LinkageName;
|
||||
W.printHex("PtrParent", Block.Header.PtrParent);
|
||||
W.printHex("PtrEnd", Block.Header.PtrEnd);
|
||||
W.printHex("CodeSize", Block.Header.CodeSize);
|
||||
printRelocatedField("CodeOffset", Sec, Block.getRelocationOffset(),
|
||||
Block.Header.CodeOffset, &LinkageName);
|
||||
W.printHex("Segment", Block.Header.Segment);
|
||||
W.printString("BlockName", Block.Name);
|
||||
W.printString("LinkageName", LinkageName);
|
||||
break;
|
||||
}
|
||||
|
||||
case S_END: {
|
||||
W.startLine() << "BlockEnd\n";
|
||||
InFunctionScope = false;
|
||||
break;
|
||||
}
|
||||
|
||||
case S_LABEL32: {
|
||||
DictScope S(W, "Label");
|
||||
ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
|
||||
auto LabelOrError = LabelSym::deserialize(
|
||||
static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
|
||||
if (!LabelOrError)
|
||||
error(LabelOrError.getError());
|
||||
auto &Label = LabelOrError.get();
|
||||
|
||||
StringRef LinkageName;
|
||||
printRelocatedField("CodeOffset", Sec, Label.getRelocationOffset(),
|
||||
Label.Header.CodeOffset, &LinkageName);
|
||||
W.printHex("Segment", Label.Header.Segment);
|
||||
W.printHex("Flags", Label.Header.Flags);
|
||||
W.printFlags("Flags", Label.Header.Flags, makeArrayRef(ProcSymFlagNames));
|
||||
W.printString("DisplayName", Label.Name);
|
||||
W.printString("LinkageName", LinkageName);
|
||||
break;
|
||||
}
|
||||
|
||||
case S_INLINESITE: {
|
||||
DictScope S(W, "InlineSite");
|
||||
ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
|
||||
auto InlineSiteOrError = InlineSiteSym::deserialize(
|
||||
static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
|
||||
if (!InlineSiteOrError)
|
||||
error(InlineSiteOrError.getError());
|
||||
auto &InlineSite = InlineSiteOrError.get();
|
||||
|
||||
W.printHex("PtrParent", InlineSite.Header.PtrParent);
|
||||
W.printHex("PtrEnd", InlineSite.Header.PtrEnd);
|
||||
printTypeIndex("Inlinee", InlineSite.Header.Inlinee);
|
||||
|
||||
ListScope BinaryAnnotations(W, "BinaryAnnotations");
|
||||
for (auto &Annotation : InlineSite.annotations()) {
|
||||
switch (Annotation.OpCode) {
|
||||
case BinaryAnnotationsOpCode::Invalid:
|
||||
return error(object_error::parse_failed);
|
||||
case BinaryAnnotationsOpCode::CodeOffset:
|
||||
case BinaryAnnotationsOpCode::ChangeCodeOffset:
|
||||
case BinaryAnnotationsOpCode::ChangeCodeLength:
|
||||
W.printHex(Annotation.Name, Annotation.U1);
|
||||
break;
|
||||
case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
|
||||
case BinaryAnnotationsOpCode::ChangeLineEndDelta:
|
||||
case BinaryAnnotationsOpCode::ChangeRangeKind:
|
||||
case BinaryAnnotationsOpCode::ChangeColumnStart:
|
||||
case BinaryAnnotationsOpCode::ChangeColumnEnd:
|
||||
W.printNumber(Annotation.Name, Annotation.U1);
|
||||
break;
|
||||
case BinaryAnnotationsOpCode::ChangeLineOffset:
|
||||
case BinaryAnnotationsOpCode::ChangeColumnEndDelta:
|
||||
W.printNumber(Annotation.Name, Annotation.S1);
|
||||
break;
|
||||
case BinaryAnnotationsOpCode::ChangeFile:
|
||||
printFileNameForOffset("ChangeFile", Annotation.U1);
|
||||
break;
|
||||
case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: {
|
||||
W.startLine() << "ChangeCodeOffsetAndLineOffset: {CodeOffset: "
|
||||
<< W.hex(Annotation.U1)
|
||||
<< ", LineOffset: " << Annotation.S1 << "}\n";
|
||||
break;
|
||||
}
|
||||
case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: {
|
||||
W.startLine() << "ChangeCodeLengthAndCodeOffset: {CodeOffset: "
|
||||
<< W.hex(Annotation.U2)
|
||||
<< ", Length: " << W.hex(Annotation.U1) << "}\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case S_INLINESITE_END: {
|
||||
DictScope S(W, "InlineSiteEnd");
|
||||
break;
|
||||
}
|
||||
|
||||
case S_CALLERS:
|
||||
case S_CALLEES: {
|
||||
ListScope S(W, Kind == S_CALLEES ? "Callees" : "Callers");
|
||||
uint32_t Count;
|
||||
error(consume(SymData, Count));
|
||||
for (uint32_t I = 0; I < Count; ++I) {
|
||||
const TypeIndex *FuncID;
|
||||
error(consumeObject(SymData, FuncID));
|
||||
printTypeIndex("FuncID", *FuncID);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case S_LOCAL: {
|
||||
DictScope S(W, "Local");
|
||||
ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
|
||||
auto LocalOrError = LocalSym::deserialize(
|
||||
static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
|
||||
if (!LocalOrError)
|
||||
error(LocalOrError.getError());
|
||||
auto &Local = LocalOrError.get();
|
||||
|
||||
printTypeIndex("Type", Local.Header.Type);
|
||||
W.printFlags("Flags", uint16_t(Local.Header.Flags),
|
||||
makeArrayRef(LocalFlags));
|
||||
W.printString("VarName", Local.Name);
|
||||
break;
|
||||
}
|
||||
|
||||
case S_DEFRANGE: {
|
||||
DictScope S(W, "DefRange");
|
||||
ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
|
||||
auto DefRangeOrError = DefRangeSym::deserialize(
|
||||
static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
|
||||
if (!DefRangeOrError)
|
||||
error(DefRangeOrError.getError());
|
||||
auto &DefRange = DefRangeOrError.get();
|
||||
|
||||
W.printString(
|
||||
"Program",
|
||||
CVStringTable.drop_front(DefRange.Header.Program).split('\0').first);
|
||||
printLocalVariableAddrRange(DefRange.Header.Range, Sec,
|
||||
DefRange.getRelocationOffset());
|
||||
printLocalVariableAddrGap(DefRange.Gaps);
|
||||
break;
|
||||
}
|
||||
case S_DEFRANGE_SUBFIELD: {
|
||||
DictScope S(W, "DefRangeSubfield");
|
||||
ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
|
||||
auto DefRangeOrError = DefRangeSubfieldSym::deserialize(
|
||||
static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
|
||||
if (!DefRangeOrError)
|
||||
error(DefRangeOrError.getError());
|
||||
auto &DefRangeSubfield = DefRangeOrError.get();
|
||||
|
||||
W.printString("Program",
|
||||
CVStringTable.drop_front(DefRangeSubfield.Header.Program)
|
||||
.split('\0')
|
||||
.first);
|
||||
W.printNumber("OffsetInParent", DefRangeSubfield.Header.OffsetInParent);
|
||||
printLocalVariableAddrRange(DefRangeSubfield.Header.Range, Sec,
|
||||
DefRangeSubfield.getRelocationOffset());
|
||||
printLocalVariableAddrGap(DefRangeSubfield.Gaps);
|
||||
break;
|
||||
}
|
||||
case S_DEFRANGE_REGISTER: {
|
||||
DictScope S(W, "DefRangeRegister");
|
||||
ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
|
||||
auto DefRangeOrError = DefRangeRegisterSym::deserialize(
|
||||
static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
|
||||
if (!DefRangeOrError)
|
||||
error(DefRangeOrError.getError());
|
||||
auto &DefRangeRegisterSym = DefRangeOrError.get();
|
||||
|
||||
W.printNumber("Register", DefRangeRegisterSym.Header.Register);
|
||||
W.printNumber("MayHaveNoName", DefRangeRegisterSym.Header.MayHaveNoName);
|
||||
printLocalVariableAddrRange(DefRangeRegisterSym.Header.Range, Sec,
|
||||
DefRangeRegisterSym.getRelocationOffset());
|
||||
printLocalVariableAddrGap(DefRangeRegisterSym.Gaps);
|
||||
break;
|
||||
}
|
||||
case S_DEFRANGE_SUBFIELD_REGISTER: {
|
||||
DictScope S(W, "DefRangeSubfieldRegister");
|
||||
ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
|
||||
auto DefRangeOrError = DefRangeSubfieldRegisterSym::deserialize(
|
||||
static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
|
||||
if (!DefRangeOrError)
|
||||
error(DefRangeOrError.getError());
|
||||
auto &DefRangeSubfieldRegister = DefRangeOrError.get();
|
||||
W.printNumber("Register", DefRangeSubfieldRegister.Header.Register);
|
||||
W.printNumber("MayHaveNoName",
|
||||
DefRangeSubfieldRegister.Header.MayHaveNoName);
|
||||
W.printNumber("OffsetInParent",
|
||||
DefRangeSubfieldRegister.Header.OffsetInParent);
|
||||
printLocalVariableAddrRange(
|
||||
DefRangeSubfieldRegister.Header.Range, Sec,
|
||||
DefRangeSubfieldRegister.getRelocationOffset());
|
||||
printLocalVariableAddrGap(DefRangeSubfieldRegister.Gaps);
|
||||
break;
|
||||
}
|
||||
case S_DEFRANGE_FRAMEPOINTER_REL: {
|
||||
DictScope S(W, "DefRangeFramePointerRel");
|
||||
ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
|
||||
auto DefRangeOrError = DefRangeFramePointerRelSym::deserialize(
|
||||
static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
|
||||
if (!DefRangeOrError)
|
||||
error(DefRangeOrError.getError());
|
||||
auto &DefRangeFramePointerRel = DefRangeOrError.get();
|
||||
W.printNumber("Offset", DefRangeFramePointerRel.Header.Offset);
|
||||
printLocalVariableAddrRange(
|
||||
DefRangeFramePointerRel.Header.Range, Sec,
|
||||
DefRangeFramePointerRel.getRelocationOffset());
|
||||
printLocalVariableAddrGap(DefRangeFramePointerRel.Gaps);
|
||||
break;
|
||||
}
|
||||
case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE: {
|
||||
DictScope S(W, "DefRangeFramePointerRelFullScope");
|
||||
ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
|
||||
auto DefRangeOrError = DefRangeFramePointerRelFullScopeSym::deserialize(
|
||||
static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
|
||||
if (!DefRangeOrError)
|
||||
error(DefRangeOrError.getError());
|
||||
auto &DefRangeFramePointerRelFullScope = DefRangeOrError.get();
|
||||
W.printNumber("Offset", DefRangeFramePointerRelFullScope.Header.Offset);
|
||||
break;
|
||||
}
|
||||
case S_DEFRANGE_REGISTER_REL: {
|
||||
DictScope S(W, "DefRangeRegisterRel");
|
||||
ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
|
||||
auto DefRangeOrError = DefRangeRegisterRelSym::deserialize(
|
||||
static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
|
||||
if (!DefRangeOrError)
|
||||
error(DefRangeOrError.getError());
|
||||
auto &DefRangeRegisterRel = DefRangeOrError.get();
|
||||
|
||||
W.printNumber("BaseRegister", DefRangeRegisterRel.Header.BaseRegister);
|
||||
W.printBoolean("HasSpilledUDTMember",
|
||||
DefRangeRegisterRel.hasSpilledUDTMember());
|
||||
W.printNumber("OffsetInParent", DefRangeRegisterRel.offsetInParent());
|
||||
W.printNumber("BasePointerOffset",
|
||||
DefRangeRegisterRel.Header.BasePointerOffset);
|
||||
printLocalVariableAddrRange(DefRangeRegisterRel.Header.Range, Sec,
|
||||
DefRangeRegisterRel.getRelocationOffset());
|
||||
printLocalVariableAddrGap(DefRangeRegisterRel.Gaps);
|
||||
break;
|
||||
}
|
||||
|
||||
case S_CALLSITEINFO: {
|
||||
DictScope S(W, "CallSiteInfo");
|
||||
ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
|
||||
auto CallSiteOrError = CallSiteInfoSym::deserialize(
|
||||
static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
|
||||
if (!CallSiteOrError)
|
||||
error(CallSiteOrError.getError());
|
||||
auto &CallSiteInfo = CallSiteOrError.get();
|
||||
|
||||
StringRef LinkageName;
|
||||
printRelocatedField("CodeOffset", Sec, CallSiteInfo.getRelocationOffset(),
|
||||
CallSiteInfo.Header.CodeOffset, &LinkageName);
|
||||
W.printHex("Segment", CallSiteInfo.Header.Segment);
|
||||
W.printHex("Reserved", CallSiteInfo.Header.Reserved);
|
||||
printTypeIndex("Type", CallSiteInfo.Header.Type);
|
||||
W.printString("LinkageName", LinkageName);
|
||||
break;
|
||||
}
|
||||
|
||||
case S_HEAPALLOCSITE: {
|
||||
DictScope S(W, "HeapAllocationSite");
|
||||
ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
|
||||
auto HeapAllocSiteOrError = HeapAllocationSiteSym::deserialize(
|
||||
static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
|
||||
if (!HeapAllocSiteOrError)
|
||||
error(HeapAllocSiteOrError.getError());
|
||||
auto &HeapAllocSite = HeapAllocSiteOrError.get();
|
||||
|
||||
StringRef LinkageName;
|
||||
printRelocatedField("CodeOffset", Sec,
|
||||
HeapAllocSite.getRelocationOffset(),
|
||||
HeapAllocSite.Header.CodeOffset, &LinkageName);
|
||||
W.printHex("Segment", HeapAllocSite.Header.Segment);
|
||||
W.printHex("CallInstructionSize",
|
||||
HeapAllocSite.Header.CallInstructionSize);
|
||||
printTypeIndex("Type", HeapAllocSite.Header.Type);
|
||||
W.printString("LinkageName", LinkageName);
|
||||
break;
|
||||
}
|
||||
|
||||
case S_FRAMECOOKIE: {
|
||||
DictScope S(W, "FrameCookie");
|
||||
ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
|
||||
auto FrameCookieOrError = FrameCookieSym::deserialize(
|
||||
static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
|
||||
if (!FrameCookieOrError)
|
||||
error(FrameCookieOrError.getError());
|
||||
auto &FrameCookie = FrameCookieOrError.get();
|
||||
|
||||
StringRef LinkageName;
|
||||
printRelocatedField("CodeOffset", Sec, FrameCookie.getRelocationOffset(),
|
||||
FrameCookie.Header.CodeOffset, &LinkageName);
|
||||
W.printHex("Register", FrameCookie.Header.Register);
|
||||
W.printEnum("CookieKind", uint16_t(FrameCookie.Header.CookieKind),
|
||||
makeArrayRef(FrameCookieKinds));
|
||||
break;
|
||||
}
|
||||
|
||||
case S_LDATA32:
|
||||
case S_GDATA32:
|
||||
case S_LMANDATA:
|
||||
case S_GMANDATA: {
|
||||
DictScope S(W, "DataSym");
|
||||
ArrayRef<uint8_t> SymBytes(SymData.bytes_begin(), SymData.bytes_end());
|
||||
auto DataOrError = DataSym::deserialize(
|
||||
static_cast<SymbolRecordKind>(Kind), RecordOffset, SymBytes);
|
||||
if (!DataOrError)
|
||||
error(DataOrError.getError());
|
||||
auto &Data = DataOrError.get();
|
||||
|
||||
StringRef LinkageName;
|
||||
printRelocatedField("DataOffset", Sec, Data.getRelocationOffset(),
|
||||
Data.Header.DataOffset, &LinkageName);
|
||||
printTypeIndex("Type", Data.Header.Type);
|
||||
W.printString("DisplayName", Data.Name);
|
||||
W.printString("LinkageName", LinkageName);
|
||||
break;
|
||||
}
|
||||
|
||||
case S_LTHREAD32:
|
||||
case S_GTHREAD32: {
|
||||
DictScope S(W, "ThreadLocalDataSym");
|
||||
ArrayRef<uint8_t> SymBytes(SymData.bytes_begin(), SymData.bytes_end());
|
||||
auto ThreadLocalDataOrError = ThreadLocalDataSym::deserialize(
|
||||
static_cast<SymbolRecordKind>(Kind), RecordOffset, SymBytes);
|
||||
if (!ThreadLocalDataOrError)
|
||||
error(ThreadLocalDataOrError.getError());
|
||||
auto &Data = ThreadLocalDataOrError.get();
|
||||
|
||||
StringRef LinkageName;
|
||||
printRelocatedField("DataOffset", Sec, Data.getRelocationOffset(),
|
||||
Data.Header.DataOffset, &LinkageName);
|
||||
printTypeIndex("Type", Data.Header.Type);
|
||||
W.printString("DisplayName", Data.Name);
|
||||
W.printString("LinkageName", LinkageName);
|
||||
break;
|
||||
}
|
||||
|
||||
case S_OBJNAME: {
|
||||
DictScope S(W, "ObjectName");
|
||||
ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
|
||||
auto ObjNameOrError = ObjNameSym::deserialize(
|
||||
static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
|
||||
if (!ObjNameOrError)
|
||||
error(ObjNameOrError.getError());
|
||||
auto &ObjName = ObjNameOrError.get();
|
||||
W.printHex("Signature", ObjName.Header.Signature);
|
||||
W.printString("ObjectName", ObjName.Name);
|
||||
break;
|
||||
}
|
||||
|
||||
case S_COMPILE3: {
|
||||
DictScope S(W, "CompilerFlags");
|
||||
ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
|
||||
auto Compile3OrError = CompileSym3::deserialize(
|
||||
static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
|
||||
if (!Compile3OrError)
|
||||
error(Compile3OrError.getError());
|
||||
auto &Compile3 = Compile3OrError.get();
|
||||
|
||||
W.printEnum("Language", Compile3.Header.getLanguage(),
|
||||
makeArrayRef(SourceLanguages));
|
||||
W.printFlags("Flags", Compile3.Header.flags & ~0xff,
|
||||
makeArrayRef(CompileSym3FlagNames));
|
||||
W.printEnum("Machine", unsigned(Compile3.Header.Machine),
|
||||
makeArrayRef(CPUTypeNames));
|
||||
std::string FrontendVersion;
|
||||
{
|
||||
raw_string_ostream Out(FrontendVersion);
|
||||
Out << Compile3.Header.VersionFrontendMajor << '.'
|
||||
<< Compile3.Header.VersionFrontendMinor << '.'
|
||||
<< Compile3.Header.VersionFrontendBuild << '.'
|
||||
<< Compile3.Header.VersionFrontendQFE;
|
||||
}
|
||||
std::string BackendVersion;
|
||||
{
|
||||
raw_string_ostream Out(BackendVersion);
|
||||
Out << Compile3.Header.VersionBackendMajor << '.'
|
||||
<< Compile3.Header.VersionBackendMinor << '.'
|
||||
<< Compile3.Header.VersionBackendBuild << '.'
|
||||
<< Compile3.Header.VersionBackendQFE;
|
||||
}
|
||||
W.printString("FrontendVersion", FrontendVersion);
|
||||
W.printString("BackendVersion", BackendVersion);
|
||||
W.printString("VersionName", Compile3.Version);
|
||||
break;
|
||||
}
|
||||
|
||||
case S_FRAMEPROC: {
|
||||
DictScope S(W, "FrameProc");
|
||||
ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
|
||||
auto FrameProcOrError = FrameProcSym::deserialize(
|
||||
static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
|
||||
if (!FrameProcOrError)
|
||||
error(FrameProcOrError.getError());
|
||||
auto &FrameProc = FrameProcOrError.get();
|
||||
W.printHex("TotalFrameBytes", FrameProc.Header.TotalFrameBytes);
|
||||
W.printHex("PaddingFrameBytes", FrameProc.Header.PaddingFrameBytes);
|
||||
W.printHex("OffsetToPadding", FrameProc.Header.OffsetToPadding);
|
||||
W.printHex("BytesOfCalleeSavedRegisters",
|
||||
FrameProc.Header.BytesOfCalleeSavedRegisters);
|
||||
W.printHex("OffsetOfExceptionHandler",
|
||||
FrameProc.Header.OffsetOfExceptionHandler);
|
||||
W.printHex("SectionIdOfExceptionHandler",
|
||||
FrameProc.Header.SectionIdOfExceptionHandler);
|
||||
W.printFlags("Flags", FrameProc.Header.Flags,
|
||||
makeArrayRef(FrameProcSymFlags));
|
||||
break;
|
||||
}
|
||||
|
||||
case S_UDT:
|
||||
case S_COBOLUDT: {
|
||||
DictScope S(W, "UDT");
|
||||
ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
|
||||
auto UdtOrError = UDTSym::deserialize(static_cast<SymbolRecordKind>(Kind),
|
||||
RecordOffset, Data);
|
||||
if (!UdtOrError)
|
||||
error(UdtOrError.getError());
|
||||
auto &UDT = UdtOrError.get();
|
||||
printTypeIndex("Type", UDT.Header.Type);
|
||||
W.printString("UDTName", UDT.Name);
|
||||
break;
|
||||
}
|
||||
|
||||
case S_BPREL32: {
|
||||
DictScope S(W, "BPRelativeSym");
|
||||
ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
|
||||
auto BPRelOrError = BPRelativeSym::deserialize(
|
||||
static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
|
||||
if (!BPRelOrError)
|
||||
error(BPRelOrError.getError());
|
||||
auto &BPRel = BPRelOrError.get();
|
||||
W.printNumber("Offset", BPRel.Header.Offset);
|
||||
printTypeIndex("Type", BPRel.Header.Type);
|
||||
W.printString("VarName", BPRel.Name);
|
||||
break;
|
||||
}
|
||||
|
||||
case S_REGREL32: {
|
||||
DictScope S(W, "RegRelativeSym");
|
||||
ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
|
||||
auto RegRelOrError = RegRelativeSym::deserialize(
|
||||
static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
|
||||
if (!RegRelOrError)
|
||||
error(RegRelOrError.getError());
|
||||
auto &RegRel = RegRelOrError.get();
|
||||
W.printHex("Offset", RegRel.Header.Offset);
|
||||
printTypeIndex("Type", RegRel.Header.Type);
|
||||
W.printHex("Register", RegRel.Header.Register);
|
||||
W.printString("VarName", RegRel.Name);
|
||||
break;
|
||||
}
|
||||
|
||||
case S_BUILDINFO: {
|
||||
DictScope S(W, "BuildInfo");
|
||||
ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
|
||||
auto BuildInfoOrError = BuildInfoSym::deserialize(
|
||||
static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
|
||||
if (!BuildInfoOrError)
|
||||
error(BuildInfoOrError.getError());
|
||||
auto &BuildInfo = BuildInfoOrError.get();
|
||||
W.printNumber("BuildId", BuildInfo.Header.BuildId);
|
||||
break;
|
||||
}
|
||||
|
||||
case S_CONSTANT:
|
||||
case S_MANCONSTANT: {
|
||||
DictScope S(W, "Constant");
|
||||
ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
|
||||
auto ConstantOrError = ConstantSym::deserialize(
|
||||
static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
|
||||
if (!ConstantOrError)
|
||||
error(ConstantOrError.getError());
|
||||
auto &Constant = ConstantOrError.get();
|
||||
printTypeIndex("Type", Constant.Header.Type);
|
||||
W.printNumber("Value", Constant.Value);
|
||||
W.printString("Name", Constant.Name);
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
DictScope S(W, "UnknownSym");
|
||||
W.printHex("Kind", unsigned(Kind));
|
||||
W.printHex("Size", Rec->RecordLen);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (opts::CodeViewSubsectionBytes)
|
||||
printBinaryBlockWithRelocs("SymData", Section, SectionContents,
|
||||
OrigSymData);
|
||||
if (!CVSD.dump(BinaryData)) {
|
||||
W.flush();
|
||||
error(object_error::parse_failed);
|
||||
}
|
||||
W.flush();
|
||||
}
|
||||
|
@ -1633,24 +970,6 @@ void COFFDumper::printCodeViewInlineeLines(StringRef Subsection) {
|
|||
}
|
||||
}
|
||||
|
||||
void COFFDumper::printLocalVariableAddrRange(
|
||||
const LocalVariableAddrRange &Range, const coff_section *Sec,
|
||||
uint32_t RelocationOffset) {
|
||||
DictScope S(W, "LocalVariableAddrRange");
|
||||
printRelocatedField("OffsetStart", Sec, RelocationOffset, Range.OffsetStart);
|
||||
W.printHex("ISectStart", Range.ISectStart);
|
||||
W.printHex("Range", Range.Range);
|
||||
}
|
||||
|
||||
void COFFDumper::printLocalVariableAddrGap(
|
||||
ArrayRef<LocalVariableAddrGap> Gaps) {
|
||||
for (auto &Gap : Gaps) {
|
||||
ListScope S(W, "LocalVariableAddrGap");
|
||||
W.printHex("GapStartOffset", Gap.GapStartOffset);
|
||||
W.printHex("Range", Gap.Range);
|
||||
}
|
||||
}
|
||||
|
||||
StringRef COFFDumper::getFileNameForFileOffset(uint32_t FileOffset) {
|
||||
// The file checksum subsection should precede all references to it.
|
||||
if (!CVFileChecksumTable.data() || !CVStringTable.data())
|
||||
|
|
Loading…
Reference in New Issue