You've already forked linux-packaging-mono
Imported Upstream version 5.18.0.234
Former-commit-id: 8071ec1a8c5eaa9be24b41745add19297608001f
This commit is contained in:
parent
f32dbaf0b2
commit
212f6bafcb
@ -1,101 +0,0 @@
|
||||
//===- AppendingTypeTableBuilder.cpp --------------------------------------===//
|
||||
//
|
||||
// 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/AppendingTypeTableBuilder.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/DebugInfo/CodeView/CodeView.h"
|
||||
#include "llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h"
|
||||
#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/Support/BinaryByteStream.h"
|
||||
#include "llvm/Support/BinaryStreamWriter.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::codeview;
|
||||
|
||||
TypeIndex AppendingTypeTableBuilder::nextTypeIndex() const {
|
||||
return TypeIndex::fromArrayIndex(SeenRecords.size());
|
||||
}
|
||||
|
||||
AppendingTypeTableBuilder::AppendingTypeTableBuilder(BumpPtrAllocator &Storage)
|
||||
: RecordStorage(Storage) {}
|
||||
|
||||
AppendingTypeTableBuilder::~AppendingTypeTableBuilder() = default;
|
||||
|
||||
Optional<TypeIndex> AppendingTypeTableBuilder::getFirst() {
|
||||
if (empty())
|
||||
return None;
|
||||
|
||||
return TypeIndex(TypeIndex::FirstNonSimpleIndex);
|
||||
}
|
||||
|
||||
Optional<TypeIndex> AppendingTypeTableBuilder::getNext(TypeIndex Prev) {
|
||||
if (++Prev == nextTypeIndex())
|
||||
return None;
|
||||
return Prev;
|
||||
}
|
||||
|
||||
CVType AppendingTypeTableBuilder::getType(TypeIndex Index) {
|
||||
CVType Type;
|
||||
Type.RecordData = SeenRecords[Index.toArrayIndex()];
|
||||
const RecordPrefix *P =
|
||||
reinterpret_cast<const RecordPrefix *>(Type.RecordData.data());
|
||||
Type.Type = static_cast<TypeLeafKind>(uint16_t(P->RecordKind));
|
||||
return Type;
|
||||
}
|
||||
|
||||
StringRef AppendingTypeTableBuilder::getTypeName(TypeIndex Index) {
|
||||
llvm_unreachable("Method not implemented");
|
||||
}
|
||||
|
||||
bool AppendingTypeTableBuilder::contains(TypeIndex Index) {
|
||||
if (Index.isSimple() || Index.isNoneType())
|
||||
return false;
|
||||
|
||||
return Index.toArrayIndex() < SeenRecords.size();
|
||||
}
|
||||
|
||||
uint32_t AppendingTypeTableBuilder::size() { return SeenRecords.size(); }
|
||||
|
||||
uint32_t AppendingTypeTableBuilder::capacity() { return SeenRecords.size(); }
|
||||
|
||||
ArrayRef<ArrayRef<uint8_t>> AppendingTypeTableBuilder::records() const {
|
||||
return SeenRecords;
|
||||
}
|
||||
|
||||
void AppendingTypeTableBuilder::reset() { SeenRecords.clear(); }
|
||||
|
||||
TypeIndex
|
||||
AppendingTypeTableBuilder::insertRecordBytes(ArrayRef<uint8_t> &Record) {
|
||||
TypeIndex NewTI = nextTypeIndex();
|
||||
uint8_t *Stable = RecordStorage.Allocate<uint8_t>(Record.size());
|
||||
memcpy(Stable, Record.data(), Record.size());
|
||||
Record = ArrayRef<uint8_t>(Stable, Record.size());
|
||||
SeenRecords.push_back(Record);
|
||||
return NewTI;
|
||||
}
|
||||
|
||||
TypeIndex
|
||||
AppendingTypeTableBuilder::insertRecord(ContinuationRecordBuilder &Builder) {
|
||||
TypeIndex TI;
|
||||
auto Fragments = Builder.end(nextTypeIndex());
|
||||
assert(!Fragments.empty());
|
||||
for (auto C : Fragments)
|
||||
TI = insertRecordBytes(C.RecordData);
|
||||
return TI;
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
add_llvm_library(LLVMDebugInfoCodeView
|
||||
AppendingTypeTableBuilder.cpp
|
||||
CodeViewError.cpp
|
||||
CodeViewRecordIO.cpp
|
||||
ContinuationRecordBuilder.cpp
|
||||
CVSymbolVisitor.cpp
|
||||
CVTypeVisitor.cpp
|
||||
DebugChecksumsSubsection.cpp
|
||||
DebugCrossExSubsection.cpp
|
||||
DebugCrossImpSubsection.cpp
|
||||
DebugFrameDataSubsection.cpp
|
||||
DebugInlineeLinesSubsection.cpp
|
||||
DebugLinesSubsection.cpp
|
||||
DebugStringTableSubsection.cpp
|
||||
DebugSubsection.cpp
|
||||
DebugSubsectionRecord.cpp
|
||||
DebugSubsectionVisitor.cpp
|
||||
DebugSymbolRVASubsection.cpp
|
||||
DebugSymbolsSubsection.cpp
|
||||
EnumTables.cpp
|
||||
Formatters.cpp
|
||||
GlobalTypeTableBuilder.cpp
|
||||
LazyRandomTypeCollection.cpp
|
||||
Line.cpp
|
||||
MergingTypeTableBuilder.cpp
|
||||
RecordName.cpp
|
||||
RecordSerialization.cpp
|
||||
SimpleTypeSerializer.cpp
|
||||
StringsAndChecksums.cpp
|
||||
SymbolRecordMapping.cpp
|
||||
SymbolDumper.cpp
|
||||
SymbolSerializer.cpp
|
||||
TypeDumpVisitor.cpp
|
||||
TypeIndex.cpp
|
||||
TypeIndexDiscovery.cpp
|
||||
TypeHashing.cpp
|
||||
TypeRecordMapping.cpp
|
||||
TypeStreamMerger.cpp
|
||||
TypeTableCollection.cpp
|
||||
|
||||
ADDITIONAL_HEADER_DIRS
|
||||
${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/CodeView
|
||||
)
|
@ -1,83 +0,0 @@
|
||||
//===- CVSymbolVisitor.cpp --------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
|
||||
|
||||
#include "llvm/DebugInfo/CodeView/CodeViewError.h"
|
||||
#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::codeview;
|
||||
|
||||
CVSymbolVisitor::CVSymbolVisitor(SymbolVisitorCallbacks &Callbacks)
|
||||
: Callbacks(Callbacks) {}
|
||||
|
||||
template <typename T>
|
||||
static Error visitKnownRecord(CVSymbol &Record,
|
||||
SymbolVisitorCallbacks &Callbacks) {
|
||||
SymbolRecordKind RK = static_cast<SymbolRecordKind>(Record.Type);
|
||||
T KnownRecord(RK);
|
||||
if (auto EC = Callbacks.visitKnownRecord(Record, KnownRecord))
|
||||
return EC;
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
static Error finishVisitation(CVSymbol &Record,
|
||||
SymbolVisitorCallbacks &Callbacks) {
|
||||
switch (Record.Type) {
|
||||
default:
|
||||
if (auto EC = Callbacks.visitUnknownSymbol(Record))
|
||||
return EC;
|
||||
break;
|
||||
#define SYMBOL_RECORD(EnumName, EnumVal, Name) \
|
||||
case EnumName: { \
|
||||
if (auto EC = visitKnownRecord<Name>(Record, Callbacks)) \
|
||||
return EC; \
|
||||
break; \
|
||||
}
|
||||
#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
|
||||
SYMBOL_RECORD(EnumVal, EnumVal, AliasName)
|
||||
#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
|
||||
}
|
||||
|
||||
if (auto EC = Callbacks.visitSymbolEnd(Record))
|
||||
return EC;
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error CVSymbolVisitor::visitSymbolRecord(CVSymbol &Record) {
|
||||
if (auto EC = Callbacks.visitSymbolBegin(Record))
|
||||
return EC;
|
||||
return finishVisitation(Record, Callbacks);
|
||||
}
|
||||
|
||||
Error CVSymbolVisitor::visitSymbolRecord(CVSymbol &Record, uint32_t Offset) {
|
||||
if (auto EC = Callbacks.visitSymbolBegin(Record, Offset))
|
||||
return EC;
|
||||
return finishVisitation(Record, Callbacks);
|
||||
}
|
||||
|
||||
Error CVSymbolVisitor::visitSymbolStream(const CVSymbolArray &Symbols) {
|
||||
for (auto I : Symbols) {
|
||||
if (auto EC = visitSymbolRecord(I))
|
||||
return EC;
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error CVSymbolVisitor::visitSymbolStream(const CVSymbolArray &Symbols,
|
||||
uint32_t InitialOffset) {
|
||||
for (auto I : Symbols) {
|
||||
if (auto EC = visitSymbolRecord(I, InitialOffset))
|
||||
return EC;
|
||||
InitialOffset += I.length();
|
||||
}
|
||||
return Error::success();
|
||||
}
|
@ -1,275 +0,0 @@
|
||||
//===- CVTypeVisitor.cpp ----------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
|
||||
|
||||
#include "llvm/DebugInfo/CodeView/CodeViewError.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeCollection.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
|
||||
#include "llvm/Support/BinaryByteStream.h"
|
||||
#include "llvm/Support/BinaryStreamReader.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::codeview;
|
||||
|
||||
|
||||
template <typename T>
|
||||
static Error visitKnownRecord(CVType &Record, TypeVisitorCallbacks &Callbacks) {
|
||||
TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Type);
|
||||
T KnownRecord(RK);
|
||||
if (auto EC = Callbacks.visitKnownRecord(Record, KnownRecord))
|
||||
return EC;
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static Error visitKnownMember(CVMemberRecord &Record,
|
||||
TypeVisitorCallbacks &Callbacks) {
|
||||
TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Kind);
|
||||
T KnownRecord(RK);
|
||||
if (auto EC = Callbacks.visitKnownMember(Record, KnownRecord))
|
||||
return EC;
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
static Error visitMemberRecord(CVMemberRecord &Record,
|
||||
TypeVisitorCallbacks &Callbacks) {
|
||||
if (auto EC = Callbacks.visitMemberBegin(Record))
|
||||
return EC;
|
||||
|
||||
switch (Record.Kind) {
|
||||
default:
|
||||
if (auto EC = Callbacks.visitUnknownMember(Record))
|
||||
return EC;
|
||||
break;
|
||||
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
|
||||
case EnumName: { \
|
||||
if (auto EC = visitKnownMember<Name##Record>(Record, Callbacks)) \
|
||||
return EC; \
|
||||
break; \
|
||||
}
|
||||
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
|
||||
MEMBER_RECORD(EnumVal, EnumVal, AliasName)
|
||||
#define TYPE_RECORD(EnumName, EnumVal, Name)
|
||||
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
|
||||
#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
|
||||
}
|
||||
|
||||
if (auto EC = Callbacks.visitMemberEnd(Record))
|
||||
return EC;
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class CVTypeVisitor {
|
||||
public:
|
||||
explicit CVTypeVisitor(TypeVisitorCallbacks &Callbacks);
|
||||
|
||||
Error visitTypeRecord(CVType &Record, TypeIndex Index);
|
||||
Error visitTypeRecord(CVType &Record);
|
||||
|
||||
/// Visits the type records in Data. Sets the error flag on parse failures.
|
||||
Error visitTypeStream(const CVTypeArray &Types);
|
||||
Error visitTypeStream(CVTypeRange Types);
|
||||
Error visitTypeStream(TypeCollection &Types);
|
||||
|
||||
Error visitMemberRecord(CVMemberRecord Record);
|
||||
Error visitFieldListMemberStream(BinaryStreamReader &Stream);
|
||||
|
||||
private:
|
||||
Error finishVisitation(CVType &Record);
|
||||
|
||||
/// The interface to the class that gets notified of each visitation.
|
||||
TypeVisitorCallbacks &Callbacks;
|
||||
};
|
||||
|
||||
CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks)
|
||||
: Callbacks(Callbacks) {}
|
||||
|
||||
Error CVTypeVisitor::finishVisitation(CVType &Record) {
|
||||
switch (Record.Type) {
|
||||
default:
|
||||
if (auto EC = Callbacks.visitUnknownType(Record))
|
||||
return EC;
|
||||
break;
|
||||
#define TYPE_RECORD(EnumName, EnumVal, Name) \
|
||||
case EnumName: { \
|
||||
if (auto EC = visitKnownRecord<Name##Record>(Record, Callbacks)) \
|
||||
return EC; \
|
||||
break; \
|
||||
}
|
||||
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
|
||||
TYPE_RECORD(EnumVal, EnumVal, AliasName)
|
||||
#define MEMBER_RECORD(EnumName, EnumVal, Name)
|
||||
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
|
||||
#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
|
||||
}
|
||||
|
||||
if (auto EC = Callbacks.visitTypeEnd(Record))
|
||||
return EC;
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error CVTypeVisitor::visitTypeRecord(CVType &Record, TypeIndex Index) {
|
||||
if (auto EC = Callbacks.visitTypeBegin(Record, Index))
|
||||
return EC;
|
||||
|
||||
return finishVisitation(Record);
|
||||
}
|
||||
|
||||
Error CVTypeVisitor::visitTypeRecord(CVType &Record) {
|
||||
if (auto EC = Callbacks.visitTypeBegin(Record))
|
||||
return EC;
|
||||
|
||||
return finishVisitation(Record);
|
||||
}
|
||||
|
||||
Error CVTypeVisitor::visitMemberRecord(CVMemberRecord Record) {
|
||||
return ::visitMemberRecord(Record, Callbacks);
|
||||
}
|
||||
|
||||
/// Visits the type records in Data. Sets the error flag on parse failures.
|
||||
Error CVTypeVisitor::visitTypeStream(const CVTypeArray &Types) {
|
||||
for (auto I : Types) {
|
||||
if (auto EC = visitTypeRecord(I))
|
||||
return EC;
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error CVTypeVisitor::visitTypeStream(CVTypeRange Types) {
|
||||
for (auto I : Types) {
|
||||
if (auto EC = visitTypeRecord(I))
|
||||
return EC;
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error CVTypeVisitor::visitTypeStream(TypeCollection &Types) {
|
||||
Optional<TypeIndex> I = Types.getFirst();
|
||||
while (I) {
|
||||
CVType Type = Types.getType(*I);
|
||||
if (auto EC = visitTypeRecord(Type, *I))
|
||||
return EC;
|
||||
I = Types.getNext(*I);
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error CVTypeVisitor::visitFieldListMemberStream(BinaryStreamReader &Reader) {
|
||||
TypeLeafKind Leaf;
|
||||
while (!Reader.empty()) {
|
||||
if (auto EC = Reader.readEnum(Leaf))
|
||||
return EC;
|
||||
|
||||
CVMemberRecord Record;
|
||||
Record.Kind = Leaf;
|
||||
if (auto EC = ::visitMemberRecord(Record, Callbacks))
|
||||
return EC;
|
||||
}
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
struct FieldListVisitHelper {
|
||||
FieldListVisitHelper(TypeVisitorCallbacks &Callbacks, ArrayRef<uint8_t> Data,
|
||||
VisitorDataSource Source)
|
||||
: Stream(Data, llvm::support::little), Reader(Stream),
|
||||
Deserializer(Reader),
|
||||
Visitor((Source == VDS_BytesPresent) ? Pipeline : Callbacks) {
|
||||
if (Source == VDS_BytesPresent) {
|
||||
Pipeline.addCallbackToPipeline(Deserializer);
|
||||
Pipeline.addCallbackToPipeline(Callbacks);
|
||||
}
|
||||
}
|
||||
|
||||
BinaryByteStream Stream;
|
||||
BinaryStreamReader Reader;
|
||||
FieldListDeserializer Deserializer;
|
||||
TypeVisitorCallbackPipeline Pipeline;
|
||||
CVTypeVisitor Visitor;
|
||||
};
|
||||
|
||||
struct VisitHelper {
|
||||
VisitHelper(TypeVisitorCallbacks &Callbacks, VisitorDataSource Source)
|
||||
: Visitor((Source == VDS_BytesPresent) ? Pipeline : Callbacks) {
|
||||
if (Source == VDS_BytesPresent) {
|
||||
Pipeline.addCallbackToPipeline(Deserializer);
|
||||
Pipeline.addCallbackToPipeline(Callbacks);
|
||||
}
|
||||
}
|
||||
|
||||
TypeDeserializer Deserializer;
|
||||
TypeVisitorCallbackPipeline Pipeline;
|
||||
CVTypeVisitor Visitor;
|
||||
};
|
||||
}
|
||||
|
||||
Error llvm::codeview::visitTypeRecord(CVType &Record, TypeIndex Index,
|
||||
TypeVisitorCallbacks &Callbacks,
|
||||
VisitorDataSource Source) {
|
||||
VisitHelper V(Callbacks, Source);
|
||||
return V.Visitor.visitTypeRecord(Record, Index);
|
||||
}
|
||||
|
||||
Error llvm::codeview::visitTypeRecord(CVType &Record,
|
||||
TypeVisitorCallbacks &Callbacks,
|
||||
VisitorDataSource Source) {
|
||||
VisitHelper V(Callbacks, Source);
|
||||
return V.Visitor.visitTypeRecord(Record);
|
||||
}
|
||||
|
||||
Error llvm::codeview::visitTypeStream(const CVTypeArray &Types,
|
||||
TypeVisitorCallbacks &Callbacks,
|
||||
VisitorDataSource Source) {
|
||||
VisitHelper V(Callbacks, Source);
|
||||
return V.Visitor.visitTypeStream(Types);
|
||||
}
|
||||
|
||||
Error llvm::codeview::visitTypeStream(CVTypeRange Types,
|
||||
TypeVisitorCallbacks &Callbacks) {
|
||||
VisitHelper V(Callbacks, VDS_BytesPresent);
|
||||
return V.Visitor.visitTypeStream(Types);
|
||||
}
|
||||
|
||||
Error llvm::codeview::visitTypeStream(TypeCollection &Types,
|
||||
TypeVisitorCallbacks &Callbacks) {
|
||||
// When the internal visitor calls Types.getType(Index) the interface is
|
||||
// required to return a CVType with the bytes filled out. So we can assume
|
||||
// that the bytes will be present when individual records are visited.
|
||||
VisitHelper V(Callbacks, VDS_BytesPresent);
|
||||
return V.Visitor.visitTypeStream(Types);
|
||||
}
|
||||
|
||||
Error llvm::codeview::visitMemberRecord(CVMemberRecord Record,
|
||||
TypeVisitorCallbacks &Callbacks,
|
||||
VisitorDataSource Source) {
|
||||
FieldListVisitHelper V(Callbacks, Record.Data, Source);
|
||||
return V.Visitor.visitMemberRecord(Record);
|
||||
}
|
||||
|
||||
Error llvm::codeview::visitMemberRecord(TypeLeafKind Kind,
|
||||
ArrayRef<uint8_t> Record,
|
||||
TypeVisitorCallbacks &Callbacks) {
|
||||
CVMemberRecord R;
|
||||
R.Data = Record;
|
||||
R.Kind = Kind;
|
||||
return visitMemberRecord(R, Callbacks, VDS_BytesPresent);
|
||||
}
|
||||
|
||||
Error llvm::codeview::visitMemberRecordStream(ArrayRef<uint8_t> FieldList,
|
||||
TypeVisitorCallbacks &Callbacks) {
|
||||
FieldListVisitHelper V(Callbacks, FieldList, VDS_BytesPresent);
|
||||
return V.Visitor.visitFieldListMemberStream(V.Reader);
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
//===- CodeViewError.cpp - Error extensions for CodeView --------*- 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/CodeViewError.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/ManagedStatic.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::codeview;
|
||||
|
||||
namespace {
|
||||
// FIXME: This class is only here to support the transition to llvm::Error. It
|
||||
// will be removed once this transition is complete. Clients should prefer to
|
||||
// deal with the Error value directly, rather than converting to error_code.
|
||||
class CodeViewErrorCategory : public std::error_category {
|
||||
public:
|
||||
const char *name() const noexcept override { return "llvm.codeview"; }
|
||||
|
||||
std::string message(int Condition) const override {
|
||||
switch (static_cast<cv_error_code>(Condition)) {
|
||||
case cv_error_code::unspecified:
|
||||
return "An unknown error has occurred.";
|
||||
case cv_error_code::insufficient_buffer:
|
||||
return "The buffer is not large enough to read the requested number of "
|
||||
"bytes.";
|
||||
case cv_error_code::corrupt_record:
|
||||
return "The CodeView record is corrupted.";
|
||||
case cv_error_code::no_records:
|
||||
return "There are no records";
|
||||
case cv_error_code::operation_unsupported:
|
||||
return "The requested operation is not supported.";
|
||||
case cv_error_code::unknown_member_record:
|
||||
return "The member record is of an unknown type.";
|
||||
}
|
||||
llvm_unreachable("Unrecognized cv_error_code");
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
static ManagedStatic<CodeViewErrorCategory> Category;
|
||||
|
||||
char CodeViewError::ID = 0;
|
||||
|
||||
CodeViewError::CodeViewError(cv_error_code C) : CodeViewError(C, "") {}
|
||||
|
||||
CodeViewError::CodeViewError(const std::string &Context)
|
||||
: CodeViewError(cv_error_code::unspecified, Context) {}
|
||||
|
||||
CodeViewError::CodeViewError(cv_error_code C, const std::string &Context)
|
||||
: Code(C) {
|
||||
ErrMsg = "CodeView Error: ";
|
||||
std::error_code EC = convertToErrorCode();
|
||||
if (Code != cv_error_code::unspecified)
|
||||
ErrMsg += EC.message() + " ";
|
||||
if (!Context.empty())
|
||||
ErrMsg += Context;
|
||||
}
|
||||
|
||||
void CodeViewError::log(raw_ostream &OS) const { OS << ErrMsg << "\n"; }
|
||||
|
||||
const std::string &CodeViewError::getErrorMessage() const { return ErrMsg; }
|
||||
|
||||
std::error_code CodeViewError::convertToErrorCode() const {
|
||||
return std::error_code(static_cast<int>(Code), *Category);
|
||||
}
|
@ -1,257 +0,0 @@
|
||||
//===- CodeViewRecordIO.cpp -------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/DebugInfo/CodeView/CodeViewRecordIO.h"
|
||||
#include "llvm/DebugInfo/CodeView/CodeView.h"
|
||||
#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
|
||||
#include "llvm/Support/BinaryStreamReader.h"
|
||||
#include "llvm/Support/BinaryStreamWriter.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::codeview;
|
||||
|
||||
Error CodeViewRecordIO::beginRecord(Optional<uint32_t> MaxLength) {
|
||||
RecordLimit Limit;
|
||||
Limit.MaxLength = MaxLength;
|
||||
Limit.BeginOffset = getCurrentOffset();
|
||||
Limits.push_back(Limit);
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error CodeViewRecordIO::endRecord() {
|
||||
assert(!Limits.empty() && "Not in a record!");
|
||||
Limits.pop_back();
|
||||
// We would like to assert that we actually read / wrote all the bytes that we
|
||||
// expected to for this record, but unfortunately we can't do this. Some
|
||||
// producers such as MASM over-allocate for certain types of records and
|
||||
// commit the extraneous data, so when reading we can't be sure every byte
|
||||
// will have been read. And when writing we over-allocate temporarily since
|
||||
// we don't know how big the record is until we're finished writing it, so
|
||||
// even though we don't commit the extraneous data, we still can't guarantee
|
||||
// we're at the end of the allocated data.
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
uint32_t CodeViewRecordIO::maxFieldLength() const {
|
||||
assert(!Limits.empty() && "Not in a record!");
|
||||
|
||||
// The max length of the next field is the minimum of all lengths that would
|
||||
// be allowed by any of the sub-records we're in. In practice, we can only
|
||||
// ever be at most 1 sub-record deep (in a FieldList), but this works for
|
||||
// the general case.
|
||||
uint32_t Offset = getCurrentOffset();
|
||||
Optional<uint32_t> Min = Limits.front().bytesRemaining(Offset);
|
||||
for (auto X : makeArrayRef(Limits).drop_front()) {
|
||||
Optional<uint32_t> ThisMin = X.bytesRemaining(Offset);
|
||||
if (ThisMin.hasValue())
|
||||
Min = (Min.hasValue()) ? std::min(*Min, *ThisMin) : *ThisMin;
|
||||
}
|
||||
assert(Min.hasValue() && "Every field must have a maximum length!");
|
||||
|
||||
return *Min;
|
||||
}
|
||||
|
||||
Error CodeViewRecordIO::padToAlignment(uint32_t Align) {
|
||||
if (isReading())
|
||||
return Reader->padToAlignment(Align);
|
||||
return Writer->padToAlignment(Align);
|
||||
}
|
||||
|
||||
Error CodeViewRecordIO::skipPadding() {
|
||||
assert(!isWriting() && "Cannot skip padding while writing!");
|
||||
|
||||
if (Reader->bytesRemaining() == 0)
|
||||
return Error::success();
|
||||
|
||||
uint8_t Leaf = Reader->peek();
|
||||
if (Leaf < LF_PAD0)
|
||||
return Error::success();
|
||||
// Leaf is greater than 0xf0. We should advance by the number of bytes in
|
||||
// the low 4 bits.
|
||||
unsigned BytesToAdvance = Leaf & 0x0F;
|
||||
return Reader->skip(BytesToAdvance);
|
||||
}
|
||||
|
||||
Error CodeViewRecordIO::mapByteVectorTail(ArrayRef<uint8_t> &Bytes) {
|
||||
if (isWriting()) {
|
||||
if (auto EC = Writer->writeBytes(Bytes))
|
||||
return EC;
|
||||
} else {
|
||||
if (auto EC = Reader->readBytes(Bytes, Reader->bytesRemaining()))
|
||||
return EC;
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error CodeViewRecordIO::mapByteVectorTail(std::vector<uint8_t> &Bytes) {
|
||||
ArrayRef<uint8_t> BytesRef(Bytes);
|
||||
if (auto EC = mapByteVectorTail(BytesRef))
|
||||
return EC;
|
||||
if (!isWriting())
|
||||
Bytes.assign(BytesRef.begin(), BytesRef.end());
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error CodeViewRecordIO::mapInteger(TypeIndex &TypeInd) {
|
||||
if (isWriting()) {
|
||||
if (auto EC = Writer->writeInteger(TypeInd.getIndex()))
|
||||
return EC;
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
uint32_t I;
|
||||
if (auto EC = Reader->readInteger(I))
|
||||
return EC;
|
||||
TypeInd.setIndex(I);
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error CodeViewRecordIO::mapEncodedInteger(int64_t &Value) {
|
||||
if (isWriting()) {
|
||||
if (Value >= 0) {
|
||||
if (auto EC = writeEncodedUnsignedInteger(static_cast<uint64_t>(Value)))
|
||||
return EC;
|
||||
} else {
|
||||
if (auto EC = writeEncodedSignedInteger(Value))
|
||||
return EC;
|
||||
}
|
||||
} else {
|
||||
APSInt N;
|
||||
if (auto EC = consume(*Reader, N))
|
||||
return EC;
|
||||
Value = N.getExtValue();
|
||||
}
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error CodeViewRecordIO::mapEncodedInteger(uint64_t &Value) {
|
||||
if (isWriting()) {
|
||||
if (auto EC = writeEncodedUnsignedInteger(Value))
|
||||
return EC;
|
||||
} else {
|
||||
APSInt N;
|
||||
if (auto EC = consume(*Reader, N))
|
||||
return EC;
|
||||
Value = N.getZExtValue();
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error CodeViewRecordIO::mapEncodedInteger(APSInt &Value) {
|
||||
if (isWriting()) {
|
||||
if (Value.isSigned())
|
||||
return writeEncodedSignedInteger(Value.getSExtValue());
|
||||
return writeEncodedUnsignedInteger(Value.getZExtValue());
|
||||
}
|
||||
|
||||
return consume(*Reader, Value);
|
||||
}
|
||||
|
||||
Error CodeViewRecordIO::mapStringZ(StringRef &Value) {
|
||||
if (isWriting()) {
|
||||
// Truncate if we attempt to write too much.
|
||||
StringRef S = Value.take_front(maxFieldLength() - 1);
|
||||
if (auto EC = Writer->writeCString(S))
|
||||
return EC;
|
||||
} else {
|
||||
if (auto EC = Reader->readCString(Value))
|
||||
return EC;
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error CodeViewRecordIO::mapGuid(GUID &Guid) {
|
||||
constexpr uint32_t GuidSize = 16;
|
||||
if (maxFieldLength() < GuidSize)
|
||||
return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
|
||||
|
||||
if (isWriting()) {
|
||||
if (auto EC = Writer->writeBytes(Guid.Guid))
|
||||
return EC;
|
||||
} else {
|
||||
ArrayRef<uint8_t> GuidBytes;
|
||||
if (auto EC = Reader->readBytes(GuidBytes, GuidSize))
|
||||
return EC;
|
||||
memcpy(Guid.Guid, GuidBytes.data(), GuidSize);
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error CodeViewRecordIO::mapStringZVectorZ(std::vector<StringRef> &Value) {
|
||||
if (isWriting()) {
|
||||
for (auto V : Value) {
|
||||
if (auto EC = mapStringZ(V))
|
||||
return EC;
|
||||
}
|
||||
if (auto EC = Writer->writeInteger<uint8_t>(0))
|
||||
return EC;
|
||||
} else {
|
||||
StringRef S;
|
||||
if (auto EC = mapStringZ(S))
|
||||
return EC;
|
||||
while (!S.empty()) {
|
||||
Value.push_back(S);
|
||||
if (auto EC = mapStringZ(S))
|
||||
return EC;
|
||||
};
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error CodeViewRecordIO::writeEncodedSignedInteger(const int64_t &Value) {
|
||||
assert(Value < 0 && "Encoded integer is not signed!");
|
||||
if (Value >= std::numeric_limits<int8_t>::min()) {
|
||||
if (auto EC = Writer->writeInteger<uint16_t>(LF_CHAR))
|
||||
return EC;
|
||||
if (auto EC = Writer->writeInteger<int8_t>(Value))
|
||||
return EC;
|
||||
} else if (Value >= std::numeric_limits<int16_t>::min()) {
|
||||
if (auto EC = Writer->writeInteger<uint16_t>(LF_SHORT))
|
||||
return EC;
|
||||
if (auto EC = Writer->writeInteger<int16_t>(Value))
|
||||
return EC;
|
||||
} else if (Value >= std::numeric_limits<int32_t>::min()) {
|
||||
if (auto EC = Writer->writeInteger<uint16_t>(LF_LONG))
|
||||
return EC;
|
||||
if (auto EC = Writer->writeInteger<int32_t>(Value))
|
||||
return EC;
|
||||
} else {
|
||||
if (auto EC = Writer->writeInteger<uint16_t>(LF_QUADWORD))
|
||||
return EC;
|
||||
if (auto EC = Writer->writeInteger(Value))
|
||||
return EC;
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error CodeViewRecordIO::writeEncodedUnsignedInteger(const uint64_t &Value) {
|
||||
if (Value < LF_NUMERIC) {
|
||||
if (auto EC = Writer->writeInteger<uint16_t>(Value))
|
||||
return EC;
|
||||
} else if (Value <= std::numeric_limits<uint16_t>::max()) {
|
||||
if (auto EC = Writer->writeInteger<uint16_t>(LF_USHORT))
|
||||
return EC;
|
||||
if (auto EC = Writer->writeInteger<uint16_t>(Value))
|
||||
return EC;
|
||||
} else if (Value <= std::numeric_limits<uint32_t>::max()) {
|
||||
if (auto EC = Writer->writeInteger<uint16_t>(LF_ULONG))
|
||||
return EC;
|
||||
if (auto EC = Writer->writeInteger<uint32_t>(Value))
|
||||
return EC;
|
||||
} else {
|
||||
if (auto EC = Writer->writeInteger<uint16_t>(LF_UQUADWORD))
|
||||
return EC;
|
||||
if (auto EC = Writer->writeInteger(Value))
|
||||
return EC;
|
||||
}
|
||||
|
||||
return Error::success();
|
||||
}
|
@ -1,259 +0,0 @@
|
||||
#include "llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::codeview;
|
||||
|
||||
namespace {
|
||||
struct ContinuationRecord {
|
||||
ulittle16_t Kind{uint16_t(TypeLeafKind::LF_INDEX)};
|
||||
ulittle16_t Size{0};
|
||||
ulittle32_t IndexRef{0xB0C0B0C0};
|
||||
};
|
||||
|
||||
struct SegmentInjection {
|
||||
SegmentInjection(TypeLeafKind Kind) { Prefix.RecordKind = Kind; }
|
||||
|
||||
ContinuationRecord Cont;
|
||||
RecordPrefix Prefix;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
static void addPadding(BinaryStreamWriter &Writer) {
|
||||
uint32_t Align = Writer.getOffset() % 4;
|
||||
if (Align == 0)
|
||||
return;
|
||||
|
||||
int PaddingBytes = 4 - Align;
|
||||
while (PaddingBytes > 0) {
|
||||
uint8_t Pad = static_cast<uint8_t>(LF_PAD0 + PaddingBytes);
|
||||
cantFail(Writer.writeInteger(Pad));
|
||||
--PaddingBytes;
|
||||
}
|
||||
}
|
||||
|
||||
static SegmentInjection InjectFieldList(TypeLeafKind::LF_FIELDLIST);
|
||||
static SegmentInjection InjectMethodOverloadList(TypeLeafKind::LF_METHODLIST);
|
||||
|
||||
static constexpr uint32_t ContinuationLength = sizeof(ContinuationRecord);
|
||||
static constexpr uint32_t MaxSegmentLength =
|
||||
MaxRecordLength - ContinuationLength;
|
||||
|
||||
static inline TypeLeafKind getTypeLeafKind(ContinuationRecordKind CK) {
|
||||
return (CK == ContinuationRecordKind::FieldList) ? LF_FIELDLIST
|
||||
: LF_METHODLIST;
|
||||
}
|
||||
|
||||
ContinuationRecordBuilder::ContinuationRecordBuilder()
|
||||
: SegmentWriter(Buffer), Mapping(SegmentWriter) {}
|
||||
|
||||
ContinuationRecordBuilder::~ContinuationRecordBuilder() {}
|
||||
|
||||
void ContinuationRecordBuilder::begin(ContinuationRecordKind RecordKind) {
|
||||
assert(!Kind.hasValue());
|
||||
Kind = RecordKind;
|
||||
Buffer.clear();
|
||||
SegmentWriter.setOffset(0);
|
||||
SegmentOffsets.clear();
|
||||
SegmentOffsets.push_back(0);
|
||||
assert(SegmentWriter.getOffset() == 0);
|
||||
assert(SegmentWriter.getLength() == 0);
|
||||
|
||||
const SegmentInjection *FLI =
|
||||
(RecordKind == ContinuationRecordKind::FieldList)
|
||||
? &InjectFieldList
|
||||
: &InjectMethodOverloadList;
|
||||
const uint8_t *FLIB = reinterpret_cast<const uint8_t *>(FLI);
|
||||
InjectedSegmentBytes =
|
||||
ArrayRef<uint8_t>(FLIB, FLIB + sizeof(SegmentInjection));
|
||||
|
||||
CVType Type;
|
||||
Type.Type = getTypeLeafKind(RecordKind);
|
||||
cantFail(Mapping.visitTypeBegin(Type));
|
||||
|
||||
// Seed the first trecord with an appropriate record prefix.
|
||||
RecordPrefix Prefix;
|
||||
Prefix.RecordLen = 0;
|
||||
Prefix.RecordKind = Type.Type;
|
||||
cantFail(SegmentWriter.writeObject(Prefix));
|
||||
}
|
||||
|
||||
template <typename RecordType>
|
||||
void ContinuationRecordBuilder::writeMemberType(RecordType &Record) {
|
||||
assert(Kind.hasValue());
|
||||
|
||||
uint32_t OriginalOffset = SegmentWriter.getOffset();
|
||||
CVMemberRecord CVMR;
|
||||
CVMR.Kind = static_cast<TypeLeafKind>(Record.getKind());
|
||||
|
||||
// Member Records aren't length-prefixed, they only have a 2-byte TypeLeafKind
|
||||
// at the beginning.
|
||||
cantFail(SegmentWriter.writeEnum(CVMR.Kind));
|
||||
|
||||
// Let the Mapping handle the rest.
|
||||
cantFail(Mapping.visitMemberBegin(CVMR));
|
||||
cantFail(Mapping.visitKnownMember(CVMR, Record));
|
||||
cantFail(Mapping.visitMemberEnd(CVMR));
|
||||
|
||||
// Make sure it's padded to 4 bytes.
|
||||
addPadding(SegmentWriter);
|
||||
assert(getCurrentSegmentLength() % 4 == 0);
|
||||
|
||||
// The maximum length of a single segment is 64KB minus the size to insert a
|
||||
// continuation. So if we are over that, inject a continuation between the
|
||||
// previous member and the member that was just written, then end the previous
|
||||
// segment after the continuation and begin a new one with the just-written
|
||||
// member.
|
||||
if (getCurrentSegmentLength() > MaxSegmentLength) {
|
||||
// We need to inject some bytes before the member we just wrote but after
|
||||
// the previous member. Save off the length of the member we just wrote so
|
||||
// that we can do some sanity checking on it.
|
||||
uint32_t MemberLength = SegmentWriter.getOffset() - OriginalOffset;
|
||||
(void) MemberLength;
|
||||
insertSegmentEnd(OriginalOffset);
|
||||
// Since this member now becomes a new top-level record, it should have
|
||||
// gotten a RecordPrefix injected, and that RecordPrefix + the member we
|
||||
// just wrote should now constitute the entirety of the current "new"
|
||||
// segment.
|
||||
assert(getCurrentSegmentLength() == MemberLength + sizeof(RecordPrefix));
|
||||
}
|
||||
|
||||
assert(getCurrentSegmentLength() % 4 == 0);
|
||||
assert(getCurrentSegmentLength() <= MaxSegmentLength);
|
||||
}
|
||||
|
||||
uint32_t ContinuationRecordBuilder::getCurrentSegmentLength() const {
|
||||
return SegmentWriter.getOffset() - SegmentOffsets.back();
|
||||
}
|
||||
|
||||
void ContinuationRecordBuilder::insertSegmentEnd(uint32_t Offset) {
|
||||
uint32_t SegmentBegin = SegmentOffsets.back();
|
||||
(void)SegmentBegin;
|
||||
assert(Offset > SegmentBegin);
|
||||
assert(Offset - SegmentBegin <= MaxSegmentLength);
|
||||
|
||||
// We need to make space for the continuation record. For now we can't fill
|
||||
// out the length or the TypeIndex of the back-reference, but we need the
|
||||
// space to at least be there.
|
||||
Buffer.insert(Offset, InjectedSegmentBytes);
|
||||
|
||||
uint32_t NewSegmentBegin = Offset + ContinuationLength;
|
||||
uint32_t SegmentLength = NewSegmentBegin - SegmentOffsets.back();
|
||||
(void) SegmentLength;
|
||||
|
||||
assert(SegmentLength % 4 == 0);
|
||||
assert(SegmentLength <= MaxRecordLength);
|
||||
SegmentOffsets.push_back(NewSegmentBegin);
|
||||
|
||||
// Seek to the end so that we can keep writing against the new segment.
|
||||
SegmentWriter.setOffset(SegmentWriter.getLength());
|
||||
assert(SegmentWriter.bytesRemaining() == 0);
|
||||
}
|
||||
|
||||
CVType ContinuationRecordBuilder::createSegmentRecord(
|
||||
uint32_t OffBegin, uint32_t OffEnd, Optional<TypeIndex> RefersTo) {
|
||||
assert(OffEnd - OffBegin <= USHRT_MAX);
|
||||
|
||||
MutableArrayRef<uint8_t> Data = Buffer.data();
|
||||
Data = Data.slice(OffBegin, OffEnd - OffBegin);
|
||||
|
||||
CVType Type;
|
||||
Type.Type = getTypeLeafKind(*Kind);
|
||||
Type.RecordData = Data;
|
||||
|
||||
// Write the length to the RecordPrefix, making sure it does not include
|
||||
// sizeof(RecordPrefix.Length)
|
||||
RecordPrefix *Prefix = reinterpret_cast<RecordPrefix *>(Data.data());
|
||||
assert(Prefix->RecordKind == Type.Type);
|
||||
Prefix->RecordLen = Data.size() - sizeof(RecordPrefix::RecordLen);
|
||||
|
||||
if (RefersTo.hasValue()) {
|
||||
auto Continuation = Data.take_back(ContinuationLength);
|
||||
ContinuationRecord *CR =
|
||||
reinterpret_cast<ContinuationRecord *>(Continuation.data());
|
||||
assert(CR->Kind == TypeLeafKind::LF_INDEX);
|
||||
assert(CR->IndexRef == 0xB0C0B0C0);
|
||||
CR->IndexRef = RefersTo->getIndex();
|
||||
}
|
||||
|
||||
return Type;
|
||||
}
|
||||
|
||||
std::vector<CVType> ContinuationRecordBuilder::end(TypeIndex Index) {
|
||||
CVType Type;
|
||||
Type.Type = getTypeLeafKind(*Kind);
|
||||
cantFail(Mapping.visitTypeEnd(Type));
|
||||
|
||||
// We're now done, and we have a series of segments each beginning at an
|
||||
// offset specified in the SegmentOffsets array. We now need to iterate
|
||||
// over each segment and post-process them in the following two ways:
|
||||
// 1) Each top-level record has a RecordPrefix whose type is either
|
||||
// LF_FIELDLIST or LF_METHODLIST, but the Length field is still 0.
|
||||
// Those should all be set to the correct length now.
|
||||
// 2) Each continuation record has an IndexRef field which we set to the
|
||||
// magic value 0xB0C0B0C0. Now that the caller has told us the TypeIndex
|
||||
// they want this sequence to start from, we can go through and update
|
||||
// each one.
|
||||
//
|
||||
// Logically, the sequence of records we've built up looks like this:
|
||||
//
|
||||
// SegmentOffsets[0]: <Length> (Initially: uninitialized)
|
||||
// SegmentOffsets[0]+2: LF_FIELDLIST
|
||||
// SegmentOffsets[0]+4: Member[0]
|
||||
// SegmentOffsets[0]+?: ...
|
||||
// SegmentOffsets[0]+?: Member[4]
|
||||
// SegmentOffsets[1]-8: LF_INDEX
|
||||
// SegmentOffsets[1]-6: 0
|
||||
// SegmentOffsets[1]-4: <Type Index of Next Record> (Initially: 0xB0C0B0C0)
|
||||
//
|
||||
// SegmentOffsets[1]: <Length> (Initially: uninitialized)
|
||||
// SegmentOffsets[1]+2: LF_FIELDLIST
|
||||
// SegmentOffsets[1]+4: Member[0]
|
||||
// SegmentOffsets[1]+?: ...
|
||||
// SegmentOffsets[1]+?: Member[s]
|
||||
// SegmentOffsets[2]-8: LF_INDEX
|
||||
// SegmentOffsets[2]-6: 0
|
||||
// SegmentOffsets[2]-4: <Type Index of Next Record> (Initially: 0xB0C0B0C0)
|
||||
//
|
||||
// ...
|
||||
//
|
||||
// SegmentOffsets[N]: <Length> (Initially: uninitialized)
|
||||
// SegmentOffsets[N]+2: LF_FIELDLIST
|
||||
// SegmentOffsets[N]+4: Member[0]
|
||||
// SegmentOffsets[N]+?: ...
|
||||
// SegmentOffsets[N]+?: Member[t]
|
||||
//
|
||||
// And this is the way we have laid them out in the serialization buffer. But
|
||||
// we cannot actually commit them to the underlying stream this way, due to
|
||||
// the topological sorting requirement of a type stream (specifically,
|
||||
// TypeIndex references can only point backwards, not forwards). So the
|
||||
// sequence that we return to the caller contains the records in reverse
|
||||
// order, which is the proper order for committing the serialized records.
|
||||
|
||||
std::vector<CVType> Types;
|
||||
Types.reserve(SegmentOffsets.size());
|
||||
|
||||
auto SO = makeArrayRef(SegmentOffsets);
|
||||
|
||||
uint32_t End = SegmentWriter.getOffset();
|
||||
|
||||
Optional<TypeIndex> RefersTo;
|
||||
for (uint32_t Offset : reverse(SO)) {
|
||||
Types.push_back(createSegmentRecord(Offset, End, RefersTo));
|
||||
|
||||
End = Offset;
|
||||
RefersTo = Index++;
|
||||
}
|
||||
|
||||
Kind.reset();
|
||||
return Types;
|
||||
}
|
||||
|
||||
// Explicitly instantiate the member function for each known type so that we can
|
||||
// implement this in the cpp file.
|
||||
#define TYPE_RECORD(EnumName, EnumVal, Name)
|
||||
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
|
||||
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
|
||||
template void llvm::codeview::ContinuationRecordBuilder::writeMemberType( \
|
||||
Name##Record &Record);
|
||||
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
|
||||
#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
|
@ -1,116 +0,0 @@
|
||||
//===- DebugChecksumsSubsection.cpp ---------------------------------------===//
|
||||
//
|
||||
// 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/DebugChecksumsSubsection.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/DebugInfo/CodeView/CodeView.h"
|
||||
#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
|
||||
#include "llvm/Support/BinaryStreamReader.h"
|
||||
#include "llvm/Support/BinaryStreamWriter.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::codeview;
|
||||
|
||||
struct FileChecksumEntryHeader {
|
||||
using ulittle32_t = support::ulittle32_t;
|
||||
|
||||
ulittle32_t FileNameOffset; // Byte offset of filename in global string table.
|
||||
uint8_t ChecksumSize; // Number of bytes of checksum.
|
||||
uint8_t ChecksumKind; // FileChecksumKind
|
||||
// Checksum bytes follow.
|
||||
};
|
||||
|
||||
Error VarStreamArrayExtractor<FileChecksumEntry>::
|
||||
operator()(BinaryStreamRef Stream, uint32_t &Len, FileChecksumEntry &Item) {
|
||||
BinaryStreamReader Reader(Stream);
|
||||
|
||||
const FileChecksumEntryHeader *Header;
|
||||
if (auto EC = Reader.readObject(Header))
|
||||
return EC;
|
||||
|
||||
Item.FileNameOffset = Header->FileNameOffset;
|
||||
Item.Kind = static_cast<FileChecksumKind>(Header->ChecksumKind);
|
||||
if (auto EC = Reader.readBytes(Item.Checksum, Header->ChecksumSize))
|
||||
return EC;
|
||||
|
||||
Len = alignTo(Header->ChecksumSize + sizeof(FileChecksumEntryHeader), 4);
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error DebugChecksumsSubsectionRef::initialize(BinaryStreamReader Reader) {
|
||||
if (auto EC = Reader.readArray(Checksums, Reader.bytesRemaining()))
|
||||
return EC;
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error DebugChecksumsSubsectionRef::initialize(BinaryStreamRef Section) {
|
||||
BinaryStreamReader Reader(Section);
|
||||
return initialize(Reader);
|
||||
}
|
||||
|
||||
DebugChecksumsSubsection::DebugChecksumsSubsection(
|
||||
DebugStringTableSubsection &Strings)
|
||||
: DebugSubsection(DebugSubsectionKind::FileChecksums), Strings(Strings) {}
|
||||
|
||||
void DebugChecksumsSubsection::addChecksum(StringRef FileName,
|
||||
FileChecksumKind Kind,
|
||||
ArrayRef<uint8_t> Bytes) {
|
||||
FileChecksumEntry Entry;
|
||||
if (!Bytes.empty()) {
|
||||
uint8_t *Copy = Storage.Allocate<uint8_t>(Bytes.size());
|
||||
::memcpy(Copy, Bytes.data(), Bytes.size());
|
||||
Entry.Checksum = makeArrayRef(Copy, Bytes.size());
|
||||
}
|
||||
|
||||
Entry.FileNameOffset = Strings.insert(FileName);
|
||||
Entry.Kind = Kind;
|
||||
Checksums.push_back(Entry);
|
||||
|
||||
// This maps the offset of this string in the string table to the offset
|
||||
// of this checksum entry in the checksum buffer.
|
||||
OffsetMap[Entry.FileNameOffset] = SerializedSize;
|
||||
assert(SerializedSize % 4 == 0);
|
||||
|
||||
uint32_t Len = alignTo(sizeof(FileChecksumEntryHeader) + Bytes.size(), 4);
|
||||
SerializedSize += Len;
|
||||
}
|
||||
|
||||
uint32_t DebugChecksumsSubsection::calculateSerializedSize() const {
|
||||
return SerializedSize;
|
||||
}
|
||||
|
||||
Error DebugChecksumsSubsection::commit(BinaryStreamWriter &Writer) const {
|
||||
for (const auto &FC : Checksums) {
|
||||
FileChecksumEntryHeader Header;
|
||||
Header.ChecksumKind = uint8_t(FC.Kind);
|
||||
Header.ChecksumSize = FC.Checksum.size();
|
||||
Header.FileNameOffset = FC.FileNameOffset;
|
||||
if (auto EC = Writer.writeObject(Header))
|
||||
return EC;
|
||||
if (auto EC = Writer.writeArray(makeArrayRef(FC.Checksum)))
|
||||
return EC;
|
||||
if (auto EC = Writer.padToAlignment(4))
|
||||
return EC;
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
uint32_t DebugChecksumsSubsection::mapChecksumOffset(StringRef FileName) const {
|
||||
uint32_t Offset = Strings.getStringId(FileName);
|
||||
auto Iter = OffsetMap.find(Offset);
|
||||
assert(Iter != OffsetMap.end());
|
||||
return Iter->second;
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
//===- DebugCrossExSubsection.cpp -----------------------------------------===//
|
||||
//
|
||||
// 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/DebugCrossExSubsection.h"
|
||||
#include "llvm/DebugInfo/CodeView/CodeViewError.h"
|
||||
#include "llvm/Support/BinaryStreamWriter.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include <cstdint>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::codeview;
|
||||
|
||||
Error DebugCrossModuleExportsSubsectionRef::initialize(
|
||||
BinaryStreamReader Reader) {
|
||||
if (Reader.bytesRemaining() % sizeof(CrossModuleExport) != 0)
|
||||
return make_error<CodeViewError>(
|
||||
cv_error_code::corrupt_record,
|
||||
"Cross Scope Exports section is an invalid size!");
|
||||
|
||||
uint32_t Size = Reader.bytesRemaining() / sizeof(CrossModuleExport);
|
||||
return Reader.readArray(References, Size);
|
||||
}
|
||||
|
||||
Error DebugCrossModuleExportsSubsectionRef::initialize(BinaryStreamRef Stream) {
|
||||
BinaryStreamReader Reader(Stream);
|
||||
return initialize(Reader);
|
||||
}
|
||||
|
||||
void DebugCrossModuleExportsSubsection::addMapping(uint32_t Local,
|
||||
uint32_t Global) {
|
||||
Mappings[Local] = Global;
|
||||
}
|
||||
|
||||
uint32_t DebugCrossModuleExportsSubsection::calculateSerializedSize() const {
|
||||
return Mappings.size() * sizeof(CrossModuleExport);
|
||||
}
|
||||
|
||||
Error DebugCrossModuleExportsSubsection::commit(
|
||||
BinaryStreamWriter &Writer) const {
|
||||
for (const auto &M : Mappings) {
|
||||
if (auto EC = Writer.writeInteger(M.first))
|
||||
return EC;
|
||||
if (auto EC = Writer.writeInteger(M.second))
|
||||
return EC;
|
||||
}
|
||||
return Error::success();
|
||||
}
|
@ -1,97 +0,0 @@
|
||||
//===- DebugCrossImpSubsection.cpp ----------------------------------------===//
|
||||
//
|
||||
// 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/DebugCrossImpSubsection.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/DebugInfo/CodeView/CodeViewError.h"
|
||||
#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
|
||||
#include "llvm/Support/BinaryStreamReader.h"
|
||||
#include "llvm/Support/BinaryStreamWriter.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::codeview;
|
||||
|
||||
Error VarStreamArrayExtractor<CrossModuleImportItem>::
|
||||
operator()(BinaryStreamRef Stream, uint32_t &Len,
|
||||
codeview::CrossModuleImportItem &Item) {
|
||||
BinaryStreamReader Reader(Stream);
|
||||
if (Reader.bytesRemaining() < sizeof(CrossModuleImport))
|
||||
return make_error<CodeViewError>(
|
||||
cv_error_code::insufficient_buffer,
|
||||
"Not enough bytes for a Cross Module Import Header!");
|
||||
if (auto EC = Reader.readObject(Item.Header))
|
||||
return EC;
|
||||
if (Reader.bytesRemaining() < Item.Header->Count * sizeof(uint32_t))
|
||||
return make_error<CodeViewError>(
|
||||
cv_error_code::insufficient_buffer,
|
||||
"Not enough to read specified number of Cross Module References!");
|
||||
if (auto EC = Reader.readArray(Item.Imports, Item.Header->Count))
|
||||
return EC;
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error DebugCrossModuleImportsSubsectionRef::initialize(
|
||||
BinaryStreamReader Reader) {
|
||||
return Reader.readArray(References, Reader.bytesRemaining());
|
||||
}
|
||||
|
||||
Error DebugCrossModuleImportsSubsectionRef::initialize(BinaryStreamRef Stream) {
|
||||
BinaryStreamReader Reader(Stream);
|
||||
return initialize(Reader);
|
||||
}
|
||||
|
||||
void DebugCrossModuleImportsSubsection::addImport(StringRef Module,
|
||||
uint32_t ImportId) {
|
||||
Strings.insert(Module);
|
||||
std::vector<support::ulittle32_t> Targets = {support::ulittle32_t(ImportId)};
|
||||
auto Result = Mappings.insert(std::make_pair(Module, Targets));
|
||||
if (!Result.second)
|
||||
Result.first->getValue().push_back(Targets[0]);
|
||||
}
|
||||
|
||||
uint32_t DebugCrossModuleImportsSubsection::calculateSerializedSize() const {
|
||||
uint32_t Size = 0;
|
||||
for (const auto &Item : Mappings) {
|
||||
Size += sizeof(CrossModuleImport);
|
||||
Size += sizeof(support::ulittle32_t) * Item.second.size();
|
||||
}
|
||||
return Size;
|
||||
}
|
||||
|
||||
Error DebugCrossModuleImportsSubsection::commit(
|
||||
BinaryStreamWriter &Writer) const {
|
||||
using T = decltype(&*Mappings.begin());
|
||||
std::vector<T> Ids;
|
||||
Ids.reserve(Mappings.size());
|
||||
|
||||
for (const auto &M : Mappings)
|
||||
Ids.push_back(&M);
|
||||
|
||||
std::sort(Ids.begin(), Ids.end(), [this](const T &L1, const T &L2) {
|
||||
return Strings.getStringId(L1->getKey()) <
|
||||
Strings.getStringId(L2->getKey());
|
||||
});
|
||||
|
||||
for (const auto &Item : Ids) {
|
||||
CrossModuleImport Imp;
|
||||
Imp.ModuleNameOffset = Strings.getStringId(Item->getKey());
|
||||
Imp.Count = Item->getValue().size();
|
||||
if (auto EC = Writer.writeObject(Imp))
|
||||
return EC;
|
||||
if (auto EC = Writer.writeArray(makeArrayRef(Item->getValue())))
|
||||
return EC;
|
||||
}
|
||||
return Error::success();
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
//===- DebugFrameDataSubsection.cpp -----------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h"
|
||||
#include "llvm/DebugInfo/CodeView/CodeViewError.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::codeview;
|
||||
|
||||
Error DebugFrameDataSubsectionRef::initialize(BinaryStreamReader Reader) {
|
||||
if (auto EC = Reader.readObject(RelocPtr))
|
||||
return EC;
|
||||
if (Reader.bytesRemaining() % sizeof(FrameData) != 0)
|
||||
return make_error<CodeViewError>(cv_error_code::corrupt_record,
|
||||
"Invalid frame data record format!");
|
||||
|
||||
uint32_t Count = Reader.bytesRemaining() / sizeof(FrameData);
|
||||
if (auto EC = Reader.readArray(Frames, Count))
|
||||
return EC;
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
uint32_t DebugFrameDataSubsection::calculateSerializedSize() const {
|
||||
return 4 + sizeof(FrameData) * Frames.size();
|
||||
}
|
||||
|
||||
Error DebugFrameDataSubsection::commit(BinaryStreamWriter &Writer) const {
|
||||
if (auto EC = Writer.writeInteger<uint32_t>(0))
|
||||
return EC;
|
||||
|
||||
if (auto EC = Writer.writeArray(makeArrayRef(Frames)))
|
||||
return EC;
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
void DebugFrameDataSubsection::addFrameData(const FrameData &Frame) {
|
||||
Frames.push_back(Frame);
|
||||
}
|
@ -1,126 +0,0 @@
|
||||
//===- DebugInlineeLinesSubsection.cpp ------------------------------------===//
|
||||
//
|
||||
// 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/DebugInlineeLinesSubsection.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/DebugInfo/CodeView/CodeView.h"
|
||||
#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
|
||||
#include "llvm/Support/BinaryStreamReader.h"
|
||||
#include "llvm/Support/BinaryStreamWriter.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::codeview;
|
||||
|
||||
Error VarStreamArrayExtractor<InlineeSourceLine>::
|
||||
operator()(BinaryStreamRef Stream, uint32_t &Len, InlineeSourceLine &Item) {
|
||||
BinaryStreamReader Reader(Stream);
|
||||
|
||||
if (auto EC = Reader.readObject(Item.Header))
|
||||
return EC;
|
||||
|
||||
if (HasExtraFiles) {
|
||||
uint32_t ExtraFileCount;
|
||||
if (auto EC = Reader.readInteger(ExtraFileCount))
|
||||
return EC;
|
||||
if (auto EC = Reader.readArray(Item.ExtraFiles, ExtraFileCount))
|
||||
return EC;
|
||||
}
|
||||
|
||||
Len = Reader.getOffset();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
DebugInlineeLinesSubsectionRef::DebugInlineeLinesSubsectionRef()
|
||||
: DebugSubsectionRef(DebugSubsectionKind::InlineeLines) {}
|
||||
|
||||
Error DebugInlineeLinesSubsectionRef::initialize(BinaryStreamReader Reader) {
|
||||
if (auto EC = Reader.readEnum(Signature))
|
||||
return EC;
|
||||
|
||||
Lines.getExtractor().HasExtraFiles = hasExtraFiles();
|
||||
if (auto EC = Reader.readArray(Lines, Reader.bytesRemaining()))
|
||||
return EC;
|
||||
|
||||
assert(Reader.bytesRemaining() == 0);
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
bool DebugInlineeLinesSubsectionRef::hasExtraFiles() const {
|
||||
return Signature == InlineeLinesSignature::ExtraFiles;
|
||||
}
|
||||
|
||||
DebugInlineeLinesSubsection::DebugInlineeLinesSubsection(
|
||||
DebugChecksumsSubsection &Checksums, bool HasExtraFiles)
|
||||
: DebugSubsection(DebugSubsectionKind::InlineeLines), Checksums(Checksums),
|
||||
HasExtraFiles(HasExtraFiles) {}
|
||||
|
||||
uint32_t DebugInlineeLinesSubsection::calculateSerializedSize() const {
|
||||
// 4 bytes for the signature
|
||||
uint32_t Size = sizeof(InlineeLinesSignature);
|
||||
|
||||
// one header for each entry.
|
||||
Size += Entries.size() * sizeof(InlineeSourceLineHeader);
|
||||
if (HasExtraFiles) {
|
||||
// If extra files are enabled, one count for each entry.
|
||||
Size += Entries.size() * sizeof(uint32_t);
|
||||
|
||||
// And one file id for each file.
|
||||
Size += ExtraFileCount * sizeof(uint32_t);
|
||||
}
|
||||
assert(Size % 4 == 0);
|
||||
return Size;
|
||||
}
|
||||
|
||||
Error DebugInlineeLinesSubsection::commit(BinaryStreamWriter &Writer) const {
|
||||
InlineeLinesSignature Sig = InlineeLinesSignature::Normal;
|
||||
if (HasExtraFiles)
|
||||
Sig = InlineeLinesSignature::ExtraFiles;
|
||||
|
||||
if (auto EC = Writer.writeEnum(Sig))
|
||||
return EC;
|
||||
|
||||
for (const auto &E : Entries) {
|
||||
if (auto EC = Writer.writeObject(E.Header))
|
||||
return EC;
|
||||
|
||||
if (!HasExtraFiles)
|
||||
continue;
|
||||
|
||||
if (auto EC = Writer.writeInteger<uint32_t>(E.ExtraFiles.size()))
|
||||
return EC;
|
||||
if (auto EC = Writer.writeArray(makeArrayRef(E.ExtraFiles)))
|
||||
return EC;
|
||||
}
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
void DebugInlineeLinesSubsection::addExtraFile(StringRef FileName) {
|
||||
uint32_t Offset = Checksums.mapChecksumOffset(FileName);
|
||||
|
||||
auto &Entry = Entries.back();
|
||||
Entry.ExtraFiles.push_back(ulittle32_t(Offset));
|
||||
++ExtraFileCount;
|
||||
}
|
||||
|
||||
void DebugInlineeLinesSubsection::addInlineSite(TypeIndex FuncId,
|
||||
StringRef FileName,
|
||||
uint32_t SourceLine) {
|
||||
uint32_t Offset = Checksums.mapChecksumOffset(FileName);
|
||||
|
||||
Entries.emplace_back();
|
||||
auto &Entry = Entries.back();
|
||||
Entry.Header.FileID = Offset;
|
||||
Entry.Header.SourceLineNum = SourceLine;
|
||||
Entry.Header.Inlinee = FuncId;
|
||||
}
|
@ -1,161 +0,0 @@
|
||||
//===- DebugLinesSubsection.cpp -------------------------------------------===//
|
||||
//
|
||||
// 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/DebugLinesSubsection.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/DebugInfo/CodeView/CodeView.h"
|
||||
#include "llvm/DebugInfo/CodeView/CodeViewError.h"
|
||||
#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
|
||||
#include "llvm/Support/BinaryStreamReader.h"
|
||||
#include "llvm/Support/BinaryStreamWriter.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::codeview;
|
||||
|
||||
Error LineColumnExtractor::operator()(BinaryStreamRef Stream, uint32_t &Len,
|
||||
LineColumnEntry &Item) {
|
||||
const LineBlockFragmentHeader *BlockHeader;
|
||||
BinaryStreamReader Reader(Stream);
|
||||
if (auto EC = Reader.readObject(BlockHeader))
|
||||
return EC;
|
||||
bool HasColumn = Header->Flags & uint16_t(LF_HaveColumns);
|
||||
uint32_t LineInfoSize =
|
||||
BlockHeader->NumLines *
|
||||
(sizeof(LineNumberEntry) + (HasColumn ? sizeof(ColumnNumberEntry) : 0));
|
||||
if (BlockHeader->BlockSize < sizeof(LineBlockFragmentHeader))
|
||||
return make_error<CodeViewError>(cv_error_code::corrupt_record,
|
||||
"Invalid line block record size");
|
||||
uint32_t Size = BlockHeader->BlockSize - sizeof(LineBlockFragmentHeader);
|
||||
if (LineInfoSize > Size)
|
||||
return make_error<CodeViewError>(cv_error_code::corrupt_record,
|
||||
"Invalid line block record size");
|
||||
// The value recorded in BlockHeader->BlockSize includes the size of
|
||||
// LineBlockFragmentHeader.
|
||||
Len = BlockHeader->BlockSize;
|
||||
Item.NameIndex = BlockHeader->NameIndex;
|
||||
if (auto EC = Reader.readArray(Item.LineNumbers, BlockHeader->NumLines))
|
||||
return EC;
|
||||
if (HasColumn) {
|
||||
if (auto EC = Reader.readArray(Item.Columns, BlockHeader->NumLines))
|
||||
return EC;
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
DebugLinesSubsectionRef::DebugLinesSubsectionRef()
|
||||
: DebugSubsectionRef(DebugSubsectionKind::Lines) {}
|
||||
|
||||
Error DebugLinesSubsectionRef::initialize(BinaryStreamReader Reader) {
|
||||
if (auto EC = Reader.readObject(Header))
|
||||
return EC;
|
||||
|
||||
LinesAndColumns.getExtractor().Header = Header;
|
||||
if (auto EC = Reader.readArray(LinesAndColumns, Reader.bytesRemaining()))
|
||||
return EC;
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
bool DebugLinesSubsectionRef::hasColumnInfo() const {
|
||||
return !!(Header->Flags & LF_HaveColumns);
|
||||
}
|
||||
|
||||
DebugLinesSubsection::DebugLinesSubsection(DebugChecksumsSubsection &Checksums,
|
||||
DebugStringTableSubsection &Strings)
|
||||
: DebugSubsection(DebugSubsectionKind::Lines), Checksums(Checksums) {}
|
||||
|
||||
void DebugLinesSubsection::createBlock(StringRef FileName) {
|
||||
uint32_t Offset = Checksums.mapChecksumOffset(FileName);
|
||||
|
||||
Blocks.emplace_back(Offset);
|
||||
}
|
||||
|
||||
void DebugLinesSubsection::addLineInfo(uint32_t Offset, const LineInfo &Line) {
|
||||
Block &B = Blocks.back();
|
||||
LineNumberEntry LNE;
|
||||
LNE.Flags = Line.getRawData();
|
||||
LNE.Offset = Offset;
|
||||
B.Lines.push_back(LNE);
|
||||
}
|
||||
|
||||
void DebugLinesSubsection::addLineAndColumnInfo(uint32_t Offset,
|
||||
const LineInfo &Line,
|
||||
uint32_t ColStart,
|
||||
uint32_t ColEnd) {
|
||||
Block &B = Blocks.back();
|
||||
assert(B.Lines.size() == B.Columns.size());
|
||||
|
||||
addLineInfo(Offset, Line);
|
||||
ColumnNumberEntry CNE;
|
||||
CNE.StartColumn = ColStart;
|
||||
CNE.EndColumn = ColEnd;
|
||||
B.Columns.push_back(CNE);
|
||||
}
|
||||
|
||||
Error DebugLinesSubsection::commit(BinaryStreamWriter &Writer) const {
|
||||
LineFragmentHeader Header;
|
||||
Header.CodeSize = CodeSize;
|
||||
Header.Flags = hasColumnInfo() ? LF_HaveColumns : 0;
|
||||
Header.RelocOffset = RelocOffset;
|
||||
Header.RelocSegment = RelocSegment;
|
||||
|
||||
if (auto EC = Writer.writeObject(Header))
|
||||
return EC;
|
||||
|
||||
for (const auto &B : Blocks) {
|
||||
LineBlockFragmentHeader BlockHeader;
|
||||
assert(B.Lines.size() == B.Columns.size() || B.Columns.empty());
|
||||
|
||||
BlockHeader.NumLines = B.Lines.size();
|
||||
BlockHeader.BlockSize = sizeof(LineBlockFragmentHeader);
|
||||
BlockHeader.BlockSize += BlockHeader.NumLines * sizeof(LineNumberEntry);
|
||||
if (hasColumnInfo())
|
||||
BlockHeader.BlockSize += BlockHeader.NumLines * sizeof(ColumnNumberEntry);
|
||||
BlockHeader.NameIndex = B.ChecksumBufferOffset;
|
||||
if (auto EC = Writer.writeObject(BlockHeader))
|
||||
return EC;
|
||||
|
||||
if (auto EC = Writer.writeArray(makeArrayRef(B.Lines)))
|
||||
return EC;
|
||||
|
||||
if (hasColumnInfo()) {
|
||||
if (auto EC = Writer.writeArray(makeArrayRef(B.Columns)))
|
||||
return EC;
|
||||
}
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
uint32_t DebugLinesSubsection::calculateSerializedSize() const {
|
||||
uint32_t Size = sizeof(LineFragmentHeader);
|
||||
for (const auto &B : Blocks) {
|
||||
Size += sizeof(LineBlockFragmentHeader);
|
||||
Size += B.Lines.size() * sizeof(LineNumberEntry);
|
||||
if (hasColumnInfo())
|
||||
Size += B.Columns.size() * sizeof(ColumnNumberEntry);
|
||||
}
|
||||
return Size;
|
||||
}
|
||||
|
||||
void DebugLinesSubsection::setRelocationAddress(uint16_t Segment,
|
||||
uint32_t Offset) {
|
||||
RelocOffset = Offset;
|
||||
RelocSegment = Segment;
|
||||
}
|
||||
|
||||
void DebugLinesSubsection::setCodeSize(uint32_t Size) { CodeSize = Size; }
|
||||
|
||||
void DebugLinesSubsection::setFlags(LineFlags Flags) { this->Flags = Flags; }
|
||||
|
||||
bool DebugLinesSubsection::hasColumnInfo() const {
|
||||
return Flags & LF_HaveColumns;
|
||||
}
|
@ -1,90 +0,0 @@
|
||||
//===- DebugStringTableSubsection.cpp - CodeView String Table -------------===//
|
||||
//
|
||||
// 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/DebugStringTableSubsection.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/DebugInfo/CodeView/CodeView.h"
|
||||
#include "llvm/Support/BinaryStreamReader.h"
|
||||
#include "llvm/Support/BinaryStreamWriter.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::codeview;
|
||||
|
||||
DebugStringTableSubsectionRef::DebugStringTableSubsectionRef()
|
||||
: DebugSubsectionRef(DebugSubsectionKind::StringTable) {}
|
||||
|
||||
Error DebugStringTableSubsectionRef::initialize(BinaryStreamRef Contents) {
|
||||
Stream = Contents;
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error DebugStringTableSubsectionRef::initialize(BinaryStreamReader &Reader) {
|
||||
return Reader.readStreamRef(Stream);
|
||||
}
|
||||
|
||||
Expected<StringRef>
|
||||
DebugStringTableSubsectionRef::getString(uint32_t Offset) const {
|
||||
BinaryStreamReader Reader(Stream);
|
||||
Reader.setOffset(Offset);
|
||||
StringRef Result;
|
||||
if (auto EC = Reader.readCString(Result))
|
||||
return std::move(EC);
|
||||
return Result;
|
||||
}
|
||||
|
||||
DebugStringTableSubsection::DebugStringTableSubsection()
|
||||
: DebugSubsection(DebugSubsectionKind::StringTable) {}
|
||||
|
||||
uint32_t DebugStringTableSubsection::insert(StringRef S) {
|
||||
auto P = Strings.insert({S, StringSize});
|
||||
|
||||
// If a given string didn't exist in the string table, we want to increment
|
||||
// the string table size.
|
||||
if (P.second)
|
||||
StringSize += S.size() + 1; // +1 for '\0'
|
||||
return P.first->second;
|
||||
}
|
||||
|
||||
uint32_t DebugStringTableSubsection::calculateSerializedSize() const {
|
||||
return StringSize;
|
||||
}
|
||||
|
||||
Error DebugStringTableSubsection::commit(BinaryStreamWriter &Writer) const {
|
||||
uint32_t Begin = Writer.getOffset();
|
||||
uint32_t End = Begin + StringSize;
|
||||
|
||||
// Write a null string at the beginning.
|
||||
if (auto EC = Writer.writeCString(StringRef()))
|
||||
return EC;
|
||||
|
||||
for (auto &Pair : Strings) {
|
||||
StringRef S = Pair.getKey();
|
||||
uint32_t Offset = Begin + Pair.getValue();
|
||||
Writer.setOffset(Offset);
|
||||
if (auto EC = Writer.writeCString(S))
|
||||
return EC;
|
||||
assert(Writer.getOffset() <= End);
|
||||
}
|
||||
|
||||
Writer.setOffset(End);
|
||||
assert((End - Begin) == StringSize);
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
uint32_t DebugStringTableSubsection::size() const { return Strings.size(); }
|
||||
|
||||
uint32_t DebugStringTableSubsection::getStringId(StringRef S) const {
|
||||
auto Iter = Strings.find(S);
|
||||
assert(Iter != Strings.end());
|
||||
return Iter->second;
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
//===- DebugSubsection.cpp -----------------------------------*- C++-*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/DebugInfo/CodeView/DebugSubsection.h"
|
||||
|
||||
using namespace llvm::codeview;
|
||||
|
||||
DebugSubsectionRef::~DebugSubsectionRef() {}
|
||||
|
||||
DebugSubsection::~DebugSubsection() {}
|
@ -1,97 +0,0 @@
|
||||
//===- DebugSubsectionRecord.cpp ------------------------------------------===//
|
||||
//
|
||||
// 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/DebugSubsectionRecord.h"
|
||||
#include "llvm/DebugInfo/CodeView/CodeView.h"
|
||||
#include "llvm/DebugInfo/CodeView/DebugSubsection.h"
|
||||
#include "llvm/Support/BinaryStreamReader.h"
|
||||
#include "llvm/Support/BinaryStreamWriter.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::codeview;
|
||||
|
||||
DebugSubsectionRecord::DebugSubsectionRecord() = default;
|
||||
|
||||
DebugSubsectionRecord::DebugSubsectionRecord(DebugSubsectionKind Kind,
|
||||
BinaryStreamRef Data,
|
||||
CodeViewContainer Container)
|
||||
: Container(Container), Kind(Kind), Data(Data) {}
|
||||
|
||||
Error DebugSubsectionRecord::initialize(BinaryStreamRef Stream,
|
||||
DebugSubsectionRecord &Info,
|
||||
CodeViewContainer Container) {
|
||||
const DebugSubsectionHeader *Header;
|
||||
BinaryStreamReader Reader(Stream);
|
||||
if (auto EC = Reader.readObject(Header))
|
||||
return EC;
|
||||
|
||||
DebugSubsectionKind Kind =
|
||||
static_cast<DebugSubsectionKind>(uint32_t(Header->Kind));
|
||||
if (auto EC = Reader.readStreamRef(Info.Data, Header->Length))
|
||||
return EC;
|
||||
Info.Container = Container;
|
||||
Info.Kind = Kind;
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
uint32_t DebugSubsectionRecord::getRecordLength() const {
|
||||
return sizeof(DebugSubsectionHeader) + Data.getLength();
|
||||
}
|
||||
|
||||
DebugSubsectionKind DebugSubsectionRecord::kind() const { return Kind; }
|
||||
|
||||
BinaryStreamRef DebugSubsectionRecord::getRecordData() const { return Data; }
|
||||
|
||||
DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder(
|
||||
std::shared_ptr<DebugSubsection> Subsection, CodeViewContainer Container)
|
||||
: Subsection(std::move(Subsection)), Container(Container) {}
|
||||
|
||||
DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder(
|
||||
const DebugSubsectionRecord &Contents, CodeViewContainer Container)
|
||||
: Contents(Contents), Container(Container) {}
|
||||
|
||||
uint32_t DebugSubsectionRecordBuilder::calculateSerializedLength() {
|
||||
uint32_t DataSize = Subsection ? Subsection->calculateSerializedSize()
|
||||
: Contents.getRecordData().getLength();
|
||||
// The length of the entire subsection is always padded to 4 bytes,
|
||||
// regardless of the container kind.
|
||||
return sizeof(DebugSubsectionHeader) + alignTo(DataSize, 4);
|
||||
}
|
||||
|
||||
Error DebugSubsectionRecordBuilder::commit(BinaryStreamWriter &Writer) const {
|
||||
assert(Writer.getOffset() % alignOf(Container) == 0 &&
|
||||
"Debug Subsection not properly aligned");
|
||||
|
||||
DebugSubsectionHeader Header;
|
||||
Header.Kind = uint32_t(Subsection ? Subsection->kind() : Contents.kind());
|
||||
// The value written into the Header's Length field is only padded to the
|
||||
// container's alignment
|
||||
uint32_t DataSize = Subsection ? Subsection->calculateSerializedSize()
|
||||
: Contents.getRecordData().getLength();
|
||||
Header.Length = alignTo(DataSize, alignOf(Container));
|
||||
|
||||
if (auto EC = Writer.writeObject(Header))
|
||||
return EC;
|
||||
if (Subsection) {
|
||||
if (auto EC = Subsection->commit(Writer))
|
||||
return EC;
|
||||
} else {
|
||||
if (auto EC = Writer.writeStreamRef(Contents.getRecordData()))
|
||||
return EC;
|
||||
}
|
||||
if (auto EC = Writer.padToAlignment(4))
|
||||
return EC;
|
||||
|
||||
return Error::success();
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
//===- DebugSubsectionVisitor.cpp -------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h"
|
||||
|
||||
#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
|
||||
#include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h"
|
||||
#include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h"
|
||||
#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h"
|
||||
#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
|
||||
#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
|
||||
#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
|
||||
#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
|
||||
#include "llvm/DebugInfo/CodeView/DebugSymbolRVASubsection.h"
|
||||
#include "llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h"
|
||||
#include "llvm/DebugInfo/CodeView/DebugUnknownSubsection.h"
|
||||
#include "llvm/Support/BinaryStreamReader.h"
|
||||
#include "llvm/Support/BinaryStreamRef.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::codeview;
|
||||
|
||||
Error llvm::codeview::visitDebugSubsection(
|
||||
const DebugSubsectionRecord &R, DebugSubsectionVisitor &V,
|
||||
const StringsAndChecksumsRef &State) {
|
||||
BinaryStreamReader Reader(R.getRecordData());
|
||||
switch (R.kind()) {
|
||||
case DebugSubsectionKind::Lines: {
|
||||
DebugLinesSubsectionRef Fragment;
|
||||
if (auto EC = Fragment.initialize(Reader))
|
||||
return EC;
|
||||
|
||||
return V.visitLines(Fragment, State);
|
||||
}
|
||||
case DebugSubsectionKind::FileChecksums: {
|
||||
DebugChecksumsSubsectionRef Fragment;
|
||||
if (auto EC = Fragment.initialize(Reader))
|
||||
return EC;
|
||||
|
||||
return V.visitFileChecksums(Fragment, State);
|
||||
}
|
||||
case DebugSubsectionKind::InlineeLines: {
|
||||
DebugInlineeLinesSubsectionRef Fragment;
|
||||
if (auto EC = Fragment.initialize(Reader))
|
||||
return EC;
|
||||
return V.visitInlineeLines(Fragment, State);
|
||||
}
|
||||
case DebugSubsectionKind::CrossScopeExports: {
|
||||
DebugCrossModuleExportsSubsectionRef Section;
|
||||
if (auto EC = Section.initialize(Reader))
|
||||
return EC;
|
||||
return V.visitCrossModuleExports(Section, State);
|
||||
}
|
||||
case DebugSubsectionKind::CrossScopeImports: {
|
||||
DebugCrossModuleImportsSubsectionRef Section;
|
||||
if (auto EC = Section.initialize(Reader))
|
||||
return EC;
|
||||
return V.visitCrossModuleImports(Section, State);
|
||||
}
|
||||
case DebugSubsectionKind::Symbols: {
|
||||
DebugSymbolsSubsectionRef Section;
|
||||
if (auto EC = Section.initialize(Reader))
|
||||
return EC;
|
||||
return V.visitSymbols(Section, State);
|
||||
}
|
||||
case DebugSubsectionKind::StringTable: {
|
||||
DebugStringTableSubsectionRef Section;
|
||||
if (auto EC = Section.initialize(Reader))
|
||||
return EC;
|
||||
return V.visitStringTable(Section, State);
|
||||
}
|
||||
case DebugSubsectionKind::FrameData: {
|
||||
DebugFrameDataSubsectionRef Section;
|
||||
if (auto EC = Section.initialize(Reader))
|
||||
return EC;
|
||||
return V.visitFrameData(Section, State);
|
||||
}
|
||||
case DebugSubsectionKind::CoffSymbolRVA: {
|
||||
DebugSymbolRVASubsectionRef Section;
|
||||
if (auto EC = Section.initialize(Reader))
|
||||
return EC;
|
||||
return V.visitCOFFSymbolRVAs(Section, State);
|
||||
}
|
||||
default: {
|
||||
DebugUnknownSubsectionRef Fragment(R.kind(), R.getRecordData());
|
||||
return V.visitUnknown(Fragment);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
//===- DebugSymbolRVASubsection.cpp ---------------------------------------===//
|
||||
//
|
||||
// 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/DebugSymbolRVASubsection.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/DebugInfo/CodeView/CodeView.h"
|
||||
#include "llvm/Support/BinaryStreamReader.h"
|
||||
#include "llvm/Support/BinaryStreamWriter.h"
|
||||
#include <cstdint>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::codeview;
|
||||
|
||||
DebugSymbolRVASubsectionRef::DebugSymbolRVASubsectionRef()
|
||||
: DebugSubsectionRef(DebugSubsectionKind::CoffSymbolRVA) {}
|
||||
|
||||
Error DebugSymbolRVASubsectionRef::initialize(BinaryStreamReader &Reader) {
|
||||
return Reader.readArray(RVAs, Reader.bytesRemaining() / sizeof(uint32_t));
|
||||
}
|
||||
|
||||
DebugSymbolRVASubsection::DebugSymbolRVASubsection()
|
||||
: DebugSubsection(DebugSubsectionKind::CoffSymbolRVA) {}
|
||||
|
||||
Error DebugSymbolRVASubsection::commit(BinaryStreamWriter &Writer) const {
|
||||
return Writer.writeArray(makeArrayRef(RVAs));
|
||||
}
|
||||
|
||||
uint32_t DebugSymbolRVASubsection::calculateSerializedSize() const {
|
||||
return RVAs.size() * sizeof(uint32_t);
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
//===- DebugSymbolsSubsection.cpp -------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::codeview;
|
||||
|
||||
Error DebugSymbolsSubsectionRef::initialize(BinaryStreamReader Reader) {
|
||||
return Reader.readArray(Records, Reader.getLength());
|
||||
}
|
||||
|
||||
uint32_t DebugSymbolsSubsection::calculateSerializedSize() const {
|
||||
return Length;
|
||||
}
|
||||
|
||||
Error DebugSymbolsSubsection::commit(BinaryStreamWriter &Writer) const {
|
||||
for (const auto &Record : Records) {
|
||||
if (auto EC = Writer.writeBytes(Record.RecordData))
|
||||
return EC;
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
void DebugSymbolsSubsection::addSymbol(CVSymbol Symbol) {
|
||||
Records.push_back(Symbol);
|
||||
Length += Symbol.length();
|
||||
}
|
367
external/llvm/lib/DebugInfo/CodeView/EnumTables.cpp
vendored
367
external/llvm/lib/DebugInfo/CodeView/EnumTables.cpp
vendored
@ -1,367 +0,0 @@
|
||||
//===- EnumTables.cpp - Enum to string conversion tables ------------------===//
|
||||
//
|
||||
// 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/EnumTables.h"
|
||||
#include "llvm/Support/ScopedPrinter.h"
|
||||
#include <type_traits>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace codeview;
|
||||
|
||||
#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<SymbolKind> SymbolTypeNames[] = {
|
||||
#define CV_SYMBOL(enum, val) {#enum, enum},
|
||||
#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
|
||||
#undef CV_SYMBOL
|
||||
};
|
||||
|
||||
static const EnumEntry<TypeLeafKind> TypeLeafNames[] = {
|
||||
#define CV_TYPE(name, val) {#name, name},
|
||||
#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
|
||||
#undef CV_TYPE
|
||||
};
|
||||
|
||||
static const EnumEntry<uint16_t> RegisterNames[] = {
|
||||
#define CV_REGISTER(name, val) CV_ENUM_CLASS_ENT(RegisterId, name),
|
||||
#include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
|
||||
#undef CV_REGISTER
|
||||
};
|
||||
|
||||
static const EnumEntry<uint32_t> PublicSymFlagNames[] = {
|
||||
CV_ENUM_CLASS_ENT(PublicSymFlags, Code),
|
||||
CV_ENUM_CLASS_ENT(PublicSymFlags, Function),
|
||||
CV_ENUM_CLASS_ENT(PublicSymFlags, Managed),
|
||||
CV_ENUM_CLASS_ENT(PublicSymFlags, MSIL),
|
||||
};
|
||||
|
||||
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<uint8_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), CV_ENUM_ENT(SourceLanguage, D),
|
||||
};
|
||||
|
||||
static const EnumEntry<uint32_t> CompileSym2FlagNames[] = {
|
||||
CV_ENUM_CLASS_ENT(CompileSym2Flags, EC),
|
||||
CV_ENUM_CLASS_ENT(CompileSym2Flags, NoDbgInfo),
|
||||
CV_ENUM_CLASS_ENT(CompileSym2Flags, LTCG),
|
||||
CV_ENUM_CLASS_ENT(CompileSym2Flags, NoDataAlign),
|
||||
CV_ENUM_CLASS_ENT(CompileSym2Flags, ManagedPresent),
|
||||
CV_ENUM_CLASS_ENT(CompileSym2Flags, SecurityChecks),
|
||||
CV_ENUM_CLASS_ENT(CompileSym2Flags, HotPatch),
|
||||
CV_ENUM_CLASS_ENT(CompileSym2Flags, CVTCIL),
|
||||
CV_ENUM_CLASS_ENT(CompileSym2Flags, MSILModule),
|
||||
};
|
||||
|
||||
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<uint32_t> FileChecksumNames[] = {
|
||||
CV_ENUM_CLASS_ENT(FileChecksumKind, None),
|
||||
CV_ENUM_CLASS_ENT(FileChecksumKind, MD5),
|
||||
CV_ENUM_CLASS_ENT(FileChecksumKind, SHA1),
|
||||
CV_ENUM_CLASS_ENT(FileChecksumKind, SHA256),
|
||||
};
|
||||
|
||||
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> FrameProcSymFlagNames[] = {
|
||||
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),
|
||||
};
|
||||
|
||||
static const EnumEntry<uint32_t> ModuleSubstreamKindNames[] = {
|
||||
CV_ENUM_CLASS_ENT(DebugSubsectionKind, None),
|
||||
CV_ENUM_CLASS_ENT(DebugSubsectionKind, Symbols),
|
||||
CV_ENUM_CLASS_ENT(DebugSubsectionKind, Lines),
|
||||
CV_ENUM_CLASS_ENT(DebugSubsectionKind, StringTable),
|
||||
CV_ENUM_CLASS_ENT(DebugSubsectionKind, FileChecksums),
|
||||
CV_ENUM_CLASS_ENT(DebugSubsectionKind, FrameData),
|
||||
CV_ENUM_CLASS_ENT(DebugSubsectionKind, InlineeLines),
|
||||
CV_ENUM_CLASS_ENT(DebugSubsectionKind, CrossScopeImports),
|
||||
CV_ENUM_CLASS_ENT(DebugSubsectionKind, CrossScopeExports),
|
||||
CV_ENUM_CLASS_ENT(DebugSubsectionKind, ILLines),
|
||||
CV_ENUM_CLASS_ENT(DebugSubsectionKind, FuncMDTokenMap),
|
||||
CV_ENUM_CLASS_ENT(DebugSubsectionKind, TypeMDTokenMap),
|
||||
CV_ENUM_CLASS_ENT(DebugSubsectionKind, MergedAssemblyInput),
|
||||
CV_ENUM_CLASS_ENT(DebugSubsectionKind, CoffSymbolRVA),
|
||||
};
|
||||
|
||||
static const EnumEntry<uint16_t> ExportSymFlagNames[] = {
|
||||
CV_ENUM_CLASS_ENT(ExportFlags, IsConstant),
|
||||
CV_ENUM_CLASS_ENT(ExportFlags, IsData),
|
||||
CV_ENUM_CLASS_ENT(ExportFlags, IsPrivate),
|
||||
CV_ENUM_CLASS_ENT(ExportFlags, HasNoName),
|
||||
CV_ENUM_CLASS_ENT(ExportFlags, HasExplicitOrdinal),
|
||||
CV_ENUM_CLASS_ENT(ExportFlags, IsForwarder),
|
||||
};
|
||||
|
||||
static const EnumEntry<uint8_t> ThunkOrdinalNames[] = {
|
||||
CV_ENUM_CLASS_ENT(ThunkOrdinal, Standard),
|
||||
CV_ENUM_CLASS_ENT(ThunkOrdinal, ThisAdjustor),
|
||||
CV_ENUM_CLASS_ENT(ThunkOrdinal, Vcall),
|
||||
CV_ENUM_CLASS_ENT(ThunkOrdinal, Pcode),
|
||||
CV_ENUM_CLASS_ENT(ThunkOrdinal, UnknownLoad),
|
||||
CV_ENUM_CLASS_ENT(ThunkOrdinal, TrampIncremental),
|
||||
CV_ENUM_CLASS_ENT(ThunkOrdinal, BranchIsland),
|
||||
};
|
||||
|
||||
static const EnumEntry<uint16_t> TrampolineNames[] = {
|
||||
CV_ENUM_CLASS_ENT(TrampolineType, TrampIncremental),
|
||||
CV_ENUM_CLASS_ENT(TrampolineType, BranchIsland),
|
||||
};
|
||||
|
||||
static const EnumEntry<COFF::SectionCharacteristics>
|
||||
ImageSectionCharacteristicNames[] = {
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_TYPE_NOLOAD),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_TYPE_NO_PAD),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_CNT_CODE),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_CNT_INITIALIZED_DATA),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_CNT_UNINITIALIZED_DATA),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_LNK_OTHER),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_LNK_INFO),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_LNK_REMOVE),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_LNK_COMDAT),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_GPREL),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_MEM_PURGEABLE),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_MEM_16BIT),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_MEM_LOCKED),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_MEM_PRELOAD),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_1BYTES),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_2BYTES),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_4BYTES),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_8BYTES),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_16BYTES),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_32BYTES),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_64BYTES),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_128BYTES),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_256BYTES),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_512BYTES),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_1024BYTES),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_2048BYTES),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_4096BYTES),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_8192BYTES),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_LNK_NRELOC_OVFL),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_MEM_DISCARDABLE),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_MEM_NOT_CACHED),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_MEM_NOT_PAGED),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_MEM_SHARED),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_MEM_EXECUTE),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_MEM_READ),
|
||||
CV_ENUM_ENT(COFF, IMAGE_SCN_MEM_WRITE)};
|
||||
|
||||
namespace llvm {
|
||||
namespace codeview {
|
||||
|
||||
ArrayRef<EnumEntry<SymbolKind>> getSymbolTypeNames() {
|
||||
return makeArrayRef(SymbolTypeNames);
|
||||
}
|
||||
|
||||
ArrayRef<EnumEntry<TypeLeafKind>> getTypeLeafNames() {
|
||||
return makeArrayRef(TypeLeafNames);
|
||||
}
|
||||
|
||||
ArrayRef<EnumEntry<uint16_t>> getRegisterNames() {
|
||||
return makeArrayRef(RegisterNames);
|
||||
}
|
||||
|
||||
ArrayRef<EnumEntry<uint32_t>> getPublicSymFlagNames() {
|
||||
return makeArrayRef(PublicSymFlagNames);
|
||||
}
|
||||
|
||||
ArrayRef<EnumEntry<uint8_t>> getProcSymFlagNames() {
|
||||
return makeArrayRef(ProcSymFlagNames);
|
||||
}
|
||||
|
||||
ArrayRef<EnumEntry<uint16_t>> getLocalFlagNames() {
|
||||
return makeArrayRef(LocalFlags);
|
||||
}
|
||||
|
||||
ArrayRef<EnumEntry<uint8_t>> getFrameCookieKindNames() {
|
||||
return makeArrayRef(FrameCookieKinds);
|
||||
}
|
||||
|
||||
ArrayRef<EnumEntry<SourceLanguage>> getSourceLanguageNames() {
|
||||
return makeArrayRef(SourceLanguages);
|
||||
}
|
||||
|
||||
ArrayRef<EnumEntry<uint32_t>> getCompileSym2FlagNames() {
|
||||
return makeArrayRef(CompileSym2FlagNames);
|
||||
}
|
||||
|
||||
ArrayRef<EnumEntry<uint32_t>> getCompileSym3FlagNames() {
|
||||
return makeArrayRef(CompileSym3FlagNames);
|
||||
}
|
||||
|
||||
ArrayRef<EnumEntry<uint32_t>> getFileChecksumNames() {
|
||||
return makeArrayRef(FileChecksumNames);
|
||||
}
|
||||
|
||||
ArrayRef<EnumEntry<unsigned>> getCPUTypeNames() {
|
||||
return makeArrayRef(CPUTypeNames);
|
||||
}
|
||||
|
||||
ArrayRef<EnumEntry<uint32_t>> getFrameProcSymFlagNames() {
|
||||
return makeArrayRef(FrameProcSymFlagNames);
|
||||
}
|
||||
|
||||
ArrayRef<EnumEntry<uint16_t>> getExportSymFlagNames() {
|
||||
return makeArrayRef(ExportSymFlagNames);
|
||||
}
|
||||
|
||||
ArrayRef<EnumEntry<uint32_t>> getModuleSubstreamKindNames() {
|
||||
return makeArrayRef(ModuleSubstreamKindNames);
|
||||
}
|
||||
|
||||
ArrayRef<EnumEntry<uint8_t>> getThunkOrdinalNames() {
|
||||
return makeArrayRef(ThunkOrdinalNames);
|
||||
}
|
||||
|
||||
ArrayRef<EnumEntry<uint16_t>> getTrampolineNames() {
|
||||
return makeArrayRef(TrampolineNames);
|
||||
}
|
||||
|
||||
ArrayRef<EnumEntry<COFF::SectionCharacteristics>>
|
||||
getImageSectionCharacteristicNames() {
|
||||
return makeArrayRef(ImageSectionCharacteristicNames);
|
||||
}
|
||||
|
||||
} // end namespace codeview
|
||||
} // end namespace llvm
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user