diff options
author | Zachary Turner <zturner@google.com> | 2016-05-23 23:41:13 +0000 |
---|---|---|
committer | Zachary Turner <zturner@google.com> | 2016-05-23 23:41:13 +0000 |
commit | 24466fcd2c598109ad3c1a511212e2608cb064ba (patch) | |
tree | 21714f91a45c86b9042db430f4ff1dfa30beb28d /include | |
parent | bc88e8bed4fbb14e94e5e1f5b30209c5d5dacdbe (diff) |
Make a symbol visitor and use it to dump CV symbols.
Differential Revision: http://reviews.llvm.org/D20534
Reviewed By: rnk
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@270511 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include')
-rw-r--r-- | include/llvm/DebugInfo/CodeView/CVSymbolTypes.def | 26 | ||||
-rw-r--r-- | include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h | 103 | ||||
-rw-r--r-- | include/llvm/DebugInfo/CodeView/SymbolDumpDelegate.h | 37 | ||||
-rw-r--r-- | include/llvm/DebugInfo/CodeView/SymbolDumper.h | 54 | ||||
-rw-r--r-- | include/llvm/DebugInfo/CodeView/SymbolRecord.h | 55 | ||||
-rw-r--r-- | include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h | 33 |
6 files changed, 290 insertions, 18 deletions
diff --git a/include/llvm/DebugInfo/CodeView/CVSymbolTypes.def b/include/llvm/DebugInfo/CodeView/CVSymbolTypes.def index 758771a403a..d3ecca534e1 100644 --- a/include/llvm/DebugInfo/CodeView/CVSymbolTypes.def +++ b/include/llvm/DebugInfo/CodeView/CVSymbolTypes.def @@ -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) diff --git a/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h b/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h new file mode 100644 index 00000000000..fe21ff9956b --- /dev/null +++ b/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h @@ -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 diff --git a/include/llvm/DebugInfo/CodeView/SymbolDumpDelegate.h b/include/llvm/DebugInfo/CodeView/SymbolDumpDelegate.h new file mode 100644 index 00000000000..30b0a40451c --- /dev/null +++ b/include/llvm/DebugInfo/CodeView/SymbolDumpDelegate.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 diff --git a/include/llvm/DebugInfo/CodeView/SymbolDumper.h b/include/llvm/DebugInfo/CodeView/SymbolDumper.h new file mode 100644 index 00000000000..62c5ab3931b --- /dev/null +++ b/include/llvm/DebugInfo/CodeView/SymbolDumper.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 diff --git a/include/llvm/DebugInfo/CodeView/SymbolRecord.h b/include/llvm/DebugInfo/CodeView/SymbolRecord.h index 2fa616c2a81..431fa1bc345 100644 --- a/include/llvm/DebugInfo/CodeView/SymbolRecord.h +++ b/include/llvm/DebugInfo/CodeView/SymbolRecord.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 diff --git a/include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h b/include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h new file mode 100644 index 00000000000..a4965168c3d --- /dev/null +++ b/include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h @@ -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 |