Imported Upstream version 6.0.0.172

Former-commit-id: f3cc9b82f3e5bd8f0fd3ebc098f789556b44e9cd
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2019-04-12 14:10:50 +00:00
parent 8016999e4d
commit 64ac736ec5
32155 changed files with 3981439 additions and 75368 deletions

View File

@ -0,0 +1,101 @@
//===- 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;
}

View File

@ -0,0 +1,43 @@
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
)

View File

@ -0,0 +1,83 @@
//===- 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();
}

View File

@ -0,0 +1,275 @@
//===- 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);
}

View File

@ -0,0 +1,71 @@
//===- 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);
}

View File

@ -0,0 +1,257 @@
//===- 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();
}

View File

@ -0,0 +1,259 @@
#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"

View File

@ -0,0 +1,116 @@
//===- 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;
}

View File

@ -0,0 +1,53 @@
//===- 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();
}

View File

@ -0,0 +1,97 @@
//===- 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();
}

View File

@ -0,0 +1,44 @@
//===- 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);
}

View File

@ -0,0 +1,126 @@
//===- 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;
}

View File

@ -0,0 +1,161 @@
//===- 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;
}

View File

@ -0,0 +1,90 @@
//===- 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;
}

View File

@ -0,0 +1,16 @@
//===- 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() {}

View File

@ -0,0 +1,97 @@
//===- 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();
}

View File

@ -0,0 +1,95 @@
//===- 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);
}
}
}

View File

@ -0,0 +1,36 @@
//===- 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);
}

View File

@ -0,0 +1,34 @@
//===- 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();
}

View File

@ -0,0 +1,367 @@
//===- 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