Files
archived-llvm/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h
Zachary Turner 24466fcd2c 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
2016-05-23 23:41:13 +00:00

104 lines
4.0 KiB
C++

//===- 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