summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/DebugInfo
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/DebugInfo')
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/ByteStream.cpp79
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/CVSymbolVisitor.cpp73
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/CVTypeDumper.cpp73
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp147
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp4
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp242
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/EnumTables.cpp10
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp132
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp102
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/MemoryTypeTableBuilder.cpp46
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/MethodListRecordBuilder.cpp49
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/ModuleSubstream.cpp11
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/ModuleSubstreamVisitor.cpp30
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/RecordSerialization.cpp192
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp539
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp464
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/TypeDatabase.cpp114
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/TypeDatabaseVisitor.cpp289
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp (renamed from contrib/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp)370
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp367
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp113
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp467
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/TypeSerializer.cpp243
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp94
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp303
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp182
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp10
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp9
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp203
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp52
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp436
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp22
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp4
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugPubTable.cpp65
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp401
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp474
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp176
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp22
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp197
-rw-r--r--contrib/llvm/lib/DebugInfo/MSF/MSFBuilder.cpp (renamed from contrib/llvm/lib/DebugInfo/PDB/Raw/MsfBuilder.cpp)113
-rw-r--r--contrib/llvm/lib/DebugInfo/MSF/MSFCommon.cpp (renamed from contrib/llvm/lib/DebugInfo/PDB/Raw/MsfCommon.cpp)29
-rw-r--r--contrib/llvm/lib/DebugInfo/MSF/MSFError.cpp70
-rw-r--r--contrib/llvm/lib/DebugInfo/MSF/MappedBlockStream.cpp415
-rw-r--r--contrib/llvm/lib/DebugInfo/MSF/StreamReader.cpp (renamed from contrib/llvm/lib/DebugInfo/CodeView/StreamReader.cpp)79
-rw-r--r--contrib/llvm/lib/DebugInfo/MSF/StreamWriter.cpp (renamed from contrib/llvm/lib/DebugInfo/CodeView/StreamWriter.cpp)39
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/DIA/DIAError.cpp11
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp47
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/GenericError.cpp9
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/IPDBSourceFile.cpp8
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDB.cpp6
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBContext.cpp4
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp9
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymDumper.cpp2
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp11
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp158
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp399
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Raw/GSI.cpp93
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Raw/GSI.h70
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Raw/GlobalsStream.cpp42
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Raw/Hash.cpp57
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Raw/IndexedStreamData.cpp25
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Raw/InfoStream.cpp25
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Raw/InfoStreamBuilder.cpp60
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Raw/MappedBlockStream.cpp310
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Raw/ModInfo.cpp86
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Raw/ModStream.cpp39
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Raw/NameHashTable.cpp10
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Raw/NameMap.cpp76
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Raw/NameMapBuilder.cpp64
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp308
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp130
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Raw/PublicsStream.cpp82
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Raw/RawError.cpp8
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Raw/RawSession.cpp56
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Raw/SymbolStream.cpp8
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Raw/TpiHashing.cpp110
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp228
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Raw/TpiStreamBuilder.cpp145
-rw-r--r--contrib/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp12
79 files changed, 6124 insertions, 4135 deletions
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/ByteStream.cpp b/contrib/llvm/lib/DebugInfo/CodeView/ByteStream.cpp
deleted file mode 100644
index 2c43bc6..0000000
--- a/contrib/llvm/lib/DebugInfo/CodeView/ByteStream.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-//===- ByteStream.cpp - Reads stream data from a byte sequence ------------===//
-//
-// 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/ByteStream.h"
-#include "llvm/DebugInfo/CodeView/CodeViewError.h"
-#include "llvm/DebugInfo/CodeView/StreamReader.h"
-#include <cstring>
-
-using namespace llvm;
-using namespace llvm::codeview;
-
-static Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Src,
- ArrayRef<uint8_t> Dest) {
- return make_error<CodeViewError>(cv_error_code::operation_unsupported,
- "ByteStream is immutable.");
-}
-
-static Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Src,
- MutableArrayRef<uint8_t> Dest) {
- if (Dest.size() < Src.size())
- return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
- if (Offset > Src.size() - Dest.size())
- return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
-
- ::memcpy(Dest.data() + Offset, Src.data(), Src.size());
- return Error::success();
-}
-
-template <bool Writable>
-Error ByteStream<Writable>::readBytes(uint32_t Offset, uint32_t Size,
- ArrayRef<uint8_t> &Buffer) const {
- if (Offset > Data.size())
- return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
- if (Data.size() < Size + Offset)
- return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
- Buffer = Data.slice(Offset, Size);
- return Error::success();
-}
-
-template <bool Writable>
-Error ByteStream<Writable>::readLongestContiguousChunk(
- uint32_t Offset, ArrayRef<uint8_t> &Buffer) const {
- if (Offset >= Data.size())
- return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
- Buffer = Data.slice(Offset);
- return Error::success();
-}
-
-template <bool Writable>
-Error ByteStream<Writable>::writeBytes(uint32_t Offset,
- ArrayRef<uint8_t> Buffer) const {
- return ::writeBytes(Offset, Buffer, Data);
-}
-
-template <bool Writable> uint32_t ByteStream<Writable>::getLength() const {
- return Data.size();
-}
-
-template <bool Writable> Error ByteStream<Writable>::commit() const {
- return Error::success();
-}
-
-template <bool Writable> StringRef ByteStream<Writable>::str() const {
- const char *CharData = reinterpret_cast<const char *>(Data.data());
- return StringRef(CharData, Data.size());
-}
-
-namespace llvm {
-namespace codeview {
-template class ByteStream<true>;
-template class ByteStream<false>;
-}
-}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/CVSymbolVisitor.cpp b/contrib/llvm/lib/DebugInfo/CodeView/CVSymbolVisitor.cpp
new file mode 100644
index 0000000..75cfd0d
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/CVSymbolVisitor.cpp
@@ -0,0 +1,73 @@
+//===- 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"
+#include "llvm/DebugInfo/MSF/ByteStream.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+template <typename T>
+static Error takeObject(ArrayRef<uint8_t> &Data, const T *&Res) {
+ if (Data.size() < sizeof(*Res))
+ return llvm::make_error<CodeViewError>(cv_error_code::insufficient_buffer);
+ Res = reinterpret_cast<const T *>(Data.data());
+ Data = Data.drop_front(sizeof(*Res));
+ return Error::success();
+}
+
+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();
+}
+
+Error CVSymbolVisitor::visitSymbolRecord(CVSymbol &Record) {
+ if (auto EC = Callbacks.visitSymbolBegin(Record))
+ return EC;
+
+ 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/CVSymbolTypes.def"
+ }
+
+ if (auto EC = Callbacks.visitSymbolEnd(Record))
+ return EC;
+
+ return Error::success();
+}
+
+Error CVSymbolVisitor::visitSymbolStream(const CVSymbolArray &Symbols) {
+ for (auto I : Symbols) {
+ if (auto EC = visitSymbolRecord(I))
+ return EC;
+ }
+ return Error::success();
+}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/CVTypeDumper.cpp b/contrib/llvm/lib/DebugInfo/CodeView/CVTypeDumper.cpp
new file mode 100644
index 0000000..fcd239c
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/CVTypeDumper.cpp
@@ -0,0 +1,73 @@
+//===-- CVTypeDumper.cpp - CodeView type info dumper ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
+#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
+#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
+#include "llvm/DebugInfo/MSF/ByteStream.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+Error CVTypeDumper::dump(const CVType &Record, TypeVisitorCallbacks &Dumper) {
+ TypeDatabaseVisitor DBV(TypeDB);
+ TypeDeserializer Deserializer;
+ TypeVisitorCallbackPipeline Pipeline;
+ Pipeline.addCallbackToPipeline(Deserializer);
+ Pipeline.addCallbackToPipeline(DBV);
+ Pipeline.addCallbackToPipeline(Dumper);
+
+ CVTypeVisitor Visitor(Pipeline);
+
+ CVType RecordCopy = Record;
+ if (auto EC = Visitor.visitTypeRecord(RecordCopy))
+ return EC;
+ return Error::success();
+}
+
+Error CVTypeDumper::dump(const CVTypeArray &Types,
+ TypeVisitorCallbacks &Dumper) {
+ TypeDatabaseVisitor DBV(TypeDB);
+ TypeDeserializer Deserializer;
+ TypeVisitorCallbackPipeline Pipeline;
+ Pipeline.addCallbackToPipeline(Deserializer);
+ Pipeline.addCallbackToPipeline(DBV);
+ Pipeline.addCallbackToPipeline(Dumper);
+
+ CVTypeVisitor Visitor(Pipeline);
+
+ if (auto EC = Visitor.visitTypeStream(Types))
+ return EC;
+ return Error::success();
+}
+
+Error CVTypeDumper::dump(ArrayRef<uint8_t> Data, TypeVisitorCallbacks &Dumper) {
+ msf::ByteStream Stream(Data);
+ CVTypeArray Types;
+ msf::StreamReader Reader(Stream);
+ if (auto EC = Reader.readArray(Types, Reader.getLength()))
+ return EC;
+
+ return dump(Types, Dumper);
+}
+
+void CVTypeDumper::printTypeIndex(ScopedPrinter &Printer, StringRef FieldName,
+ TypeIndex TI, TypeDatabase &DB) {
+ StringRef TypeName;
+ if (!TI.isNoneType())
+ TypeName = DB.getTypeName(TI);
+ if (!TypeName.empty())
+ Printer.printHex(FieldName, TypeName, TI.getIndex());
+ else
+ Printer.printHex(FieldName, TI.getIndex());
+}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp b/contrib/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
index 09f7221..5171e24 100644
--- a/contrib/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
+++ b/contrib/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
@@ -9,115 +9,128 @@
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
+#include "llvm/DebugInfo/MSF/ByteStream.h"
+
using namespace llvm;
using namespace llvm::codeview;
+CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks)
+ : Callbacks(Callbacks) {}
+
template <typename T>
-static Error takeObject(ArrayRef<uint8_t> &Data, const T *&Res) {
- if (Data.size() < sizeof(*Res))
- return llvm::make_error<CodeViewError>(cv_error_code::insufficient_buffer);
- Res = reinterpret_cast<const T *>(Data.data());
- Data = Data.drop_front(sizeof(*Res));
+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();
}
-CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks)
- : Callbacks(Callbacks) {}
+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();
+}
-Error CVTypeVisitor::visitTypeRecord(const CVRecord<TypeLeafKind> &Record) {
- ArrayRef<uint8_t> LeafData = Record.Data;
+Error CVTypeVisitor::visitTypeRecord(CVType &Record) {
if (auto EC = Callbacks.visitTypeBegin(Record))
return EC;
+
switch (Record.Type) {
default:
if (auto EC = Callbacks.visitUnknownType(Record))
return EC;
break;
- case LF_FIELDLIST:
- if (auto EC = Callbacks.visitFieldListBegin(Record))
- return EC;
- if (auto EC = visitFieldList(Record))
- return EC;
- if (auto EC = Callbacks.visitFieldListEnd(Record))
- return EC;
- break;
#define TYPE_RECORD(EnumName, EnumVal, Name) \
case EnumName: { \
- TypeRecordKind RK = static_cast<TypeRecordKind>(EnumName); \
- auto Result = Name##Record::deserialize(RK, LeafData); \
- if (Result.getError()) \
- return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record); \
- if (auto EC = Callbacks.visit##Name(*Result)) \
+ 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/TypeRecords.def"
}
+
if (auto EC = Callbacks.visitTypeEnd(Record))
return EC;
- return Error::success();
-}
-/// Visits the type records in Data. Sets the error flag on parse failures.
-Error CVTypeVisitor::visitTypeStream(const CVTypeArray &Types) {
- for (const auto &I : Types) {
- if (auto EC = visitTypeRecord(I))
- return EC;
- }
return Error::success();
}
-Error CVTypeVisitor::skipPadding(ArrayRef<uint8_t> &Data) {
- if (Data.empty())
- return Error::success();
- uint8_t Leaf = Data.front();
- 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;
- if (Data.size() < BytesToAdvance) {
- return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record,
- "Invalid padding bytes!");
- }
- Data = Data.drop_front(BytesToAdvance);
- return Error::success();
-}
+static Error visitMemberRecord(CVMemberRecord &Record,
+ TypeVisitorCallbacks &Callbacks) {
+ if (auto EC = Callbacks.visitMemberBegin(Record))
+ return EC;
-/// Visits individual member records of a field list record. Member records do
-/// not describe their own length, and need special handling.
-Error CVTypeVisitor::visitFieldList(const CVRecord<TypeLeafKind> &Record) {
- ArrayRef<uint8_t> RecordData = Record.Data;
- while (!RecordData.empty()) {
- const ulittle16_t *LeafPtr;
- if (auto EC = takeObject(RecordData, LeafPtr))
+ switch (Record.Kind) {
+ default:
+ if (auto EC = Callbacks.visitUnknownMember(Record))
return EC;
- TypeLeafKind Leaf = TypeLeafKind(unsigned(*LeafPtr));
- switch (Leaf) {
- default:
- // Field list records do not describe their own length, so we cannot
- // continue parsing past an unknown member type.
- if (auto EC = Callbacks.visitUnknownMember(Record))
- return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record);
+ break;
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
case EnumName: { \
- TypeRecordKind RK = static_cast<TypeRecordKind>(EnumName); \
- auto Result = Name##Record::deserialize(RK, RecordData); \
- if (Result.getError()) \
- return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record); \
- if (auto EC = Callbacks.visit##Name(*Result)) \
+ 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/TypeRecords.def"
- }
- if (auto EC = skipPadding(RecordData))
+ }
+
+ if (auto EC = Callbacks.visitMemberEnd(Record))
+ return EC;
+
+ return Error::success();
+}
+
+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::visitFieldListMemberStream(msf::StreamReader Reader) {
+ FieldListDeserializer Deserializer(Reader);
+ TypeVisitorCallbackPipeline Pipeline;
+ Pipeline.addCallbackToPipeline(Deserializer);
+ Pipeline.addCallbackToPipeline(Callbacks);
+
+ TypeLeafKind Leaf;
+ while (!Reader.empty()) {
+ if (auto EC = Reader.readEnum(Leaf))
+ return EC;
+
+ CVMemberRecord Record;
+ Record.Kind = Leaf;
+ if (auto EC = ::visitMemberRecord(Record, Pipeline))
+ return EC;
+ }
+
+ return Error::success();
+}
+
+Error CVTypeVisitor::visitFieldListMemberStream(ArrayRef<uint8_t> Data) {
+ msf::ByteStream S(Data);
+ msf::StreamReader SR(S);
+ return visitFieldListMemberStream(SR);
+}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp b/contrib/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp
index aad1d8b..55c10c0 100644
--- a/contrib/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp
+++ b/contrib/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp
@@ -20,7 +20,7 @@ namespace {
// deal with the Error value directly, rather than converting to error_code.
class CodeViewErrorCategory : public std::error_category {
public:
- const char *name() const LLVM_NOEXCEPT override { return "llvm.codeview"; }
+ const char *name() const noexcept override { return "llvm.codeview"; }
std::string message(int Condition) const override {
switch (static_cast<cv_error_code>(Condition)) {
@@ -33,6 +33,8 @@ public:
return "The CodeView record is corrupted.";
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");
}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp b/contrib/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
new file mode 100644
index 0000000..9bd85cf
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
@@ -0,0 +1,242 @@
+//===- 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/DebugInfo/MSF/StreamReader.h"
+#include "llvm/DebugInfo/MSF/StreamWriter.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();
+ 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::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->writeZeroString(S))
+ return EC;
+ } else {
+ if (auto EC = Reader->readZeroString(Value))
+ return EC;
+ }
+ return Error::success();
+}
+
+Error CodeViewRecordIO::mapGuid(StringRef &Guid) {
+ constexpr uint32_t GuidSize = 16;
+ if (maxFieldLength() < GuidSize)
+ return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
+
+ if (isWriting()) {
+ assert(Guid.size() == 16 && "Invalid Guid Size!");
+ if (auto EC = Writer->writeFixedString(Guid))
+ return EC;
+ } else {
+ if (auto EC = Reader->readFixedString(Guid, 16))
+ return EC;
+ }
+ 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(static_cast<uint16_t>(LF_CHAR)))
+ return EC;
+ if (auto EC = Writer->writeInteger(static_cast<int8_t>(Value)))
+ return EC;
+ } else if (Value >= std::numeric_limits<int16_t>::min()) {
+ if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_SHORT)))
+ return EC;
+ if (auto EC = Writer->writeInteger(static_cast<int16_t>(Value)))
+ return EC;
+ } else if (Value >= std::numeric_limits<int32_t>::min()) {
+ if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_LONG)))
+ return EC;
+ if (auto EC = Writer->writeInteger(static_cast<int32_t>(Value)))
+ return EC;
+ } else {
+ if (auto EC = Writer->writeInteger(static_cast<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(static_cast<uint16_t>(Value)))
+ return EC;
+ } else if (Value <= std::numeric_limits<uint16_t>::max()) {
+ if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_USHORT)))
+ return EC;
+ if (auto EC = Writer->writeInteger(static_cast<uint16_t>(Value)))
+ return EC;
+ } else if (Value <= std::numeric_limits<uint32_t>::max()) {
+ if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_ULONG)))
+ return EC;
+ if (auto EC = Writer->writeInteger(static_cast<uint32_t>(Value)))
+ return EC;
+ } else {
+ if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_UQUADWORD)))
+ return EC;
+ if (auto EC = Writer->writeInteger(Value))
+ return EC;
+ }
+
+ return Error::success();
+}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/EnumTables.cpp b/contrib/llvm/lib/DebugInfo/CodeView/EnumTables.cpp
index d59271b..0e20bcb 100644
--- a/contrib/llvm/lib/DebugInfo/CodeView/EnumTables.cpp
+++ b/contrib/llvm/lib/DebugInfo/CodeView/EnumTables.cpp
@@ -24,6 +24,12 @@ static const EnumEntry<SymbolKind> SymbolTypeNames[] = {
#undef CV_SYMBOL
};
+static const EnumEntry<TypeLeafKind> TypeLeafNames[] = {
+#define CV_TYPE(name, val) {#name, name},
+#include "llvm/DebugInfo/CodeView/TypeRecords.def"
+#undef CV_TYPE
+};
+
static const EnumEntry<uint16_t> RegisterNames[] = {
CV_ENUM_CLASS_ENT(RegisterId, Unknown),
CV_ENUM_CLASS_ENT(RegisterId, VFrame),
@@ -324,6 +330,10 @@ ArrayRef<EnumEntry<SymbolKind>> getSymbolTypeNames() {
return makeArrayRef(SymbolTypeNames);
}
+ArrayRef<EnumEntry<TypeLeafKind>> getTypeLeafNames() {
+ return makeArrayRef(TypeLeafNames);
+}
+
ArrayRef<EnumEntry<uint16_t>> getRegisterNames() {
return makeArrayRef(RegisterNames);
}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp b/contrib/llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp
deleted file mode 100644
index 5f229e3..0000000
--- a/contrib/llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp
+++ /dev/null
@@ -1,132 +0,0 @@
-//===-- FieldListRecordBuilder.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/FieldListRecordBuilder.h"
-
-using namespace llvm;
-using namespace codeview;
-
-FieldListRecordBuilder::FieldListRecordBuilder()
- : ListRecordBuilder(TypeRecordKind::FieldList) {}
-
-void FieldListRecordBuilder::writeBaseClass(const BaseClassRecord &Record) {
- TypeRecordBuilder &Builder = getBuilder();
-
- Builder.writeTypeRecordKind(TypeRecordKind::BaseClass);
- Builder.writeUInt16(static_cast<uint16_t>(Record.getAccess()));
- Builder.writeTypeIndex(Record.getBaseType());
- Builder.writeEncodedUnsignedInteger(Record.getBaseOffset());
-
- finishSubRecord();
-}
-
-void FieldListRecordBuilder::writeEnumerator(const EnumeratorRecord &Record) {
- TypeRecordBuilder &Builder = getBuilder();
-
- Builder.writeTypeRecordKind(TypeRecordKind::Enumerator);
- Builder.writeUInt16(static_cast<uint16_t>(Record.getAccess()));
- // FIXME: Handle full APInt such as __int128.
- Builder.writeEncodedUnsignedInteger(Record.getValue().getZExtValue());
- Builder.writeNullTerminatedString(Record.getName());
-
- finishSubRecord();
-}
-
-void FieldListRecordBuilder::writeDataMember(const DataMemberRecord &Record) {
- TypeRecordBuilder &Builder = getBuilder();
-
- Builder.writeTypeRecordKind(Record.getKind());
- Builder.writeUInt16(static_cast<uint16_t>(Record.getAccess()));
- Builder.writeTypeIndex(Record.getType());
- Builder.writeEncodedUnsignedInteger(Record.getFieldOffset());
- Builder.writeNullTerminatedString(Record.getName());
-
- finishSubRecord();
-}
-
-void FieldListRecordBuilder::writeOverloadedMethod(
- const OverloadedMethodRecord &Record) {
- TypeRecordBuilder &Builder = getBuilder();
-
- Builder.writeTypeRecordKind(TypeRecordKind::OverloadedMethod);
- Builder.writeUInt16(Record.getNumOverloads());
- Builder.writeTypeIndex(Record.getMethodList());
- Builder.writeNullTerminatedString(Record.getName());
-
- finishSubRecord();
-}
-
-void FieldListRecordBuilder::writeOneMethod(const OneMethodRecord &Record) {
- TypeRecordBuilder &Builder = getBuilder();
-
- uint16_t Flags = static_cast<uint16_t>(Record.getAccess());
- Flags |= static_cast<uint16_t>(Record.getKind()) << MethodKindShift;
- Flags |= static_cast<uint16_t>(Record.getOptions());
-
- Builder.writeTypeRecordKind(TypeRecordKind::OneMethod);
- Builder.writeUInt16(Flags);
- Builder.writeTypeIndex(Record.getType());
- if (Record.isIntroducingVirtual()) {
- assert(Record.getVFTableOffset() >= 0);
- Builder.writeInt32(Record.getVFTableOffset());
- } else {
- assert(Record.getVFTableOffset() == -1);
- }
-
- Builder.writeNullTerminatedString(Record.getName());
-
- finishSubRecord();
-}
-
-void FieldListRecordBuilder::writeNestedType(const NestedTypeRecord &Record) {
- TypeRecordBuilder &Builder = getBuilder();
-
- Builder.writeTypeRecordKind(Record.getKind());
- Builder.writeUInt16(0);
- Builder.writeTypeIndex(Record.getNestedType());
- Builder.writeNullTerminatedString(Record.getName());
-
- finishSubRecord();
-}
-
-void FieldListRecordBuilder::writeStaticDataMember(
- const StaticDataMemberRecord &Record) {
- TypeRecordBuilder &Builder = getBuilder();
-
- Builder.writeTypeRecordKind(Record.getKind());
- Builder.writeUInt16(static_cast<uint16_t>(Record.getAccess()));
- Builder.writeTypeIndex(Record.getType());
- Builder.writeNullTerminatedString(Record.getName());
-
- finishSubRecord();
-}
-
-void FieldListRecordBuilder::writeVirtualBaseClass(
- const VirtualBaseClassRecord &Record) {
- TypeRecordBuilder &Builder = getBuilder();
-
- Builder.writeTypeRecordKind(Record.getKind());
- Builder.writeUInt16(static_cast<uint16_t>(Record.getAccess()));
- Builder.writeTypeIndex(Record.getBaseType());
- Builder.writeTypeIndex(Record.getVBPtrType());
- Builder.writeEncodedInteger(Record.getVBPtrOffset());
- Builder.writeEncodedUnsignedInteger(Record.getVTableIndex());
-
- finishSubRecord();
-}
-
-void FieldListRecordBuilder::writeVFPtr(const VFPtrRecord &Record) {
- TypeRecordBuilder &Builder = getBuilder();
-
- Builder.writeTypeRecordKind(TypeRecordKind::VFPtr);
- Builder.writeUInt16(0);
- Builder.writeTypeIndex(Record.getType());
-
- finishSubRecord();
-}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp b/contrib/llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp
deleted file mode 100644
index eb79e8a..0000000
--- a/contrib/llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-//===-- ListRecordBuilder.cpp ---------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/SmallString.h"
-#include "llvm/DebugInfo/CodeView/ListRecordBuilder.h"
-#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
-
-using namespace llvm;
-using namespace codeview;
-
-ListRecordBuilder::ListRecordBuilder(TypeRecordKind Kind)
- : Kind(Kind), Builder(Kind) {}
-
-void ListRecordBuilder::writeListContinuation(const ListContinuationRecord &R) {
- TypeRecordBuilder &Builder = getBuilder();
-
- assert(getLastContinuationSize() < 65535 - 8 && "continuation won't fit");
-
- Builder.writeTypeRecordKind(TypeRecordKind::ListContinuation);
- Builder.writeUInt16(0);
- Builder.writeTypeIndex(R.getContinuationIndex());
-
- // End the current segment manually so that nothing comes after the
- // continuation.
- ContinuationOffsets.push_back(Builder.size());
- SubrecordStart = Builder.size();
-}
-
-void ListRecordBuilder::finishSubRecord() {
- // The type table inserts a 16 bit size field before each list, so factor that
- // into our alignment padding.
- uint32_t Remainder =
- (Builder.size() + 2 * (ContinuationOffsets.size() + 1)) % 4;
- if (Remainder != 0) {
- for (int32_t PaddingBytesLeft = 4 - Remainder; PaddingBytesLeft > 0;
- --PaddingBytesLeft) {
- Builder.writeUInt8(LF_PAD0 + PaddingBytesLeft);
- }
- }
-
- // Check if this subrecord makes the current segment not fit in 64K minus the
- // space for a continuation record (8 bytes). If the segment does not fit,
- // back up and insert a continuation record, sliding the current subrecord
- // down.
- if (getLastContinuationSize() > 65535 - 8) {
- assert(SubrecordStart != 0 && "can't slide from the start!");
- SmallString<128> SubrecordCopy(
- Builder.str().slice(SubrecordStart, Builder.size()));
- assert(SubrecordCopy.size() < 65530 && "subrecord is too large to slide!");
- Builder.truncate(SubrecordStart);
-
- // Write a placeholder continuation record.
- Builder.writeTypeRecordKind(TypeRecordKind::ListContinuation);
- Builder.writeUInt16(0);
- Builder.writeUInt32(0);
- ContinuationOffsets.push_back(Builder.size());
- assert(Builder.size() == SubrecordStart + 8 && "wrong continuation size");
- assert(getLastContinuationSize() < 65535 && "segment too big");
-
- // Start a new list record of the appropriate kind, and copy the previous
- // subrecord into place.
- Builder.writeTypeRecordKind(Kind);
- Builder.writeBytes(SubrecordCopy);
- }
-
- SubrecordStart = Builder.size();
-}
-
-TypeIndex ListRecordBuilder::writeListRecord(TypeTableBuilder &Table) {
- // Get the continuation segments as a reversed vector of StringRefs for
- // convenience.
- SmallVector<StringRef, 1> Segments;
- StringRef Data = str();
- size_t LastEnd = 0;
- for (size_t SegEnd : ContinuationOffsets) {
- Segments.push_back(Data.slice(LastEnd, SegEnd));
- LastEnd = SegEnd;
- }
- Segments.push_back(Data.slice(LastEnd, Builder.size()));
-
- // Pop the last record off and emit it directly.
- StringRef LastRec = Segments.pop_back_val();
- TypeIndex ContinuationIndex = Table.writeRecord(LastRec);
-
- // Emit each record with a continuation in reverse order, so that each one
- // references the previous record.
- for (StringRef Rec : reverse(Segments)) {
- assert(*reinterpret_cast<const ulittle16_t *>(Rec.data()) ==
- unsigned(Kind));
- ulittle32_t *ContinuationPtr =
- reinterpret_cast<ulittle32_t *>(const_cast<char *>(Rec.end())) - 1;
- *ContinuationPtr = ContinuationIndex.getIndex();
- ContinuationIndex = Table.writeRecord(Rec);
- }
- return ContinuationIndex;
-}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/MemoryTypeTableBuilder.cpp b/contrib/llvm/lib/DebugInfo/CodeView/MemoryTypeTableBuilder.cpp
deleted file mode 100644
index 8b9e73b..0000000
--- a/contrib/llvm/lib/DebugInfo/CodeView/MemoryTypeTableBuilder.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-//===-- MemoryTypeTableBuilder.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/MemoryTypeTableBuilder.h"
-#include "llvm/DebugInfo/CodeView/TypeIndex.h"
-
-using namespace llvm;
-using namespace codeview;
-
-TypeIndex MemoryTypeTableBuilder::writeRecord(StringRef Data) {
- assert(Data.size() <= UINT16_MAX);
- auto I = HashedRecords.find(Data);
- if (I != HashedRecords.end()) {
- return I->second;
- }
-
- // The record provided by the user lacks the 2 byte size field prefix and is
- // not padded to 4 bytes. Ultimately, that is what gets emitted in the object
- // file, so pad it out now.
- const int SizeOfRecLen = 2;
- const int Align = 4;
- int TotalSize = alignTo(Data.size() + SizeOfRecLen, Align);
- assert(TotalSize - SizeOfRecLen <= UINT16_MAX);
- char *Mem =
- reinterpret_cast<char *>(RecordStorage.Allocate(TotalSize, Align));
- *reinterpret_cast<ulittle16_t *>(Mem) = uint16_t(TotalSize - SizeOfRecLen);
- memcpy(Mem + SizeOfRecLen, Data.data(), Data.size());
- for (int I = Data.size() + SizeOfRecLen; I < TotalSize; ++I)
- Mem[I] = LF_PAD0 + (TotalSize - I);
-
- TypeIndex TI(static_cast<uint32_t>(Records.size()) +
- TypeIndex::FirstNonSimpleIndex);
-
- // Use only the data supplied by the user as a key to the hash table, so that
- // future lookups will succeed.
- HashedRecords.insert(std::make_pair(StringRef(Mem + SizeOfRecLen, Data.size()), TI));
- Records.push_back(StringRef(Mem, TotalSize));
-
- return TI;
-}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/MethodListRecordBuilder.cpp b/contrib/llvm/lib/DebugInfo/CodeView/MethodListRecordBuilder.cpp
deleted file mode 100644
index ae089a3..0000000
--- a/contrib/llvm/lib/DebugInfo/CodeView/MethodListRecordBuilder.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-//===-- MethodListRecordBuilder.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/MethodListRecordBuilder.h"
-#include "llvm/DebugInfo/CodeView/FieldListRecordBuilder.h"
-
-using namespace llvm;
-using namespace codeview;
-
-MethodListRecordBuilder::MethodListRecordBuilder()
- : ListRecordBuilder(TypeRecordKind::MethodOverloadList) {}
-
-void MethodListRecordBuilder::writeMethod(MemberAccess Access, MethodKind Kind,
- MethodOptions Options, TypeIndex Type,
- int32_t VTableSlotOffset) {
- TypeRecordBuilder &Builder = getBuilder();
-
- uint16_t Flags = static_cast<uint16_t>(Access);
- Flags |= static_cast<uint16_t>(Kind) << MethodKindShift;
- Flags |= static_cast<uint16_t>(Options);
-
- Builder.writeUInt16(Flags);
- Builder.writeUInt16(0);
- Builder.writeTypeIndex(Type);
- switch (Kind) {
- case MethodKind::IntroducingVirtual:
- case MethodKind::PureIntroducingVirtual:
- assert(VTableSlotOffset >= 0);
- Builder.writeInt32(VTableSlotOffset);
- break;
-
- default:
- assert(VTableSlotOffset == -1);
- break;
- }
-
- // TODO: Fail if too big?
-}
-
-void MethodListRecordBuilder::writeMethod(const MethodInfo &Method) {
- writeMethod(Method.getAccess(), Method.getKind(), Method.getOptions(),
- Method.getType(), Method.getVTableSlotOffset());
-}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/ModuleSubstream.cpp b/contrib/llvm/lib/DebugInfo/CodeView/ModuleSubstream.cpp
index 2e31ed6..768ebaa 100644
--- a/contrib/llvm/lib/DebugInfo/CodeView/ModuleSubstream.cpp
+++ b/contrib/llvm/lib/DebugInfo/CodeView/ModuleSubstream.cpp
@@ -9,17 +9,20 @@
#include "llvm/DebugInfo/CodeView/ModuleSubstream.h"
-#include "llvm/DebugInfo/CodeView/StreamReader.h"
+#include "llvm/DebugInfo/MSF/StreamReader.h"
using namespace llvm;
using namespace llvm::codeview;
+using namespace llvm::msf;
ModuleSubstream::ModuleSubstream() : Kind(ModuleSubstreamKind::None) {}
-ModuleSubstream::ModuleSubstream(ModuleSubstreamKind Kind, StreamRef Data)
+ModuleSubstream::ModuleSubstream(ModuleSubstreamKind Kind,
+ ReadableStreamRef Data)
: Kind(Kind), Data(Data) {}
-Error ModuleSubstream::initialize(StreamRef Stream, ModuleSubstream &Info) {
+Error ModuleSubstream::initialize(ReadableStreamRef Stream,
+ ModuleSubstream &Info) {
const ModuleSubsectionHeader *Header;
StreamReader Reader(Stream);
if (auto EC = Reader.readObject(Header))
@@ -39,4 +42,4 @@ uint32_t ModuleSubstream::getRecordLength() const {
ModuleSubstreamKind ModuleSubstream::getSubstreamKind() const { return Kind; }
-StreamRef ModuleSubstream::getRecordData() const { return Data; }
+ReadableStreamRef ModuleSubstream::getRecordData() const { return Data; }
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/ModuleSubstreamVisitor.cpp b/contrib/llvm/lib/DebugInfo/CodeView/ModuleSubstreamVisitor.cpp
index 6f237ee..5247932 100644
--- a/contrib/llvm/lib/DebugInfo/CodeView/ModuleSubstreamVisitor.cpp
+++ b/contrib/llvm/lib/DebugInfo/CodeView/ModuleSubstreamVisitor.cpp
@@ -8,50 +8,54 @@
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h"
+#include "llvm/DebugInfo/MSF/StreamReader.h"
+#include "llvm/DebugInfo/MSF/StreamRef.h"
using namespace llvm;
using namespace llvm::codeview;
+using namespace llvm::msf;
-Error IModuleSubstreamVisitor::visitSymbols(StreamRef Data) {
+Error IModuleSubstreamVisitor::visitSymbols(ReadableStreamRef Data) {
return visitUnknown(ModuleSubstreamKind::Symbols, Data);
}
-Error IModuleSubstreamVisitor::visitLines(StreamRef Data,
+Error IModuleSubstreamVisitor::visitLines(ReadableStreamRef Data,
const LineSubstreamHeader *Header,
const LineInfoArray &Lines) {
return visitUnknown(ModuleSubstreamKind::Lines, Data);
}
-Error IModuleSubstreamVisitor::visitStringTable(StreamRef Data) {
+Error IModuleSubstreamVisitor::visitStringTable(ReadableStreamRef Data) {
return visitUnknown(ModuleSubstreamKind::StringTable, Data);
}
Error IModuleSubstreamVisitor::visitFileChecksums(
- StreamRef Data, const FileChecksumArray &Checksums) {
+ ReadableStreamRef Data, const FileChecksumArray &Checksums) {
return visitUnknown(ModuleSubstreamKind::FileChecksums, Data);
}
-Error IModuleSubstreamVisitor::visitFrameData(StreamRef Data) {
+Error IModuleSubstreamVisitor::visitFrameData(ReadableStreamRef Data) {
return visitUnknown(ModuleSubstreamKind::FrameData, Data);
}
-Error IModuleSubstreamVisitor::visitInlineeLines(StreamRef Data) {
+Error IModuleSubstreamVisitor::visitInlineeLines(ReadableStreamRef Data) {
return visitUnknown(ModuleSubstreamKind::InlineeLines, Data);
}
-Error IModuleSubstreamVisitor::visitCrossScopeImports(StreamRef Data) {
+Error IModuleSubstreamVisitor::visitCrossScopeImports(ReadableStreamRef Data) {
return visitUnknown(ModuleSubstreamKind::CrossScopeExports, Data);
}
-Error IModuleSubstreamVisitor::visitCrossScopeExports(StreamRef Data) {
+Error IModuleSubstreamVisitor::visitCrossScopeExports(ReadableStreamRef Data) {
return visitUnknown(ModuleSubstreamKind::CrossScopeImports, Data);
}
-Error IModuleSubstreamVisitor::visitILLines(StreamRef Data) {
+Error IModuleSubstreamVisitor::visitILLines(ReadableStreamRef Data) {
return visitUnknown(ModuleSubstreamKind::ILLines, Data);
}
-Error IModuleSubstreamVisitor::visitFuncMDTokenMap(StreamRef Data) {
+Error IModuleSubstreamVisitor::visitFuncMDTokenMap(ReadableStreamRef Data) {
return visitUnknown(ModuleSubstreamKind::FuncMDTokenMap, Data);
}
-Error IModuleSubstreamVisitor::visitTypeMDTokenMap(StreamRef Data) {
+Error IModuleSubstreamVisitor::visitTypeMDTokenMap(ReadableStreamRef Data) {
return visitUnknown(ModuleSubstreamKind::TypeMDTokenMap, Data);
}
-Error IModuleSubstreamVisitor::visitMergedAssemblyInput(StreamRef Data) {
+Error IModuleSubstreamVisitor::visitMergedAssemblyInput(
+ ReadableStreamRef Data) {
return visitUnknown(ModuleSubstreamKind::MergedAssemblyInput, Data);
}
-Error IModuleSubstreamVisitor::visitCoffSymbolRVA(StreamRef Data) {
+Error IModuleSubstreamVisitor::visitCoffSymbolRVA(ReadableStreamRef Data) {
return visitUnknown(ModuleSubstreamKind::CoffSymbolRVA, Data);
}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/RecordSerialization.cpp b/contrib/llvm/lib/DebugInfo/CodeView/RecordSerialization.cpp
index ab9206a..6f29caa 100644
--- a/contrib/llvm/lib/DebugInfo/CodeView/RecordSerialization.cpp
+++ b/contrib/llvm/lib/DebugInfo/CodeView/RecordSerialization.cpp
@@ -14,7 +14,9 @@
#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/APSInt.h"
+#include "llvm/DebugInfo/CodeView/CodeViewError.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/MSF/ByteStream.h"
using namespace llvm;
using namespace llvm::codeview;
@@ -31,141 +33,117 @@ StringRef llvm::codeview::getBytesAsCString(ArrayRef<uint8_t> LeafData) {
return getBytesAsCharacters(LeafData).split('\0').first;
}
-std::error_code llvm::codeview::consume(ArrayRef<uint8_t> &Data, APSInt &Num) {
+Error llvm::codeview::consume(msf::StreamReader &Reader, APSInt &Num) {
// Used to avoid overload ambiguity on APInt construtor.
bool FalseVal = false;
- if (Data.size() < 2)
- return std::make_error_code(std::errc::illegal_byte_sequence);
- uint16_t Short = *reinterpret_cast<const ulittle16_t *>(Data.data());
- Data = Data.drop_front(2);
+ uint16_t Short;
+ if (auto EC = Reader.readInteger(Short))
+ return EC;
+
if (Short < LF_NUMERIC) {
Num = APSInt(APInt(/*numBits=*/16, Short, /*isSigned=*/false),
/*isUnsigned=*/true);
- return std::error_code();
+ return Error::success();
}
+
switch (Short) {
- case LF_CHAR:
- if (Data.size() < 1)
- return std::make_error_code(std::errc::illegal_byte_sequence);
- Num = APSInt(APInt(/*numBits=*/8,
- *reinterpret_cast<const int8_t *>(Data.data()),
- /*isSigned=*/true),
- /*isUnsigned=*/false);
- Data = Data.drop_front(1);
- return std::error_code();
- case LF_SHORT:
- if (Data.size() < 2)
- return std::make_error_code(std::errc::illegal_byte_sequence);
- Num = APSInt(APInt(/*numBits=*/16,
- *reinterpret_cast<const little16_t *>(Data.data()),
- /*isSigned=*/true),
- /*isUnsigned=*/false);
- Data = Data.drop_front(2);
- return std::error_code();
- case LF_USHORT:
- if (Data.size() < 2)
- return std::make_error_code(std::errc::illegal_byte_sequence);
- Num = APSInt(APInt(/*numBits=*/16,
- *reinterpret_cast<const ulittle16_t *>(Data.data()),
- /*isSigned=*/false),
- /*isUnsigned=*/true);
- Data = Data.drop_front(2);
- return std::error_code();
- case LF_LONG:
- if (Data.size() < 4)
- return std::make_error_code(std::errc::illegal_byte_sequence);
- Num = APSInt(APInt(/*numBits=*/32,
- *reinterpret_cast<const little32_t *>(Data.data()),
- /*isSigned=*/true),
- /*isUnsigned=*/false);
- Data = Data.drop_front(4);
- return std::error_code();
- case LF_ULONG:
- if (Data.size() < 4)
- return std::make_error_code(std::errc::illegal_byte_sequence);
- Num = APSInt(APInt(/*numBits=*/32,
- *reinterpret_cast<const ulittle32_t *>(Data.data()),
- /*isSigned=*/FalseVal),
- /*isUnsigned=*/true);
- Data = Data.drop_front(4);
- return std::error_code();
- case LF_QUADWORD:
- if (Data.size() < 8)
- return std::make_error_code(std::errc::illegal_byte_sequence);
- Num = APSInt(APInt(/*numBits=*/64,
- *reinterpret_cast<const little64_t *>(Data.data()),
- /*isSigned=*/true),
- /*isUnsigned=*/false);
- Data = Data.drop_front(8);
- return std::error_code();
- case LF_UQUADWORD:
- if (Data.size() < 8)
- return std::make_error_code(std::errc::illegal_byte_sequence);
- Num = APSInt(APInt(/*numBits=*/64,
- *reinterpret_cast<const ulittle64_t *>(Data.data()),
- /*isSigned=*/false),
- /*isUnsigned=*/true);
- Data = Data.drop_front(8);
- return std::error_code();
+ case LF_CHAR: {
+ int8_t N;
+ if (auto EC = Reader.readInteger(N))
+ return EC;
+ Num = APSInt(APInt(8, N, true), false);
+ return Error::success();
+ }
+ case LF_SHORT: {
+ int16_t N;
+ if (auto EC = Reader.readInteger(N))
+ return EC;
+ Num = APSInt(APInt(16, N, true), false);
+ return Error::success();
+ }
+ case LF_USHORT: {
+ uint16_t N;
+ if (auto EC = Reader.readInteger(N))
+ return EC;
+ Num = APSInt(APInt(16, N, false), true);
+ return Error::success();
}
- return std::make_error_code(std::errc::illegal_byte_sequence);
+ case LF_LONG: {
+ int32_t N;
+ if (auto EC = Reader.readInteger(N))
+ return EC;
+ Num = APSInt(APInt(32, N, true), false);
+ return Error::success();
+ }
+ case LF_ULONG: {
+ uint32_t N;
+ if (auto EC = Reader.readInteger(N))
+ return EC;
+ Num = APSInt(APInt(32, N, FalseVal), true);
+ return Error::success();
+ }
+ case LF_QUADWORD: {
+ int64_t N;
+ if (auto EC = Reader.readInteger(N))
+ return EC;
+ Num = APSInt(APInt(64, N, true), false);
+ return Error::success();
+ }
+ case LF_UQUADWORD: {
+ uint64_t N;
+ if (auto EC = Reader.readInteger(N))
+ return EC;
+ Num = APSInt(APInt(64, N, false), true);
+ return Error::success();
+ }
+ }
+ return make_error<CodeViewError>(cv_error_code::corrupt_record,
+ "Buffer contains invalid APSInt type");
}
-std::error_code llvm::codeview::consume(StringRef &Data, APSInt &Num) {
+Error llvm::codeview::consume(StringRef &Data, APSInt &Num) {
ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end());
- auto EC = consume(Bytes, Num);
- Data = StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size());
+ msf::ByteStream S(Bytes);
+ msf::StreamReader SR(S);
+ auto EC = consume(SR, Num);
+ Data = Data.take_back(SR.bytesRemaining());
return EC;
}
/// Decode a numeric leaf value that is known to be a uint64_t.
-std::error_code llvm::codeview::consume_numeric(ArrayRef<uint8_t> &Data,
- uint64_t &Num) {
+Error llvm::codeview::consume_numeric(msf::StreamReader &Reader,
+ uint64_t &Num) {
APSInt N;
- if (auto EC = consume(Data, N))
+ if (auto EC = consume(Reader, N))
return EC;
if (N.isSigned() || !N.isIntN(64))
- return std::make_error_code(std::errc::illegal_byte_sequence);
+ return make_error<CodeViewError>(cv_error_code::corrupt_record,
+ "Data is not a numeric value!");
Num = N.getLimitedValue();
- return std::error_code();
+ return Error::success();
}
-std::error_code llvm::codeview::consume(ArrayRef<uint8_t> &Data,
- uint32_t &Item) {
- const support::ulittle32_t *IntPtr;
- if (auto EC = consumeObject(Data, IntPtr))
- return EC;
- Item = *IntPtr;
- return std::error_code();
+Error llvm::codeview::consume(msf::StreamReader &Reader, uint32_t &Item) {
+ return Reader.readInteger(Item);
}
-std::error_code llvm::codeview::consume(StringRef &Data, uint32_t &Item) {
+Error llvm::codeview::consume(StringRef &Data, uint32_t &Item) {
ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end());
- auto EC = consume(Bytes, Item);
- Data = StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size());
+ msf::ByteStream S(Bytes);
+ msf::StreamReader SR(S);
+ auto EC = consume(SR, Item);
+ Data = Data.take_back(SR.bytesRemaining());
return EC;
}
-std::error_code llvm::codeview::consume(ArrayRef<uint8_t> &Data,
- int32_t &Item) {
- const support::little32_t *IntPtr;
- if (auto EC = consumeObject(Data, IntPtr))
- return EC;
- Item = *IntPtr;
- return std::error_code();
+Error llvm::codeview::consume(msf::StreamReader &Reader, int32_t &Item) {
+ return Reader.readInteger(Item);
}
-std::error_code llvm::codeview::consume(ArrayRef<uint8_t> &Data,
- StringRef &Item) {
- if (Data.empty())
- return std::make_error_code(std::errc::illegal_byte_sequence);
-
- StringRef Rest;
- std::tie(Item, Rest) = getBytesAsCharacters(Data).split('\0');
- // We expect this to be null terminated. If it was not, it is an error.
- if (Data.size() == Item.size())
- return std::make_error_code(std::errc::illegal_byte_sequence);
+Error llvm::codeview::consume(msf::StreamReader &Reader, StringRef &Item) {
+ if (Reader.empty())
+ return make_error<CodeViewError>(cv_error_code::corrupt_record,
+ "Null terminated string buffer is empty!");
- Data = ArrayRef<uint8_t>(Rest.bytes_begin(), Rest.bytes_end());
- return std::error_code();
+ return Reader.readZeroString(Item);
}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp b/contrib/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp
index 6763c3d..fd54fba 100644
--- a/contrib/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp
+++ b/contrib/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp
@@ -11,11 +11,15 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
+#include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
#include "llvm/DebugInfo/CodeView/EnumTables.h"
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
#include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
-#include "llvm/DebugInfo/CodeView/TypeDumper.h"
+#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h"
+#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/ScopedPrinter.h"
#include <system_error>
@@ -26,29 +30,30 @@ using namespace llvm::codeview;
namespace {
/// Use this private dumper implementation to keep implementation details about
/// the visitor out of SymbolDumper.h.
-class CVSymbolDumperImpl : public CVSymbolVisitor<CVSymbolDumperImpl> {
+class CVSymbolDumperImpl : public SymbolVisitorCallbacks {
public:
- CVSymbolDumperImpl(CVTypeDumper &CVTD, SymbolDumpDelegate *ObjDelegate,
+ CVSymbolDumperImpl(TypeDatabase &TypeDB, SymbolDumpDelegate *ObjDelegate,
ScopedPrinter &W, bool PrintRecordBytes)
- : CVSymbolVisitor(ObjDelegate), CVTD(CVTD), ObjDelegate(ObjDelegate),
- W(W), PrintRecordBytes(PrintRecordBytes), InFunctionScope(false) {}
+ : TypeDB(TypeDB), ObjDelegate(ObjDelegate), W(W),
+ PrintRecordBytes(PrintRecordBytes), InFunctionScope(false) {}
/// CVSymbolVisitor overrides.
#define SYMBOL_RECORD(EnumName, EnumVal, Name) \
- void visit##Name(SymbolKind Kind, Name &Record);
+ Error visitKnownRecord(CVSymbol &CVR, Name &Record) override;
#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "llvm/DebugInfo/CodeView/CVSymbolTypes.def"
- void visitSymbolBegin(SymbolKind Kind, ArrayRef<uint8_t> Data);
- void visitSymbolEnd(SymbolKind Kind, ArrayRef<uint8_t> OriginalSymData);
- void visitUnknownSymbol(SymbolKind Kind, ArrayRef<uint8_t> Data);
+ Error visitSymbolBegin(CVSymbol &Record) override;
+ Error visitSymbolEnd(CVSymbol &Record) override;
+ Error visitUnknownSymbol(CVSymbol &Record) override;
private:
void printLocalVariableAddrRange(const LocalVariableAddrRange &Range,
uint32_t RelocationOffset);
void printLocalVariableAddrGap(ArrayRef<LocalVariableAddrGap> Gaps);
+ void printTypeIndex(StringRef FieldName, TypeIndex TI);
- CVTypeDumper &CVTD;
+ TypeDatabase &TypeDB;
SymbolDumpDelegate *ObjDelegate;
ScopedPrinter &W;
@@ -76,376 +81,395 @@ void CVSymbolDumperImpl::printLocalVariableAddrGap(
}
}
-void CVSymbolDumperImpl::visitSymbolBegin(SymbolKind Kind,
- ArrayRef<uint8_t> Data) {}
+void CVSymbolDumperImpl::printTypeIndex(StringRef FieldName, TypeIndex TI) {
+ CVTypeDumper::printTypeIndex(W, FieldName, TI, TypeDB);
+}
+
+Error CVSymbolDumperImpl::visitSymbolBegin(CVSymbol &CVR) {
+ return Error::success();
+}
-void CVSymbolDumperImpl::visitSymbolEnd(SymbolKind Kind,
- ArrayRef<uint8_t> OriginalSymData) {
+Error CVSymbolDumperImpl::visitSymbolEnd(CVSymbol &CVR) {
if (PrintRecordBytes && ObjDelegate)
- ObjDelegate->printBinaryBlockWithRelocs("SymData", OriginalSymData);
+ ObjDelegate->printBinaryBlockWithRelocs("SymData", CVR.content());
+ return Error::success();
}
-void CVSymbolDumperImpl::visitBlockSym(SymbolKind Kind, BlockSym &Block) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, BlockSym &Block) {
DictScope S(W, "BlockStart");
StringRef LinkageName;
- W.printHex("PtrParent", Block.Header.PtrParent);
- W.printHex("PtrEnd", Block.Header.PtrEnd);
- W.printHex("CodeSize", Block.Header.CodeSize);
+ W.printHex("PtrParent", Block.Parent);
+ W.printHex("PtrEnd", Block.End);
+ W.printHex("CodeSize", Block.CodeSize);
if (ObjDelegate) {
ObjDelegate->printRelocatedField("CodeOffset", Block.getRelocationOffset(),
- Block.Header.CodeOffset, &LinkageName);
+ Block.CodeOffset, &LinkageName);
}
- W.printHex("Segment", Block.Header.Segment);
+ W.printHex("Segment", Block.Segment);
W.printString("BlockName", Block.Name);
W.printString("LinkageName", LinkageName);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitThunk32Sym(SymbolKind Kind, Thunk32Sym &Thunk) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, Thunk32Sym &Thunk) {
DictScope S(W, "Thunk32");
- W.printNumber("Parent", Thunk.Header.Parent);
- W.printNumber("End", Thunk.Header.End);
- W.printNumber("Next", Thunk.Header.Next);
- W.printNumber("Off", Thunk.Header.Off);
- W.printNumber("Seg", Thunk.Header.Seg);
- W.printNumber("Len", Thunk.Header.Len);
- W.printEnum("Ordinal", Thunk.Header.Ord, getThunkOrdinalNames());
-}
-
-void CVSymbolDumperImpl::visitTrampolineSym(SymbolKind Kind,
- TrampolineSym &Tramp) {
+ W.printNumber("Parent", Thunk.Parent);
+ W.printNumber("End", Thunk.End);
+ W.printNumber("Next", Thunk.Next);
+ W.printNumber("Off", Thunk.Offset);
+ W.printNumber("Seg", Thunk.Segment);
+ W.printNumber("Len", Thunk.Length);
+ W.printEnum("Ordinal", uint8_t(Thunk.Thunk), getThunkOrdinalNames());
+ return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+ TrampolineSym &Tramp) {
DictScope S(W, "Trampoline");
- W.printEnum("Type", Tramp.Header.Type, getTrampolineNames());
- W.printNumber("Size", Tramp.Header.Size);
- W.printNumber("ThunkOff", Tramp.Header.ThunkOff);
- W.printNumber("TargetOff", Tramp.Header.TargetOff);
- W.printNumber("ThunkSection", Tramp.Header.ThunkSection);
- W.printNumber("TargetSection", Tramp.Header.TargetSection);
+ W.printEnum("Type", uint16_t(Tramp.Type), getTrampolineNames());
+ W.printNumber("Size", Tramp.Size);
+ W.printNumber("ThunkOff", Tramp.ThunkOffset);
+ W.printNumber("TargetOff", Tramp.TargetOffset);
+ W.printNumber("ThunkSection", Tramp.ThunkSection);
+ W.printNumber("TargetSection", Tramp.TargetSection);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitSectionSym(SymbolKind Kind, SectionSym &Section) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, SectionSym &Section) {
DictScope S(W, "Section");
- W.printNumber("SectionNumber", Section.Header.SectionNumber);
- W.printNumber("Alignment", Section.Header.Alignment);
- W.printNumber("Reserved", Section.Header.Reserved);
- W.printNumber("Rva", Section.Header.Rva);
- W.printNumber("Length", Section.Header.Length);
- W.printFlags("Characteristics", Section.Header.Characteristics,
+ W.printNumber("SectionNumber", Section.SectionNumber);
+ W.printNumber("Alignment", Section.Alignment);
+ W.printNumber("Rva", Section.Rva);
+ W.printNumber("Length", Section.Length);
+ W.printFlags("Characteristics", Section.Characteristics,
getImageSectionCharacteristicNames(),
COFF::SectionCharacteristics(0x00F00000));
W.printString("Name", Section.Name);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitCoffGroupSym(SymbolKind Kind,
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
CoffGroupSym &CoffGroup) {
DictScope S(W, "COFF Group");
- W.printNumber("Size", CoffGroup.Header.Size);
- W.printFlags("Characteristics", CoffGroup.Header.Characteristics,
+ W.printNumber("Size", CoffGroup.Size);
+ W.printFlags("Characteristics", CoffGroup.Characteristics,
getImageSectionCharacteristicNames(),
COFF::SectionCharacteristics(0x00F00000));
- W.printNumber("Offset", CoffGroup.Header.Offset);
- W.printNumber("Segment", CoffGroup.Header.Segment);
+ W.printNumber("Offset", CoffGroup.Offset);
+ W.printNumber("Segment", CoffGroup.Segment);
W.printString("Name", CoffGroup.Name);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitBPRelativeSym(SymbolKind Kind,
- BPRelativeSym &BPRel) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+ BPRelativeSym &BPRel) {
DictScope S(W, "BPRelativeSym");
- W.printNumber("Offset", BPRel.Header.Offset);
- CVTD.printTypeIndex("Type", BPRel.Header.Type);
+ W.printNumber("Offset", BPRel.Offset);
+ printTypeIndex("Type", BPRel.Type);
W.printString("VarName", BPRel.Name);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitBuildInfoSym(SymbolKind Kind,
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
BuildInfoSym &BuildInfo) {
DictScope S(W, "BuildInfo");
- W.printNumber("BuildId", BuildInfo.Header.BuildId);
+ W.printNumber("BuildId", BuildInfo.BuildId);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitCallSiteInfoSym(SymbolKind Kind,
- CallSiteInfoSym &CallSiteInfo) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+ CallSiteInfoSym &CallSiteInfo) {
DictScope S(W, "CallSiteInfo");
StringRef LinkageName;
if (ObjDelegate) {
- ObjDelegate->printRelocatedField(
- "CodeOffset", CallSiteInfo.getRelocationOffset(),
- CallSiteInfo.Header.CodeOffset, &LinkageName);
+ ObjDelegate->printRelocatedField("CodeOffset",
+ CallSiteInfo.getRelocationOffset(),
+ CallSiteInfo.CodeOffset, &LinkageName);
}
- W.printHex("Segment", CallSiteInfo.Header.Segment);
- W.printHex("Reserved", CallSiteInfo.Header.Reserved);
- CVTD.printTypeIndex("Type", CallSiteInfo.Header.Type);
+ W.printHex("Segment", CallSiteInfo.Segment);
+ printTypeIndex("Type", CallSiteInfo.Type);
if (!LinkageName.empty())
W.printString("LinkageName", LinkageName);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitEnvBlockSym(SymbolKind Kind,
- EnvBlockSym &EnvBlock) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+ EnvBlockSym &EnvBlock) {
DictScope S(W, "EnvBlock");
- W.printNumber("Reserved", EnvBlock.Header.Reserved);
ListScope L(W, "Entries");
for (auto Entry : EnvBlock.Fields) {
W.printString(Entry);
}
+ return Error::success();
}
-void CVSymbolDumperImpl::visitFileStaticSym(SymbolKind Kind,
- FileStaticSym &FileStatic) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+ FileStaticSym &FileStatic) {
DictScope S(W, "FileStatic");
- W.printNumber("Index", FileStatic.Header.Index);
- W.printNumber("ModFilenameOffset", FileStatic.Header.ModFilenameOffset);
- W.printFlags("Flags", uint16_t(FileStatic.Header.Flags), getLocalFlagNames());
+ W.printNumber("Index", FileStatic.Index);
+ W.printNumber("ModFilenameOffset", FileStatic.ModFilenameOffset);
+ W.printFlags("Flags", uint16_t(FileStatic.Flags), getLocalFlagNames());
W.printString("Name", FileStatic.Name);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitExportSym(SymbolKind Kind, ExportSym &Export) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ExportSym &Export) {
DictScope S(W, "Export");
- W.printNumber("Ordinal", Export.Header.Ordinal);
- W.printFlags("Flags", Export.Header.Flags, getExportSymFlagNames());
+ W.printNumber("Ordinal", Export.Ordinal);
+ W.printFlags("Flags", uint16_t(Export.Flags), getExportSymFlagNames());
W.printString("Name", Export.Name);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitCompile2Sym(SymbolKind Kind,
- Compile2Sym &Compile2) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+ Compile2Sym &Compile2) {
DictScope S(W, "CompilerFlags2");
- W.printEnum("Language", Compile2.Header.getLanguage(),
- getSourceLanguageNames());
- W.printFlags("Flags", Compile2.Header.flags & ~0xff,
- getCompileSym2FlagNames());
- W.printEnum("Machine", unsigned(Compile2.Header.Machine), getCPUTypeNames());
+ W.printEnum("Language", Compile2.getLanguage(), getSourceLanguageNames());
+ W.printFlags("Flags", Compile2.getFlags(), getCompileSym2FlagNames());
+ W.printEnum("Machine", unsigned(Compile2.Machine), getCPUTypeNames());
std::string FrontendVersion;
{
raw_string_ostream Out(FrontendVersion);
- Out << Compile2.Header.VersionFrontendMajor << '.'
- << Compile2.Header.VersionFrontendMinor << '.'
- << Compile2.Header.VersionFrontendBuild;
+ Out << Compile2.VersionFrontendMajor << '.' << Compile2.VersionFrontendMinor
+ << '.' << Compile2.VersionFrontendBuild;
}
std::string BackendVersion;
{
raw_string_ostream Out(BackendVersion);
- Out << Compile2.Header.VersionBackendMajor << '.'
- << Compile2.Header.VersionBackendMinor << '.'
- << Compile2.Header.VersionBackendBuild;
+ Out << Compile2.VersionBackendMajor << '.' << Compile2.VersionBackendMinor
+ << '.' << Compile2.VersionBackendBuild;
}
W.printString("FrontendVersion", FrontendVersion);
W.printString("BackendVersion", BackendVersion);
W.printString("VersionName", Compile2.Version);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitCompile3Sym(SymbolKind Kind,
- Compile3Sym &Compile3) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+ Compile3Sym &Compile3) {
DictScope S(W, "CompilerFlags3");
- W.printEnum("Language", Compile3.Header.getLanguage(),
- getSourceLanguageNames());
- W.printFlags("Flags", Compile3.Header.flags & ~0xff,
- getCompileSym3FlagNames());
- W.printEnum("Machine", unsigned(Compile3.Header.Machine), getCPUTypeNames());
+ W.printEnum("Language", Compile3.getLanguage(), getSourceLanguageNames());
+ W.printFlags("Flags", Compile3.getFlags(), getCompileSym3FlagNames());
+ W.printEnum("Machine", unsigned(Compile3.Machine), getCPUTypeNames());
std::string FrontendVersion;
{
raw_string_ostream Out(FrontendVersion);
- Out << Compile3.Header.VersionFrontendMajor << '.'
- << Compile3.Header.VersionFrontendMinor << '.'
- << Compile3.Header.VersionFrontendBuild << '.'
- << Compile3.Header.VersionFrontendQFE;
+ Out << Compile3.VersionFrontendMajor << '.' << Compile3.VersionFrontendMinor
+ << '.' << Compile3.VersionFrontendBuild << '.'
+ << Compile3.VersionFrontendQFE;
}
std::string BackendVersion;
{
raw_string_ostream Out(BackendVersion);
- Out << Compile3.Header.VersionBackendMajor << '.'
- << Compile3.Header.VersionBackendMinor << '.'
- << Compile3.Header.VersionBackendBuild << '.'
- << Compile3.Header.VersionBackendQFE;
+ Out << Compile3.VersionBackendMajor << '.' << Compile3.VersionBackendMinor
+ << '.' << Compile3.VersionBackendBuild << '.'
+ << Compile3.VersionBackendQFE;
}
W.printString("FrontendVersion", FrontendVersion);
W.printString("BackendVersion", BackendVersion);
W.printString("VersionName", Compile3.Version);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitConstantSym(SymbolKind Kind,
- ConstantSym &Constant) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+ ConstantSym &Constant) {
DictScope S(W, "Constant");
- CVTD.printTypeIndex("Type", Constant.Header.Type);
+ printTypeIndex("Type", Constant.Type);
W.printNumber("Value", Constant.Value);
W.printString("Name", Constant.Name);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitDataSym(SymbolKind Kind, DataSym &Data) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, DataSym &Data) {
DictScope S(W, "DataSym");
- W.printEnum("Kind", uint16_t(Kind), getSymbolTypeNames());
+ W.printEnum("Kind", uint16_t(CVR.kind()), getSymbolTypeNames());
StringRef LinkageName;
if (ObjDelegate) {
ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(),
- Data.Header.DataOffset, &LinkageName);
+ Data.DataOffset, &LinkageName);
}
- CVTD.printTypeIndex("Type", Data.Header.Type);
+ printTypeIndex("Type", Data.Type);
W.printString("DisplayName", Data.Name);
if (!LinkageName.empty())
W.printString("LinkageName", LinkageName);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitDefRangeFramePointerRelFullScopeSym(
- SymbolKind Kind,
+Error CVSymbolDumperImpl::visitKnownRecord(
+ CVSymbol &CVR,
DefRangeFramePointerRelFullScopeSym &DefRangeFramePointerRelFullScope) {
DictScope S(W, "DefRangeFramePointerRelFullScope");
- W.printNumber("Offset", DefRangeFramePointerRelFullScope.Header.Offset);
+ W.printNumber("Offset", DefRangeFramePointerRelFullScope.Offset);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitDefRangeFramePointerRelSym(
- SymbolKind Kind, DefRangeFramePointerRelSym &DefRangeFramePointerRel) {
+Error CVSymbolDumperImpl::visitKnownRecord(
+ CVSymbol &CVR, DefRangeFramePointerRelSym &DefRangeFramePointerRel) {
DictScope S(W, "DefRangeFramePointerRel");
- W.printNumber("Offset", DefRangeFramePointerRel.Header.Offset);
- printLocalVariableAddrRange(DefRangeFramePointerRel.Header.Range,
+ W.printNumber("Offset", DefRangeFramePointerRel.Offset);
+ printLocalVariableAddrRange(DefRangeFramePointerRel.Range,
DefRangeFramePointerRel.getRelocationOffset());
printLocalVariableAddrGap(DefRangeFramePointerRel.Gaps);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitDefRangeRegisterRelSym(
- SymbolKind Kind, DefRangeRegisterRelSym &DefRangeRegisterRel) {
+Error CVSymbolDumperImpl::visitKnownRecord(
+ CVSymbol &CVR, DefRangeRegisterRelSym &DefRangeRegisterRel) {
DictScope S(W, "DefRangeRegisterRel");
- W.printNumber("BaseRegister", DefRangeRegisterRel.Header.BaseRegister);
+ W.printNumber("BaseRegister", DefRangeRegisterRel.Hdr.Register);
W.printBoolean("HasSpilledUDTMember",
DefRangeRegisterRel.hasSpilledUDTMember());
W.printNumber("OffsetInParent", DefRangeRegisterRel.offsetInParent());
- W.printNumber("BasePointerOffset",
- DefRangeRegisterRel.Header.BasePointerOffset);
- printLocalVariableAddrRange(DefRangeRegisterRel.Header.Range,
+ W.printNumber("BasePointerOffset", DefRangeRegisterRel.Hdr.BasePointerOffset);
+ printLocalVariableAddrRange(DefRangeRegisterRel.Range,
DefRangeRegisterRel.getRelocationOffset());
printLocalVariableAddrGap(DefRangeRegisterRel.Gaps);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitDefRangeRegisterSym(
- SymbolKind Kind, DefRangeRegisterSym &DefRangeRegister) {
+Error CVSymbolDumperImpl::visitKnownRecord(
+ CVSymbol &CVR, DefRangeRegisterSym &DefRangeRegister) {
DictScope S(W, "DefRangeRegister");
- W.printNumber("Register", DefRangeRegister.Header.Register);
- W.printNumber("MayHaveNoName", DefRangeRegister.Header.MayHaveNoName);
- printLocalVariableAddrRange(DefRangeRegister.Header.Range,
+ W.printNumber("Register", DefRangeRegister.Hdr.Register);
+ W.printNumber("MayHaveNoName", DefRangeRegister.Hdr.MayHaveNoName);
+ printLocalVariableAddrRange(DefRangeRegister.Range,
DefRangeRegister.getRelocationOffset());
printLocalVariableAddrGap(DefRangeRegister.Gaps);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitDefRangeSubfieldRegisterSym(
- SymbolKind Kind, DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) {
+Error CVSymbolDumperImpl::visitKnownRecord(
+ CVSymbol &CVR, DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) {
DictScope S(W, "DefRangeSubfieldRegister");
- W.printNumber("Register", DefRangeSubfieldRegister.Header.Register);
- W.printNumber("MayHaveNoName", DefRangeSubfieldRegister.Header.MayHaveNoName);
- W.printNumber("OffsetInParent",
- DefRangeSubfieldRegister.Header.OffsetInParent);
- printLocalVariableAddrRange(DefRangeSubfieldRegister.Header.Range,
+ W.printNumber("Register", DefRangeSubfieldRegister.Hdr.Register);
+ W.printNumber("MayHaveNoName", DefRangeSubfieldRegister.Hdr.MayHaveNoName);
+ W.printNumber("OffsetInParent", DefRangeSubfieldRegister.Hdr.OffsetInParent);
+ printLocalVariableAddrRange(DefRangeSubfieldRegister.Range,
DefRangeSubfieldRegister.getRelocationOffset());
printLocalVariableAddrGap(DefRangeSubfieldRegister.Gaps);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitDefRangeSubfieldSym(
- SymbolKind Kind, DefRangeSubfieldSym &DefRangeSubfield) {
+Error CVSymbolDumperImpl::visitKnownRecord(
+ CVSymbol &CVR, DefRangeSubfieldSym &DefRangeSubfield) {
DictScope S(W, "DefRangeSubfield");
if (ObjDelegate) {
StringRef StringTable = ObjDelegate->getStringTable();
- auto ProgramStringTableOffset = DefRangeSubfield.Header.Program;
+ auto ProgramStringTableOffset = DefRangeSubfield.Program;
if (ProgramStringTableOffset >= StringTable.size())
- return parseError();
+ return llvm::make_error<CodeViewError>(
+ "String table offset outside of bounds of String Table!");
StringRef Program =
StringTable.drop_front(ProgramStringTableOffset).split('\0').first;
W.printString("Program", Program);
}
- W.printNumber("OffsetInParent", DefRangeSubfield.Header.OffsetInParent);
- printLocalVariableAddrRange(DefRangeSubfield.Header.Range,
+ W.printNumber("OffsetInParent", DefRangeSubfield.OffsetInParent);
+ printLocalVariableAddrRange(DefRangeSubfield.Range,
DefRangeSubfield.getRelocationOffset());
printLocalVariableAddrGap(DefRangeSubfield.Gaps);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitDefRangeSym(SymbolKind Kind,
- DefRangeSym &DefRange) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+ DefRangeSym &DefRange) {
DictScope S(W, "DefRange");
if (ObjDelegate) {
StringRef StringTable = ObjDelegate->getStringTable();
- auto ProgramStringTableOffset = DefRange.Header.Program;
+ auto ProgramStringTableOffset = DefRange.Program;
if (ProgramStringTableOffset >= StringTable.size())
- return parseError();
+ return llvm::make_error<CodeViewError>(
+ "String table offset outside of bounds of String Table!");
StringRef Program =
StringTable.drop_front(ProgramStringTableOffset).split('\0').first;
W.printString("Program", Program);
}
- printLocalVariableAddrRange(DefRange.Header.Range,
- DefRange.getRelocationOffset());
+ printLocalVariableAddrRange(DefRange.Range, DefRange.getRelocationOffset());
printLocalVariableAddrGap(DefRange.Gaps);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitFrameCookieSym(SymbolKind Kind,
- FrameCookieSym &FrameCookie) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+ FrameCookieSym &FrameCookie) {
DictScope S(W, "FrameCookie");
StringRef LinkageName;
if (ObjDelegate) {
- ObjDelegate->printRelocatedField(
- "CodeOffset", FrameCookie.getRelocationOffset(),
- FrameCookie.Header.CodeOffset, &LinkageName);
+ ObjDelegate->printRelocatedField("CodeOffset",
+ FrameCookie.getRelocationOffset(),
+ FrameCookie.CodeOffset, &LinkageName);
}
- W.printHex("Register", FrameCookie.Header.Register);
- W.printEnum("CookieKind", uint16_t(FrameCookie.Header.CookieKind),
+ W.printHex("Register", FrameCookie.Register);
+ W.printEnum("CookieKind", uint16_t(FrameCookie.CookieKind),
getFrameCookieKindNames());
- W.printHex("Flags", FrameCookie.Header.Flags);
+ W.printHex("Flags", FrameCookie.Flags);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitFrameProcSym(SymbolKind Kind,
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
FrameProcSym &FrameProc) {
DictScope S(W, "FrameProc");
- W.printHex("TotalFrameBytes", FrameProc.Header.TotalFrameBytes);
- W.printHex("PaddingFrameBytes", FrameProc.Header.PaddingFrameBytes);
- W.printHex("OffsetToPadding", FrameProc.Header.OffsetToPadding);
+ W.printHex("TotalFrameBytes", FrameProc.TotalFrameBytes);
+ W.printHex("PaddingFrameBytes", FrameProc.PaddingFrameBytes);
+ W.printHex("OffsetToPadding", FrameProc.OffsetToPadding);
W.printHex("BytesOfCalleeSavedRegisters",
- FrameProc.Header.BytesOfCalleeSavedRegisters);
- W.printHex("OffsetOfExceptionHandler",
- FrameProc.Header.OffsetOfExceptionHandler);
+ FrameProc.BytesOfCalleeSavedRegisters);
+ W.printHex("OffsetOfExceptionHandler", FrameProc.OffsetOfExceptionHandler);
W.printHex("SectionIdOfExceptionHandler",
- FrameProc.Header.SectionIdOfExceptionHandler);
- W.printFlags("Flags", FrameProc.Header.Flags, getFrameProcSymFlagNames());
+ FrameProc.SectionIdOfExceptionHandler);
+ W.printFlags("Flags", static_cast<uint32_t>(FrameProc.Flags),
+ getFrameProcSymFlagNames());
+ return Error::success();
}
-void CVSymbolDumperImpl::visitHeapAllocationSiteSym(
- SymbolKind Kind, HeapAllocationSiteSym &HeapAllocSite) {
+Error CVSymbolDumperImpl::visitKnownRecord(
+ CVSymbol &CVR, HeapAllocationSiteSym &HeapAllocSite) {
DictScope S(W, "HeapAllocationSite");
StringRef LinkageName;
if (ObjDelegate) {
- ObjDelegate->printRelocatedField(
- "CodeOffset", HeapAllocSite.getRelocationOffset(),
- HeapAllocSite.Header.CodeOffset, &LinkageName);
+ ObjDelegate->printRelocatedField("CodeOffset",
+ HeapAllocSite.getRelocationOffset(),
+ HeapAllocSite.CodeOffset, &LinkageName);
}
- W.printHex("Segment", HeapAllocSite.Header.Segment);
- W.printHex("CallInstructionSize", HeapAllocSite.Header.CallInstructionSize);
- CVTD.printTypeIndex("Type", HeapAllocSite.Header.Type);
+ W.printHex("Segment", HeapAllocSite.Segment);
+ W.printHex("CallInstructionSize", HeapAllocSite.CallInstructionSize);
+ printTypeIndex("Type", HeapAllocSite.Type);
if (!LinkageName.empty())
W.printString("LinkageName", LinkageName);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitInlineSiteSym(SymbolKind Kind,
- InlineSiteSym &InlineSite) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+ InlineSiteSym &InlineSite) {
DictScope S(W, "InlineSite");
- W.printHex("PtrParent", InlineSite.Header.PtrParent);
- W.printHex("PtrEnd", InlineSite.Header.PtrEnd);
- CVTD.printTypeIndex("Inlinee", InlineSite.Header.Inlinee);
+ W.printHex("PtrParent", InlineSite.Parent);
+ W.printHex("PtrEnd", InlineSite.End);
+ printTypeIndex("Inlinee", InlineSite.Inlinee);
ListScope BinaryAnnotations(W, "BinaryAnnotations");
for (auto &Annotation : InlineSite.annotations()) {
switch (Annotation.OpCode) {
case BinaryAnnotationsOpCode::Invalid:
- return parseError();
+ return llvm::make_error<CodeViewError>(
+ "Invalid binary annotation opcode!");
case BinaryAnnotationsOpCode::CodeOffset:
case BinaryAnnotationsOpCode::ChangeCodeOffset:
case BinaryAnnotationsOpCode::ChangeCodeLength:
@@ -486,157 +510,180 @@ void CVSymbolDumperImpl::visitInlineSiteSym(SymbolKind Kind,
}
}
}
+ return Error::success();
}
-void CVSymbolDumperImpl::visitRegisterSym(SymbolKind Kind,
- RegisterSym &Register) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+ RegisterSym &Register) {
DictScope S(W, "RegisterSym");
- W.printNumber("Type", Register.Header.Index);
- W.printEnum("Seg", uint16_t(Register.Header.Register), getRegisterNames());
+ W.printNumber("Type", Register.Index);
+ W.printEnum("Seg", uint16_t(Register.Register), getRegisterNames());
W.printString("Name", Register.Name);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitPublicSym32(SymbolKind Kind,
- PublicSym32 &Public) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, PublicSym32 &Public) {
DictScope S(W, "PublicSym");
- W.printNumber("Type", Public.Header.Index);
- W.printNumber("Seg", Public.Header.Seg);
- W.printNumber("Off", Public.Header.Off);
+ W.printNumber("Type", Public.Index);
+ W.printNumber("Seg", Public.Segment);
+ W.printNumber("Off", Public.Offset);
W.printString("Name", Public.Name);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitProcRefSym(SymbolKind Kind, ProcRefSym &ProcRef) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ProcRefSym &ProcRef) {
DictScope S(W, "ProcRef");
- W.printNumber("SumName", ProcRef.Header.SumName);
- W.printNumber("SymOffset", ProcRef.Header.SymOffset);
- W.printNumber("Mod", ProcRef.Header.Mod);
+ W.printNumber("SumName", ProcRef.SumName);
+ W.printNumber("SymOffset", ProcRef.SymOffset);
+ W.printNumber("Mod", ProcRef.Module);
W.printString("Name", ProcRef.Name);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitLabelSym(SymbolKind Kind, LabelSym &Label) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, LabelSym &Label) {
DictScope S(W, "Label");
StringRef LinkageName;
if (ObjDelegate) {
ObjDelegate->printRelocatedField("CodeOffset", Label.getRelocationOffset(),
- Label.Header.CodeOffset, &LinkageName);
+ Label.CodeOffset, &LinkageName);
}
- W.printHex("Segment", Label.Header.Segment);
- W.printHex("Flags", Label.Header.Flags);
- W.printFlags("Flags", Label.Header.Flags, getProcSymFlagNames());
+ W.printHex("Segment", Label.Segment);
+ W.printHex("Flags", uint8_t(Label.Flags));
+ W.printFlags("Flags", uint8_t(Label.Flags), getProcSymFlagNames());
W.printString("DisplayName", Label.Name);
if (!LinkageName.empty())
W.printString("LinkageName", LinkageName);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitLocalSym(SymbolKind Kind, LocalSym &Local) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, LocalSym &Local) {
DictScope S(W, "Local");
- CVTD.printTypeIndex("Type", Local.Header.Type);
- W.printFlags("Flags", uint16_t(Local.Header.Flags), getLocalFlagNames());
+ printTypeIndex("Type", Local.Type);
+ W.printFlags("Flags", uint16_t(Local.Flags), getLocalFlagNames());
W.printString("VarName", Local.Name);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitObjNameSym(SymbolKind Kind, ObjNameSym &ObjName) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ObjNameSym &ObjName) {
DictScope S(W, "ObjectName");
- W.printHex("Signature", ObjName.Header.Signature);
+ W.printHex("Signature", ObjName.Signature);
W.printString("ObjectName", ObjName.Name);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitProcSym(SymbolKind Kind, ProcSym &Proc) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ProcSym &Proc) {
DictScope S(W, "ProcStart");
if (InFunctionScope)
- return parseError();
+ return llvm::make_error<CodeViewError>(
+ "Visiting a ProcSym while inside function scope!");
InFunctionScope = true;
StringRef LinkageName;
- W.printEnum("Kind", uint16_t(Kind), getSymbolTypeNames());
- W.printHex("PtrParent", Proc.Header.PtrParent);
- W.printHex("PtrEnd", Proc.Header.PtrEnd);
- W.printHex("PtrNext", Proc.Header.PtrNext);
- W.printHex("CodeSize", Proc.Header.CodeSize);
- W.printHex("DbgStart", Proc.Header.DbgStart);
- W.printHex("DbgEnd", Proc.Header.DbgEnd);
- CVTD.printTypeIndex("FunctionType", Proc.Header.FunctionType);
+ W.printEnum("Kind", uint16_t(CVR.kind()), getSymbolTypeNames());
+ W.printHex("PtrParent", Proc.Parent);
+ W.printHex("PtrEnd", Proc.End);
+ W.printHex("PtrNext", Proc.Next);
+ W.printHex("CodeSize", Proc.CodeSize);
+ W.printHex("DbgStart", Proc.DbgStart);
+ W.printHex("DbgEnd", Proc.DbgEnd);
+ printTypeIndex("FunctionType", Proc.FunctionType);
if (ObjDelegate) {
ObjDelegate->printRelocatedField("CodeOffset", Proc.getRelocationOffset(),
- Proc.Header.CodeOffset, &LinkageName);
+ Proc.CodeOffset, &LinkageName);
}
- W.printHex("Segment", Proc.Header.Segment);
- W.printFlags("Flags", static_cast<uint8_t>(Proc.Header.Flags),
+ W.printHex("Segment", Proc.Segment);
+ W.printFlags("Flags", static_cast<uint8_t>(Proc.Flags),
getProcSymFlagNames());
W.printString("DisplayName", Proc.Name);
if (!LinkageName.empty())
W.printString("LinkageName", LinkageName);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitScopeEndSym(SymbolKind Kind,
- ScopeEndSym &ScopeEnd) {
- if (Kind == SymbolKind::S_END)
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+ ScopeEndSym &ScopeEnd) {
+ if (CVR.kind() == SymbolKind::S_END)
DictScope S(W, "BlockEnd");
- else if (Kind == SymbolKind::S_PROC_ID_END)
+ else if (CVR.kind() == SymbolKind::S_PROC_ID_END)
DictScope S(W, "ProcEnd");
- else if (Kind == SymbolKind::S_INLINESITE_END)
+ else if (CVR.kind() == SymbolKind::S_INLINESITE_END)
DictScope S(W, "InlineSiteEnd");
InFunctionScope = false;
+ return Error::success();
}
-void CVSymbolDumperImpl::visitCallerSym(SymbolKind Kind, CallerSym &Caller) {
- ListScope S(W, Kind == S_CALLEES ? "Callees" : "Callers");
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, CallerSym &Caller) {
+ ListScope S(W, CVR.kind() == S_CALLEES ? "Callees" : "Callers");
for (auto FuncID : Caller.Indices)
- CVTD.printTypeIndex("FuncID", FuncID);
+ printTypeIndex("FuncID", FuncID);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitRegRelativeSym(SymbolKind Kind,
- RegRelativeSym &RegRel) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+ RegRelativeSym &RegRel) {
DictScope S(W, "RegRelativeSym");
- W.printHex("Offset", RegRel.Header.Offset);
- CVTD.printTypeIndex("Type", RegRel.Header.Type);
- W.printHex("Register", RegRel.Header.Register);
+ W.printHex("Offset", RegRel.Offset);
+ printTypeIndex("Type", RegRel.Type);
+ W.printHex("Register", RegRel.Register);
W.printString("VarName", RegRel.Name);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitThreadLocalDataSym(SymbolKind Kind,
- ThreadLocalDataSym &Data) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+ ThreadLocalDataSym &Data) {
DictScope S(W, "ThreadLocalDataSym");
StringRef LinkageName;
if (ObjDelegate) {
ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(),
- Data.Header.DataOffset, &LinkageName);
+ Data.DataOffset, &LinkageName);
}
- CVTD.printTypeIndex("Type", Data.Header.Type);
+ printTypeIndex("Type", Data.Type);
W.printString("DisplayName", Data.Name);
if (!LinkageName.empty())
W.printString("LinkageName", LinkageName);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitUDTSym(SymbolKind Kind, UDTSym &UDT) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, UDTSym &UDT) {
DictScope S(W, "UDT");
- CVTD.printTypeIndex("Type", UDT.Header.Type);
+ printTypeIndex("Type", UDT.Type);
W.printString("UDTName", UDT.Name);
+ return Error::success();
}
-void CVSymbolDumperImpl::visitUnknownSymbol(SymbolKind Kind,
- ArrayRef<uint8_t> Data) {
+Error CVSymbolDumperImpl::visitUnknownSymbol(CVSymbol &CVR) {
DictScope S(W, "UnknownSym");
- W.printEnum("Kind", uint16_t(Kind), getSymbolTypeNames());
- W.printNumber("Length", uint32_t(Data.size()));
+ W.printEnum("Kind", uint16_t(CVR.kind()), getSymbolTypeNames());
+ W.printNumber("Length", CVR.length());
+ return Error::success();
}
-bool CVSymbolDumper::dump(const CVRecord<SymbolKind> &Record) {
- CVSymbolDumperImpl Dumper(CVTD, ObjDelegate.get(), W, PrintRecordBytes);
- Dumper.visitSymbolRecord(Record);
- return !Dumper.hadError();
+Error CVSymbolDumper::dump(CVRecord<SymbolKind> &Record) {
+ SymbolVisitorCallbackPipeline Pipeline;
+ SymbolDeserializer Deserializer(ObjDelegate.get());
+ CVSymbolDumperImpl Dumper(TypeDB, ObjDelegate.get(), W, PrintRecordBytes);
+
+ Pipeline.addCallbackToPipeline(Deserializer);
+ Pipeline.addCallbackToPipeline(Dumper);
+ CVSymbolVisitor Visitor(Pipeline);
+ return Visitor.visitSymbolRecord(Record);
}
-bool CVSymbolDumper::dump(const CVSymbolArray &Symbols) {
- CVSymbolDumperImpl Dumper(CVTD, ObjDelegate.get(), W, PrintRecordBytes);
- Dumper.visitSymbolStream(Symbols);
- return !Dumper.hadError();
+Error CVSymbolDumper::dump(const CVSymbolArray &Symbols) {
+ SymbolVisitorCallbackPipeline Pipeline;
+ SymbolDeserializer Deserializer(ObjDelegate.get());
+ CVSymbolDumperImpl Dumper(TypeDB, ObjDelegate.get(), W, PrintRecordBytes);
+
+ Pipeline.addCallbackToPipeline(Deserializer);
+ Pipeline.addCallbackToPipeline(Dumper);
+ CVSymbolVisitor Visitor(Pipeline);
+ return Visitor.visitSymbolStream(Symbols);
}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp b/contrib/llvm/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp
new file mode 100644
index 0000000..bb17314
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp
@@ -0,0 +1,464 @@
+//===- SymbolRecordMapping.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/SymbolRecordMapping.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+#define error(X) \
+ if (auto EC = X) \
+ return EC;
+
+namespace {
+struct MapGap {
+ Error operator()(CodeViewRecordIO &IO, LocalVariableAddrGap &Gap) const {
+ error(IO.mapInteger(Gap.GapStartOffset));
+ error(IO.mapInteger(Gap.Range));
+ return Error::success();
+ }
+};
+}
+
+static Error mapLocalVariableAddrRange(CodeViewRecordIO &IO,
+ LocalVariableAddrRange &Range) {
+ error(IO.mapInteger(Range.OffsetStart));
+ error(IO.mapInteger(Range.ISectStart));
+ error(IO.mapInteger(Range.Range));
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitSymbolBegin(CVSymbol &Record) {
+ error(IO.beginRecord(MaxRecordLength - sizeof(RecordPrefix)));
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitSymbolEnd(CVSymbol &Record) {
+ error(IO.endRecord());
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, BlockSym &Block) {
+
+ error(IO.mapInteger(Block.Parent));
+ error(IO.mapInteger(Block.End));
+ error(IO.mapInteger(Block.CodeSize));
+ error(IO.mapInteger(Block.CodeOffset));
+ error(IO.mapInteger(Block.Segment));
+ error(IO.mapStringZ(Block.Name));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, Thunk32Sym &Thunk) {
+
+ error(IO.mapInteger(Thunk.Parent));
+ error(IO.mapInteger(Thunk.End));
+ error(IO.mapInteger(Thunk.Next));
+ error(IO.mapInteger(Thunk.Offset));
+ error(IO.mapInteger(Thunk.Segment));
+ error(IO.mapInteger(Thunk.Length));
+ error(IO.mapEnum(Thunk.Thunk));
+ error(IO.mapStringZ(Thunk.Name));
+ error(IO.mapByteVectorTail(Thunk.VariantData));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ TrampolineSym &Tramp) {
+
+ error(IO.mapEnum(Tramp.Type));
+ error(IO.mapInteger(Tramp.Size));
+ error(IO.mapInteger(Tramp.ThunkOffset));
+ error(IO.mapInteger(Tramp.TargetOffset));
+ error(IO.mapInteger(Tramp.ThunkSection));
+ error(IO.mapInteger(Tramp.TargetSection));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ SectionSym &Section) {
+ uint8_t Padding = 0;
+
+ error(IO.mapInteger(Section.SectionNumber));
+ error(IO.mapInteger(Section.Alignment));
+ error(IO.mapInteger(Padding));
+ error(IO.mapInteger(Section.Rva));
+ error(IO.mapInteger(Section.Length));
+ error(IO.mapInteger(Section.Characteristics));
+ error(IO.mapStringZ(Section.Name));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ CoffGroupSym &CoffGroup) {
+
+ error(IO.mapInteger(CoffGroup.Size));
+ error(IO.mapInteger(CoffGroup.Characteristics));
+ error(IO.mapInteger(CoffGroup.Offset));
+ error(IO.mapInteger(CoffGroup.Segment));
+ error(IO.mapStringZ(CoffGroup.Name));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ BPRelativeSym &BPRel) {
+
+ error(IO.mapInteger(BPRel.Offset));
+ error(IO.mapInteger(BPRel.Type));
+ error(IO.mapStringZ(BPRel.Name));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ BuildInfoSym &BuildInfo) {
+
+ error(IO.mapInteger(BuildInfo.BuildId));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ CallSiteInfoSym &CallSiteInfo) {
+ uint16_t Padding = 0;
+
+ error(IO.mapInteger(CallSiteInfo.CodeOffset));
+ error(IO.mapInteger(CallSiteInfo.Segment));
+ error(IO.mapInteger(Padding));
+ error(IO.mapInteger(CallSiteInfo.Type));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ EnvBlockSym &EnvBlock) {
+
+ uint8_t Reserved = 0;
+ error(IO.mapInteger(Reserved));
+ error(IO.mapStringZVectorZ(EnvBlock.Fields));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ FileStaticSym &FileStatic) {
+
+ error(IO.mapInteger(FileStatic.Index));
+ error(IO.mapInteger(FileStatic.ModFilenameOffset));
+ error(IO.mapEnum(FileStatic.Flags));
+ error(IO.mapStringZ(FileStatic.Name));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, ExportSym &Export) {
+
+ error(IO.mapInteger(Export.Ordinal));
+ error(IO.mapEnum(Export.Flags));
+ error(IO.mapStringZ(Export.Name));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ Compile2Sym &Compile2) {
+
+ error(IO.mapEnum(Compile2.Flags));
+ error(IO.mapEnum(Compile2.Machine));
+ error(IO.mapInteger(Compile2.VersionFrontendMajor));
+ error(IO.mapInteger(Compile2.VersionFrontendMinor));
+ error(IO.mapInteger(Compile2.VersionFrontendBuild));
+ error(IO.mapInteger(Compile2.VersionBackendMajor));
+ error(IO.mapInteger(Compile2.VersionBackendMinor));
+ error(IO.mapInteger(Compile2.VersionBackendBuild));
+ error(IO.mapStringZ(Compile2.Version));
+ error(IO.mapStringZVectorZ(Compile2.ExtraStrings));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ Compile3Sym &Compile3) {
+
+ error(IO.mapEnum(Compile3.Flags));
+ error(IO.mapEnum(Compile3.Machine));
+ error(IO.mapInteger(Compile3.VersionFrontendMajor));
+ error(IO.mapInteger(Compile3.VersionFrontendMinor));
+ error(IO.mapInteger(Compile3.VersionFrontendBuild));
+ error(IO.mapInteger(Compile3.VersionFrontendQFE));
+ error(IO.mapInteger(Compile3.VersionBackendMajor));
+ error(IO.mapInteger(Compile3.VersionBackendMinor));
+ error(IO.mapInteger(Compile3.VersionBackendBuild));
+ error(IO.mapInteger(Compile3.VersionBackendQFE));
+ error(IO.mapStringZ(Compile3.Version));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ ConstantSym &Constant) {
+
+ error(IO.mapInteger(Constant.Type));
+ error(IO.mapEncodedInteger(Constant.Value));
+ error(IO.mapStringZ(Constant.Name));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, DataSym &Data) {
+
+ error(IO.mapInteger(Data.Type));
+ error(IO.mapInteger(Data.DataOffset));
+ error(IO.mapInteger(Data.Segment));
+ error(IO.mapStringZ(Data.Name));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(
+ CVSymbol &CVR, DefRangeFramePointerRelSym &DefRangeFramePointerRel) {
+
+ error(IO.mapInteger(DefRangeFramePointerRel.Offset));
+ error(mapLocalVariableAddrRange(IO, DefRangeFramePointerRel.Range));
+ error(IO.mapVectorTail(DefRangeFramePointerRel.Gaps, MapGap()));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(
+ CVSymbol &CVR,
+ DefRangeFramePointerRelFullScopeSym &DefRangeFramePointerRelFullScope) {
+
+ error(IO.mapInteger(DefRangeFramePointerRelFullScope.Offset));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(
+ CVSymbol &CVR, DefRangeRegisterRelSym &DefRangeRegisterRel) {
+
+ error(IO.mapObject(DefRangeRegisterRel.Hdr.Register));
+ error(IO.mapObject(DefRangeRegisterRel.Hdr.Flags));
+ error(IO.mapObject(DefRangeRegisterRel.Hdr.BasePointerOffset));
+ error(mapLocalVariableAddrRange(IO, DefRangeRegisterRel.Range));
+ error(IO.mapVectorTail(DefRangeRegisterRel.Gaps, MapGap()));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(
+ CVSymbol &CVR, DefRangeRegisterSym &DefRangeRegister) {
+
+ error(IO.mapObject(DefRangeRegister.Hdr.Register));
+ error(IO.mapObject(DefRangeRegister.Hdr.MayHaveNoName));
+ error(mapLocalVariableAddrRange(IO, DefRangeRegister.Range));
+ error(IO.mapVectorTail(DefRangeRegister.Gaps, MapGap()));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(
+ CVSymbol &CVR, DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) {
+
+ error(IO.mapObject(DefRangeSubfieldRegister.Hdr.Register));
+ error(IO.mapObject(DefRangeSubfieldRegister.Hdr.MayHaveNoName));
+ error(IO.mapObject(DefRangeSubfieldRegister.Hdr.OffsetInParent));
+ error(mapLocalVariableAddrRange(IO, DefRangeSubfieldRegister.Range));
+ error(IO.mapVectorTail(DefRangeSubfieldRegister.Gaps, MapGap()));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(
+ CVSymbol &CVR, DefRangeSubfieldSym &DefRangeSubfield) {
+
+ error(IO.mapInteger(DefRangeSubfield.Program));
+ error(IO.mapInteger(DefRangeSubfield.OffsetInParent));
+ error(mapLocalVariableAddrRange(IO, DefRangeSubfield.Range));
+ error(IO.mapVectorTail(DefRangeSubfield.Gaps, MapGap()));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ DefRangeSym &DefRange) {
+
+ error(IO.mapInteger(DefRange.Program));
+ error(mapLocalVariableAddrRange(IO, DefRange.Range));
+ error(IO.mapVectorTail(DefRange.Gaps, MapGap()));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ FrameCookieSym &FrameCookie) {
+
+ error(IO.mapInteger(FrameCookie.CodeOffset));
+ error(IO.mapInteger(FrameCookie.Register));
+ error(IO.mapInteger(FrameCookie.CookieKind));
+ error(IO.mapInteger(FrameCookie.Flags));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ FrameProcSym &FrameProc) {
+ error(IO.mapInteger(FrameProc.TotalFrameBytes));
+ error(IO.mapInteger(FrameProc.PaddingFrameBytes));
+ error(IO.mapInteger(FrameProc.OffsetToPadding));
+ error(IO.mapInteger(FrameProc.BytesOfCalleeSavedRegisters));
+ error(IO.mapInteger(FrameProc.OffsetOfExceptionHandler));
+ error(IO.mapInteger(FrameProc.SectionIdOfExceptionHandler));
+ error(IO.mapEnum(FrameProc.Flags));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(
+ CVSymbol &CVR, HeapAllocationSiteSym &HeapAllocSite) {
+
+ error(IO.mapInteger(HeapAllocSite.CodeOffset));
+ error(IO.mapInteger(HeapAllocSite.Segment));
+ error(IO.mapInteger(HeapAllocSite.CallInstructionSize));
+ error(IO.mapInteger(HeapAllocSite.Type));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ InlineSiteSym &InlineSite) {
+
+ error(IO.mapInteger(InlineSite.Parent));
+ error(IO.mapInteger(InlineSite.End));
+ error(IO.mapInteger(InlineSite.Inlinee));
+ error(IO.mapByteVectorTail(InlineSite.AnnotationData));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ RegisterSym &Register) {
+
+ error(IO.mapInteger(Register.Index));
+ error(IO.mapEnum(Register.Register));
+ error(IO.mapStringZ(Register.Name));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ PublicSym32 &Public) {
+
+ error(IO.mapInteger(Public.Index));
+ error(IO.mapInteger(Public.Offset));
+ error(IO.mapInteger(Public.Segment));
+ error(IO.mapStringZ(Public.Name));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ ProcRefSym &ProcRef) {
+
+ error(IO.mapInteger(ProcRef.SumName));
+ error(IO.mapInteger(ProcRef.SymOffset));
+ error(IO.mapInteger(ProcRef.Module));
+ error(IO.mapStringZ(ProcRef.Name));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, LabelSym &Label) {
+
+ error(IO.mapInteger(Label.CodeOffset));
+ error(IO.mapInteger(Label.Segment));
+ error(IO.mapEnum(Label.Flags));
+ error(IO.mapStringZ(Label.Name));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, LocalSym &Local) {
+ error(IO.mapInteger(Local.Type));
+ error(IO.mapEnum(Local.Flags));
+ error(IO.mapStringZ(Local.Name));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ ObjNameSym &ObjName) {
+
+ error(IO.mapInteger(ObjName.Signature));
+ error(IO.mapStringZ(ObjName.Name));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, ProcSym &Proc) {
+ error(IO.mapInteger(Proc.Parent));
+ error(IO.mapInteger(Proc.End));
+ error(IO.mapInteger(Proc.Next));
+ error(IO.mapInteger(Proc.CodeSize));
+ error(IO.mapInteger(Proc.DbgStart));
+ error(IO.mapInteger(Proc.DbgEnd));
+ error(IO.mapInteger(Proc.FunctionType));
+ error(IO.mapInteger(Proc.CodeOffset));
+ error(IO.mapInteger(Proc.Segment));
+ error(IO.mapEnum(Proc.Flags));
+ error(IO.mapStringZ(Proc.Name));
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ ScopeEndSym &ScopeEnd) {
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, CallerSym &Caller) {
+ error(IO.mapVectorN<uint32_t>(
+ Caller.Indices,
+ [](CodeViewRecordIO &IO, TypeIndex &N) { return IO.mapInteger(N); }));
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ RegRelativeSym &RegRel) {
+
+ error(IO.mapInteger(RegRel.Offset));
+ error(IO.mapInteger(RegRel.Type));
+ error(IO.mapInteger(RegRel.Register));
+ error(IO.mapStringZ(RegRel.Name));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+ ThreadLocalDataSym &Data) {
+
+ error(IO.mapInteger(Data.Type));
+ error(IO.mapInteger(Data.DataOffset));
+ error(IO.mapInteger(Data.Segment));
+ error(IO.mapStringZ(Data.Name));
+
+ return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, UDTSym &UDT) {
+
+ error(IO.mapInteger(UDT.Type));
+ error(IO.mapStringZ(UDT.Name));
+
+ return Error::success();
+}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/TypeDatabase.cpp b/contrib/llvm/lib/DebugInfo/CodeView/TypeDatabase.cpp
new file mode 100644
index 0000000..c7f7255
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/TypeDatabase.cpp
@@ -0,0 +1,114 @@
+//===- TypeDatabase.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/TypeDatabase.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+namespace {
+struct SimpleTypeEntry {
+ StringRef Name;
+ SimpleTypeKind Kind;
+};
+}
+
+/// The names here all end in "*". If the simple type is a pointer type, we
+/// return the whole name. Otherwise we lop off the last character in our
+/// StringRef.
+static const SimpleTypeEntry SimpleTypeNames[] = {
+ {"void*", SimpleTypeKind::Void},
+ {"<not translated>*", SimpleTypeKind::NotTranslated},
+ {"HRESULT*", SimpleTypeKind::HResult},
+ {"signed char*", SimpleTypeKind::SignedCharacter},
+ {"unsigned char*", SimpleTypeKind::UnsignedCharacter},
+ {"char*", SimpleTypeKind::NarrowCharacter},
+ {"wchar_t*", SimpleTypeKind::WideCharacter},
+ {"char16_t*", SimpleTypeKind::Character16},
+ {"char32_t*", SimpleTypeKind::Character32},
+ {"__int8*", SimpleTypeKind::SByte},
+ {"unsigned __int8*", SimpleTypeKind::Byte},
+ {"short*", SimpleTypeKind::Int16Short},
+ {"unsigned short*", SimpleTypeKind::UInt16Short},
+ {"__int16*", SimpleTypeKind::Int16},
+ {"unsigned __int16*", SimpleTypeKind::UInt16},
+ {"long*", SimpleTypeKind::Int32Long},
+ {"unsigned long*", SimpleTypeKind::UInt32Long},
+ {"int*", SimpleTypeKind::Int32},
+ {"unsigned*", SimpleTypeKind::UInt32},
+ {"__int64*", SimpleTypeKind::Int64Quad},
+ {"unsigned __int64*", SimpleTypeKind::UInt64Quad},
+ {"__int64*", SimpleTypeKind::Int64},
+ {"unsigned __int64*", SimpleTypeKind::UInt64},
+ {"__int128*", SimpleTypeKind::Int128},
+ {"unsigned __int128*", SimpleTypeKind::UInt128},
+ {"__half*", SimpleTypeKind::Float16},
+ {"float*", SimpleTypeKind::Float32},
+ {"float*", SimpleTypeKind::Float32PartialPrecision},
+ {"__float48*", SimpleTypeKind::Float48},
+ {"double*", SimpleTypeKind::Float64},
+ {"long double*", SimpleTypeKind::Float80},
+ {"__float128*", SimpleTypeKind::Float128},
+ {"_Complex float*", SimpleTypeKind::Complex32},
+ {"_Complex double*", SimpleTypeKind::Complex64},
+ {"_Complex long double*", SimpleTypeKind::Complex80},
+ {"_Complex __float128*", SimpleTypeKind::Complex128},
+ {"bool*", SimpleTypeKind::Boolean8},
+ {"__bool16*", SimpleTypeKind::Boolean16},
+ {"__bool32*", SimpleTypeKind::Boolean32},
+ {"__bool64*", SimpleTypeKind::Boolean64},
+};
+
+/// Gets the type index for the next type record.
+TypeIndex TypeDatabase::getNextTypeIndex() const {
+ return TypeIndex(TypeIndex::FirstNonSimpleIndex + CVUDTNames.size());
+}
+
+/// Records the name of a type, and reserves its type index.
+void TypeDatabase::recordType(StringRef Name, CVType Data) {
+ CVUDTNames.push_back(Name);
+ TypeRecords.push_back(Data);
+}
+
+/// Saves the name in a StringSet and creates a stable StringRef.
+StringRef TypeDatabase::saveTypeName(StringRef TypeName) {
+ return TypeNameStorage.save(TypeName);
+}
+
+StringRef TypeDatabase::getTypeName(TypeIndex Index) const {
+ if (Index.isNoneType())
+ return "<no type>";
+
+ if (Index.isSimple()) {
+ // This is a simple type.
+ for (const auto &SimpleTypeName : SimpleTypeNames) {
+ if (SimpleTypeName.Kind == Index.getSimpleKind()) {
+ if (Index.getSimpleMode() == SimpleTypeMode::Direct)
+ return SimpleTypeName.Name.drop_back(1);
+ // Otherwise, this is a pointer type. We gloss over the distinction
+ // between near, far, 64, 32, etc, and just give a pointer type.
+ return SimpleTypeName.Name;
+ }
+ }
+ return "<unknown simple type>";
+ }
+
+ uint32_t I = Index.getIndex() - TypeIndex::FirstNonSimpleIndex;
+ if (I < CVUDTNames.size())
+ return CVUDTNames[I];
+
+ return "<unknown UDT>";
+}
+
+bool TypeDatabase::containsTypeIndex(TypeIndex Index) const {
+ uint32_t I = Index.getIndex() - TypeIndex::FirstNonSimpleIndex;
+ return I < CVUDTNames.size();
+}
+
+uint32_t TypeDatabase::size() const { return CVUDTNames.size(); }
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/TypeDatabaseVisitor.cpp b/contrib/llvm/lib/DebugInfo/CodeView/TypeDatabaseVisitor.cpp
new file mode 100644
index 0000000..d9d5639
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/TypeDatabaseVisitor.cpp
@@ -0,0 +1,289 @@
+//===- TypeDatabaseVisitor.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/TypeDatabaseVisitor.h"
+
+#include "llvm/ADT/SmallString.h"
+
+using namespace llvm;
+
+using namespace llvm::codeview;
+
+Error TypeDatabaseVisitor::visitTypeBegin(CVRecord<TypeLeafKind> &Record) {
+ assert(!IsInFieldList);
+ // Reset Name to the empty string. If the visitor sets it, we know it.
+ Name = "";
+
+ if (Record.Type == LF_FIELDLIST) {
+ // Record that we're in a field list so that members do not get assigned
+ // type indices.
+ IsInFieldList = true;
+ }
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitTypeEnd(CVType &CVR) {
+ if (CVR.Type == LF_FIELDLIST) {
+ assert(IsInFieldList);
+ IsInFieldList = false;
+ }
+ assert(!IsInFieldList);
+
+ // Record every type that is not a field list member, even if Name is empty.
+ // CVUDTNames is indexed by type index, and must have one entry for every
+ // type. Field list members are not recorded, and are only referenced by
+ // their containing field list record.
+ TypeDB.recordType(Name, CVR);
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitMemberBegin(CVMemberRecord &Record) {
+ assert(IsInFieldList);
+ // Reset Name to the empty string. If the visitor sets it, we know it.
+ Name = "";
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitMemberEnd(CVMemberRecord &Record) {
+ assert(IsInFieldList);
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR,
+ FieldListRecord &FieldList) {
+ Name = "<field list>";
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
+ StringIdRecord &String) {
+ // Put this in the database so it gets printed with LF_UDT_SRC_LINE.
+ Name = String.getString();
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, ArgListRecord &Args) {
+ auto Indices = Args.getIndices();
+ uint32_t Size = Indices.size();
+ SmallString<256> TypeName("(");
+ for (uint32_t I = 0; I < Size; ++I) {
+ StringRef ArgTypeName = TypeDB.getTypeName(Indices[I]);
+ TypeName.append(ArgTypeName);
+ if (I + 1 != Size)
+ TypeName.append(", ");
+ }
+ TypeName.push_back(')');
+ Name = TypeDB.saveTypeName(TypeName);
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, ClassRecord &Class) {
+ Name = Class.getName();
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, UnionRecord &Union) {
+ Name = Union.getName();
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, EnumRecord &Enum) {
+ Name = Enum.getName();
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, ArrayRecord &AT) {
+ Name = AT.getName();
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, VFTableRecord &VFT) {
+ Name = VFT.getName();
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR,
+ MemberFuncIdRecord &Id) {
+ Name = Id.getName();
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR,
+ ProcedureRecord &Proc) {
+ StringRef ReturnTypeName = TypeDB.getTypeName(Proc.getReturnType());
+ StringRef ArgListTypeName = TypeDB.getTypeName(Proc.getArgumentList());
+ SmallString<256> TypeName(ReturnTypeName);
+ TypeName.push_back(' ');
+ TypeName.append(ArgListTypeName);
+ Name = TypeDB.saveTypeName(TypeName);
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR,
+ MemberFunctionRecord &MF) {
+ StringRef ReturnTypeName = TypeDB.getTypeName(MF.getReturnType());
+ StringRef ClassTypeName = TypeDB.getTypeName(MF.getClassType());
+ StringRef ArgListTypeName = TypeDB.getTypeName(MF.getArgumentList());
+ SmallString<256> TypeName(ReturnTypeName);
+ TypeName.push_back(' ');
+ TypeName.append(ClassTypeName);
+ TypeName.append("::");
+ TypeName.append(ArgListTypeName);
+ Name = TypeDB.saveTypeName(TypeName);
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) {
+ Name = Func.getName();
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR,
+ TypeServer2Record &TS) {
+ Name = TS.getName();
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) {
+
+ if (Ptr.isPointerToMember()) {
+ const MemberPointerInfo &MI = Ptr.getMemberInfo();
+
+ StringRef PointeeName = TypeDB.getTypeName(Ptr.getReferentType());
+ StringRef ClassName = TypeDB.getTypeName(MI.getContainingType());
+ SmallString<256> TypeName(PointeeName);
+ TypeName.push_back(' ');
+ TypeName.append(ClassName);
+ TypeName.append("::*");
+ Name = TypeDB.saveTypeName(TypeName);
+ } else {
+ SmallString<256> TypeName;
+ if (Ptr.isConst())
+ TypeName.append("const ");
+ if (Ptr.isVolatile())
+ TypeName.append("volatile ");
+ if (Ptr.isUnaligned())
+ TypeName.append("__unaligned ");
+
+ TypeName.append(TypeDB.getTypeName(Ptr.getReferentType()));
+
+ if (Ptr.getMode() == PointerMode::LValueReference)
+ TypeName.append("&");
+ else if (Ptr.getMode() == PointerMode::RValueReference)
+ TypeName.append("&&");
+ else if (Ptr.getMode() == PointerMode::Pointer)
+ TypeName.append("*");
+
+ if (!TypeName.empty())
+ Name = TypeDB.saveTypeName(TypeName);
+ }
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) {
+ uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers());
+
+ StringRef ModifiedName = TypeDB.getTypeName(Mod.getModifiedType());
+ SmallString<256> TypeName;
+ if (Mods & uint16_t(ModifierOptions::Const))
+ TypeName.append("const ");
+ if (Mods & uint16_t(ModifierOptions::Volatile))
+ TypeName.append("volatile ");
+ if (Mods & uint16_t(ModifierOptions::Unaligned))
+ TypeName.append("__unaligned ");
+ TypeName.append(ModifiedName);
+ Name = TypeDB.saveTypeName(TypeName);
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR,
+ VFTableShapeRecord &Shape) {
+ Name = TypeDB.saveTypeName("<vftable " + utostr(Shape.getEntryCount()) +
+ " methods>");
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
+ NestedTypeRecord &Nested) {
+ Name = Nested.getName();
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
+ OneMethodRecord &Method) {
+ Name = Method.getName();
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
+ OverloadedMethodRecord &Method) {
+ Name = Method.getName();
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
+ DataMemberRecord &Field) {
+ Name = Field.getName();
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
+ StaticDataMemberRecord &Field) {
+ Name = Field.getName();
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
+ EnumeratorRecord &Enum) {
+ Name = Enum.getName();
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
+ BaseClassRecord &Base) {
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
+ VirtualBaseClassRecord &VBase) {
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
+ ListContinuationRecord &Cont) {
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(
+ CVType &CVR, UdtModSourceLineRecord &ModSourceLine) {
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR,
+ UdtSourceLineRecord &SourceLine) {
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, BitFieldRecord &BF) {
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(
+ CVType &CVR, MethodOverloadListRecord &Overloads) {
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, BuildInfoRecord &BI) {
+ return Error::success();
+}
+
+Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
+ VFPtrRecord &VFP) {
+ return Error::success();
+}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp b/contrib/llvm/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp
index 345e2a49..033585b 100644
--- a/contrib/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp
+++ b/contrib/llvm/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp
@@ -1,4 +1,5 @@
-//===-- TypeDumper.cpp - CodeView type info dumper --------------*- C++ -*-===//
+//===-- TypeDumpVisitor.cpp - CodeView type info dumper -----------*- C++
+//-*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,63 +8,23 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/DebugInfo/CodeView/TypeDumper.h"
+#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
+
#include "llvm/ADT/SmallString.h"
+#include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
+#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/CodeView/ByteStream.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
+#include "llvm/DebugInfo/MSF/ByteStream.h"
#include "llvm/Support/ScopedPrinter.h"
using namespace llvm;
using namespace llvm::codeview;
-/// The names here all end in "*". If the simple type is a pointer type, we
-/// return the whole name. Otherwise we lop off the last character in our
-/// StringRef.
-static const EnumEntry<SimpleTypeKind> SimpleTypeNames[] = {
- {"void*", SimpleTypeKind::Void},
- {"<not translated>*", SimpleTypeKind::NotTranslated},
- {"HRESULT*", SimpleTypeKind::HResult},
- {"signed char*", SimpleTypeKind::SignedCharacter},
- {"unsigned char*", SimpleTypeKind::UnsignedCharacter},
- {"char*", SimpleTypeKind::NarrowCharacter},
- {"wchar_t*", SimpleTypeKind::WideCharacter},
- {"char16_t*", SimpleTypeKind::Character16},
- {"char32_t*", SimpleTypeKind::Character32},
- {"__int8*", SimpleTypeKind::SByte},
- {"unsigned __int8*", SimpleTypeKind::Byte},
- {"short*", SimpleTypeKind::Int16Short},
- {"unsigned short*", SimpleTypeKind::UInt16Short},
- {"__int16*", SimpleTypeKind::Int16},
- {"unsigned __int16*", SimpleTypeKind::UInt16},
- {"long*", SimpleTypeKind::Int32Long},
- {"unsigned long*", SimpleTypeKind::UInt32Long},
- {"int*", SimpleTypeKind::Int32},
- {"unsigned*", SimpleTypeKind::UInt32},
- {"__int64*", SimpleTypeKind::Int64Quad},
- {"unsigned __int64*", SimpleTypeKind::UInt64Quad},
- {"__int64*", SimpleTypeKind::Int64},
- {"unsigned __int64*", SimpleTypeKind::UInt64},
- {"__int128*", SimpleTypeKind::Int128},
- {"unsigned __int128*", SimpleTypeKind::UInt128},
- {"__half*", SimpleTypeKind::Float16},
- {"float*", SimpleTypeKind::Float32},
- {"float*", SimpleTypeKind::Float32PartialPrecision},
- {"__float48*", SimpleTypeKind::Float48},
- {"double*", SimpleTypeKind::Float64},
- {"long double*", SimpleTypeKind::Float80},
- {"__float128*", SimpleTypeKind::Float128},
- {"_Complex float*", SimpleTypeKind::Complex32},
- {"_Complex double*", SimpleTypeKind::Complex64},
- {"_Complex long double*", SimpleTypeKind::Complex80},
- {"_Complex __float128*", SimpleTypeKind::Complex128},
- {"bool*", SimpleTypeKind::Boolean8},
- {"__bool16*", SimpleTypeKind::Boolean16},
- {"__bool32*", SimpleTypeKind::Boolean32},
- {"__bool64*", SimpleTypeKind::Boolean64},
-};
-
static const EnumEntry<TypeLeafKind> LeafTypeNames[] = {
#define CV_TYPE(enum, val) {#enum, enum},
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
@@ -88,10 +49,8 @@ static const EnumEntry<uint16_t> ClassOptionNames[] = {
};
static const EnumEntry<uint8_t> MemberAccessNames[] = {
- ENUM_ENTRY(MemberAccess, None),
- ENUM_ENTRY(MemberAccess, Private),
- ENUM_ENTRY(MemberAccess, Protected),
- ENUM_ENTRY(MemberAccess, Public),
+ ENUM_ENTRY(MemberAccess, None), ENUM_ENTRY(MemberAccess, Private),
+ ENUM_ENTRY(MemberAccess, Protected), ENUM_ENTRY(MemberAccess, Public),
};
static const EnumEntry<uint16_t> MethodOptionNames[] = {
@@ -149,8 +108,7 @@ static const EnumEntry<uint16_t> PtrMemberRepNames[] = {
};
static const EnumEntry<uint16_t> TypeModifierNames[] = {
- ENUM_ENTRY(ModifierOptions, Const),
- ENUM_ENTRY(ModifierOptions, Volatile),
+ ENUM_ENTRY(ModifierOptions, Const), ENUM_ENTRY(ModifierOptions, Volatile),
ENUM_ENTRY(ModifierOptions, Unaligned),
};
@@ -195,34 +153,46 @@ static StringRef getLeafTypeName(TypeLeafKind LT) {
case ename: \
return #name;
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
- case LF_FIELDLIST:
- return "FieldList";
default:
break;
}
return "UnknownLeaf";
}
-Error CVTypeDumper::visitTypeBegin(const CVRecord<TypeLeafKind> &Record) {
- // Reset Name to the empty string. If the visitor sets it, we know it.
- Name = "";
+void TypeDumpVisitor::printTypeIndex(StringRef FieldName, TypeIndex TI) const {
+ CVTypeDumper::printTypeIndex(*W, FieldName, TI, TypeDB);
+}
- W->startLine() << getLeafTypeName(Record.Type) << " ("
- << HexNumber(getNextTypeIndex()) << ") {\n";
+Error TypeDumpVisitor::visitTypeBegin(CVType &Record) {
+ W->startLine() << getLeafTypeName(Record.Type);
+ W->getOStream() << " (" << HexNumber(TypeDB.getNextTypeIndex().getIndex())
+ << ")";
+ W->getOStream() << " {\n";
W->indent();
W->printEnum("TypeLeafKind", unsigned(Record.Type),
makeArrayRef(LeafTypeNames));
return Error::success();
}
-Error CVTypeDumper::visitTypeEnd(const CVRecord<TypeLeafKind> &Record) {
- if (Record.Type == LF_FIELDLIST)
- Name = "<field list>";
+Error TypeDumpVisitor::visitTypeEnd(CVType &Record) {
+ if (PrintRecordBytes)
+ W->printBinaryBlock("LeafData", getBytesAsCharacters(Record.content()));
- // Always record some name for every type, even if Name is empty. CVUDTNames
- // is indexed by type index, and must have one entry for every type.
- recordType(Name);
+ W->unindent();
+ W->startLine() << "}\n";
+ return Error::success();
+}
+Error TypeDumpVisitor::visitMemberBegin(CVMemberRecord &Record) {
+ W->startLine() << getLeafTypeName(Record.Kind);
+ W->getOStream() << " {\n";
+ W->indent();
+ W->printEnum("TypeLeafKind", unsigned(Record.Kind),
+ makeArrayRef(LeafTypeNames));
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitMemberEnd(CVMemberRecord &Record) {
if (PrintRecordBytes)
W->printBinaryBlock("LeafData", getBytesAsCharacters(Record.Data));
@@ -231,33 +201,33 @@ Error CVTypeDumper::visitTypeEnd(const CVRecord<TypeLeafKind> &Record) {
return Error::success();
}
-Error CVTypeDumper::visitStringId(StringIdRecord &String) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ FieldListRecord &FieldList) {
+ CVTypeVisitor Visitor(*this);
+ if (auto EC = Visitor.visitFieldListMemberStream(FieldList.Data))
+ return EC;
+
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, StringIdRecord &String) {
printTypeIndex("Id", String.getId());
W->printString("StringData", String.getString());
- // Put this in CVUDTNames so it gets printed with LF_UDT_SRC_LINE.
- Name = String.getString();
return Error::success();
}
-Error CVTypeDumper::visitArgList(ArgListRecord &Args) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ArgListRecord &Args) {
auto Indices = Args.getIndices();
uint32_t Size = Indices.size();
W->printNumber("NumArgs", Size);
ListScope Arguments(*W, "Arguments");
- SmallString<256> TypeName("(");
for (uint32_t I = 0; I < Size; ++I) {
printTypeIndex("ArgType", Indices[I]);
- StringRef ArgTypeName = getTypeName(Indices[I]);
- TypeName.append(ArgTypeName);
- if (I + 1 != Size)
- TypeName.append(", ");
}
- TypeName.push_back(')');
- Name = saveName(TypeName);
return Error::success();
}
-Error CVTypeDumper::visitClass(ClassRecord &Class) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ClassRecord &Class) {
uint16_t Props = static_cast<uint16_t>(Class.getOptions());
W->printNumber("MemberCount", Class.getMemberCount());
W->printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
@@ -268,11 +238,10 @@ Error CVTypeDumper::visitClass(ClassRecord &Class) {
W->printString("Name", Class.getName());
if (Props & uint16_t(ClassOptions::HasUniqueName))
W->printString("LinkageName", Class.getUniqueName());
- Name = Class.getName();
return Error::success();
}
-Error CVTypeDumper::visitUnion(UnionRecord &Union) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, UnionRecord &Union) {
uint16_t Props = static_cast<uint16_t>(Union.getOptions());
W->printNumber("MemberCount", Union.getMemberCount());
W->printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
@@ -281,11 +250,10 @@ Error CVTypeDumper::visitUnion(UnionRecord &Union) {
W->printString("Name", Union.getName());
if (Props & uint16_t(ClassOptions::HasUniqueName))
W->printString("LinkageName", Union.getUniqueName());
- Name = Union.getName();
return Error::success();
}
-Error CVTypeDumper::visitEnum(EnumRecord &Enum) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, EnumRecord &Enum) {
uint16_t Props = static_cast<uint16_t>(Enum.getOptions());
W->printNumber("NumEnumerators", Enum.getMemberCount());
W->printFlags("Properties", uint16_t(Enum.getOptions()),
@@ -295,39 +263,35 @@ Error CVTypeDumper::visitEnum(EnumRecord &Enum) {
W->printString("Name", Enum.getName());
if (Props & uint16_t(ClassOptions::HasUniqueName))
W->printString("LinkageName", Enum.getUniqueName());
- Name = Enum.getName();
return Error::success();
}
-Error CVTypeDumper::visitArray(ArrayRecord &AT) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ArrayRecord &AT) {
printTypeIndex("ElementType", AT.getElementType());
printTypeIndex("IndexType", AT.getIndexType());
W->printNumber("SizeOf", AT.getSize());
W->printString("Name", AT.getName());
- Name = AT.getName();
return Error::success();
}
-Error CVTypeDumper::visitVFTable(VFTableRecord &VFT) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, VFTableRecord &VFT) {
printTypeIndex("CompleteClass", VFT.getCompleteClass());
printTypeIndex("OverriddenVFTable", VFT.getOverriddenVTable());
W->printHex("VFPtrOffset", VFT.getVFPtrOffset());
W->printString("VFTableName", VFT.getName());
for (auto N : VFT.getMethodNames())
W->printString("MethodName", N);
- Name = VFT.getName();
return Error::success();
}
-Error CVTypeDumper::visitMemberFuncId(MemberFuncIdRecord &Id) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, MemberFuncIdRecord &Id) {
printTypeIndex("ClassType", Id.getClassType());
printTypeIndex("FunctionType", Id.getFunctionType());
W->printString("Name", Id.getName());
- Name = Id.getName();
return Error::success();
}
-Error CVTypeDumper::visitProcedure(ProcedureRecord &Proc) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ProcedureRecord &Proc) {
printTypeIndex("ReturnType", Proc.getReturnType());
W->printEnum("CallingConvention", uint8_t(Proc.getCallConv()),
makeArrayRef(CallingConventions));
@@ -335,17 +299,10 @@ Error CVTypeDumper::visitProcedure(ProcedureRecord &Proc) {
makeArrayRef(FunctionOptionEnum));
W->printNumber("NumParameters", Proc.getParameterCount());
printTypeIndex("ArgListType", Proc.getArgumentList());
-
- StringRef ReturnTypeName = getTypeName(Proc.getReturnType());
- StringRef ArgListTypeName = getTypeName(Proc.getArgumentList());
- SmallString<256> TypeName(ReturnTypeName);
- TypeName.push_back(' ');
- TypeName.append(ArgListTypeName);
- Name = saveName(TypeName);
return Error::success();
}
-Error CVTypeDumper::visitMemberFunction(MemberFunctionRecord &MF) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, MemberFunctionRecord &MF) {
printTypeIndex("ReturnType", MF.getReturnType());
printTypeIndex("ClassType", MF.getClassType());
printTypeIndex("ThisType", MF.getThisType());
@@ -356,24 +313,14 @@ Error CVTypeDumper::visitMemberFunction(MemberFunctionRecord &MF) {
W->printNumber("NumParameters", MF.getParameterCount());
printTypeIndex("ArgListType", MF.getArgumentList());
W->printNumber("ThisAdjustment", MF.getThisPointerAdjustment());
-
- StringRef ReturnTypeName = getTypeName(MF.getReturnType());
- StringRef ClassTypeName = getTypeName(MF.getClassType());
- StringRef ArgListTypeName = getTypeName(MF.getArgumentList());
- SmallString<256> TypeName(ReturnTypeName);
- TypeName.push_back(' ');
- TypeName.append(ClassTypeName);
- TypeName.append("::");
- TypeName.append(ArgListTypeName);
- Name = saveName(TypeName);
return Error::success();
}
-Error CVTypeDumper::visitMethodOverloadList(
- MethodOverloadListRecord &MethodList) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ MethodOverloadListRecord &MethodList) {
for (auto &M : MethodList.getMethods()) {
ListScope S(*W, "Method");
- printMemberAttributes(M.getAccess(), M.getKind(), M.getOptions());
+ printMemberAttributes(M.getAccess(), M.getMethodKind(), M.getOptions());
printTypeIndex("Type", M.getType());
if (M.isIntroducingVirtual())
W->printHex("VFTableOffset", M.getVFTableOffset());
@@ -381,23 +328,21 @@ Error CVTypeDumper::visitMethodOverloadList(
return Error::success();
}
-Error CVTypeDumper::visitFuncId(FuncIdRecord &Func) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) {
printTypeIndex("ParentScope", Func.getParentScope());
printTypeIndex("FunctionType", Func.getFunctionType());
W->printString("Name", Func.getName());
- Name = Func.getName();
return Error::success();
}
-Error CVTypeDumper::visitTypeServer2(TypeServer2Record &TS) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, TypeServer2Record &TS) {
W->printBinary("Signature", TS.getGuid());
W->printNumber("Age", TS.getAge());
W->printString("Name", TS.getName());
- Name = TS.getName();
return Error::success();
}
-Error CVTypeDumper::visitPointer(PointerRecord &Ptr) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) {
printTypeIndex("PointeeType", Ptr.getReferentType());
W->printHex("PointerAttributes", uint32_t(Ptr.getOptions()));
W->printEnum("PtrType", unsigned(Ptr.getPointerKind()),
@@ -416,76 +361,42 @@ Error CVTypeDumper::visitPointer(PointerRecord &Ptr) {
printTypeIndex("ClassType", MI.getContainingType());
W->printEnum("Representation", uint16_t(MI.getRepresentation()),
makeArrayRef(PtrMemberRepNames));
-
- StringRef PointeeName = getTypeName(Ptr.getReferentType());
- StringRef ClassName = getTypeName(MI.getContainingType());
- SmallString<256> TypeName(PointeeName);
- TypeName.push_back(' ');
- TypeName.append(ClassName);
- TypeName.append("::*");
- Name = saveName(TypeName);
- } else {
- SmallString<256> TypeName;
- if (Ptr.isConst())
- TypeName.append("const ");
- if (Ptr.isVolatile())
- TypeName.append("volatile ");
- if (Ptr.isUnaligned())
- TypeName.append("__unaligned ");
-
- TypeName.append(getTypeName(Ptr.getReferentType()));
-
- if (Ptr.getMode() == PointerMode::LValueReference)
- TypeName.append("&");
- else if (Ptr.getMode() == PointerMode::RValueReference)
- TypeName.append("&&");
- else if (Ptr.getMode() == PointerMode::Pointer)
- TypeName.append("*");
-
- if (!TypeName.empty())
- Name = saveName(TypeName);
}
+
return Error::success();
}
-Error CVTypeDumper::visitModifier(ModifierRecord &Mod) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) {
uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers());
printTypeIndex("ModifiedType", Mod.getModifiedType());
W->printFlags("Modifiers", Mods, makeArrayRef(TypeModifierNames));
- StringRef ModifiedName = getTypeName(Mod.getModifiedType());
- SmallString<256> TypeName;
- if (Mods & uint16_t(ModifierOptions::Const))
- TypeName.append("const ");
- if (Mods & uint16_t(ModifierOptions::Volatile))
- TypeName.append("volatile ");
- if (Mods & uint16_t(ModifierOptions::Unaligned))
- TypeName.append("__unaligned ");
- TypeName.append(ModifiedName);
- Name = saveName(TypeName);
return Error::success();
}
-Error CVTypeDumper::visitBitField(BitFieldRecord &BitField) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, BitFieldRecord &BitField) {
printTypeIndex("Type", BitField.getType());
W->printNumber("BitSize", BitField.getBitSize());
W->printNumber("BitOffset", BitField.getBitOffset());
return Error::success();
}
-Error CVTypeDumper::visitVFTableShape(VFTableShapeRecord &Shape) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ VFTableShapeRecord &Shape) {
W->printNumber("VFEntryCount", Shape.getEntryCount());
return Error::success();
}
-Error CVTypeDumper::visitUdtSourceLine(UdtSourceLineRecord &Line) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ UdtSourceLineRecord &Line) {
printTypeIndex("UDT", Line.getUDT());
printTypeIndex("SourceFile", Line.getSourceFile());
W->printNumber("LineNumber", Line.getLineNumber());
return Error::success();
}
-Error CVTypeDumper::visitUdtModSourceLine(UdtModSourceLineRecord &Line) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ UdtModSourceLineRecord &Line) {
printTypeIndex("UDT", Line.getUDT());
printTypeIndex("SourceFile", Line.getSourceFile());
W->printNumber("LineNumber", Line.getLineNumber());
@@ -493,7 +404,7 @@ Error CVTypeDumper::visitUdtModSourceLine(UdtModSourceLineRecord &Line) {
return Error::success();
}
-Error CVTypeDumper::visitBuildInfo(BuildInfoRecord &Args) {
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, BuildInfoRecord &Args) {
W->printNumber("NumArgs", static_cast<uint32_t>(Args.getArgs().size()));
ListScope Arguments(*W, "Arguments");
@@ -503,13 +414,14 @@ Error CVTypeDumper::visitBuildInfo(BuildInfoRecord &Args) {
return Error::success();
}
-void CVTypeDumper::printMemberAttributes(MemberAttributes Attrs) {
+void TypeDumpVisitor::printMemberAttributes(MemberAttributes Attrs) {
return printMemberAttributes(Attrs.getAccess(), Attrs.getMethodKind(),
Attrs.getFlags());
}
-void CVTypeDumper::printMemberAttributes(MemberAccess Access, MethodKind Kind,
- MethodOptions Options) {
+void TypeDumpVisitor::printMemberAttributes(MemberAccess Access,
+ MethodKind Kind,
+ MethodOptions Options) {
W->printEnum("AccessSpecifier", uint8_t(Access),
makeArrayRef(MemberAccessNames));
// Data members will be vanilla. Don't try to print a method kind for them.
@@ -521,87 +433,80 @@ void CVTypeDumper::printMemberAttributes(MemberAccess Access, MethodKind Kind,
}
}
-Error CVTypeDumper::visitUnknownMember(const CVRecord<TypeLeafKind> &Record) {
- W->printHex("UnknownMember", unsigned(Record.Type));
+Error TypeDumpVisitor::visitUnknownMember(CVMemberRecord &Record) {
+ W->printHex("UnknownMember", unsigned(Record.Kind));
return Error::success();
}
-Error CVTypeDumper::visitUnknownType(const CVRecord<TypeLeafKind> &Record) {
- DictScope S(*W, "UnknownType");
- W->printEnum("Kind", uint16_t(Record.Type), makeArrayRef(LeafTypeNames));
- W->printNumber("Length", uint32_t(Record.Data.size()));
+Error TypeDumpVisitor::visitUnknownType(CVType &Record) {
+ W->printEnum("Kind", uint16_t(Record.kind()), makeArrayRef(LeafTypeNames));
+ W->printNumber("Length", uint32_t(Record.content().size()));
return Error::success();
}
-Error CVTypeDumper::visitNestedType(NestedTypeRecord &Nested) {
- DictScope S(*W, "NestedType");
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ NestedTypeRecord &Nested) {
printTypeIndex("Type", Nested.getNestedType());
W->printString("Name", Nested.getName());
- Name = Nested.getName();
return Error::success();
}
-Error CVTypeDumper::visitOneMethod(OneMethodRecord &Method) {
- DictScope S(*W, "OneMethod");
- MethodKind K = Method.getKind();
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ OneMethodRecord &Method) {
+ MethodKind K = Method.getMethodKind();
printMemberAttributes(Method.getAccess(), K, Method.getOptions());
printTypeIndex("Type", Method.getType());
// If virtual, then read the vftable offset.
if (Method.isIntroducingVirtual())
W->printHex("VFTableOffset", Method.getVFTableOffset());
W->printString("Name", Method.getName());
- Name = Method.getName();
return Error::success();
}
-Error CVTypeDumper::visitOverloadedMethod(OverloadedMethodRecord &Method) {
- DictScope S(*W, "OverloadedMethod");
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ OverloadedMethodRecord &Method) {
W->printHex("MethodCount", Method.getNumOverloads());
printTypeIndex("MethodListIndex", Method.getMethodList());
W->printString("Name", Method.getName());
- Name = Method.getName();
return Error::success();
}
-Error CVTypeDumper::visitDataMember(DataMemberRecord &Field) {
- DictScope S(*W, "DataMember");
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ DataMemberRecord &Field) {
printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
MethodOptions::None);
printTypeIndex("Type", Field.getType());
W->printHex("FieldOffset", Field.getFieldOffset());
W->printString("Name", Field.getName());
- Name = Field.getName();
return Error::success();
}
-Error CVTypeDumper::visitStaticDataMember(StaticDataMemberRecord &Field) {
- DictScope S(*W, "StaticDataMember");
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ StaticDataMemberRecord &Field) {
printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
MethodOptions::None);
printTypeIndex("Type", Field.getType());
W->printString("Name", Field.getName());
- Name = Field.getName();
return Error::success();
}
-Error CVTypeDumper::visitVFPtr(VFPtrRecord &VFTable) {
- DictScope S(*W, "VFPtr");
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ VFPtrRecord &VFTable) {
printTypeIndex("Type", VFTable.getType());
return Error::success();
}
-Error CVTypeDumper::visitEnumerator(EnumeratorRecord &Enum) {
- DictScope S(*W, "Enumerator");
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ EnumeratorRecord &Enum) {
printMemberAttributes(Enum.getAccess(), MethodKind::Vanilla,
MethodOptions::None);
W->printNumber("EnumValue", Enum.getValue());
W->printString("Name", Enum.getName());
- Name = Enum.getName();
return Error::success();
}
-Error CVTypeDumper::visitBaseClass(BaseClassRecord &Base) {
- DictScope S(*W, "BaseClass");
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ BaseClassRecord &Base) {
printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
MethodOptions::None);
printTypeIndex("BaseType", Base.getBaseType());
@@ -609,8 +514,8 @@ Error CVTypeDumper::visitBaseClass(BaseClassRecord &Base) {
return Error::success();
}
-Error CVTypeDumper::visitVirtualBaseClass(VirtualBaseClassRecord &Base) {
- DictScope S(*W, "VirtualBaseClass");
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ VirtualBaseClassRecord &Base) {
printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
MethodOptions::None);
printTypeIndex("BaseType", Base.getBaseType());
@@ -620,77 +525,8 @@ Error CVTypeDumper::visitVirtualBaseClass(VirtualBaseClassRecord &Base) {
return Error::success();
}
-Error CVTypeDumper::visitListContinuation(ListContinuationRecord &Cont) {
- DictScope S(*W, "ListContinuation");
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ ListContinuationRecord &Cont) {
printTypeIndex("ContinuationIndex", Cont.getContinuationIndex());
return Error::success();
}
-
-StringRef CVTypeDumper::getTypeName(TypeIndex TI) {
- if (TI.isNoneType())
- return "<no type>";
-
- if (TI.isSimple()) {
- // This is a simple type.
- for (const auto &SimpleTypeName : SimpleTypeNames) {
- if (SimpleTypeName.Value == TI.getSimpleKind()) {
- if (TI.getSimpleMode() == SimpleTypeMode::Direct)
- return SimpleTypeName.Name.drop_back(1);
- // Otherwise, this is a pointer type. We gloss over the distinction
- // between near, far, 64, 32, etc, and just give a pointer type.
- return SimpleTypeName.Name;
- }
- }
- return "<unknown simple type>";
- }
-
- // User-defined type.
- StringRef UDTName;
- unsigned UDTIndex = TI.getIndex() - 0x1000;
- if (UDTIndex < CVUDTNames.size())
- return CVUDTNames[UDTIndex];
-
- return "<unknown UDT>";
-}
-
-void CVTypeDumper::printTypeIndex(StringRef FieldName, TypeIndex TI) {
- StringRef TypeName;
- if (!TI.isNoneType())
- TypeName = getTypeName(TI);
- if (!TypeName.empty())
- W->printHex(FieldName, TypeName, TI.getIndex());
- else
- W->printHex(FieldName, TI.getIndex());
-}
-
-Error CVTypeDumper::dump(const CVRecord<TypeLeafKind> &Record) {
- assert(W && "printer should not be null");
- CVTypeVisitor Visitor(*this);
-
- if (auto EC = Visitor.visitTypeRecord(Record))
- return EC;
- return Error::success();
-}
-
-Error CVTypeDumper::dump(const CVTypeArray &Types) {
- assert(W && "printer should not be null");
- CVTypeVisitor Visitor(*this);
- if (auto EC = Visitor.visitTypeStream(Types))
- return EC;
- return Error::success();
-}
-
-Error CVTypeDumper::dump(ArrayRef<uint8_t> Data) {
- ByteStream<> Stream(Data);
- CVTypeArray Types;
- StreamReader Reader(Stream);
- if (auto EC = Reader.readArray(Types, Reader.getLength()))
- return EC;
-
- return dump(Types);
-}
-
-void CVTypeDumper::setPrinter(ScopedPrinter *P) {
- static ScopedPrinter NullP(llvm::nulls());
- W = P ? P : &NullP;
-}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp b/contrib/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp
index f63371e..b951c06 100644
--- a/contrib/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp
+++ b/contrib/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp
@@ -8,374 +8,15 @@
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/DebugInfo/MSF/ByteStream.h"
+#include "llvm/DebugInfo/MSF/StreamReader.h"
using namespace llvm;
using namespace llvm::codeview;
//===----------------------------------------------------------------------===//
-// Type record deserialization
-//===----------------------------------------------------------------------===//
-
-ErrorOr<MemberPointerInfo>
-MemberPointerInfo::deserialize(ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- if (auto EC = consumeObject(Data, L))
- return EC;
-
- TypeIndex T = L->ClassType;
- uint16_t R = L->Representation;
- PointerToMemberRepresentation PMR =
- static_cast<PointerToMemberRepresentation>(R);
- return MemberPointerInfo(T, PMR);
-}
-
-ErrorOr<ModifierRecord> ModifierRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- if (auto EC = consumeObject(Data, L))
- return EC;
-
- TypeIndex M = L->ModifiedType;
- uint16_t O = L->Modifiers;
- ModifierOptions MO = static_cast<ModifierOptions>(O);
- return ModifierRecord(M, MO);
-}
-
-ErrorOr<ProcedureRecord> ProcedureRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- if (auto EC = consumeObject(Data, L))
- return EC;
- return ProcedureRecord(L->ReturnType, L->CallConv, L->Options,
- L->NumParameters, L->ArgListType);
-}
-
-ErrorOr<MemberFunctionRecord>
-MemberFunctionRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- CV_DESERIALIZE(Data, L);
- return MemberFunctionRecord(L->ReturnType, L->ClassType, L->ThisType,
- L->CallConv, L->Options, L->NumParameters,
- L->ArgListType, L->ThisAdjustment);
-}
-
-ErrorOr<MemberFuncIdRecord>
-MemberFuncIdRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- StringRef Name;
- CV_DESERIALIZE(Data, L, Name);
- return MemberFuncIdRecord(L->ClassType, L->FunctionType, Name);
-}
-
-ErrorOr<ArgListRecord> ArgListRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- if (Kind != TypeRecordKind::StringList && Kind != TypeRecordKind::ArgList)
- return std::make_error_code(std::errc::illegal_byte_sequence);
-
- const Layout *L = nullptr;
- ArrayRef<TypeIndex> Indices;
- CV_DESERIALIZE(Data, L, CV_ARRAY_FIELD_N(Indices, L->NumArgs));
- return ArgListRecord(Kind, Indices);
-}
-
-ErrorOr<PointerRecord> PointerRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- if (auto EC = consumeObject(Data, L))
- return EC;
-
- PointerKind PtrKind = L->getPtrKind();
- PointerMode Mode = L->getPtrMode();
- uint32_t Opts = L->Attrs;
- PointerOptions Options = static_cast<PointerOptions>(Opts);
- uint8_t Size = L->getPtrSize();
-
- if (L->isPointerToMember()) {
- auto E = MemberPointerInfo::deserialize(Data);
- if (E.getError())
- return std::make_error_code(std::errc::illegal_byte_sequence);
- return PointerRecord(L->PointeeType, PtrKind, Mode, Options, Size, *E);
- }
-
- return PointerRecord(L->PointeeType, PtrKind, Mode, Options, Size);
-}
-
-ErrorOr<NestedTypeRecord>
-NestedTypeRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- StringRef Name;
- CV_DESERIALIZE(Data, L, Name);
- return NestedTypeRecord(L->Type, Name);
-}
-
-ErrorOr<ArrayRecord> ArrayRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- uint64_t Size;
- StringRef Name;
- CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Size), Name);
- return ArrayRecord(L->ElementType, L->IndexType, Size, Name);
-}
-
-ErrorOr<ClassRecord> ClassRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- uint64_t Size = 0;
- StringRef Name;
- StringRef UniqueName;
- uint16_t Props;
- const Layout *L = nullptr;
-
- CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Size), Name,
- CV_CONDITIONAL_FIELD(UniqueName, L->hasUniqueName()));
-
- Props = L->Properties;
- uint16_t WrtValue = (Props & WinRTKindMask) >> WinRTKindShift;
- WindowsRTClassKind WRT = static_cast<WindowsRTClassKind>(WrtValue);
- uint16_t HfaMask = (Props & HfaKindMask) >> HfaKindShift;
- HfaKind Hfa = static_cast<HfaKind>(HfaMask);
-
- ClassOptions Options = static_cast<ClassOptions>(Props);
- return ClassRecord(Kind, L->MemberCount, Options, Hfa, WRT, L->FieldList,
- L->DerivedFrom, L->VShape, Size, Name, UniqueName);
-}
-
-ErrorOr<UnionRecord> UnionRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- uint64_t Size = 0;
- StringRef Name;
- StringRef UniqueName;
- uint16_t Props;
-
- const Layout *L = nullptr;
- CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Size), Name,
- CV_CONDITIONAL_FIELD(UniqueName, L->hasUniqueName()));
-
- Props = L->Properties;
-
- uint16_t HfaMask = (Props & HfaKindMask) >> HfaKindShift;
- HfaKind Hfa = static_cast<HfaKind>(HfaMask);
- ClassOptions Options = static_cast<ClassOptions>(Props);
- return UnionRecord(L->MemberCount, Options, Hfa, L->FieldList, Size, Name,
- UniqueName);
-}
-
-ErrorOr<EnumRecord> EnumRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- StringRef Name;
- StringRef UniqueName;
- CV_DESERIALIZE(Data, L, Name,
- CV_CONDITIONAL_FIELD(UniqueName, L->hasUniqueName()));
-
- uint16_t P = L->Properties;
- ClassOptions Options = static_cast<ClassOptions>(P);
- return EnumRecord(L->NumEnumerators, Options, L->FieldListType, Name,
- UniqueName, L->UnderlyingType);
-}
-
-ErrorOr<BitFieldRecord> BitFieldRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- CV_DESERIALIZE(Data, L);
- return BitFieldRecord(L->Type, L->BitSize, L->BitOffset);
-}
-
-ErrorOr<VFTableShapeRecord>
-VFTableShapeRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- if (auto EC = consumeObject(Data, L))
- return EC;
-
- std::vector<VFTableSlotKind> Slots;
- uint16_t Count = L->VFEntryCount;
- while (Count > 0) {
- if (Data.empty())
- return std::make_error_code(std::errc::illegal_byte_sequence);
-
- // Process up to 2 nibbles at a time (if there are at least 2 remaining)
- uint8_t Value = Data[0] & 0x0F;
- Slots.push_back(static_cast<VFTableSlotKind>(Value));
- if (--Count > 0) {
- Value = (Data[0] & 0xF0) >> 4;
- Slots.push_back(static_cast<VFTableSlotKind>(Value));
- --Count;
- }
- Data = Data.slice(1);
- }
-
- return VFTableShapeRecord(Slots);
-}
-
-ErrorOr<TypeServer2Record>
-TypeServer2Record::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- StringRef Name;
- CV_DESERIALIZE(Data, L, Name);
- return TypeServer2Record(StringRef(L->Guid, 16), L->Age, Name);
-}
-
-ErrorOr<StringIdRecord> StringIdRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- StringRef Name;
- CV_DESERIALIZE(Data, L, Name);
- return StringIdRecord(L->id, Name);
-}
-
-ErrorOr<FuncIdRecord> FuncIdRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- StringRef Name;
- CV_DESERIALIZE(Data, L, Name);
- return FuncIdRecord(L->ParentScope, L->FunctionType, Name);
-}
-
-ErrorOr<UdtSourceLineRecord>
-UdtSourceLineRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- CV_DESERIALIZE(Data, L);
- return UdtSourceLineRecord(L->UDT, L->SourceFile, L->LineNumber);
-}
-
-ErrorOr<BuildInfoRecord> BuildInfoRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- ArrayRef<TypeIndex> Indices;
- CV_DESERIALIZE(Data, L, CV_ARRAY_FIELD_N(Indices, L->NumArgs));
- return BuildInfoRecord(Indices);
-}
-
-ErrorOr<VFTableRecord> VFTableRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- StringRef Name;
- std::vector<StringRef> Names;
- CV_DESERIALIZE(Data, L, Name, CV_ARRAY_FIELD_TAIL(Names));
- return VFTableRecord(L->CompleteClass, L->OverriddenVFTable, L->VFPtrOffset,
- Name, Names);
-}
-
-ErrorOr<OneMethodRecord> OneMethodRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- StringRef Name;
- int32_t VFTableOffset = -1;
-
- CV_DESERIALIZE(Data, L, CV_CONDITIONAL_FIELD(VFTableOffset,
- L->Attrs.isIntroducedVirtual()),
- Name);
-
- MethodOptions Options = L->Attrs.getFlags();
- MethodKind MethKind = L->Attrs.getMethodKind();
- MemberAccess Access = L->Attrs.getAccess();
- OneMethodRecord Method(L->Type, MethKind, Options, Access, VFTableOffset,
- Name);
- // Validate the vftable offset.
- if (Method.isIntroducingVirtual() && Method.getVFTableOffset() < 0)
- return std::make_error_code(std::errc::illegal_byte_sequence);
- return Method;
-}
-
-ErrorOr<MethodOverloadListRecord>
-MethodOverloadListRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- std::vector<OneMethodRecord> Methods;
- while (!Data.empty()) {
- const Layout *L = nullptr;
- int32_t VFTableOffset = -1;
- CV_DESERIALIZE(Data, L, CV_CONDITIONAL_FIELD(
- VFTableOffset, L->Attrs.isIntroducedVirtual()));
-
- MethodOptions Options = L->Attrs.getFlags();
- MethodKind MethKind = L->Attrs.getMethodKind();
- MemberAccess Access = L->Attrs.getAccess();
-
- Methods.emplace_back(L->Type, MethKind, Options, Access, VFTableOffset,
- StringRef());
-
- // Validate the vftable offset.
- auto &Method = Methods.back();
- if (Method.isIntroducingVirtual() && Method.getVFTableOffset() < 0)
- return std::make_error_code(std::errc::illegal_byte_sequence);
- }
- return MethodOverloadListRecord(Methods);
-}
-
-ErrorOr<OverloadedMethodRecord>
-OverloadedMethodRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- StringRef Name;
- CV_DESERIALIZE(Data, L, Name);
- return OverloadedMethodRecord(L->MethodCount, L->MethList, Name);
-}
-
-ErrorOr<DataMemberRecord>
-DataMemberRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- uint64_t Offset;
- StringRef Name;
- CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Offset), Name);
- return DataMemberRecord(L->Attrs.getAccess(), L->Type, Offset, Name);
-}
-
-ErrorOr<StaticDataMemberRecord>
-StaticDataMemberRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- StringRef Name;
- CV_DESERIALIZE(Data, L, Name);
- return StaticDataMemberRecord(L->Attrs.getAccess(), L->Type, Name);
-}
-
-ErrorOr<EnumeratorRecord>
-EnumeratorRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- APSInt Value;
- StringRef Name;
- CV_DESERIALIZE(Data, L, Value, Name);
- return EnumeratorRecord(L->Attrs.getAccess(), Value, Name);
-}
-
-ErrorOr<VFPtrRecord> VFPtrRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- if (auto EC = consumeObject(Data, L))
- return EC;
- return VFPtrRecord(L->Type);
-}
-
-ErrorOr<BaseClassRecord> BaseClassRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- uint64_t Offset;
- CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Offset));
- return BaseClassRecord(L->Attrs.getAccess(), L->BaseType, Offset);
-}
-
-ErrorOr<VirtualBaseClassRecord>
-VirtualBaseClassRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- uint64_t Offset;
- uint64_t Index;
- CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Offset), CV_NUMERIC_FIELD(Index));
- return VirtualBaseClassRecord(L->Attrs.getAccess(), L->BaseType, L->VBPtrType,
- Offset, Index);
-}
-
-ErrorOr<ListContinuationRecord>
-ListContinuationRecord::deserialize(TypeRecordKind Kind,
- ArrayRef<uint8_t> &Data) {
- const Layout *L = nullptr;
- CV_DESERIALIZE(Data, L);
- return ListContinuationRecord(L->ContinuationIndex);
-}
-
-//===----------------------------------------------------------------------===//
// Type index remapping
//===----------------------------------------------------------------------===//
@@ -437,7 +78,7 @@ bool PointerRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
bool Success = true;
Success &= remapIndex(IndexMap, ReferentType);
if (isPointerToMember())
- Success &= MemberInfo.remapTypeIndices(IndexMap);
+ Success &= MemberInfo->remapTypeIndices(IndexMap);
return Success;
}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp b/contrib/llvm/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp
deleted file mode 100644
index 112612c..0000000
--- a/contrib/llvm/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-//===-- TypeRecordBuilder.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/TypeRecordBuilder.h"
-
-using namespace llvm;
-using namespace codeview;
-
-TypeRecordBuilder::TypeRecordBuilder(TypeRecordKind Kind)
- : Stream(Buffer), Writer(Stream) {
- writeTypeRecordKind(Kind);
-}
-
-StringRef TypeRecordBuilder::str() {
- return StringRef(Buffer.data(), Buffer.size());
-}
-
-void TypeRecordBuilder::writeUInt8(uint8_t Value) {
- Writer.write(Value);
-}
-
-void TypeRecordBuilder::writeInt16(int16_t Value) {
- Writer.write(Value);
-}
-
-void TypeRecordBuilder::writeUInt16(uint16_t Value) {
- Writer.write(Value);
-}
-
-void TypeRecordBuilder::writeInt32(int32_t Value) {
- Writer.write(Value);
-}
-
-void TypeRecordBuilder::writeUInt32(uint32_t Value) {
- Writer.write(Value);
-}
-
-void TypeRecordBuilder::writeInt64(int64_t Value) {
- Writer.write(Value);
-}
-
-void TypeRecordBuilder::writeUInt64(uint64_t Value) {
- Writer.write(Value);
-}
-
-void TypeRecordBuilder::writeEncodedInteger(int64_t Value) {
- if (Value >= 0) {
- writeEncodedUnsignedInteger(static_cast<uint64_t>(Value));
- } else {
- writeEncodedSignedInteger(Value);
- }
-}
-
-void TypeRecordBuilder::writeEncodedSignedInteger(int64_t Value) {
- if (Value >= std::numeric_limits<int8_t>::min() &&
- Value <= std::numeric_limits<int8_t>::max()) {
- writeUInt16(LF_CHAR);
- writeInt16(static_cast<int8_t>(Value));
- } else if (Value >= std::numeric_limits<int16_t>::min() &&
- Value <= std::numeric_limits<int16_t>::max()) {
- writeUInt16(LF_SHORT);
- writeInt16(static_cast<int16_t>(Value));
- } else if (Value >= std::numeric_limits<int32_t>::min() &&
- Value <= std::numeric_limits<int32_t>::max()) {
- writeUInt16(LF_LONG);
- writeInt32(static_cast<int32_t>(Value));
- } else {
- writeUInt16(LF_QUADWORD);
- writeInt64(Value);
- }
-}
-
-void TypeRecordBuilder::writeEncodedUnsignedInteger(uint64_t Value) {
- if (Value < LF_CHAR) {
- writeUInt16(static_cast<uint16_t>(Value));
- } else if (Value <= std::numeric_limits<uint16_t>::max()) {
- writeUInt16(LF_USHORT);
- writeUInt16(static_cast<uint16_t>(Value));
- } else if (Value <= std::numeric_limits<uint32_t>::max()) {
- writeUInt16(LF_ULONG);
- writeUInt32(static_cast<uint32_t>(Value));
- } else {
- writeUInt16(LF_UQUADWORD);
- writeUInt64(Value);
- }
-}
-
-void TypeRecordBuilder::writeNullTerminatedString(StringRef Value) {
- // Microsoft's linker seems to have trouble with symbol names longer than
- // 0xffd8 bytes.
- Value = Value.substr(0, 0xffd8);
- Stream.write(Value.data(), Value.size());
- writeUInt8(0);
-}
-
-void TypeRecordBuilder::writeGuid(StringRef Guid) {
- assert(Guid.size() == 16);
- Stream.write(Guid.data(), 16);
-}
-
-void TypeRecordBuilder::writeTypeIndex(TypeIndex TypeInd) {
- writeUInt32(TypeInd.getIndex());
-}
-
-void TypeRecordBuilder::writeTypeRecordKind(TypeRecordKind Kind) {
- writeUInt16(static_cast<uint16_t>(Kind));
-}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp b/contrib/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp
new file mode 100644
index 0000000..f46e08d
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp
@@ -0,0 +1,467 @@
+//===- TypeRecordMapping.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/TypeRecordMapping.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+#define error(X) \
+ if (auto EC = X) \
+ return EC;
+
+namespace {
+struct MapOneMethodRecord {
+ explicit MapOneMethodRecord(bool IsFromOverloadList)
+ : IsFromOverloadList(IsFromOverloadList) {}
+
+ Error operator()(CodeViewRecordIO &IO, OneMethodRecord &Method) const {
+ error(IO.mapInteger(Method.Attrs.Attrs));
+ if (IsFromOverloadList) {
+ uint16_t Padding = 0;
+ error(IO.mapInteger(Padding));
+ }
+ error(IO.mapInteger(Method.Type));
+ if (Method.isIntroducingVirtual()) {
+ error(IO.mapInteger(Method.VFTableOffset));
+ } else if (!IO.isWriting())
+ Method.VFTableOffset = -1;
+
+ if (!IsFromOverloadList)
+ error(IO.mapStringZ(Method.Name));
+
+ return Error::success();
+ }
+
+private:
+ bool IsFromOverloadList;
+};
+}
+
+static Error mapNameAndUniqueName(CodeViewRecordIO &IO, StringRef &Name,
+ StringRef &UniqueName, bool HasUniqueName) {
+ if (IO.isWriting()) {
+ // Try to be smart about what we write here. We can't write anything too
+ // large, so if we're going to go over the limit, truncate both the name
+ // and unique name by the same amount.
+ size_t BytesLeft = IO.maxFieldLength();
+ if (HasUniqueName) {
+ size_t BytesNeeded = Name.size() + UniqueName.size() + 2;
+ StringRef N = Name;
+ StringRef U = UniqueName;
+ if (BytesNeeded > BytesLeft) {
+ size_t BytesToDrop = (BytesNeeded - BytesLeft);
+ size_t DropN = std::min(N.size(), BytesToDrop / 2);
+ size_t DropU = std::min(U.size(), BytesToDrop - DropN);
+
+ N = N.drop_back(DropN);
+ U = U.drop_back(DropU);
+ }
+
+ error(IO.mapStringZ(N));
+ error(IO.mapStringZ(U));
+ } else {
+ size_t BytesNeeded = Name.size() + 1;
+ StringRef N = Name;
+ if (BytesNeeded > BytesLeft) {
+ size_t BytesToDrop = std::min(N.size(), BytesToDrop);
+ N = N.drop_back(BytesToDrop);
+ }
+ error(IO.mapStringZ(N));
+ }
+ } else {
+ error(IO.mapStringZ(Name));
+ if (HasUniqueName)
+ error(IO.mapStringZ(UniqueName));
+ }
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitTypeBegin(CVType &CVR) {
+ assert(!TypeKind.hasValue() && "Already in a type mapping!");
+ assert(!MemberKind.hasValue() && "Already in a member mapping!");
+
+ // FieldList and MethodList records can be any length because they can be
+ // split with continuation records. All other record types cannot be
+ // longer than the maximum record length.
+ Optional<uint32_t> MaxLen;
+ if (CVR.Type != TypeLeafKind::LF_FIELDLIST &&
+ CVR.Type != TypeLeafKind::LF_METHODLIST)
+ MaxLen = MaxRecordLength - sizeof(RecordPrefix);
+ error(IO.beginRecord(MaxLen));
+ TypeKind = CVR.Type;
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitTypeEnd(CVType &Record) {
+ assert(TypeKind.hasValue() && "Not in a type mapping!");
+ assert(!MemberKind.hasValue() && "Still in a member mapping!");
+
+ error(IO.endRecord());
+
+ TypeKind.reset();
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitMemberBegin(CVMemberRecord &Record) {
+ assert(TypeKind.hasValue() && "Not in a type mapping!");
+ assert(!MemberKind.hasValue() && "Already in a member mapping!");
+
+ // The largest possible subrecord is one in which there is a record prefix,
+ // followed by the subrecord, followed by a continuation, and that entire
+ // sequence spaws `MaxRecordLength` bytes. So the record's length is
+ // calculated as follows.
+ constexpr uint32_t ContinuationLength = 8;
+ error(IO.beginRecord(MaxRecordLength - sizeof(RecordPrefix) -
+ ContinuationLength));
+
+ MemberKind = Record.Kind;
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitMemberEnd(CVMemberRecord &Record) {
+ assert(TypeKind.hasValue() && "Not in a type mapping!");
+ assert(MemberKind.hasValue() && "Not in a member mapping!");
+
+ if (!IO.isWriting()) {
+ if (auto EC = IO.skipPadding())
+ return EC;
+ }
+
+ MemberKind.reset();
+ error(IO.endRecord());
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ModifierRecord &Record) {
+ error(IO.mapInteger(Record.ModifiedType));
+ error(IO.mapEnum(Record.Modifiers));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
+ ProcedureRecord &Record) {
+ error(IO.mapInteger(Record.ReturnType));
+ error(IO.mapEnum(Record.CallConv));
+ error(IO.mapEnum(Record.Options));
+ error(IO.mapInteger(Record.ParameterCount));
+ error(IO.mapInteger(Record.ArgumentList));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
+ MemberFunctionRecord &Record) {
+ error(IO.mapInteger(Record.ReturnType));
+ error(IO.mapInteger(Record.ClassType));
+ error(IO.mapInteger(Record.ThisType));
+ error(IO.mapEnum(Record.CallConv));
+ error(IO.mapEnum(Record.Options));
+ error(IO.mapInteger(Record.ParameterCount));
+ error(IO.mapInteger(Record.ArgumentList));
+ error(IO.mapInteger(Record.ThisPointerAdjustment));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ArgListRecord &Record) {
+ error(IO.mapVectorN<uint32_t>(
+ Record.StringIndices,
+ [](CodeViewRecordIO &IO, TypeIndex &N) { return IO.mapInteger(N); }));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR, PointerRecord &Record) {
+ error(IO.mapInteger(Record.ReferentType));
+ error(IO.mapInteger(Record.Attrs));
+
+ if (Record.isPointerToMember()) {
+ if (!IO.isWriting())
+ Record.MemberInfo.emplace();
+
+ MemberPointerInfo &M = *Record.MemberInfo;
+ error(IO.mapInteger(M.ContainingType));
+ error(IO.mapEnum(M.Representation));
+ }
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ArrayRecord &Record) {
+ error(IO.mapInteger(Record.ElementType));
+ error(IO.mapInteger(Record.IndexType));
+ error(IO.mapEncodedInteger(Record.Size));
+ error(IO.mapStringZ(Record.Name));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ClassRecord &Record) {
+ assert((CVR.Type == TypeLeafKind::LF_STRUCTURE) ||
+ (CVR.Type == TypeLeafKind::LF_CLASS) ||
+ (CVR.Type == TypeLeafKind::LF_INTERFACE));
+
+ error(IO.mapInteger(Record.MemberCount));
+ error(IO.mapEnum(Record.Options));
+ error(IO.mapInteger(Record.FieldList));
+ error(IO.mapInteger(Record.DerivationList));
+ error(IO.mapInteger(Record.VTableShape));
+ error(IO.mapEncodedInteger(Record.Size));
+ error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
+ Record.hasUniqueName()));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR, UnionRecord &Record) {
+ error(IO.mapInteger(Record.MemberCount));
+ error(IO.mapEnum(Record.Options));
+ error(IO.mapInteger(Record.FieldList));
+ error(IO.mapEncodedInteger(Record.Size));
+ error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
+ Record.hasUniqueName()));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR, EnumRecord &Record) {
+ error(IO.mapInteger(Record.MemberCount));
+ error(IO.mapEnum(Record.Options));
+ error(IO.mapInteger(Record.UnderlyingType));
+ error(IO.mapInteger(Record.FieldList));
+ error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
+ Record.hasUniqueName()));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR, BitFieldRecord &Record) {
+ error(IO.mapInteger(Record.Type));
+ error(IO.mapInteger(Record.BitSize));
+ error(IO.mapInteger(Record.BitOffset));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
+ VFTableShapeRecord &Record) {
+ uint16_t Size;
+ if (IO.isWriting()) {
+ ArrayRef<VFTableSlotKind> Slots = Record.getSlots();
+ Size = Slots.size();
+ error(IO.mapInteger(Size));
+
+ for (size_t SlotIndex = 0; SlotIndex < Slots.size(); SlotIndex += 2) {
+ uint8_t Byte = static_cast<uint8_t>(Slots[SlotIndex]) << 4;
+ if ((SlotIndex + 1) < Slots.size()) {
+ Byte |= static_cast<uint8_t>(Slots[SlotIndex + 1]);
+ }
+ error(IO.mapInteger(Byte));
+ }
+ } else {
+ error(IO.mapInteger(Size));
+ for (uint16_t I = 0; I < Size; I += 2) {
+ uint8_t Byte;
+ error(IO.mapInteger(Byte));
+ Record.Slots.push_back(static_cast<VFTableSlotKind>(Byte & 0xF));
+ if ((I + 1) < Size)
+ Record.Slots.push_back(static_cast<VFTableSlotKind>(Byte >> 4));
+ }
+ }
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR, VFTableRecord &Record) {
+ error(IO.mapInteger(Record.CompleteClass));
+ error(IO.mapInteger(Record.OverriddenVFTable));
+ error(IO.mapInteger(Record.VFPtrOffset));
+ uint32_t NamesLen = 0;
+ if (IO.isWriting()) {
+ for (auto Name : Record.MethodNames)
+ NamesLen += Name.size() + 1;
+ }
+ error(IO.mapInteger(NamesLen));
+ error(IO.mapVectorTail(
+ Record.MethodNames,
+ [](CodeViewRecordIO &IO, StringRef &S) { return IO.mapStringZ(S); }));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR, StringIdRecord &Record) {
+ error(IO.mapInteger(Record.Id));
+ error(IO.mapStringZ(Record.String));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
+ UdtSourceLineRecord &Record) {
+ error(IO.mapInteger(Record.UDT));
+ error(IO.mapInteger(Record.SourceFile));
+ error(IO.mapInteger(Record.LineNumber));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
+ UdtModSourceLineRecord &Record) {
+ error(IO.mapInteger(Record.UDT));
+ error(IO.mapInteger(Record.SourceFile));
+ error(IO.mapInteger(Record.LineNumber));
+ error(IO.mapInteger(Record.Module));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR, FuncIdRecord &Record) {
+ error(IO.mapInteger(Record.ParentScope));
+ error(IO.mapInteger(Record.FunctionType));
+ error(IO.mapStringZ(Record.Name));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
+ MemberFuncIdRecord &Record) {
+ error(IO.mapInteger(Record.ClassType));
+ error(IO.mapInteger(Record.FunctionType));
+ error(IO.mapStringZ(Record.Name));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
+ BuildInfoRecord &Record) {
+ error(IO.mapVectorN<uint16_t>(
+ Record.ArgIndices,
+ [](CodeViewRecordIO &IO, TypeIndex &N) { return IO.mapInteger(N); }));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
+ MethodOverloadListRecord &Record) {
+ // TODO: Split the list into multiple records if it's longer than 64KB, using
+ // a subrecord of TypeRecordKind::Index to chain the records together.
+ error(IO.mapVectorTail(Record.Methods, MapOneMethodRecord(true)));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
+ FieldListRecord &Record) {
+ error(IO.mapByteVectorTail(Record.Data));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
+ TypeServer2Record &Record) {
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
+ BaseClassRecord &Record) {
+ error(IO.mapInteger(Record.Attrs.Attrs));
+ error(IO.mapInteger(Record.Type));
+ error(IO.mapEncodedInteger(Record.Offset));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
+ EnumeratorRecord &Record) {
+ error(IO.mapInteger(Record.Attrs.Attrs));
+
+ // FIXME: Handle full APInt such as __int128.
+ error(IO.mapEncodedInteger(Record.Value));
+ error(IO.mapStringZ(Record.Name));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
+ DataMemberRecord &Record) {
+ error(IO.mapInteger(Record.Attrs.Attrs));
+ error(IO.mapInteger(Record.Type));
+ error(IO.mapEncodedInteger(Record.FieldOffset));
+ error(IO.mapStringZ(Record.Name));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
+ OverloadedMethodRecord &Record) {
+ error(IO.mapInteger(Record.NumOverloads));
+ error(IO.mapInteger(Record.MethodList));
+ error(IO.mapStringZ(Record.Name));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
+ OneMethodRecord &Record) {
+ MapOneMethodRecord Mapper(false);
+ return Mapper(IO, Record);
+}
+
+Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
+ NestedTypeRecord &Record) {
+ uint16_t Padding = 0;
+ error(IO.mapInteger(Padding));
+ error(IO.mapInteger(Record.Type));
+ error(IO.mapStringZ(Record.Name));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
+ StaticDataMemberRecord &Record) {
+
+ error(IO.mapInteger(Record.Attrs.Attrs));
+ error(IO.mapInteger(Record.Type));
+ error(IO.mapStringZ(Record.Name));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
+ VirtualBaseClassRecord &Record) {
+
+ error(IO.mapInteger(Record.Attrs.Attrs));
+ error(IO.mapInteger(Record.BaseType));
+ error(IO.mapInteger(Record.VBPtrType));
+ error(IO.mapEncodedInteger(Record.VBPtrOffset));
+ error(IO.mapEncodedInteger(Record.VTableIndex));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
+ VFPtrRecord &Record) {
+ uint16_t Padding = 0;
+ error(IO.mapInteger(Padding));
+ error(IO.mapInteger(Record.Type));
+
+ return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
+ ListContinuationRecord &Record) {
+ uint16_t Padding = 0;
+ error(IO.mapInteger(Padding));
+ error(IO.mapInteger(Record.ContinuationIndex));
+
+ return Error::success();
+}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/TypeSerializer.cpp b/contrib/llvm/lib/DebugInfo/CodeView/TypeSerializer.cpp
new file mode 100644
index 0000000..f24fcff
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/TypeSerializer.cpp
@@ -0,0 +1,243 @@
+//===- TypeSerialzier.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/TypeSerializer.h"
+
+#include "llvm/DebugInfo/MSF/StreamWriter.h"
+
+#include <string.h>
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+bool TypeSerializer::isInFieldList() const {
+ return TypeKind.hasValue() && *TypeKind == TypeLeafKind::LF_FIELDLIST;
+}
+
+TypeIndex TypeSerializer::calcNextTypeIndex() const {
+ if (LastTypeIndex.isNoneType())
+ return TypeIndex(TypeIndex::FirstNonSimpleIndex);
+ else
+ return TypeIndex(LastTypeIndex.getIndex() + 1);
+}
+
+TypeIndex TypeSerializer::incrementTypeIndex() {
+ TypeIndex Previous = LastTypeIndex;
+ LastTypeIndex = calcNextTypeIndex();
+ return Previous;
+}
+
+MutableArrayRef<uint8_t> TypeSerializer::getCurrentSubRecordData() {
+ assert(isInFieldList());
+ return getCurrentRecordData().drop_front(CurrentSegment.length());
+}
+
+MutableArrayRef<uint8_t> TypeSerializer::getCurrentRecordData() {
+ return MutableArrayRef<uint8_t>(RecordBuffer).take_front(Writer.getOffset());
+}
+
+Error TypeSerializer::writeRecordPrefix(TypeLeafKind Kind) {
+ RecordPrefix Prefix;
+ Prefix.RecordKind = Kind;
+ Prefix.RecordLen = 0;
+ if (auto EC = Writer.writeObject(Prefix))
+ return EC;
+ return Error::success();
+}
+
+TypeIndex
+TypeSerializer::insertRecordBytesPrivate(MutableArrayRef<uint8_t> Record) {
+ assert(Record.size() % 4 == 0 && "Record is not aligned to 4 bytes!");
+
+ StringRef S(reinterpret_cast<const char *>(Record.data()), Record.size());
+
+ TypeIndex NextTypeIndex = calcNextTypeIndex();
+ auto Result = HashedRecords.try_emplace(S, NextTypeIndex);
+ if (Result.second) {
+ LastTypeIndex = NextTypeIndex;
+ SeenRecords.push_back(Record);
+ }
+ return Result.first->getValue();
+}
+
+Expected<MutableArrayRef<uint8_t>>
+TypeSerializer::addPadding(MutableArrayRef<uint8_t> Record) {
+ uint32_t Align = Record.size() % 4;
+ if (Align == 0)
+ return Record;
+
+ int PaddingBytes = 4 - Align;
+ int N = PaddingBytes;
+ while (PaddingBytes > 0) {
+ uint8_t Pad = static_cast<uint8_t>(LF_PAD0 + PaddingBytes);
+ if (auto EC = Writer.writeInteger(Pad))
+ return std::move(EC);
+ --PaddingBytes;
+ }
+ return MutableArrayRef<uint8_t>(Record.data(), Record.size() + N);
+}
+
+TypeSerializer::TypeSerializer(BumpPtrAllocator &Storage)
+ : RecordStorage(Storage), LastTypeIndex(),
+ RecordBuffer(MaxRecordLength * 2), Stream(RecordBuffer), Writer(Stream),
+ Mapping(Writer) {
+ // RecordBuffer needs to be able to hold enough data so that if we are 1
+ // byte short of MaxRecordLen, and then we try to write MaxRecordLen bytes,
+ // we won't overflow.
+}
+
+ArrayRef<MutableArrayRef<uint8_t>> TypeSerializer::records() const {
+ return SeenRecords;
+}
+
+TypeIndex TypeSerializer::getLastTypeIndex() const { return LastTypeIndex; }
+
+TypeIndex TypeSerializer::insertRecordBytes(MutableArrayRef<uint8_t> Record) {
+ assert(!TypeKind.hasValue() && "Already in a type mapping!");
+ assert(Writer.getOffset() == 0 && "Stream has data already!");
+
+ return insertRecordBytesPrivate(Record);
+}
+
+Error TypeSerializer::visitTypeBegin(CVType &Record) {
+ assert(!TypeKind.hasValue() && "Already in a type mapping!");
+ assert(Writer.getOffset() == 0 && "Stream has data already!");
+
+ if (auto EC = writeRecordPrefix(Record.kind()))
+ return EC;
+
+ TypeKind = Record.kind();
+ if (auto EC = Mapping.visitTypeBegin(Record))
+ return EC;
+
+ return Error::success();
+}
+
+Expected<TypeIndex> TypeSerializer::visitTypeEndGetIndex(CVType &Record) {
+ assert(TypeKind.hasValue() && "Not in a type mapping!");
+ if (auto EC = Mapping.visitTypeEnd(Record))
+ return std::move(EC);
+
+ // Update the record's length and fill out the CVType members to point to
+ // the stable memory holding the record's data.
+ auto ThisRecordData = getCurrentRecordData();
+ auto ExpectedData = addPadding(ThisRecordData);
+ if (!ExpectedData)
+ return ExpectedData.takeError();
+ ThisRecordData = *ExpectedData;
+
+ RecordPrefix *Prefix =
+ reinterpret_cast<RecordPrefix *>(ThisRecordData.data());
+ Prefix->RecordLen = ThisRecordData.size() - sizeof(uint16_t);
+
+ uint8_t *Copy = RecordStorage.Allocate<uint8_t>(ThisRecordData.size());
+ ::memcpy(Copy, ThisRecordData.data(), ThisRecordData.size());
+ ThisRecordData = MutableArrayRef<uint8_t>(Copy, ThisRecordData.size());
+ Record = CVType(*TypeKind, ThisRecordData);
+ TypeIndex InsertedTypeIndex = insertRecordBytesPrivate(ThisRecordData);
+
+ // Write out each additional segment in reverse order, and update each
+ // record's continuation index to point to the previous one.
+ for (auto X : reverse(FieldListSegments)) {
+ auto CIBytes = X.take_back(sizeof(uint32_t));
+ support::ulittle32_t *CI =
+ reinterpret_cast<support::ulittle32_t *>(CIBytes.data());
+ assert(*CI == 0xB0C0B0C0 && "Invalid TypeIndex placeholder");
+ *CI = InsertedTypeIndex.getIndex();
+ InsertedTypeIndex = insertRecordBytesPrivate(X);
+ }
+
+ TypeKind.reset();
+ Writer.setOffset(0);
+ FieldListSegments.clear();
+ CurrentSegment.SubRecords.clear();
+
+ return InsertedTypeIndex;
+}
+
+Error TypeSerializer::visitTypeEnd(CVType &Record) {
+ auto ExpectedIndex = visitTypeEndGetIndex(Record);
+ if (!ExpectedIndex)
+ return ExpectedIndex.takeError();
+ return Error::success();
+}
+
+Error TypeSerializer::visitMemberBegin(CVMemberRecord &Record) {
+ assert(isInFieldList() && "Not in a field list!");
+ assert(!MemberKind.hasValue() && "Already in a member record!");
+ MemberKind = Record.Kind;
+
+ if (auto EC = Mapping.visitMemberBegin(Record))
+ return EC;
+
+ return Error::success();
+}
+
+Error TypeSerializer::visitMemberEnd(CVMemberRecord &Record) {
+ if (auto EC = Mapping.visitMemberEnd(Record))
+ return EC;
+
+ // Check if this subrecord makes the current segment not fit in 64K minus
+ // the space for a continuation record (8 bytes). If the segment does not
+ // fit, insert a continuation record.
+ if (Writer.getOffset() > MaxRecordLength - ContinuationLength) {
+ MutableArrayRef<uint8_t> Data = getCurrentRecordData();
+ SubRecord LastSubRecord = CurrentSegment.SubRecords.back();
+ uint32_t CopySize = CurrentSegment.length() - LastSubRecord.Size;
+ auto CopyData = Data.take_front(CopySize);
+ auto LeftOverData = Data.drop_front(CopySize);
+ assert(LastSubRecord.Size == LeftOverData.size());
+
+ // Allocate stable storage for the record and copy the old record plus
+ // continuation over.
+ uint16_t LengthWithSize = CopySize + ContinuationLength;
+ assert(LengthWithSize <= MaxRecordLength);
+ RecordPrefix *Prefix = reinterpret_cast<RecordPrefix *>(CopyData.data());
+ Prefix->RecordLen = LengthWithSize - sizeof(uint16_t);
+
+ uint8_t *SegmentBytes = RecordStorage.Allocate<uint8_t>(LengthWithSize);
+ auto SavedSegment = MutableArrayRef<uint8_t>(SegmentBytes, LengthWithSize);
+ msf::MutableByteStream CS(SavedSegment);
+ msf::StreamWriter CW(CS);
+ if (auto EC = CW.writeBytes(CopyData))
+ return EC;
+ if (auto EC = CW.writeEnum(TypeLeafKind::LF_INDEX))
+ return EC;
+ if (auto EC = CW.writeInteger(uint16_t(0)))
+ return EC;
+ if (auto EC = CW.writeInteger(uint32_t(0xB0C0B0C0)))
+ return EC;
+ FieldListSegments.push_back(SavedSegment);
+
+ // Write a new placeholder record prefix to mark the start of this new
+ // top-level record.
+ Writer.setOffset(0);
+ if (auto EC = writeRecordPrefix(TypeLeafKind::LF_FIELDLIST))
+ return EC;
+
+ // Then move over the subrecord that overflowed the old segment to the
+ // beginning of this segment. Note that we have to use memmove here
+ // instead of Writer.writeBytes(), because the new and old locations
+ // could overlap.
+ ::memmove(Stream.data().data() + sizeof(RecordPrefix), LeftOverData.data(),
+ LeftOverData.size());
+ // And point the segment writer at the end of that subrecord.
+ Writer.setOffset(LeftOverData.size() + sizeof(RecordPrefix));
+
+ CurrentSegment.SubRecords.clear();
+ CurrentSegment.SubRecords.push_back(LastSubRecord);
+ }
+
+ // Update the CVMemberRecord since we may have shifted around or gotten
+ // padded.
+ Record.Data = getCurrentSubRecordData();
+
+ MemberKind.reset();
+ return Error::success();
+}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp b/contrib/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
index ebfda24..ed6cf57 100644
--- a/contrib/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
+++ b/contrib/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
@@ -11,10 +11,11 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
-#include "llvm/DebugInfo/CodeView/FieldListRecordBuilder.h"
-#include "llvm/DebugInfo/CodeView/StreamRef.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ScopedPrinter.h"
@@ -53,37 +54,61 @@ namespace {
/// existing destination type index.
class TypeStreamMerger : public TypeVisitorCallbacks {
public:
- TypeStreamMerger(TypeTableBuilder &DestStream) : DestStream(DestStream) {
+ TypeStreamMerger(TypeTableBuilder &DestStream)
+ : DestStream(DestStream), FieldListBuilder(DestStream) {
assert(!hadError());
}
/// TypeVisitorCallbacks overrides.
#define TYPE_RECORD(EnumName, EnumVal, Name) \
- Error visit##Name(Name##Record &Record) override;
+ Error visitKnownRecord(CVType &CVR, Name##Record &Record) override;
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
- TYPE_RECORD(EnumName, EnumVal, Name)
+ Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override;
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
- Error visitUnknownType(const CVRecord<TypeLeafKind> &Record) override;
+ Error visitUnknownType(CVType &Record) override;
- Error visitTypeBegin(const CVRecord<TypeLeafKind> &Record) override;
- Error visitTypeEnd(const CVRecord<TypeLeafKind> &Record) override;
-
- Error visitFieldListEnd(const CVRecord<TypeLeafKind> &Record) override;
+ Error visitTypeBegin(CVType &Record) override;
+ Error visitTypeEnd(CVType &Record) override;
+ Error visitMemberEnd(CVMemberRecord &Record) override;
bool mergeStream(const CVTypeArray &Types);
private:
+ template <typename RecordType>
+ Error visitKnownRecordImpl(RecordType &Record) {
+ FoundBadTypeIndex |= !Record.remapTypeIndices(IndexMap);
+ IndexMap.push_back(DestStream.writeKnownType(Record));
+ return Error::success();
+ }
+
+ Error visitKnownRecordImpl(FieldListRecord &Record) {
+ CVTypeVisitor Visitor(*this);
+
+ if (auto EC = Visitor.visitFieldListMemberStream(Record.Data))
+ return EC;
+ return Error::success();
+ }
+
+ template <typename RecordType>
+ Error visitKnownMemberRecordImpl(RecordType &Record) {
+ FoundBadTypeIndex |= !Record.remapTypeIndices(IndexMap);
+ FieldListBuilder.writeMemberType(Record);
+ return Error::success();
+ }
+
bool hadError() { return FoundBadTypeIndex; }
bool FoundBadTypeIndex = false;
- FieldListRecordBuilder FieldBuilder;
+ BumpPtrAllocator Allocator;
TypeTableBuilder &DestStream;
+ FieldListRecordBuilder FieldListBuilder;
+ bool IsInFieldList{false};
size_t BeginIndexMapSize = 0;
/// Map from source type index to destination type index. Indexed by source
@@ -93,39 +118,45 @@ private:
} // end anonymous namespace
-Error TypeStreamMerger::visitTypeBegin(const CVRecord<TypeLeafKind> &Rec) {
- BeginIndexMapSize = IndexMap.size();
+Error TypeStreamMerger::visitTypeBegin(CVRecord<TypeLeafKind> &Rec) {
+ if (Rec.Type == TypeLeafKind::LF_FIELDLIST) {
+ assert(!IsInFieldList);
+ IsInFieldList = true;
+ FieldListBuilder.begin();
+ } else
+ BeginIndexMapSize = IndexMap.size();
return Error::success();
}
-Error TypeStreamMerger::visitTypeEnd(const CVRecord<TypeLeafKind> &Rec) {
- assert(IndexMap.size() == BeginIndexMapSize + 1);
+Error TypeStreamMerger::visitTypeEnd(CVRecord<TypeLeafKind> &Rec) {
+ if (Rec.Type == TypeLeafKind::LF_FIELDLIST) {
+ TypeIndex Index = FieldListBuilder.end();
+ IndexMap.push_back(Index);
+ IsInFieldList = false;
+ }
return Error::success();
}
-Error TypeStreamMerger::visitFieldListEnd(const CVRecord<TypeLeafKind> &Rec) {
- IndexMap.push_back(DestStream.writeFieldList(FieldBuilder));
- FieldBuilder.reset();
+Error TypeStreamMerger::visitMemberEnd(CVMemberRecord &Rec) {
+ assert(IndexMap.size() == BeginIndexMapSize + 1);
return Error::success();
}
#define TYPE_RECORD(EnumName, EnumVal, Name) \
- Error TypeStreamMerger::visit##Name(Name##Record &Record) { \
- FoundBadTypeIndex |= !Record.remapTypeIndices(IndexMap); \
- IndexMap.push_back(DestStream.write##Name(Record)); \
- return Error::success(); \
+ Error TypeStreamMerger::visitKnownRecord(CVType &CVR, \
+ Name##Record &Record) { \
+ return visitKnownRecordImpl(Record); \
}
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
- Error TypeStreamMerger::visit##Name(Name##Record &Record) { \
- FoundBadTypeIndex |= !Record.remapTypeIndices(IndexMap); \
- FieldBuilder.write##Name(Record); \
- return Error::success(); \
+ Error TypeStreamMerger::visitKnownMember(CVMemberRecord &CVR, \
+ Name##Record &Record) { \
+ return visitKnownMemberRecordImpl(Record); \
}
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
-Error TypeStreamMerger::visitUnknownType(const CVRecord<TypeLeafKind> &Rec) {
+Error TypeStreamMerger::visitUnknownType(CVType &Rec) {
// We failed to translate a type. Translate this index as "not translated".
IndexMap.push_back(
TypeIndex(SimpleTypeKind::NotTranslated, SimpleTypeMode::Direct));
@@ -134,7 +165,14 @@ Error TypeStreamMerger::visitUnknownType(const CVRecord<TypeLeafKind> &Rec) {
bool TypeStreamMerger::mergeStream(const CVTypeArray &Types) {
assert(IndexMap.empty());
- CVTypeVisitor Visitor(*this);
+ TypeVisitorCallbackPipeline Pipeline;
+
+ TypeDeserializer Deserializer;
+ Pipeline.addCallbackToPipeline(Deserializer);
+ Pipeline.addCallbackToPipeline(*this);
+
+ CVTypeVisitor Visitor(Pipeline);
+
if (auto EC = Visitor.visitTypeStream(Types)) {
consumeError(std::move(EC));
return false;
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp b/contrib/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp
deleted file mode 100644
index 647538e..0000000
--- a/contrib/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp
+++ /dev/null
@@ -1,303 +0,0 @@
-//===-- TypeTableBuilder.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/TypeTableBuilder.h"
-#include "llvm/DebugInfo/CodeView/FieldListRecordBuilder.h"
-#include "llvm/DebugInfo/CodeView/MethodListRecordBuilder.h"
-#include "llvm/DebugInfo/CodeView/TypeIndex.h"
-#include "llvm/DebugInfo/CodeView/TypeRecordBuilder.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm;
-using namespace codeview;
-
-TypeTableBuilder::TypeTableBuilder() {}
-
-TypeTableBuilder::~TypeTableBuilder() {}
-
-TypeIndex TypeTableBuilder::writeModifier(const ModifierRecord &Record) {
- TypeRecordBuilder Builder(Record.getKind());
-
- Builder.writeTypeIndex(Record.getModifiedType());
- Builder.writeUInt16(static_cast<uint16_t>(Record.getModifiers()));
-
- return writeRecord(Builder);
-}
-
-TypeIndex TypeTableBuilder::writeProcedure(const ProcedureRecord &Record) {
- TypeRecordBuilder Builder(Record.getKind());
-
- Builder.writeTypeIndex(Record.getReturnType());
- Builder.writeUInt8(static_cast<uint8_t>(Record.getCallConv()));
- Builder.writeUInt8(static_cast<uint8_t>(Record.getOptions()));
- Builder.writeUInt16(Record.getParameterCount());
- Builder.writeTypeIndex(Record.getArgumentList());
-
- return writeRecord(Builder);
-}
-
-TypeIndex
-TypeTableBuilder::writeMemberFunction(const MemberFunctionRecord &Record) {
- TypeRecordBuilder Builder(Record.getKind());
-
- Builder.writeTypeIndex(Record.getReturnType());
- Builder.writeTypeIndex(Record.getClassType());
- Builder.writeTypeIndex(Record.getThisType());
- Builder.writeUInt8(static_cast<uint8_t>(Record.getCallConv()));
- Builder.writeUInt8(static_cast<uint8_t>(Record.getOptions()));
- Builder.writeUInt16(Record.getParameterCount());
- Builder.writeTypeIndex(Record.getArgumentList());
- Builder.writeInt32(Record.getThisPointerAdjustment());
-
- return writeRecord(Builder);
-}
-
-TypeIndex TypeTableBuilder::writeArgList(const ArgListRecord &Record) {
- TypeRecordBuilder Builder(Record.getKind());
-
- Builder.writeUInt32(Record.getIndices().size());
- for (TypeIndex TI : Record.getIndices()) {
- Builder.writeTypeIndex(TI);
- }
-
- return writeRecord(Builder);
-}
-
-TypeIndex TypeTableBuilder::writePointer(const PointerRecord &Record) {
- TypeRecordBuilder Builder(Record.getKind());
-
- Builder.writeTypeIndex(Record.getReferentType());
- uint32_t flags = static_cast<uint32_t>(Record.getOptions()) |
- (Record.getSize() << PointerRecord::PointerSizeShift) |
- (static_cast<uint32_t>(Record.getMode())
- << PointerRecord::PointerModeShift) |
- (static_cast<uint32_t>(Record.getPointerKind())
- << PointerRecord::PointerKindShift);
- Builder.writeUInt32(flags);
-
- if (Record.isPointerToMember()) {
- const MemberPointerInfo &M = Record.getMemberInfo();
- Builder.writeTypeIndex(M.getContainingType());
- Builder.writeUInt16(static_cast<uint16_t>(M.getRepresentation()));
- }
-
- return writeRecord(Builder);
-}
-
-TypeIndex TypeTableBuilder::writeArray(const ArrayRecord &Record) {
- TypeRecordBuilder Builder(Record.getKind());
-
- Builder.writeTypeIndex(Record.getElementType());
- Builder.writeTypeIndex(Record.getIndexType());
- Builder.writeEncodedUnsignedInteger(Record.getSize());
- Builder.writeNullTerminatedString(Record.getName());
-
- return writeRecord(Builder);
-}
-
-TypeIndex TypeTableBuilder::writeClass(const ClassRecord &Record) {
- assert((Record.getKind() == TypeRecordKind::Struct) ||
- (Record.getKind() == TypeRecordKind::Class) ||
- (Record.getKind() == TypeRecordKind::Interface));
-
- TypeRecordBuilder Builder(Record.getKind());
-
- Builder.writeUInt16(Record.getMemberCount());
- uint16_t Flags =
- static_cast<uint16_t>(Record.getOptions()) |
- (static_cast<uint16_t>(Record.getHfa()) << ClassRecord::HfaKindShift) |
- (static_cast<uint16_t>(Record.getWinRTKind())
- << ClassRecord::WinRTKindShift);
- Builder.writeUInt16(Flags);
- Builder.writeTypeIndex(Record.getFieldList());
- Builder.writeTypeIndex(Record.getDerivationList());
- Builder.writeTypeIndex(Record.getVTableShape());
- Builder.writeEncodedUnsignedInteger(Record.getSize());
- Builder.writeNullTerminatedString(Record.getName());
- if ((Record.getOptions() & ClassOptions::HasUniqueName) !=
- ClassOptions::None) {
- Builder.writeNullTerminatedString(Record.getUniqueName());
- }
-
- return writeRecord(Builder);
-}
-
-TypeIndex TypeTableBuilder::writeUnion(const UnionRecord &Record) {
- TypeRecordBuilder Builder(TypeRecordKind::Union);
- Builder.writeUInt16(Record.getMemberCount());
- uint16_t Flags =
- static_cast<uint16_t>(Record.getOptions()) |
- (static_cast<uint16_t>(Record.getHfa()) << ClassRecord::HfaKindShift);
- Builder.writeUInt16(Flags);
- Builder.writeTypeIndex(Record.getFieldList());
- Builder.writeEncodedUnsignedInteger(Record.getSize());
- Builder.writeNullTerminatedString(Record.getName());
- if ((Record.getOptions() & ClassOptions::HasUniqueName) !=
- ClassOptions::None) {
- Builder.writeNullTerminatedString(Record.getUniqueName());
- }
- return writeRecord(Builder);
-}
-
-TypeIndex TypeTableBuilder::writeEnum(const EnumRecord &Record) {
- TypeRecordBuilder Builder(Record.getKind());
-
- Builder.writeUInt16(Record.getMemberCount());
- Builder.writeUInt16(static_cast<uint16_t>(Record.getOptions()));
- Builder.writeTypeIndex(Record.getUnderlyingType());
- Builder.writeTypeIndex(Record.getFieldList());
- Builder.writeNullTerminatedString(Record.getName());
- if ((Record.getOptions() & ClassOptions::HasUniqueName) !=
- ClassOptions::None) {
- Builder.writeNullTerminatedString(Record.getUniqueName());
- }
-
- return writeRecord(Builder);
-}
-
-TypeIndex TypeTableBuilder::writeBitField(const BitFieldRecord &Record) {
- TypeRecordBuilder Builder(Record.getKind());
-
- Builder.writeTypeIndex(Record.getType());
- Builder.writeUInt8(Record.getBitSize());
- Builder.writeUInt8(Record.getBitOffset());
-
- return writeRecord(Builder);
-}
-
-TypeIndex
-TypeTableBuilder::writeVFTableShape(const VFTableShapeRecord &Record) {
- TypeRecordBuilder Builder(Record.getKind());
-
- ArrayRef<VFTableSlotKind> Slots = Record.getSlots();
-
- Builder.writeUInt16(Slots.size());
- for (size_t SlotIndex = 0; SlotIndex < Slots.size(); SlotIndex += 2) {
- uint8_t Byte = static_cast<uint8_t>(Slots[SlotIndex]) << 4;
- if ((SlotIndex + 1) < Slots.size()) {
- Byte |= static_cast<uint8_t>(Slots[SlotIndex + 1]);
- }
- Builder.writeUInt8(Byte);
- }
-
- return writeRecord(Builder);
-}
-
-TypeIndex
-TypeTableBuilder::writeVFTable(const VFTableRecord &Record) {
- TypeRecordBuilder Builder(Record.getKind());
- Builder.writeTypeIndex(Record.getCompleteClass());
- Builder.writeTypeIndex(Record.getOverriddenVTable());
- Builder.writeUInt32(Record.getVFPtrOffset());
-
- // Sum up the lengths of the null-terminated names.
- size_t NamesLen = Record.getName().size() + 1;
- for (StringRef MethodName : Record.getMethodNames())
- NamesLen += MethodName.size() + 1;
-
- Builder.writeUInt32(NamesLen);
- Builder.writeNullTerminatedString(Record.getName());
- for (StringRef MethodName : Record.getMethodNames())
- Builder.writeNullTerminatedString(MethodName);
-
- return writeRecord(Builder);
-}
-
-TypeIndex TypeTableBuilder::writeStringId(const StringIdRecord &Record) {
- TypeRecordBuilder Builder(TypeRecordKind::StringId);
- Builder.writeTypeIndex(Record.getId());
- Builder.writeNullTerminatedString(Record.getString());
- return writeRecord(Builder);
-}
-
-TypeIndex
-TypeTableBuilder::writeUdtSourceLine(const UdtSourceLineRecord &Record) {
- TypeRecordBuilder Builder(Record.getKind());
- Builder.writeTypeIndex(Record.getUDT());
- Builder.writeTypeIndex(Record.getSourceFile());
- Builder.writeUInt32(Record.getLineNumber());
- return writeRecord(Builder);
-}
-
-TypeIndex
-TypeTableBuilder::writeUdtModSourceLine(const UdtModSourceLineRecord &Record) {
- TypeRecordBuilder Builder(Record.getKind());
- Builder.writeTypeIndex(Record.getUDT());
- Builder.writeTypeIndex(Record.getSourceFile());
- Builder.writeUInt32(Record.getLineNumber());
- Builder.writeUInt16(Record.getModule());
- return writeRecord(Builder);
-}
-
-TypeIndex TypeTableBuilder::writeFuncId(const FuncIdRecord &Record) {
- TypeRecordBuilder Builder(Record.getKind());
- Builder.writeTypeIndex(Record.getParentScope());
- Builder.writeTypeIndex(Record.getFunctionType());
- Builder.writeNullTerminatedString(Record.getName());
- return writeRecord(Builder);
-}
-
-TypeIndex
-TypeTableBuilder::writeMemberFuncId(const MemberFuncIdRecord &Record) {
- TypeRecordBuilder Builder(Record.getKind());
- Builder.writeTypeIndex(Record.getClassType());
- Builder.writeTypeIndex(Record.getFunctionType());
- Builder.writeNullTerminatedString(Record.getName());
- return writeRecord(Builder);
-}
-
-TypeIndex
-TypeTableBuilder::writeBuildInfo(const BuildInfoRecord &Record) {
- TypeRecordBuilder Builder(Record.getKind());
- assert(Record.getArgs().size() <= UINT16_MAX);
- Builder.writeUInt16(Record.getArgs().size());
- for (TypeIndex Arg : Record.getArgs())
- Builder.writeTypeIndex(Arg);
- return writeRecord(Builder);
-}
-
-TypeIndex TypeTableBuilder::writeRecord(TypeRecordBuilder &Builder) {
- return writeRecord(Builder.str());
-}
-
-TypeIndex TypeTableBuilder::writeFieldList(FieldListRecordBuilder &FieldList) {
- return FieldList.writeListRecord(*this);
-}
-
-TypeIndex TypeTableBuilder::writeMethodOverloadList(
- const MethodOverloadListRecord &Record) {
- TypeRecordBuilder Builder(Record.getKind());
- for (const OneMethodRecord &Method : Record.getMethods()) {
- uint16_t Flags = static_cast<uint16_t>(Method.getAccess());
- Flags |= static_cast<uint16_t>(Method.getKind())
- << MemberAttributes::MethodKindShift;
- Flags |= static_cast<uint16_t>(Method.getOptions());
- Builder.writeUInt16(Flags);
- Builder.writeUInt16(0); // padding
- Builder.writeTypeIndex(Method.getType());
- if (Method.isIntroducingVirtual()) {
- assert(Method.getVFTableOffset() >= 0);
- Builder.writeInt32(Method.getVFTableOffset());
- } else {
- assert(Method.getVFTableOffset() == -1);
- }
- }
-
- // TODO: Split the list into multiple records if it's longer than 64KB, using
- // a subrecord of TypeRecordKind::Index to chain the records together.
- return writeRecord(Builder);
-}
-
-TypeIndex TypeTableBuilder::writeTypeServer2(const TypeServer2Record &Record) {
- TypeRecordBuilder Builder(Record.getKind());
- Builder.writeGuid(Record.getGuid());
- Builder.writeUInt32(Record.getAge());
- Builder.writeNullTerminatedString(Record.getName());
- return writeRecord(Builder);
-}
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp
index 9314c9e..08bc74a 100644
--- a/contrib/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp
@@ -8,6 +8,8 @@
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
+#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
@@ -16,9 +18,11 @@ using namespace dwarf;
void DWARFAbbreviationDeclaration::clear() {
Code = 0;
- Tag = 0;
+ Tag = DW_TAG_null;
+ CodeByteSize = 0;
HasChildren = false;
AttributeSpecs.clear();
+ FixedAttributeSize.reset();
}
DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration() {
@@ -26,72 +30,190 @@ DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration() {
}
bool
-DWARFAbbreviationDeclaration::extract(DataExtractor Data, uint32_t* OffsetPtr) {
+DWARFAbbreviationDeclaration::extract(DataExtractor Data,
+ uint32_t* OffsetPtr) {
clear();
+ const uint32_t Offset = *OffsetPtr;
Code = Data.getULEB128(OffsetPtr);
if (Code == 0) {
return false;
}
- Tag = Data.getULEB128(OffsetPtr);
+ CodeByteSize = *OffsetPtr - Offset;
+ Tag = static_cast<llvm::dwarf::Tag>(Data.getULEB128(OffsetPtr));
+ if (Tag == DW_TAG_null) {
+ clear();
+ return false;
+ }
uint8_t ChildrenByte = Data.getU8(OffsetPtr);
HasChildren = (ChildrenByte == DW_CHILDREN_yes);
+ // Assign a value to our optional FixedAttributeSize member variable. If
+ // this member variable still has a value after the while loop below, then
+ // all attribute data in this abbreviation declaration has a fixed byte size.
+ FixedAttributeSize = FixedSizeInfo();
+ // Read all of the abbreviation attributes and forms.
while (true) {
- uint32_t CurOffset = *OffsetPtr;
- uint16_t Attr = Data.getULEB128(OffsetPtr);
- if (CurOffset == *OffsetPtr) {
- clear();
- return false;
- }
- CurOffset = *OffsetPtr;
- uint16_t Form = Data.getULEB128(OffsetPtr);
- if (CurOffset == *OffsetPtr) {
+ auto A = static_cast<Attribute>(Data.getULEB128(OffsetPtr));
+ auto F = static_cast<Form>(Data.getULEB128(OffsetPtr));
+ if (A && F) {
+ Optional<int64_t> V;
+ bool IsImplicitConst = (F == DW_FORM_implicit_const);
+ if (IsImplicitConst)
+ V = Data.getSLEB128(OffsetPtr);
+ else if (auto Size = DWARFFormValue::getFixedByteSize(F))
+ V = *Size;
+ AttributeSpecs.push_back(AttributeSpec(A, F, V));
+ if (IsImplicitConst)
+ continue;
+ // If this abbrevation still has a fixed byte size, then update the
+ // FixedAttributeSize as needed.
+ if (FixedAttributeSize) {
+ if (V)
+ FixedAttributeSize->NumBytes += *V;
+ else {
+ switch (F) {
+ case DW_FORM_addr:
+ ++FixedAttributeSize->NumAddrs;
+ break;
+
+ case DW_FORM_ref_addr:
+ ++FixedAttributeSize->NumRefAddrs;
+ break;
+
+ case DW_FORM_strp:
+ case DW_FORM_GNU_ref_alt:
+ case DW_FORM_GNU_strp_alt:
+ case DW_FORM_line_strp:
+ case DW_FORM_sec_offset:
+ case DW_FORM_strp_sup:
+ case DW_FORM_ref_sup:
+ ++FixedAttributeSize->NumDwarfOffsets;
+ break;
+
+ default:
+ // Indicate we no longer have a fixed byte size for this
+ // abbreviation by clearing the FixedAttributeSize optional value
+ // so it doesn't have a value.
+ FixedAttributeSize.reset();
+ break;
+ }
+ }
+ }
+ } else if (A == 0 && F == 0) {
+ // We successfully reached the end of this abbreviation declaration
+ // since both attribute and form are zero.
+ break;
+ } else {
+ // Attribute and form pairs must either both be non-zero, in which case
+ // they are added to the abbreviation declaration, or both be zero to
+ // terminate the abbrevation declaration. In this case only one was
+ // zero which is an error.
clear();
return false;
}
- if (Attr == 0 && Form == 0)
- break;
- AttributeSpecs.push_back(AttributeSpec(Attr, Form));
- }
-
- if (Tag == 0) {
- clear();
- return false;
}
return true;
}
void DWARFAbbreviationDeclaration::dump(raw_ostream &OS) const {
- const char *tagString = TagString(getTag());
+ auto tagString = TagString(getTag());
OS << '[' << getCode() << "] ";
- if (tagString)
+ if (!tagString.empty())
OS << tagString;
else
OS << format("DW_TAG_Unknown_%x", getTag());
OS << "\tDW_CHILDREN_" << (hasChildren() ? "yes" : "no") << '\n';
for (const AttributeSpec &Spec : AttributeSpecs) {
OS << '\t';
- const char *attrString = AttributeString(Spec.Attr);
- if (attrString)
+ auto attrString = AttributeString(Spec.Attr);
+ if (!attrString.empty())
OS << attrString;
else
OS << format("DW_AT_Unknown_%x", Spec.Attr);
OS << '\t';
- const char *formString = FormEncodingString(Spec.Form);
- if (formString)
+ auto formString = FormEncodingString(Spec.Form);
+ if (!formString.empty())
OS << formString;
else
OS << format("DW_FORM_Unknown_%x", Spec.Form);
+ if (Spec.isImplicitConst())
+ OS << '\t' << *Spec.ByteSizeOrValue;
OS << '\n';
}
OS << '\n';
}
-uint32_t
-DWARFAbbreviationDeclaration::findAttributeIndex(uint16_t attr) const {
+Optional<uint32_t>
+DWARFAbbreviationDeclaration::findAttributeIndex(dwarf::Attribute Attr) const {
for (uint32_t i = 0, e = AttributeSpecs.size(); i != e; ++i) {
- if (AttributeSpecs[i].Attr == attr)
+ if (AttributeSpecs[i].Attr == Attr)
return i;
}
- return -1U;
+ return None;
+}
+
+Optional<DWARFFormValue> DWARFAbbreviationDeclaration::getAttributeValue(
+ const uint32_t DIEOffset, const dwarf::Attribute Attr,
+ const DWARFUnit &U) const {
+ Optional<uint32_t> MatchAttrIndex = findAttributeIndex(Attr);
+ if (!MatchAttrIndex)
+ return None;
+
+ auto DebugInfoData = U.getDebugInfoExtractor();
+
+ // Add the byte size of ULEB that for the abbrev Code so we can start
+ // skipping the attribute data.
+ uint32_t Offset = DIEOffset + CodeByteSize;
+ uint32_t AttrIndex = 0;
+ for (const auto &Spec : AttributeSpecs) {
+ if (*MatchAttrIndex == AttrIndex) {
+ // We have arrived at the attribute to extract, extract if from Offset.
+ DWARFFormValue FormValue(Spec.Form);
+ if (Spec.isImplicitConst()) {
+ FormValue.setSValue(*Spec.ByteSizeOrValue);
+ return FormValue;
+ }
+ if (FormValue.extractValue(DebugInfoData, &Offset, &U))
+ return FormValue;
+ }
+ // March Offset along until we get to the attribute we want.
+ if (auto FixedSize = Spec.getByteSize(U))
+ Offset += *FixedSize;
+ else
+ DWARFFormValue::skipValue(Spec.Form, DebugInfoData, &Offset, &U);
+ ++AttrIndex;
+ }
+ return None;
+}
+
+size_t DWARFAbbreviationDeclaration::FixedSizeInfo::getByteSize(
+ const DWARFUnit &U) const {
+ size_t ByteSize = NumBytes;
+ if (NumAddrs)
+ ByteSize += NumAddrs * U.getAddressByteSize();
+ if (NumRefAddrs)
+ ByteSize += NumRefAddrs * U.getRefAddrByteSize();
+ if (NumDwarfOffsets)
+ ByteSize += NumDwarfOffsets * U.getDwarfOffsetByteSize();
+ return ByteSize;
+}
+
+Optional<int64_t> DWARFAbbreviationDeclaration::AttributeSpec::getByteSize(
+ const DWARFUnit &U) const {
+ if (isImplicitConst())
+ return 0;
+ if (ByteSizeOrValue)
+ return ByteSizeOrValue;
+ Optional<int64_t> S;
+ auto FixedByteSize = DWARFFormValue::getFixedByteSize(Form, &U);
+ if (FixedByteSize)
+ S = *FixedByteSize;
+ return S;
+}
+
+Optional<size_t> DWARFAbbreviationDeclaration::getFixedAttributesByteSize(
+ const DWARFUnit &U) const {
+ if (FixedAttributeSize)
+ return FixedAttributeSize->getByteSize(U);
+ return None;
}
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
index 8ae0543..7111ad3 100644
--- a/contrib/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
@@ -39,7 +39,7 @@ bool DWARFAcceleratorTable::extract() {
for (unsigned i = 0; i < NumAtoms; ++i) {
uint16_t AtomType = AccelSection.getU16(&Offset);
- uint16_t AtomForm = AccelSection.getU16(&Offset);
+ auto AtomForm = static_cast<dwarf::Form>(AccelSection.getU16(&Offset));
HdrData.Atoms.push_back(std::make_pair(AtomType, AtomForm));
}
@@ -61,12 +61,14 @@ void DWARFAcceleratorTable::dump(raw_ostream &OS) const {
SmallVector<DWARFFormValue, 3> AtomForms;
for (const auto &Atom: HdrData.Atoms) {
OS << format("Atom[%d] Type: ", i++);
- if (const char *TypeString = dwarf::AtomTypeString(Atom.first))
+ auto TypeString = dwarf::AtomTypeString(Atom.first);
+ if (!TypeString.empty())
OS << TypeString;
else
OS << format("DW_ATOM_Unknown_0x%x", Atom.first);
OS << " Form: ";
- if (const char *FormString = dwarf::FormEncodingString(Atom.second))
+ auto FormString = dwarf::FormEncodingString(Atom.second);
+ if (!FormString.empty())
OS << FormString;
else
OS << format("DW_FORM_Unknown_0x%x", Atom.second);
@@ -118,7 +120,7 @@ void DWARFAcceleratorTable::dump(raw_ostream &OS) const {
for (auto &Atom : AtomForms) {
OS << format("{Atom[%d]: ", i++);
if (Atom.extractValue(AccelSection, &DataOffset, nullptr))
- Atom.dump(OS, nullptr);
+ Atom.dump(OS);
else
OS << "Error extracting the value";
OS << "} ";
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp
index 39a7c77..948972f 100644
--- a/contrib/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp
@@ -8,6 +8,8 @@
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
+#include "llvm/DebugInfo/DWARF/DWARFDie.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
@@ -22,12 +24,11 @@ void DWARFCompileUnit::dump(raw_ostream &OS) {
<< " (next unit at " << format("0x%08x", getNextUnitOffset())
<< ")\n";
- if (const DWARFDebugInfoEntryMinimal *CU = getUnitDIE(false))
- CU->dump(OS, this, -1U);
+ if (DWARFDie CUDie = getUnitDIE(false))
+ CUDie.dump(OS, -1U);
else
OS << "<compile unit can't be parsed!>\n\n";
}
// VTable anchor.
-DWARFCompileUnit::~DWARFCompileUnit() {
-}
+DWARFCompileUnit::~DWARFCompileUnit() = default;
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
index e8ea71b..77f6f65 100644
--- a/contrib/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -12,7 +12,9 @@
#include "llvm/ADT/StringSwitch.h"
#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h"
#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
+#include "llvm/Object/Decompressor.h"
#include "llvm/Object/MachO.h"
#include "llvm/Object/RelocVisitor.h"
#include "llvm/Support/Compression.h"
@@ -32,37 +34,6 @@ typedef DWARFDebugLine::LineTable DWARFLineTable;
typedef DILineInfoSpecifier::FileLineInfoKind FileLineInfoKind;
typedef DILineInfoSpecifier::FunctionNameKind FunctionNameKind;
-static void dumpPubSection(raw_ostream &OS, StringRef Name, StringRef Data,
- bool LittleEndian, bool GnuStyle) {
- OS << "\n." << Name << " contents:\n";
- DataExtractor pubNames(Data, LittleEndian, 0);
- uint32_t offset = 0;
- while (pubNames.isValidOffset(offset)) {
- OS << "length = " << format("0x%08x", pubNames.getU32(&offset));
- OS << " version = " << format("0x%04x", pubNames.getU16(&offset));
- OS << " unit_offset = " << format("0x%08x", pubNames.getU32(&offset));
- OS << " unit_size = " << format("0x%08x", pubNames.getU32(&offset)) << '\n';
- if (GnuStyle)
- OS << "Offset Linkage Kind Name\n";
- else
- OS << "Offset Name\n";
-
- while (offset < Data.size()) {
- uint32_t dieRef = pubNames.getU32(&offset);
- if (dieRef == 0)
- break;
- OS << format("0x%8.8x ", dieRef);
- if (GnuStyle) {
- PubIndexEntryDescriptor desc(pubNames.getU8(&offset));
- OS << format("%-8s", dwarf::GDBIndexEntryLinkageString(desc.Linkage))
- << ' ' << format("%-8s", dwarf::GDBIndexEntryKindString(desc.Kind))
- << ' ';
- }
- OS << '\"' << pubNames.getCStr(&offset) << "\"\n";
- }
- }
-}
-
static void dumpAccelSection(raw_ostream &OS, StringRef Name,
const DWARFSection& Section, StringRef StringSection,
bool LittleEndian) {
@@ -75,7 +46,8 @@ static void dumpAccelSection(raw_ostream &OS, StringRef Name,
Accel.dump(OS);
}
-void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType, bool DumpEH) {
+void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType, bool DumpEH,
+ bool SummarizeTypes) {
if (DumpType == DIDT_All || DumpType == DIDT_Abbrev) {
OS << ".debug_abbrev contents:\n";
getDebugAbbrev()->dump(OS);
@@ -104,7 +76,7 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType, bool DumpEH) {
OS << "\n.debug_types contents:\n";
for (const auto &TUS : type_unit_sections())
for (const auto &TU : TUS)
- TU->dump(OS);
+ TU->dump(OS, SummarizeTypes);
}
if ((DumpType == DIDT_All || DumpType == DIDT_TypesDwo) &&
@@ -112,7 +84,7 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType, bool DumpEH) {
OS << "\n.debug_types.dwo contents:\n";
for (const auto &DWOTUS : dwo_type_unit_sections())
for (const auto &DWOTU : DWOTUS)
- DWOTU->dump(OS);
+ DWOTU->dump(OS, SummarizeTypes);
}
if (DumpType == DIDT_All || DumpType == DIDT_Loc) {
@@ -153,16 +125,16 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType, bool DumpEH) {
OS << "\n.debug_line contents:\n";
for (const auto &CU : compile_units()) {
savedAddressByteSize = CU->getAddressByteSize();
- const auto *CUDIE = CU->getUnitDIE();
- if (CUDIE == nullptr)
+ auto CUDIE = CU->getUnitDIE();
+ if (!CUDIE)
continue;
- unsigned stmtOffset = CUDIE->getAttributeValueAsSectionOffset(
- CU.get(), DW_AT_stmt_list, -1U);
- if (stmtOffset != -1U) {
+ if (auto StmtOffset =
+ CUDIE.getAttributeValueAsSectionOffset(DW_AT_stmt_list)) {
DataExtractor lineData(getLineSection().Data, isLittleEndian(),
savedAddressByteSize);
DWARFDebugLine::LineTable LineTable;
- LineTable.parse(lineData, &getLineSection().Relocs, &stmtOffset);
+ uint32_t Offset = *StmtOffset;
+ LineTable.parse(lineData, &getLineSection().Relocs, &Offset);
LineTable.dump(OS);
}
}
@@ -228,20 +200,22 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType, bool DumpEH) {
}
if (DumpType == DIDT_All || DumpType == DIDT_Pubnames)
- dumpPubSection(OS, "debug_pubnames", getPubNamesSection(),
- isLittleEndian(), false);
+ DWARFDebugPubTable(getPubNamesSection(), isLittleEndian(), false)
+ .dump("debug_pubnames", OS);
if (DumpType == DIDT_All || DumpType == DIDT_Pubtypes)
- dumpPubSection(OS, "debug_pubtypes", getPubTypesSection(),
- isLittleEndian(), false);
+ DWARFDebugPubTable(getPubTypesSection(), isLittleEndian(), false)
+ .dump("debug_pubtypes", OS);
if (DumpType == DIDT_All || DumpType == DIDT_GnuPubnames)
- dumpPubSection(OS, "debug_gnu_pubnames", getGnuPubNamesSection(),
- isLittleEndian(), true /* GnuStyle */);
+ DWARFDebugPubTable(getGnuPubNamesSection(), isLittleEndian(),
+ true /* GnuStyle */)
+ .dump("debug_gnu_pubnames", OS);
if (DumpType == DIDT_All || DumpType == DIDT_GnuPubtypes)
- dumpPubSection(OS, "debug_gnu_pubtypes", getGnuPubTypesSection(),
- isLittleEndian(), true /* GnuStyle */);
+ DWARFDebugPubTable(getGnuPubTypesSection(), isLittleEndian(),
+ true /* GnuStyle */)
+ .dump("debug_gnu_pubtypes", OS);
if ((DumpType == DIDT_All || DumpType == DIDT_StrOffsetsDwo) &&
!getStringOffsetDWOSection().empty()) {
@@ -256,6 +230,12 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType, bool DumpEH) {
}
}
+ if ((DumpType == DIDT_All || DumpType == DIDT_GdbIndex) &&
+ !getGdbIndexSection().empty()) {
+ OS << "\n.gnu_index contents:\n";
+ getGdbIndex().dump(OS);
+ }
+
if (DumpType == DIDT_All || DumpType == DIDT_AppleNames)
dumpAccelSection(OS, "apple_names", getAppleNamesSection(),
getStringSection(), isLittleEndian());
@@ -295,6 +275,16 @@ const DWARFUnitIndex &DWARFContext::getTUIndex() {
return *TUIndex;
}
+DWARFGdbIndex &DWARFContext::getGdbIndex() {
+ if (GdbIndex)
+ return *GdbIndex;
+
+ DataExtractor GdbIndexData(getGdbIndexSection(), true /*LE*/, 0);
+ GdbIndex = llvm::make_unique<DWARFGdbIndex>();
+ GdbIndex->parse(GdbIndexData);
+ return *GdbIndex;
+}
+
const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() {
if (Abbrev)
return Abbrev.get();
@@ -393,16 +383,15 @@ DWARFContext::getLineTableForUnit(DWARFUnit *U) {
if (!Line)
Line.reset(new DWARFDebugLine(&getLineSection().Relocs));
- const auto *UnitDIE = U->getUnitDIE();
- if (UnitDIE == nullptr)
+ auto UnitDIE = U->getUnitDIE();
+ if (!UnitDIE)
return nullptr;
- unsigned stmtOffset =
- UnitDIE->getAttributeValueAsSectionOffset(U, DW_AT_stmt_list, -1U);
- if (stmtOffset == -1U)
+ auto Offset = UnitDIE.getAttributeValueAsSectionOffset(DW_AT_stmt_list);
+ if (!Offset)
return nullptr; // No line table for this compile unit.
- stmtOffset += U->getLineTableOffset();
+ uint32_t stmtOffset = *Offset + U->getLineTableOffset();
// See if the line table is cached.
if (const DWARFLineTable *lt = Line->getLineTable(stmtOffset))
return lt;
@@ -458,14 +447,12 @@ static bool getFunctionNameForAddress(DWARFCompileUnit *CU, uint64_t Address,
return false;
// The address may correspond to instruction in some inlined function,
// so we have to build the chain of inlined functions and take the
- // name of the topmost function in it.
- const DWARFDebugInfoEntryInlinedChain &InlinedChain =
- CU->getInlinedChainForAddress(Address);
- if (InlinedChain.DIEs.size() == 0)
+ // name of the topmost function in it.SmallVectorImpl<DWARFDie> &InlinedChain
+ SmallVector<DWARFDie, 4> InlinedChain;
+ CU->getInlinedChainForAddress(Address, InlinedChain);
+ if (InlinedChain.size() == 0)
return false;
- const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain.DIEs[0];
- if (const char *Name =
- TopFunctionDIE.getSubroutineName(InlinedChain.U, Kind)) {
+ if (const char *Name = InlinedChain[0].getSubroutineName(Kind)) {
FunctionName = Name;
return true;
}
@@ -540,9 +527,9 @@ DWARFContext::getInliningInfoForAddress(uint64_t Address,
return InliningInfo;
const DWARFLineTable *LineTable = nullptr;
- const DWARFDebugInfoEntryInlinedChain &InlinedChain =
- CU->getInlinedChainForAddress(Address);
- if (InlinedChain.DIEs.size() == 0) {
+ SmallVector<DWARFDie, 4> InlinedChain;
+ CU->getInlinedChainForAddress(Address, InlinedChain);
+ if (InlinedChain.size() == 0) {
// If there is no DIE for address (e.g. it is in unavailable .dwo file),
// try to at least get file/line info from symbol table.
if (Spec.FLIKind != FileLineInfoKind::None) {
@@ -557,12 +544,11 @@ DWARFContext::getInliningInfoForAddress(uint64_t Address,
}
uint32_t CallFile = 0, CallLine = 0, CallColumn = 0;
- for (uint32_t i = 0, n = InlinedChain.DIEs.size(); i != n; i++) {
- const DWARFDebugInfoEntryMinimal &FunctionDIE = InlinedChain.DIEs[i];
+ for (uint32_t i = 0, n = InlinedChain.size(); i != n; i++) {
+ DWARFDie &FunctionDIE = InlinedChain[i];
DILineInfo Frame;
// Get function name if necessary.
- if (const char *Name =
- FunctionDIE.getSubroutineName(InlinedChain.U, Spec.FNKind))
+ if (const char *Name = FunctionDIE.getSubroutineName(Spec.FNKind))
Frame.FunctionName = Name;
if (Spec.FLIKind != FileLineInfoKind::None) {
if (i == 0) {
@@ -584,8 +570,7 @@ DWARFContext::getInliningInfoForAddress(uint64_t Address,
}
// Get call file/line/column of a current DIE.
if (i + 1 < n) {
- FunctionDIE.getCallerFrame(InlinedChain.U, CallFile, CallLine,
- CallColumn);
+ FunctionDIE.getCallerFrame(CallFile, CallLine, CallColumn);
}
}
InliningInfo.addFrame(Frame);
@@ -593,66 +578,6 @@ DWARFContext::getInliningInfoForAddress(uint64_t Address,
return InliningInfo;
}
-static bool consumeCompressedGnuHeader(StringRef &data,
- uint64_t &OriginalSize) {
- // Consume "ZLIB" prefix.
- if (!data.startswith("ZLIB"))
- return false;
- data = data.substr(4);
- // Consume uncompressed section size (big-endian 8 bytes).
- DataExtractor extractor(data, false, 8);
- uint32_t Offset = 0;
- OriginalSize = extractor.getU64(&Offset);
- if (Offset == 0)
- return false;
- data = data.substr(Offset);
- return true;
-}
-
-static bool consumeCompressedZLibHeader(StringRef &Data, uint64_t &OriginalSize,
- bool IsLE, bool Is64Bit) {
- using namespace ELF;
- uint64_t HdrSize = Is64Bit ? sizeof(Elf64_Chdr) : sizeof(Elf32_Chdr);
- if (Data.size() < HdrSize)
- return false;
-
- DataExtractor Extractor(Data, IsLE, 0);
- uint32_t Offset = 0;
- if (Extractor.getUnsigned(&Offset, Is64Bit ? sizeof(Elf64_Word)
- : sizeof(Elf32_Word)) !=
- ELFCOMPRESS_ZLIB)
- return false;
-
- // Skip Elf64_Chdr::ch_reserved field.
- if (Is64Bit)
- Offset += sizeof(Elf64_Word);
-
- OriginalSize = Extractor.getUnsigned(&Offset, Is64Bit ? sizeof(Elf64_Xword)
- : sizeof(Elf32_Word));
- Data = Data.substr(HdrSize);
- return true;
-}
-
-static bool tryDecompress(StringRef &Name, StringRef &Data,
- SmallString<32> &Out, bool ZLibStyle, bool IsLE,
- bool Is64Bit) {
- if (!zlib::isAvailable())
- return false;
-
- uint64_t OriginalSize;
- bool Result =
- ZLibStyle ? consumeCompressedZLibHeader(Data, OriginalSize, IsLE, Is64Bit)
- : consumeCompressedGnuHeader(Data, OriginalSize);
-
- if (!Result || zlib::uncompress(Data, Out, OriginalSize) != zlib::StatusOK)
- return false;
-
- // gnu-style names are started from "z", consume that.
- if (!ZLibStyle)
- Name = Name.substr(1);
- return true;
-}
-
DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
const LoadedObjectInfo *L)
: IsLittleEndian(Obj.isLittleEndian()),
@@ -676,18 +601,23 @@ DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
if (!L || !L->getLoadedSectionContents(*RelocatedSection,data))
Section.getContents(data);
- name = name.substr(name.find_first_not_of("._")); // Skip . and _ prefixes.
-
- bool ZLibStyleCompressed = Section.isCompressed();
- if (ZLibStyleCompressed || name.startswith("zdebug_")) {
+ if (Decompressor::isCompressed(Section)) {
+ Expected<Decompressor> Decompressor =
+ Decompressor::create(name, data, IsLittleEndian, AddressSize == 8);
+ if (!Decompressor)
+ continue;
SmallString<32> Out;
- if (!tryDecompress(name, data, Out, ZLibStyleCompressed, IsLittleEndian,
- AddressSize == 8))
+ if (auto Err = Decompressor->decompress(Out))
continue;
UncompressedSections.emplace_back(std::move(Out));
data = UncompressedSections.back();
}
+ // Compressed sections names in GNU style starts from ".z",
+ // at this point section is decompressed and we drop compression prefix.
+ name = name.substr(
+ name.find_first_not_of("._z")); // Skip ".", "z" and "_" prefixes.
+
StringRef *SectionData =
StringSwitch<StringRef *>(name)
.Case("debug_info", &InfoSection.Data)
@@ -718,6 +648,7 @@ DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
.Case("apple_objc", &AppleObjCSection.Data)
.Case("debug_cu_index", &CUIndexSection)
.Case("debug_tu_index", &TUIndexSection)
+ .Case("gdb_index", &GdbIndexSection)
// Any more debug info sections go here.
.Default(nullptr);
if (SectionData) {
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
index 9b6a9a7..32b8320 100644
--- a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
@@ -12,31 +12,36 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <cinttypes>
+#include <cstdint>
#include <string>
-#include <utility>
#include <vector>
using namespace llvm;
using namespace dwarf;
-
/// \brief Abstract frame entry defining the common interface concrete
/// entries implement.
class llvm::FrameEntry {
public:
enum FrameKind {FK_CIE, FK_FDE};
+
FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length)
: Kind(K), Offset(Offset), Length(Length) {}
- virtual ~FrameEntry() {
- }
+ virtual ~FrameEntry() = default;
FrameKind getKind() const { return Kind; }
virtual uint64_t getOffset() const { return Offset; }
@@ -95,7 +100,6 @@ protected:
}
};
-
// See DWARF standard v3, section 7.23
const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0;
const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f;
@@ -194,6 +198,7 @@ void FrameEntry::parseInstructions(DataExtractor Data, uint32_t *Offset,
}
namespace {
+
/// \brief DWARF Common Information Entry (CIE)
class CIE : public FrameEntry {
public:
@@ -215,14 +220,16 @@ public:
FDEPointerEncoding(FDEPointerEncoding),
LSDAPointerEncoding(LSDAPointerEncoding) {}
- ~CIE() override {}
+ ~CIE() override = default;
StringRef getAugmentationString() const { return Augmentation; }
uint64_t getCodeAlignmentFactor() const { return CodeAlignmentFactor; }
int64_t getDataAlignmentFactor() const { return DataAlignmentFactor; }
+
uint32_t getFDEPointerEncoding() const {
return FDEPointerEncoding;
}
+
uint32_t getLSDAPointerEncoding() const {
return LSDAPointerEncoding;
}
@@ -274,7 +281,6 @@ private:
uint32_t LSDAPointerEncoding;
};
-
/// \brief DWARF Frame Description Entry (FDE)
class FDE : public FrameEntry {
public:
@@ -288,7 +294,7 @@ public:
InitialLocation(InitialLocation), AddressRange(AddressRange),
LinkedCIE(Cie) {}
- ~FDE() override {}
+ ~FDE() override = default;
CIE *getLinkedCIE() const { return LinkedCIE; }
@@ -336,7 +342,7 @@ static ArrayRef<OperandType[2]> getOperandTypes() {
do { \
OpTypes[OP][0] = OPTYPE0; \
OpTypes[OP][1] = OPTYPE1; \
- } while (0)
+ } while (false)
#define DECLARE_OP1(OP, OPTYPE0) DECLARE_OP2(OP, OPTYPE0, OT_None)
#define DECLARE_OP0(OP) DECLARE_OP1(OP, OT_None)
@@ -373,6 +379,7 @@ static ArrayRef<OperandType[2]> getOperandTypes() {
#undef DECLARE_OP0
#undef DECLARE_OP1
#undef DECLARE_OP2
+
return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1);
}
@@ -387,13 +394,15 @@ static void printOperand(raw_ostream &OS, uint8_t Opcode, unsigned OperandIdx,
OperandType Type = OpTypes[Opcode][OperandIdx];
switch (Type) {
- case OT_Unset:
+ case OT_Unset: {
OS << " Unsupported " << (OperandIdx ? "second" : "first") << " operand to";
- if (const char *OpcodeName = CallFrameString(Opcode))
+ auto OpcodeName = CallFrameString(Opcode);
+ if (!OpcodeName.empty())
OS << " " << OpcodeName;
else
OS << format(" Opcode %x", Opcode);
break;
+ }
case OT_None:
break;
case OT_Address:
@@ -459,8 +468,7 @@ void FrameEntry::dumpInstructions(raw_ostream &OS) const {
DWARFDebugFrame::DWARFDebugFrame(bool IsEH) : IsEH(IsEH) {
}
-DWARFDebugFrame::~DWARFDebugFrame() {
-}
+DWARFDebugFrame::~DWARFDebugFrame() = default;
static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data,
uint32_t Offset, int Length) {
@@ -611,12 +619,14 @@ void DWARFDebugFrame::parse(DataExtractor Data) {
}
}
- auto Cie = make_unique<CIE>(StartOffset, Length, Version,
- AugmentationString, AddressSize,
- SegmentDescriptorSize, CodeAlignmentFactor,
- DataAlignmentFactor, ReturnAddressRegister,
- AugmentationData, FDEPointerEncoding,
- LSDAPointerEncoding);
+ auto Cie = llvm::make_unique<CIE>(StartOffset, Length, Version,
+ AugmentationString, AddressSize,
+ SegmentDescriptorSize,
+ CodeAlignmentFactor,
+ DataAlignmentFactor,
+ ReturnAddressRegister,
+ AugmentationData, FDEPointerEncoding,
+ LSDAPointerEncoding);
CIEs[StartOffset] = Cie.get();
Entries.emplace_back(std::move(Cie));
} else {
@@ -668,7 +678,6 @@ void DWARFDebugFrame::parse(DataExtractor Data) {
}
}
-
void DWARFDebugFrame::dump(raw_ostream &OS) const {
OS << "\n";
for (const auto &Entry : Entries) {
@@ -677,4 +686,3 @@ void DWARFDebugFrame::dump(raw_ostream &OS) const {
OS << "\n";
}
}
-
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp
index 62d5e66..c487e1d 100644
--- a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp
@@ -22,170 +22,17 @@ using namespace llvm;
using namespace dwarf;
using namespace syntax;
-// Small helper to extract a DIE pointed by a reference
-// attribute. It looks up the Unit containing the DIE and calls
-// DIE.extractFast with the right unit. Returns new unit on success,
-// nullptr otherwise.
-static const DWARFUnit *findUnitAndExtractFast(DWARFDebugInfoEntryMinimal &DIE,
- const DWARFUnit *Unit,
- uint32_t *Offset) {
- Unit = Unit->getUnitSection().getUnitForOffset(*Offset);
- return (Unit && DIE.extractFast(Unit, Offset)) ? Unit : nullptr;
-}
-
-void DWARFDebugInfoEntryMinimal::dump(raw_ostream &OS, DWARFUnit *u,
- unsigned recurseDepth,
- unsigned indent) const {
- DataExtractor debug_info_data = u->getDebugInfoExtractor();
- uint32_t offset = Offset;
-
- if (debug_info_data.isValidOffset(offset)) {
- uint32_t abbrCode = debug_info_data.getULEB128(&offset);
- WithColor(OS, syntax::Address).get() << format("\n0x%8.8x: ", Offset);
-
- if (abbrCode) {
- if (AbbrevDecl) {
- const char *tagString = TagString(getTag());
- if (tagString)
- WithColor(OS, syntax::Tag).get().indent(indent) << tagString;
- else
- WithColor(OS, syntax::Tag).get().indent(indent) <<
- format("DW_TAG_Unknown_%x", getTag());
-
- OS << format(" [%u] %c\n", abbrCode,
- AbbrevDecl->hasChildren() ? '*' : ' ');
-
- // Dump all data in the DIE for the attributes.
- for (const auto &AttrSpec : AbbrevDecl->attributes()) {
- dumpAttribute(OS, u, &offset, AttrSpec.Attr, AttrSpec.Form, indent);
- }
-
- const DWARFDebugInfoEntryMinimal *child = getFirstChild();
- if (recurseDepth > 0 && child) {
- while (child) {
- child->dump(OS, u, recurseDepth-1, indent+2);
- child = child->getSibling();
- }
- }
- } else {
- OS << "Abbreviation code not found in 'debug_abbrev' class for code: "
- << abbrCode << '\n';
- }
- } else {
- OS.indent(indent) << "NULL\n";
- }
- }
-}
-
-static void dumpApplePropertyAttribute(raw_ostream &OS, uint64_t Val) {
- OS << " (";
- do {
- uint64_t Shift = countTrailingZeros(Val);
- assert(Shift < 64 && "undefined behavior");
- uint64_t Bit = 1ULL << Shift;
- if (const char *PropName = ApplePropertyString(Bit))
- OS << PropName;
- else
- OS << format("DW_APPLE_PROPERTY_0x%" PRIx64, Bit);
- if (!(Val ^= Bit))
- break;
- OS << ", ";
- } while (true);
- OS << ")";
-}
-
-static void dumpRanges(raw_ostream &OS, const DWARFAddressRangesVector& Ranges,
- unsigned AddressSize, unsigned Indent) {
- if (Ranges.empty())
- return;
-
- for (const auto &Range: Ranges) {
- OS << '\n';
- OS.indent(Indent);
- OS << format("[0x%0*" PRIx64 " - 0x%0*" PRIx64 ")",
- AddressSize*2, Range.first,
- AddressSize*2, Range.second);
- }
-}
-
-void DWARFDebugInfoEntryMinimal::dumpAttribute(raw_ostream &OS,
- DWARFUnit *u,
- uint32_t *offset_ptr,
- uint16_t attr, uint16_t form,
- unsigned indent) const {
- const char BaseIndent[] = " ";
- OS << BaseIndent;
- OS.indent(indent+2);
- const char *attrString = AttributeString(attr);
- if (attrString)
- WithColor(OS, syntax::Attribute) << attrString;
- else
- WithColor(OS, syntax::Attribute).get() << format("DW_AT_Unknown_%x", attr);
-
- const char *formString = FormEncodingString(form);
- if (formString)
- OS << " [" << formString << ']';
- else
- OS << format(" [DW_FORM_Unknown_%x]", form);
-
- DWARFFormValue formValue(form);
-
- if (!formValue.extractValue(u->getDebugInfoExtractor(), offset_ptr, u))
- return;
-
- OS << "\t(";
-
- const char *Name = nullptr;
- std::string File;
- auto Color = syntax::Enumerator;
- if (attr == DW_AT_decl_file || attr == DW_AT_call_file) {
- Color = syntax::String;
- if (const auto *LT = u->getContext().getLineTableForUnit(u))
- if (LT->getFileNameByIndex(
- formValue.getAsUnsignedConstant().getValue(),
- u->getCompilationDir(),
- DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, File)) {
- File = '"' + File + '"';
- Name = File.c_str();
- }
- } else if (Optional<uint64_t> Val = formValue.getAsUnsignedConstant())
- Name = AttributeValueString(attr, *Val);
-
- if (Name)
- WithColor(OS, Color) << Name;
- else if (attr == DW_AT_decl_line || attr == DW_AT_call_line)
- OS << *formValue.getAsUnsignedConstant();
- else
- formValue.dump(OS, u);
-
- // We have dumped the attribute raw value. For some attributes
- // having both the raw value and the pretty-printed value is
- // interesting. These attributes are handled below.
- if (attr == DW_AT_specification || attr == DW_AT_abstract_origin) {
- Optional<uint64_t> Ref = formValue.getAsReference(u);
- if (Ref.hasValue()) {
- uint32_t RefOffset = Ref.getValue();
- DWARFDebugInfoEntryMinimal DIE;
- if (const DWARFUnit *RefU = findUnitAndExtractFast(DIE, u, &RefOffset))
- if (const char *Name = DIE.getName(RefU, DINameKind::LinkageName))
- OS << " \"" << Name << '\"';
- }
- } else if (attr == DW_AT_APPLE_property_attribute) {
- if (Optional<uint64_t> OptVal = formValue.getAsUnsignedConstant())
- dumpApplePropertyAttribute(OS, *OptVal);
- } else if (attr == DW_AT_ranges) {
- dumpRanges(OS, getAddressRanges(u), u->getAddressByteSize(),
- sizeof(BaseIndent)+indent+4);
- }
-
- OS << ")\n";
-}
-
-bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFUnit *U,
+bool DWARFDebugInfoEntry::extractFast(const DWARFUnit &U,
uint32_t *OffsetPtr) {
+ DataExtractor DebugInfoData = U.getDebugInfoExtractor();
+ const uint32_t UEndOffset = U.getNextUnitOffset();
+ return extractFast(U, OffsetPtr, DebugInfoData, UEndOffset, 0);
+}
+bool DWARFDebugInfoEntry::extractFast(const DWARFUnit &U, uint32_t *OffsetPtr,
+ const DataExtractor &DebugInfoData,
+ uint32_t UEndOffset, uint32_t D) {
Offset = *OffsetPtr;
- DataExtractor DebugInfoData = U->getDebugInfoExtractor();
- uint32_t UEndOffset = U->getNextUnitOffset();
+ Depth = D;
if (Offset >= UEndOffset || !DebugInfoData.isValidOffset(Offset))
return false;
uint64_t AbbrCode = DebugInfoData.getULEB128(OffsetPtr);
@@ -194,267 +41,32 @@ bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFUnit *U,
AbbrevDecl = nullptr;
return true;
}
- AbbrevDecl = U->getAbbreviations()->getAbbreviationDeclaration(AbbrCode);
+ AbbrevDecl = U.getAbbreviations()->getAbbreviationDeclaration(AbbrCode);
if (nullptr == AbbrevDecl) {
// Restore the original offset.
*OffsetPtr = Offset;
return false;
}
- ArrayRef<uint8_t> FixedFormSizes = DWARFFormValue::getFixedFormSizes(
- U->getAddressByteSize(), U->getVersion());
- assert(FixedFormSizes.size() > 0);
+ // See if all attributes in this DIE have fixed byte sizes. If so, we can
+ // just add this size to the offset to skip to the next DIE.
+ if (Optional<size_t> FixedSize = AbbrevDecl->getFixedAttributesByteSize(U)) {
+ *OffsetPtr += *FixedSize;
+ return true;
+ }
// Skip all data in the .debug_info for the attributes
for (const auto &AttrSpec : AbbrevDecl->attributes()) {
- uint16_t Form = AttrSpec.Form;
-
- uint8_t FixedFormSize =
- (Form < FixedFormSizes.size()) ? FixedFormSizes[Form] : 0;
- if (FixedFormSize)
- *OffsetPtr += FixedFormSize;
- else if (!DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr, U)) {
- // Restore the original offset.
+ // Check if this attribute has a fixed byte size.
+ if (auto FixedSize = AttrSpec.getByteSize(U)) {
+ // Attribute byte size if fixed, just add the size to the offset.
+ *OffsetPtr += *FixedSize;
+ } else if (!DWARFFormValue::skipValue(AttrSpec.Form, DebugInfoData,
+ OffsetPtr, &U)) {
+ // We failed to skip this attribute's value, restore the original offset
+ // and return the failure status.
*OffsetPtr = Offset;
return false;
}
}
return true;
}
-
-bool DWARFDebugInfoEntryMinimal::isSubprogramDIE() const {
- return getTag() == DW_TAG_subprogram;
-}
-
-bool DWARFDebugInfoEntryMinimal::isSubroutineDIE() const {
- uint32_t Tag = getTag();
- return Tag == DW_TAG_subprogram ||
- Tag == DW_TAG_inlined_subroutine;
-}
-
-bool DWARFDebugInfoEntryMinimal::getAttributeValue(
- const DWARFUnit *U, const uint16_t Attr, DWARFFormValue &FormValue) const {
- if (!AbbrevDecl)
- return false;
-
- uint32_t AttrIdx = AbbrevDecl->findAttributeIndex(Attr);
- if (AttrIdx == -1U)
- return false;
-
- DataExtractor DebugInfoData = U->getDebugInfoExtractor();
- uint32_t DebugInfoOffset = getOffset();
-
- // Skip the abbreviation code so we are at the data for the attributes
- DebugInfoData.getULEB128(&DebugInfoOffset);
-
- // Skip preceding attribute values.
- for (uint32_t i = 0; i < AttrIdx; ++i) {
- DWARFFormValue::skipValue(AbbrevDecl->getFormByIndex(i),
- DebugInfoData, &DebugInfoOffset, U);
- }
-
- FormValue = DWARFFormValue(AbbrevDecl->getFormByIndex(AttrIdx));
- return FormValue.extractValue(DebugInfoData, &DebugInfoOffset, U);
-}
-
-const char *DWARFDebugInfoEntryMinimal::getAttributeValueAsString(
- const DWARFUnit *U, const uint16_t Attr, const char *FailValue) const {
- DWARFFormValue FormValue;
- if (!getAttributeValue(U, Attr, FormValue))
- return FailValue;
- Optional<const char *> Result = FormValue.getAsCString(U);
- return Result.hasValue() ? Result.getValue() : FailValue;
-}
-
-uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsAddress(
- const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const {
- DWARFFormValue FormValue;
- if (!getAttributeValue(U, Attr, FormValue))
- return FailValue;
- Optional<uint64_t> Result = FormValue.getAsAddress(U);
- return Result.hasValue() ? Result.getValue() : FailValue;
-}
-
-uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsUnsignedConstant(
- const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const {
- DWARFFormValue FormValue;
- if (!getAttributeValue(U, Attr, FormValue))
- return FailValue;
- Optional<uint64_t> Result = FormValue.getAsUnsignedConstant();
- return Result.hasValue() ? Result.getValue() : FailValue;
-}
-
-uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsReference(
- const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const {
- DWARFFormValue FormValue;
- if (!getAttributeValue(U, Attr, FormValue))
- return FailValue;
- Optional<uint64_t> Result = FormValue.getAsReference(U);
- return Result.hasValue() ? Result.getValue() : FailValue;
-}
-
-uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsSectionOffset(
- const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const {
- DWARFFormValue FormValue;
- if (!getAttributeValue(U, Attr, FormValue))
- return FailValue;
- Optional<uint64_t> Result = FormValue.getAsSectionOffset();
- return Result.hasValue() ? Result.getValue() : FailValue;
-}
-
-uint64_t
-DWARFDebugInfoEntryMinimal::getRangesBaseAttribute(const DWARFUnit *U,
- uint64_t FailValue) const {
- uint64_t Result =
- getAttributeValueAsSectionOffset(U, DW_AT_ranges_base, -1ULL);
- if (Result != -1ULL)
- return Result;
- return getAttributeValueAsSectionOffset(U, DW_AT_GNU_ranges_base, FailValue);
-}
-
-bool DWARFDebugInfoEntryMinimal::getLowAndHighPC(const DWARFUnit *U,
- uint64_t &LowPC,
- uint64_t &HighPC) const {
- LowPC = getAttributeValueAsAddress(U, DW_AT_low_pc, -1ULL);
- if (LowPC == -1ULL)
- return false;
- HighPC = getAttributeValueAsAddress(U, DW_AT_high_pc, -1ULL);
- if (HighPC == -1ULL) {
- // Since DWARF4, DW_AT_high_pc may also be of class constant, in which case
- // it represents function size.
- HighPC = getAttributeValueAsUnsignedConstant(U, DW_AT_high_pc, -1ULL);
- if (HighPC != -1ULL)
- HighPC += LowPC;
- }
- return (HighPC != -1ULL);
-}
-
-DWARFAddressRangesVector
-DWARFDebugInfoEntryMinimal::getAddressRanges(const DWARFUnit *U) const {
- if (isNULL())
- return DWARFAddressRangesVector();
- // Single range specified by low/high PC.
- uint64_t LowPC, HighPC;
- if (getLowAndHighPC(U, LowPC, HighPC)) {
- return DWARFAddressRangesVector(1, std::make_pair(LowPC, HighPC));
- }
- // Multiple ranges from .debug_ranges section.
- uint32_t RangesOffset =
- getAttributeValueAsSectionOffset(U, DW_AT_ranges, -1U);
- if (RangesOffset != -1U) {
- DWARFDebugRangeList RangeList;
- if (U->extractRangeList(RangesOffset, RangeList))
- return RangeList.getAbsoluteRanges(U->getBaseAddress());
- }
- return DWARFAddressRangesVector();
-}
-
-void DWARFDebugInfoEntryMinimal::collectChildrenAddressRanges(
- const DWARFUnit *U, DWARFAddressRangesVector& Ranges) const {
- if (isNULL())
- return;
- if (isSubprogramDIE()) {
- const auto &DIERanges = getAddressRanges(U);
- Ranges.insert(Ranges.end(), DIERanges.begin(), DIERanges.end());
- }
-
- const DWARFDebugInfoEntryMinimal *Child = getFirstChild();
- while (Child) {
- Child->collectChildrenAddressRanges(U, Ranges);
- Child = Child->getSibling();
- }
-}
-
-bool DWARFDebugInfoEntryMinimal::addressRangeContainsAddress(
- const DWARFUnit *U, const uint64_t Address) const {
- for (const auto& R : getAddressRanges(U)) {
- if (R.first <= Address && Address < R.second)
- return true;
- }
- return false;
-}
-
-const char *
-DWARFDebugInfoEntryMinimal::getSubroutineName(const DWARFUnit *U,
- DINameKind Kind) const {
- if (!isSubroutineDIE())
- return nullptr;
- return getName(U, Kind);
-}
-
-const char *
-DWARFDebugInfoEntryMinimal::getName(const DWARFUnit *U,
- DINameKind Kind) const {
- if (Kind == DINameKind::None)
- return nullptr;
- // Try to get mangled name only if it was asked for.
- if (Kind == DINameKind::LinkageName) {
- if (const char *name =
- getAttributeValueAsString(U, DW_AT_MIPS_linkage_name, nullptr))
- return name;
- if (const char *name =
- getAttributeValueAsString(U, DW_AT_linkage_name, nullptr))
- return name;
- }
- if (const char *name = getAttributeValueAsString(U, DW_AT_name, nullptr))
- return name;
- // Try to get name from specification DIE.
- uint32_t spec_ref =
- getAttributeValueAsReference(U, DW_AT_specification, -1U);
- if (spec_ref != -1U) {
- DWARFDebugInfoEntryMinimal spec_die;
- if (const DWARFUnit *RefU = findUnitAndExtractFast(spec_die, U, &spec_ref)) {
- if (const char *name = spec_die.getName(RefU, Kind))
- return name;
- }
- }
- // Try to get name from abstract origin DIE.
- uint32_t abs_origin_ref =
- getAttributeValueAsReference(U, DW_AT_abstract_origin, -1U);
- if (abs_origin_ref != -1U) {
- DWARFDebugInfoEntryMinimal abs_origin_die;
- if (const DWARFUnit *RefU = findUnitAndExtractFast(abs_origin_die, U,
- &abs_origin_ref)) {
- if (const char *name = abs_origin_die.getName(RefU, Kind))
- return name;
- }
- }
- return nullptr;
-}
-
-void DWARFDebugInfoEntryMinimal::getCallerFrame(const DWARFUnit *U,
- uint32_t &CallFile,
- uint32_t &CallLine,
- uint32_t &CallColumn) const {
- CallFile = getAttributeValueAsUnsignedConstant(U, DW_AT_call_file, 0);
- CallLine = getAttributeValueAsUnsignedConstant(U, DW_AT_call_line, 0);
- CallColumn = getAttributeValueAsUnsignedConstant(U, DW_AT_call_column, 0);
-}
-
-DWARFDebugInfoEntryInlinedChain
-DWARFDebugInfoEntryMinimal::getInlinedChainForAddress(
- const DWARFUnit *U, const uint64_t Address) const {
- DWARFDebugInfoEntryInlinedChain InlinedChain;
- InlinedChain.U = U;
- if (isNULL())
- return InlinedChain;
- for (const DWARFDebugInfoEntryMinimal *DIE = this; DIE; ) {
- // Append current DIE to inlined chain only if it has correct tag
- // (e.g. it is not a lexical block).
- if (DIE->isSubroutineDIE()) {
- InlinedChain.DIEs.push_back(*DIE);
- }
- // Try to get child which also contains provided address.
- const DWARFDebugInfoEntryMinimal *Child = DIE->getFirstChild();
- while (Child) {
- if (Child->addressRangeContainsAddress(U, Address)) {
- // Assume there is only one such child.
- break;
- }
- Child = Child->getSibling();
- }
- DIE = Child;
- }
- // Reverse the obtained chain to make the root of inlined chain last.
- std::reverse(InlinedChain.DIEs.begin(), InlinedChain.DIEs.end());
- return InlinedChain;
-}
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
index 30cb833..4940594 100644
--- a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
@@ -42,8 +42,8 @@ void DWARFDebugLine::Prologue::dump(raw_ostream &OS) const {
<< format(" opcode_base: %u\n", OpcodeBase);
for (uint32_t i = 0; i < StandardOpcodeLengths.size(); ++i)
- OS << format("standard_opcode_lengths[%s] = %u\n", LNStandardString(i + 1),
- StandardOpcodeLengths[i]);
+ OS << format("standard_opcode_lengths[%s] = %u\n",
+ LNStandardString(i + 1).data(), StandardOpcodeLengths[i]);
if (!IncludeDirectories.empty())
for (uint32_t i = 0; i < IncludeDirectories.size(); ++i)
@@ -624,12 +624,17 @@ bool DWARFDebugLine::LineTable::lookupAddressRange(
return true;
}
-bool DWARFDebugLine::LineTable::getFileNameByIndex(uint64_t FileIndex,
- const char *CompDir,
- FileLineInfoKind Kind,
- std::string &Result) const {
- if (FileIndex == 0 || FileIndex > Prologue.FileNames.size() ||
- Kind == FileLineInfoKind::None)
+bool
+DWARFDebugLine::LineTable::hasFileAtIndex(uint64_t FileIndex) const {
+ return FileIndex != 0 && FileIndex <= Prologue.FileNames.size();
+}
+
+bool
+DWARFDebugLine::LineTable::getFileNameByIndex(uint64_t FileIndex,
+ const char *CompDir,
+ FileLineInfoKind Kind,
+ std::string &Result) const {
+ if (Kind == FileLineInfoKind::None || !hasFileAtIndex(FileIndex))
return false;
const FileNameEntry &Entry = Prologue.FileNames[FileIndex - 1];
const char *FileName = Entry.Name;
@@ -673,5 +678,6 @@ bool DWARFDebugLine::LineTable::getFileLineInfoForAddress(
return false;
Result.Line = Row.Line;
Result.Column = Row.Column;
+ Result.Discriminator = Row.Discriminator;
return true;
}
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
index a7b46b8..ae5b9d7 100644
--- a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
@@ -82,9 +82,9 @@ void DWARFDebugLocDWO::parse(DataExtractor data) {
Loc.Offset = Offset;
dwarf::LocationListEntry Kind;
while ((Kind = static_cast<dwarf::LocationListEntry>(
- data.getU8(&Offset))) != dwarf::DW_LLE_end_of_list_entry) {
+ data.getU8(&Offset))) != dwarf::DW_LLE_end_of_list) {
- if (Kind != dwarf::DW_LLE_start_length_entry) {
+ if (Kind != dwarf::DW_LLE_startx_length) {
llvm::errs() << "error: dumping support for LLE of kind " << (int)Kind
<< " not implemented\n";
return;
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugPubTable.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugPubTable.cpp
new file mode 100644
index 0000000..3c1fe93
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugPubTable.cpp
@@ -0,0 +1,65 @@
+//===-- DWARFDebugPubTable.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/DWARF/DWARFDebugPubTable.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+using namespace llvm::dwarf;
+
+DWARFDebugPubTable::DWARFDebugPubTable(StringRef Data, bool LittleEndian,
+ bool GnuStyle)
+ : GnuStyle(GnuStyle) {
+ DataExtractor PubNames(Data, LittleEndian, 0);
+ uint32_t Offset = 0;
+ while (PubNames.isValidOffset(Offset)) {
+ Sets.push_back({});
+ Set &SetData = Sets.back();
+
+ SetData.Length = PubNames.getU32(&Offset);
+ SetData.Version = PubNames.getU16(&Offset);
+ SetData.Offset = PubNames.getU32(&Offset);
+ SetData.Size = PubNames.getU32(&Offset);
+
+ while (Offset < Data.size()) {
+ uint32_t DieRef = PubNames.getU32(&Offset);
+ if (DieRef == 0)
+ break;
+ uint8_t IndexEntryValue = GnuStyle ? PubNames.getU8(&Offset) : 0;
+ const char *Name = PubNames.getCStr(&Offset);
+ SetData.Entries.push_back(
+ {DieRef, PubIndexEntryDescriptor(IndexEntryValue), Name});
+ }
+ }
+}
+
+void DWARFDebugPubTable::dump(StringRef Name, raw_ostream &OS) const {
+ OS << "\n." << Name << " contents: a\n";
+ for (const Set &S : Sets) {
+ OS << "length = " << format("0x%08x", S.Length);
+ OS << " version = " << format("0x%04x", S.Version);
+ OS << " unit_offset = " << format("0x%08x", S.Offset);
+ OS << " unit_size = " << format("0x%08x", S.Size) << '\n';
+ OS << (GnuStyle ? "Offset Linkage Kind Name\n"
+ : "Offset Name\n");
+
+ for (const Entry &E : S.Entries) {
+ OS << format("0x%8.8x ", E.SecOffset);
+ if (GnuStyle) {
+ StringRef EntryLinkage =
+ dwarf::GDBIndexEntryLinkageString(E.Descriptor.Linkage);
+ StringRef EntryKind = dwarf::GDBIndexEntryKindString(E.Descriptor.Kind);
+ OS << format("%-8s", EntryLinkage.data()) << ' '
+ << format("%-8s", EntryKind.data()) << ' ';
+ }
+ OS << '\"' << E.Name << "\"\n";
+ }
+ }
+}
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
new file mode 100644
index 0000000..89b83b1
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
@@ -0,0 +1,401 @@
+//===-- DWARFDie.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/DWARF/DWARFDie.h"
+#include "SyntaxHighlighting.h"
+#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
+#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+using namespace dwarf;
+using namespace syntax;
+
+namespace {
+ static void dumpApplePropertyAttribute(raw_ostream &OS, uint64_t Val) {
+ OS << " (";
+ do {
+ uint64_t Shift = countTrailingZeros(Val);
+ assert(Shift < 64 && "undefined behavior");
+ uint64_t Bit = 1ULL << Shift;
+ auto PropName = ApplePropertyString(Bit);
+ if (!PropName.empty())
+ OS << PropName;
+ else
+ OS << format("DW_APPLE_PROPERTY_0x%" PRIx64, Bit);
+ if (!(Val ^= Bit))
+ break;
+ OS << ", ";
+ } while (true);
+ OS << ")";
+}
+
+static void dumpRanges(raw_ostream &OS, const DWARFAddressRangesVector& Ranges,
+ unsigned AddressSize, unsigned Indent) {
+ if (Ranges.empty())
+ return;
+
+ for (const auto &Range: Ranges) {
+ OS << '\n';
+ OS.indent(Indent);
+ OS << format("[0x%0*" PRIx64 " - 0x%0*" PRIx64 ")",
+ AddressSize*2, Range.first,
+ AddressSize*2, Range.second);
+ }
+}
+
+static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die,
+ uint32_t *OffsetPtr, dwarf::Attribute Attr,
+ dwarf::Form Form, unsigned Indent) {
+ if (!Die.isValid())
+ return;
+ const char BaseIndent[] = " ";
+ OS << BaseIndent;
+ OS.indent(Indent+2);
+ auto attrString = AttributeString(Attr);
+ if (!attrString.empty())
+ WithColor(OS, syntax::Attribute) << attrString;
+ else
+ WithColor(OS, syntax::Attribute).get() << format("DW_AT_Unknown_%x", Attr);
+
+ auto formString = FormEncodingString(Form);
+ if (!formString.empty())
+ OS << " [" << formString << ']';
+ else
+ OS << format(" [DW_FORM_Unknown_%x]", Form);
+
+ DWARFUnit *U = Die.getDwarfUnit();
+ DWARFFormValue formValue(Form);
+
+ if (!formValue.extractValue(U->getDebugInfoExtractor(), OffsetPtr, U))
+ return;
+
+ OS << "\t(";
+
+ StringRef Name;
+ std::string File;
+ auto Color = syntax::Enumerator;
+ if (Attr == DW_AT_decl_file || Attr == DW_AT_call_file) {
+ Color = syntax::String;
+ if (const auto *LT = U->getContext().getLineTableForUnit(U))
+ if (LT->getFileNameByIndex(formValue.getAsUnsignedConstant().getValue(), U->getCompilationDir(), DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, File)) {
+ File = '"' + File + '"';
+ Name = File;
+ }
+ } else if (Optional<uint64_t> Val = formValue.getAsUnsignedConstant())
+ Name = AttributeValueString(Attr, *Val);
+
+ if (!Name.empty())
+ WithColor(OS, Color) << Name;
+ else if (Attr == DW_AT_decl_line || Attr == DW_AT_call_line)
+ OS << *formValue.getAsUnsignedConstant();
+ else
+ formValue.dump(OS);
+
+ // We have dumped the attribute raw value. For some attributes
+ // having both the raw value and the pretty-printed value is
+ // interesting. These attributes are handled below.
+ if (Attr == DW_AT_specification || Attr == DW_AT_abstract_origin) {
+ if (const char *Name = Die.getAttributeValueAsReferencedDie(Attr).getName(DINameKind::LinkageName))
+ OS << " \"" << Name << '\"';
+ } else if (Attr == DW_AT_APPLE_property_attribute) {
+ if (Optional<uint64_t> OptVal = formValue.getAsUnsignedConstant())
+ dumpApplePropertyAttribute(OS, *OptVal);
+ } else if (Attr == DW_AT_ranges) {
+ dumpRanges(OS, Die.getAddressRanges(), U->getAddressByteSize(),
+ sizeof(BaseIndent)+Indent+4);
+ }
+
+ OS << ")\n";
+}
+
+} // end anonymous namespace
+
+bool DWARFDie::isSubprogramDIE() const {
+ return getTag() == DW_TAG_subprogram;
+}
+
+bool DWARFDie::isSubroutineDIE() const {
+ auto Tag = getTag();
+ return Tag == DW_TAG_subprogram || Tag == DW_TAG_inlined_subroutine;
+}
+
+Optional<DWARFFormValue>
+DWARFDie::getAttributeValue(dwarf::Attribute Attr) const {
+ if (!isValid())
+ return None;
+ auto AbbrevDecl = getAbbreviationDeclarationPtr();
+ if (AbbrevDecl)
+ return AbbrevDecl->getAttributeValue(getOffset(), Attr, *U);
+ return None;
+}
+
+const char *DWARFDie::getAttributeValueAsString(dwarf::Attribute Attr,
+ const char *FailValue) const {
+ auto FormValue = getAttributeValue(Attr);
+ if (!FormValue)
+ return FailValue;
+ Optional<const char *> Result = FormValue->getAsCString();
+ return Result.hasValue() ? Result.getValue() : FailValue;
+}
+
+Optional<uint64_t>
+DWARFDie::getAttributeValueAsAddress(dwarf::Attribute Attr) const {
+ if (auto FormValue = getAttributeValue(Attr))
+ return FormValue->getAsAddress();
+ return None;
+}
+
+Optional<int64_t>
+DWARFDie::getAttributeValueAsSignedConstant(dwarf::Attribute Attr) const {
+ if (auto FormValue = getAttributeValue(Attr))
+ return FormValue->getAsSignedConstant();
+ return None;
+}
+
+Optional<uint64_t>
+DWARFDie::getAttributeValueAsUnsignedConstant(dwarf::Attribute Attr) const {
+ if (auto FormValue = getAttributeValue(Attr))
+ return FormValue->getAsUnsignedConstant();
+ return None;
+}
+
+Optional<uint64_t>
+DWARFDie::getAttributeValueAsReference(dwarf::Attribute Attr) const {
+ if (auto FormValue = getAttributeValue(Attr))
+ return FormValue->getAsReference();
+ return None;
+}
+
+Optional<uint64_t>
+DWARFDie::getAttributeValueAsSectionOffset(dwarf::Attribute Attr) const {
+ if (auto FormValue = getAttributeValue(Attr))
+ return FormValue->getAsSectionOffset();
+ return None;
+}
+
+
+DWARFDie
+DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const {
+ auto SpecRef = getAttributeValueAsReference(Attr);
+ if (SpecRef) {
+ auto SpecUnit = U->getUnitSection().getUnitForOffset(*SpecRef);
+ if (SpecUnit)
+ return SpecUnit->getDIEForOffset(*SpecRef);
+ }
+ return DWARFDie();
+}
+
+Optional<uint64_t>
+DWARFDie::getRangesBaseAttribute() const {
+ auto Result = getAttributeValueAsSectionOffset(DW_AT_rnglists_base);
+ if (Result)
+ return Result;
+ return getAttributeValueAsSectionOffset(DW_AT_GNU_ranges_base);
+}
+
+Optional<uint64_t> DWARFDie::getHighPC(uint64_t LowPC) const {
+ if (auto FormValue = getAttributeValue(DW_AT_high_pc)) {
+ if (auto Address = FormValue->getAsAddress()) {
+ // High PC is an address.
+ return Address;
+ }
+ if (auto Offset = FormValue->getAsUnsignedConstant()) {
+ // High PC is an offset from LowPC.
+ return LowPC + *Offset;
+ }
+ }
+ return None;
+}
+
+bool DWARFDie::getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC) const {
+ auto LowPcAddr = getAttributeValueAsAddress(DW_AT_low_pc);
+ if (!LowPcAddr)
+ return false;
+ if (auto HighPcAddr = getHighPC(*LowPcAddr)) {
+ LowPC = *LowPcAddr;
+ HighPC = *HighPcAddr;
+ return true;
+ }
+ return false;
+}
+
+DWARFAddressRangesVector
+DWARFDie::getAddressRanges() const {
+ if (isNULL())
+ return DWARFAddressRangesVector();
+ // Single range specified by low/high PC.
+ uint64_t LowPC, HighPC;
+ if (getLowAndHighPC(LowPC, HighPC)) {
+ return DWARFAddressRangesVector(1, std::make_pair(LowPC, HighPC));
+ }
+ // Multiple ranges from .debug_ranges section.
+ auto RangesOffset = getAttributeValueAsSectionOffset(DW_AT_ranges);
+ if (RangesOffset) {
+ DWARFDebugRangeList RangeList;
+ if (U->extractRangeList(*RangesOffset, RangeList))
+ return RangeList.getAbsoluteRanges(U->getBaseAddress());
+ }
+ return DWARFAddressRangesVector();
+}
+
+void
+DWARFDie::collectChildrenAddressRanges(DWARFAddressRangesVector& Ranges) const {
+ if (isNULL())
+ return;
+ if (isSubprogramDIE()) {
+ const auto &DIERanges = getAddressRanges();
+ Ranges.insert(Ranges.end(), DIERanges.begin(), DIERanges.end());
+ }
+
+ for (auto Child: children())
+ Child.collectChildrenAddressRanges(Ranges);
+}
+
+bool DWARFDie::addressRangeContainsAddress(const uint64_t Address) const {
+ for (const auto& R : getAddressRanges()) {
+ if (R.first <= Address && Address < R.second)
+ return true;
+ }
+ return false;
+}
+
+const char *
+DWARFDie::getSubroutineName(DINameKind Kind) const {
+ if (!isSubroutineDIE())
+ return nullptr;
+ return getName(Kind);
+}
+
+const char *
+DWARFDie::getName(DINameKind Kind) const {
+ if (!isValid() || Kind == DINameKind::None)
+ return nullptr;
+ const char *name = nullptr;
+ // Try to get mangled name only if it was asked for.
+ if (Kind == DINameKind::LinkageName) {
+ if ((name = getAttributeValueAsString(DW_AT_MIPS_linkage_name, nullptr)))
+ return name;
+ if ((name = getAttributeValueAsString(DW_AT_linkage_name, nullptr)))
+ return name;
+ }
+ if ((name = getAttributeValueAsString(DW_AT_name, nullptr)))
+ return name;
+ // Try to get name from specification DIE.
+ DWARFDie SpecDie = getAttributeValueAsReferencedDie(DW_AT_specification);
+ if (SpecDie && (name = SpecDie.getName(Kind)))
+ return name;
+ // Try to get name from abstract origin DIE.
+ DWARFDie AbsDie = getAttributeValueAsReferencedDie(DW_AT_abstract_origin);
+ if (AbsDie && (name = AbsDie.getName(Kind)))
+ return name;
+ return nullptr;
+}
+
+void DWARFDie::getCallerFrame(uint32_t &CallFile, uint32_t &CallLine,
+ uint32_t &CallColumn) const {
+ CallFile = getAttributeValueAsUnsignedConstant(DW_AT_call_file).getValueOr(0);
+ CallLine = getAttributeValueAsUnsignedConstant(DW_AT_call_line).getValueOr(0);
+ CallColumn =
+ getAttributeValueAsUnsignedConstant(DW_AT_call_column).getValueOr(0);
+}
+
+void DWARFDie::dump(raw_ostream &OS, unsigned RecurseDepth,
+ unsigned Indent) const {
+ if (!isValid())
+ return;
+ DataExtractor debug_info_data = U->getDebugInfoExtractor();
+ const uint32_t Offset = getOffset();
+ uint32_t offset = Offset;
+
+ if (debug_info_data.isValidOffset(offset)) {
+ uint32_t abbrCode = debug_info_data.getULEB128(&offset);
+ WithColor(OS, syntax::Address).get() << format("\n0x%8.8x: ", Offset);
+
+ if (abbrCode) {
+ auto AbbrevDecl = getAbbreviationDeclarationPtr();
+ if (AbbrevDecl) {
+ auto tagString = TagString(getTag());
+ if (!tagString.empty())
+ WithColor(OS, syntax::Tag).get().indent(Indent) << tagString;
+ else
+ WithColor(OS, syntax::Tag).get().indent(Indent)
+ << format("DW_TAG_Unknown_%x", getTag());
+
+ OS << format(" [%u] %c\n", abbrCode,
+ AbbrevDecl->hasChildren() ? '*' : ' ');
+
+ // Dump all data in the DIE for the attributes.
+ for (const auto &AttrSpec : AbbrevDecl->attributes()) {
+ dumpAttribute(OS, *this, &offset, AttrSpec.Attr, AttrSpec.Form,
+ Indent);
+ }
+
+ DWARFDie child = getFirstChild();
+ if (RecurseDepth > 0 && child) {
+ while (child) {
+ child.dump(OS, RecurseDepth-1, Indent+2);
+ child = child.getSibling();
+ }
+ }
+ } else {
+ OS << "Abbreviation code not found in 'debug_abbrev' class for code: "
+ << abbrCode << '\n';
+ }
+ } else {
+ OS.indent(Indent) << "NULL\n";
+ }
+ }
+}
+
+
+void DWARFDie::getInlinedChainForAddress(
+ const uint64_t Address, SmallVectorImpl<DWARFDie> &InlinedChain) const {
+ if (isNULL())
+ return;
+ DWARFDie DIE(*this);
+ while (DIE) {
+ // Append current DIE to inlined chain only if it has correct tag
+ // (e.g. it is not a lexical block).
+ if (DIE.isSubroutineDIE())
+ InlinedChain.push_back(DIE);
+
+ // Try to get child which also contains provided address.
+ DWARFDie Child = DIE.getFirstChild();
+ while (Child) {
+ if (Child.addressRangeContainsAddress(Address)) {
+ // Assume there is only one such child.
+ break;
+ }
+ Child = Child.getSibling();
+ }
+ DIE = Child;
+ }
+ // Reverse the obtained chain to make the root of inlined chain last.
+ std::reverse(InlinedChain.begin(), InlinedChain.end());
+}
+
+DWARFDie DWARFDie::getParent() const {
+ if (isValid())
+ return U->getParent(Die);
+ return DWARFDie();
+}
+
+DWARFDie DWARFDie::getSibling() const {
+ if (isValid())
+ return U->getSibling(Die);
+ return DWARFDie();
+}
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp
index 3dc5842..dc9310d 100644
--- a/contrib/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp
@@ -23,60 +23,6 @@ using namespace llvm;
using namespace dwarf;
using namespace syntax;
-namespace {
-uint8_t getRefAddrSize(uint8_t AddrSize, uint16_t Version) {
- // FIXME: Support DWARF64.
- return (Version == 2) ? AddrSize : 4;
-}
-
-template <uint8_t AddrSize, uint8_t RefAddrSize>
-ArrayRef<uint8_t> makeFixedFormSizesArrayRef() {
- static const uint8_t sizes[] = {
- 0, // 0x00 unused
- AddrSize, // 0x01 DW_FORM_addr
- 0, // 0x02 unused
- 0, // 0x03 DW_FORM_block2
- 0, // 0x04 DW_FORM_block4
- 2, // 0x05 DW_FORM_data2
- 4, // 0x06 DW_FORM_data4
- 8, // 0x07 DW_FORM_data8
- 0, // 0x08 DW_FORM_string
- 0, // 0x09 DW_FORM_block
- 0, // 0x0a DW_FORM_block1
- 1, // 0x0b DW_FORM_data1
- 1, // 0x0c DW_FORM_flag
- 0, // 0x0d DW_FORM_sdata
- 4, // 0x0e DW_FORM_strp
- 0, // 0x0f DW_FORM_udata
- RefAddrSize, // 0x10 DW_FORM_ref_addr
- 1, // 0x11 DW_FORM_ref1
- 2, // 0x12 DW_FORM_ref2
- 4, // 0x13 DW_FORM_ref4
- 8, // 0x14 DW_FORM_ref8
- 0, // 0x15 DW_FORM_ref_udata
- 0, // 0x16 DW_FORM_indirect
- 4, // 0x17 DW_FORM_sec_offset
- 0, // 0x18 DW_FORM_exprloc
- 0, // 0x19 DW_FORM_flag_present
- };
- return makeArrayRef(sizes);
-}
-}
-
-ArrayRef<uint8_t> DWARFFormValue::getFixedFormSizes(uint8_t AddrSize,
- uint16_t Version) {
- uint8_t RefAddrSize = getRefAddrSize(AddrSize, Version);
- if (AddrSize == 4 && RefAddrSize == 4)
- return makeFixedFormSizesArrayRef<4, 4>();
- if (AddrSize == 4 && RefAddrSize == 8)
- return makeFixedFormSizesArrayRef<4, 8>();
- if (AddrSize == 8 && RefAddrSize == 4)
- return makeFixedFormSizesArrayRef<8, 4>();
- if (AddrSize == 8 && RefAddrSize == 8)
- return makeFixedFormSizesArrayRef<8, 8>();
- return None;
-}
-
static const DWARFFormValue::FormClass DWARF4FormClasses[] = {
DWARFFormValue::FC_Unknown, // 0x0
DWARFFormValue::FC_Address, // 0x01 DW_FORM_addr
@@ -108,6 +54,217 @@ static const DWARFFormValue::FormClass DWARF4FormClasses[] = {
DWARFFormValue::FC_Flag, // 0x19 DW_FORM_flag_present
};
+namespace {
+
+/// A helper class that can be used in DWARFFormValue.cpp functions that need
+/// to know the byte size of DW_FORM values that vary in size depending on the
+/// DWARF version, address byte size, or DWARF32 or DWARF64.
+class FormSizeHelper {
+ uint16_t Version;
+ uint8_t AddrSize;
+ llvm::dwarf::DwarfFormat Format;
+
+public:
+ FormSizeHelper(uint16_t V, uint8_t A, llvm::dwarf::DwarfFormat F)
+ : Version(V), AddrSize(A), Format(F) {}
+ uint8_t getAddressByteSize() const { return AddrSize; }
+ uint8_t getRefAddrByteSize() const {
+ if (Version == 2)
+ return AddrSize;
+ return getDwarfOffsetByteSize();
+ }
+ uint8_t getDwarfOffsetByteSize() const {
+ switch (Format) {
+ case dwarf::DwarfFormat::DWARF32:
+ return 4;
+ case dwarf::DwarfFormat::DWARF64:
+ return 8;
+ }
+ llvm_unreachable("Invalid Format value");
+ }
+};
+
+} // end anonymous namespace
+
+template <class T>
+static Optional<uint8_t> getFixedByteSize(dwarf::Form Form, const T *U) {
+ switch (Form) {
+ case DW_FORM_addr:
+ if (U)
+ return U->getAddressByteSize();
+ return None;
+
+ case DW_FORM_block: // ULEB128 length L followed by L bytes.
+ case DW_FORM_block1: // 1 byte length L followed by L bytes.
+ case DW_FORM_block2: // 2 byte length L followed by L bytes.
+ case DW_FORM_block4: // 4 byte length L followed by L bytes.
+ case DW_FORM_string: // C-string with null terminator.
+ case DW_FORM_sdata: // SLEB128.
+ case DW_FORM_udata: // ULEB128.
+ case DW_FORM_ref_udata: // ULEB128.
+ case DW_FORM_indirect: // ULEB128.
+ case DW_FORM_exprloc: // ULEB128 length L followed by L bytes.
+ case DW_FORM_strx: // ULEB128.
+ case DW_FORM_addrx: // ULEB128.
+ case DW_FORM_loclistx: // ULEB128.
+ case DW_FORM_rnglistx: // ULEB128.
+ case DW_FORM_GNU_addr_index: // ULEB128.
+ case DW_FORM_GNU_str_index: // ULEB128.
+ return None;
+
+ case DW_FORM_ref_addr:
+ if (U)
+ return U->getRefAddrByteSize();
+ return None;
+
+ case DW_FORM_flag:
+ case DW_FORM_data1:
+ case DW_FORM_ref1:
+ return 1;
+
+ case DW_FORM_data2:
+ case DW_FORM_ref2:
+ return 2;
+
+ case DW_FORM_data4:
+ case DW_FORM_ref4:
+ return 4;
+
+ case DW_FORM_strp:
+ case DW_FORM_GNU_ref_alt:
+ case DW_FORM_GNU_strp_alt:
+ case DW_FORM_line_strp:
+ case DW_FORM_sec_offset:
+ case DW_FORM_strp_sup:
+ case DW_FORM_ref_sup:
+ if (U)
+ return U->getDwarfOffsetByteSize();
+ return None;
+
+ case DW_FORM_data8:
+ case DW_FORM_ref8:
+ case DW_FORM_ref_sig8:
+ return 8;
+
+ case DW_FORM_flag_present:
+ return 0;
+
+ case DW_FORM_data16:
+ return 16;
+
+ case DW_FORM_implicit_const:
+ // The implicit value is stored in the abbreviation as a SLEB128, and
+ // there no data in debug info.
+ return 0;
+
+ default:
+ llvm_unreachable("Handle this form in this switch statement");
+ }
+ return None;
+}
+
+template <class T>
+static bool skipFormValue(dwarf::Form Form, const DataExtractor &DebugInfoData,
+ uint32_t *OffsetPtr, const T *U) {
+ bool Indirect = false;
+ do {
+ switch (Form) {
+ // Blocks of inlined data that have a length field and the data bytes
+ // inlined in the .debug_info.
+ case DW_FORM_exprloc:
+ case DW_FORM_block: {
+ uint64_t size = DebugInfoData.getULEB128(OffsetPtr);
+ *OffsetPtr += size;
+ return true;
+ }
+ case DW_FORM_block1: {
+ uint8_t size = DebugInfoData.getU8(OffsetPtr);
+ *OffsetPtr += size;
+ return true;
+ }
+ case DW_FORM_block2: {
+ uint16_t size = DebugInfoData.getU16(OffsetPtr);
+ *OffsetPtr += size;
+ return true;
+ }
+ case DW_FORM_block4: {
+ uint32_t size = DebugInfoData.getU32(OffsetPtr);
+ *OffsetPtr += size;
+ return true;
+ }
+
+ // Inlined NULL terminated C-strings.
+ case DW_FORM_string:
+ DebugInfoData.getCStr(OffsetPtr);
+ return true;
+
+ case DW_FORM_addr:
+ case DW_FORM_ref_addr:
+ case DW_FORM_flag_present:
+ case DW_FORM_data1:
+ case DW_FORM_data2:
+ case DW_FORM_data4:
+ case DW_FORM_data8:
+ case DW_FORM_flag:
+ case DW_FORM_ref1:
+ case DW_FORM_ref2:
+ case DW_FORM_ref4:
+ case DW_FORM_ref8:
+ case DW_FORM_ref_sig8:
+ case DW_FORM_ref_sup:
+ case DW_FORM_sec_offset:
+ case DW_FORM_strp:
+ case DW_FORM_strp_sup:
+ case DW_FORM_line_strp:
+ case DW_FORM_GNU_ref_alt:
+ case DW_FORM_GNU_strp_alt:
+ if (Optional<uint8_t> FixedSize = ::getFixedByteSize(Form, U)) {
+ *OffsetPtr += *FixedSize;
+ return true;
+ }
+ return false;
+
+ // signed or unsigned LEB 128 values.
+ case DW_FORM_sdata:
+ DebugInfoData.getSLEB128(OffsetPtr);
+ return true;
+
+ case DW_FORM_udata:
+ case DW_FORM_ref_udata:
+ case DW_FORM_strx:
+ case DW_FORM_addrx:
+ case DW_FORM_loclistx:
+ case DW_FORM_rnglistx:
+ case DW_FORM_GNU_addr_index:
+ case DW_FORM_GNU_str_index:
+ DebugInfoData.getULEB128(OffsetPtr);
+ return true;
+
+ case DW_FORM_indirect:
+ Indirect = true;
+ Form = static_cast<dwarf::Form>(DebugInfoData.getULEB128(OffsetPtr));
+ break;
+
+ default:
+ return false;
+ }
+ } while (Indirect);
+ return true;
+}
+
+Optional<uint8_t> DWARFFormValue::getFixedByteSize(dwarf::Form Form,
+ const DWARFUnit *U) {
+ return ::getFixedByteSize(Form, U);
+}
+
+Optional<uint8_t>
+DWARFFormValue::getFixedByteSize(dwarf::Form Form, uint16_t Version,
+ uint8_t AddrSize,
+ llvm::dwarf::DwarfFormat Format) {
+ FormSizeHelper FSH(Version, AddrSize, Format);
+ return ::getFixedByteSize(Form, &FSH);
+}
+
bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const {
// First, check DWARF4 form classes.
if (Form < makeArrayRef(DWARF4FormClasses).size() &&
@@ -123,6 +280,10 @@ bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const {
case DW_FORM_GNU_str_index:
case DW_FORM_GNU_strp_alt:
return (FC == FC_String);
+ case DW_FORM_implicit_const:
+ return (FC == FC_Constant);
+ default:
+ break;
}
// In DWARF3 DW_FORM_data4 and DW_FORM_data8 served also as a section offset.
// Don't check for DWARF version here, as some producers may still do this
@@ -131,8 +292,10 @@ bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const {
FC == FC_SectionOffset;
}
-bool DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
+bool DWARFFormValue::extractValue(const DataExtractor &data,
+ uint32_t *offset_ptr,
const DWARFUnit *cu) {
+ U = cu;
bool indirect = false;
bool is_block = false;
Value.data = nullptr;
@@ -143,16 +306,15 @@ bool DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
switch (Form) {
case DW_FORM_addr:
case DW_FORM_ref_addr: {
- if (!cu)
+ if (!U)
return false;
uint16_t AddrSize =
(Form == DW_FORM_addr)
- ? cu->getAddressByteSize()
- : getRefAddrSize(cu->getAddressByteSize(), cu->getVersion());
- RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr);
- if (AI != cu->getRelocMap()->end()) {
- const std::pair<uint8_t, int64_t> &R = AI->second;
- Value.uval = data.getUnsigned(offset_ptr, AddrSize) + R.second;
+ ? U->getAddressByteSize()
+ : U->getRefAddrByteSize();
+ RelocAddrMap::const_iterator AI = U->getRelocMap()->find(*offset_ptr);
+ if (AI != U->getRelocMap()->end()) {
+ Value.uval = data.getUnsigned(offset_ptr, AddrSize) + AI->second.second;
} else
Value.uval = data.getUnsigned(offset_ptr, AddrSize);
break;
@@ -186,10 +348,10 @@ bool DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
case DW_FORM_data4:
case DW_FORM_ref4: {
Value.uval = data.getU32(offset_ptr);
- if (!cu)
+ if (!U)
break;
- RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr-4);
- if (AI != cu->getRelocMap()->end())
+ RelocAddrMap::const_iterator AI = U->getRelocMap()->find(*offset_ptr-4);
+ if (AI != U->getRelocMap()->end())
Value.uval += AI->second.second;
break;
}
@@ -208,20 +370,22 @@ bool DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
Value.cstr = data.getCStr(offset_ptr);
break;
case DW_FORM_indirect:
- Form = data.getULEB128(offset_ptr);
+ Form = static_cast<dwarf::Form>(data.getULEB128(offset_ptr));
indirect = true;
break;
- case DW_FORM_sec_offset:
case DW_FORM_strp:
+ case DW_FORM_sec_offset:
case DW_FORM_GNU_ref_alt:
- case DW_FORM_GNU_strp_alt: {
- // FIXME: This is 64-bit for DWARF64.
- Value.uval = data.getU32(offset_ptr);
- if (!cu)
- break;
- RelocAddrMap::const_iterator AI =
- cu->getRelocMap()->find(*offset_ptr - 4);
- if (AI != cu->getRelocMap()->end())
+ case DW_FORM_GNU_strp_alt:
+ case DW_FORM_line_strp:
+ case DW_FORM_strp_sup:
+ case DW_FORM_ref_sup: {
+ if (!U)
+ return false;
+ RelocAddrMap::const_iterator AI = U->getRelocMap()->find(*offset_ptr);
+ uint8_t Size = U->getDwarfOffsetByteSize();
+ Value.uval = data.getUnsigned(offset_ptr, Size);
+ if (AI != U->getRelocMap()->end())
Value.uval += AI->second.second;
break;
}
@@ -252,123 +416,26 @@ bool DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
return true;
}
-bool
-DWARFFormValue::skipValue(DataExtractor debug_info_data, uint32_t* offset_ptr,
- const DWARFUnit *cu) const {
- return DWARFFormValue::skipValue(Form, debug_info_data, offset_ptr, cu);
+bool DWARFFormValue::skipValue(DataExtractor DebugInfoData,
+ uint32_t *offset_ptr, const DWARFUnit *U) const {
+ return DWARFFormValue::skipValue(Form, DebugInfoData, offset_ptr, U);
}
-bool
-DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data,
- uint32_t *offset_ptr, const DWARFUnit *cu) {
- return skipValue(form, debug_info_data, offset_ptr, cu->getVersion(),
- cu->getAddressByteSize());
+bool DWARFFormValue::skipValue(dwarf::Form form, DataExtractor DebugInfoData,
+ uint32_t *offset_ptr, const DWARFUnit *U) {
+ return skipFormValue(form, DebugInfoData, offset_ptr, U);
}
-bool DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data,
- uint32_t *offset_ptr, uint16_t Version,
- uint8_t AddrSize) {
- bool indirect = false;
- do {
- switch (form) {
- // Blocks if inlined data that have a length field and the data bytes
- // inlined in the .debug_info
- case DW_FORM_exprloc:
- case DW_FORM_block: {
- uint64_t size = debug_info_data.getULEB128(offset_ptr);
- *offset_ptr += size;
- return true;
- }
- case DW_FORM_block1: {
- uint8_t size = debug_info_data.getU8(offset_ptr);
- *offset_ptr += size;
- return true;
- }
- case DW_FORM_block2: {
- uint16_t size = debug_info_data.getU16(offset_ptr);
- *offset_ptr += size;
- return true;
- }
- case DW_FORM_block4: {
- uint32_t size = debug_info_data.getU32(offset_ptr);
- *offset_ptr += size;
- return true;
- }
-
- // Inlined NULL terminated C-strings
- case DW_FORM_string:
- debug_info_data.getCStr(offset_ptr);
- return true;
-
- // Compile unit address sized values
- case DW_FORM_addr:
- *offset_ptr += AddrSize;
- return true;
- case DW_FORM_ref_addr:
- *offset_ptr += getRefAddrSize(AddrSize, Version);
- return true;
-
- // 0 byte values - implied from the form.
- case DW_FORM_flag_present:
- return true;
-
- // 1 byte values
- case DW_FORM_data1:
- case DW_FORM_flag:
- case DW_FORM_ref1:
- *offset_ptr += 1;
- return true;
-
- // 2 byte values
- case DW_FORM_data2:
- case DW_FORM_ref2:
- *offset_ptr += 2;
- return true;
-
- // 4 byte values
- case DW_FORM_data4:
- case DW_FORM_ref4:
- *offset_ptr += 4;
- return true;
- // 8 byte values
- case DW_FORM_data8:
- case DW_FORM_ref8:
- case DW_FORM_ref_sig8:
- *offset_ptr += 8;
- return true;
-
- // signed or unsigned LEB 128 values
- // case DW_FORM_APPLE_db_str:
- case DW_FORM_sdata:
- case DW_FORM_udata:
- case DW_FORM_ref_udata:
- case DW_FORM_GNU_str_index:
- case DW_FORM_GNU_addr_index:
- debug_info_data.getULEB128(offset_ptr);
- return true;
-
- case DW_FORM_indirect:
- indirect = true;
- form = debug_info_data.getULEB128(offset_ptr);
- break;
-
- // FIXME: 4 for DWARF32, 8 for DWARF64.
- case DW_FORM_sec_offset:
- case DW_FORM_strp:
- case DW_FORM_GNU_ref_alt:
- case DW_FORM_GNU_strp_alt:
- *offset_ptr += 4;
- return true;
-
- default:
- return false;
- }
- } while (indirect);
- return true;
+bool DWARFFormValue::skipValue(dwarf::Form form, DataExtractor DebugInfoData,
+ uint32_t *offset_ptr, uint16_t Version,
+ uint8_t AddrSize,
+ llvm::dwarf::DwarfFormat Format) {
+ FormSizeHelper FSH(Version, AddrSize, Format);
+ return skipFormValue(form, DebugInfoData, offset_ptr, &FSH);
}
void
-DWARFFormValue::dump(raw_ostream &OS, const DWARFUnit *cu) const {
+DWARFFormValue::dump(raw_ostream &OS) const {
uint64_t uvalue = Value.uval;
bool cu_relative_offset = false;
@@ -377,7 +444,9 @@ DWARFFormValue::dump(raw_ostream &OS, const DWARFUnit *cu) const {
case DW_FORM_GNU_addr_index: {
OS << format(" indexed (%8.8x) address = ", (uint32_t)uvalue);
uint64_t Address;
- if (cu->getAddrOffsetSectionItem(uvalue, Address))
+ if (U == nullptr)
+ OS << "<invalid dwarf unit>";
+ else if (U->getAddrOffsetSectionItem(uvalue, Address))
OS << format("0x%016" PRIx64, Address);
else
OS << "<no .debug_addr section>";
@@ -428,17 +497,17 @@ DWARFFormValue::dump(raw_ostream &OS, const DWARFUnit *cu) const {
case DW_FORM_udata: OS << Value.uval; break;
case DW_FORM_strp: {
OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue);
- dumpString(OS, cu);
+ dumpString(OS);
break;
}
case DW_FORM_GNU_str_index: {
OS << format(" indexed (%8.8x) string = ", (uint32_t)uvalue);
- dumpString(OS, cu);
+ dumpString(OS);
break;
}
case DW_FORM_GNU_strp_alt: {
OS << format("alt indirect string, offset: 0x%" PRIx64 "", uvalue);
- dumpString(OS, cu);
+ dumpString(OS);
break;
}
case DW_FORM_ref_addr:
@@ -487,13 +556,13 @@ DWARFFormValue::dump(raw_ostream &OS, const DWARFUnit *cu) const {
if (cu_relative_offset) {
OS << " => {";
WithColor(OS, syntax::Address).get()
- << format("0x%8.8" PRIx64, uvalue + (cu ? cu->getOffset() : 0));
+ << format("0x%8.8" PRIx64, uvalue + (U ? U->getOffset() : 0));
OS << "}";
}
}
-void DWARFFormValue::dumpString(raw_ostream &OS, const DWARFUnit *U) const {
- Optional<const char *> DbgStr = getAsCString(U);
+void DWARFFormValue::dumpString(raw_ostream &OS) const {
+ Optional<const char *> DbgStr = getAsCString();
if (DbgStr.hasValue()) {
raw_ostream &COS = WithColor(OS, syntax::String);
COS << '"';
@@ -502,7 +571,7 @@ void DWARFFormValue::dumpString(raw_ostream &OS, const DWARFUnit *U) const {
}
}
-Optional<const char *> DWARFFormValue::getAsCString(const DWARFUnit *U) const {
+Optional<const char *> DWARFFormValue::getAsCString() const {
if (!isFormClass(FC_String))
return None;
if (Form == DW_FORM_string)
@@ -523,7 +592,7 @@ Optional<const char *> DWARFFormValue::getAsCString(const DWARFUnit *U) const {
return None;
}
-Optional<uint64_t> DWARFFormValue::getAsAddress(const DWARFUnit *U) const {
+Optional<uint64_t> DWARFFormValue::getAsAddress() const {
if (!isFormClass(FC_Address))
return None;
if (Form == DW_FORM_GNU_addr_index) {
@@ -536,7 +605,7 @@ Optional<uint64_t> DWARFFormValue::getAsAddress(const DWARFUnit *U) const {
return Value.uval;
}
-Optional<uint64_t> DWARFFormValue::getAsReference(const DWARFUnit *U) const {
+Optional<uint64_t> DWARFFormValue::getAsReference() const {
if (!isFormClass(FC_Reference))
return None;
switch (Form) {
@@ -549,8 +618,9 @@ Optional<uint64_t> DWARFFormValue::getAsReference(const DWARFUnit *U) const {
return None;
return Value.uval + U->getOffset();
case DW_FORM_ref_addr:
+ case DW_FORM_ref_sig8:
+ case DW_FORM_GNU_ref_alt:
return Value.uval;
- // FIXME: Add proper support for DW_FORM_ref_sig8 and DW_FORM_GNU_ref_alt.
default:
return None;
}
@@ -593,3 +663,15 @@ Optional<ArrayRef<uint8_t>> DWARFFormValue::getAsBlock() const {
return makeArrayRef(Value.data, Value.uval);
}
+Optional<uint64_t> DWARFFormValue::getAsCStringOffset() const {
+ if (!isFormClass(FC_String) && Form == DW_FORM_string)
+ return None;
+ return Value.uval;
+}
+
+Optional<uint64_t> DWARFFormValue::getAsReferenceUVal() const {
+ if (!isFormClass(FC_Reference))
+ return None;
+ return Value.uval;
+}
+
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp
new file mode 100644
index 0000000..ebb9961
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp
@@ -0,0 +1,176 @@
+//===-- DWARFGdbIndex.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/DWARF/DWARFGdbIndex.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
+
+using namespace llvm;
+
+// .gdb_index section format reference:
+// https://sourceware.org/gdb/onlinedocs/gdb/Index-Section-Format.html
+
+void DWARFGdbIndex::dumpCUList(raw_ostream &OS) const {
+ OS << format("\n CU list offset = 0x%x, has %" PRId64 " entries:",
+ CuListOffset, (uint64_t)CuList.size())
+ << '\n';
+ uint32_t I = 0;
+ for (const CompUnitEntry &CU : CuList)
+ OS << format(" %d: Offset = 0x%llx, Length = 0x%llx\n", I++, CU.Offset,
+ CU.Length);
+}
+
+void DWARFGdbIndex::dumpAddressArea(raw_ostream &OS) const {
+ OS << format("\n Address area offset = 0x%x, has %" PRId64 " entries:",
+ AddressAreaOffset, (uint64_t)AddressArea.size())
+ << '\n';
+ for (const AddressEntry &Addr : AddressArea)
+ OS << format(
+ " Low address = 0x%llx, High address = 0x%llx, CU index = %d\n",
+ Addr.LowAddress, Addr.HighAddress, Addr.CuIndex);
+}
+
+void DWARFGdbIndex::dumpSymbolTable(raw_ostream &OS) const {
+ OS << format("\n Symbol table offset = 0x%x, size = %" PRId64
+ ", filled slots:",
+ SymbolTableOffset, (uint64_t)SymbolTable.size())
+ << '\n';
+ uint32_t I = -1;
+ for (const SymTableEntry &E : SymbolTable) {
+ ++I;
+ if (!E.NameOffset && !E.VecOffset)
+ continue;
+
+ OS << format(" %d: Name offset = 0x%x, CU vector offset = 0x%x\n", I,
+ E.NameOffset, E.VecOffset);
+
+ StringRef Name = ConstantPoolStrings.substr(
+ ConstantPoolOffset - StringPoolOffset + E.NameOffset);
+
+ auto CuVector = std::find_if(
+ ConstantPoolVectors.begin(), ConstantPoolVectors.end(),
+ [&](const std::pair<uint32_t, SmallVector<uint32_t, 0>> &V) {
+ return V.first == E.VecOffset;
+ });
+ assert(CuVector != ConstantPoolVectors.end() && "Invalid symbol table");
+ uint32_t CuVectorId = CuVector - ConstantPoolVectors.begin();
+ OS << format(" String name: %s, CU vector index: %d\n", Name.data(),
+ CuVectorId);
+ }
+}
+
+void DWARFGdbIndex::dumpConstantPool(raw_ostream &OS) const {
+ OS << format("\n Constant pool offset = 0x%x, has %" PRId64 " CU vectors:",
+ ConstantPoolOffset, (uint64_t)ConstantPoolVectors.size());
+ uint32_t I = 0;
+ for (const auto &V : ConstantPoolVectors) {
+ OS << format("\n %d(0x%x): ", I++, V.first);
+ for (uint32_t Val : V.second)
+ OS << format("0x%x ", Val);
+ }
+ OS << '\n';
+}
+
+void DWARFGdbIndex::dump(raw_ostream &OS) {
+ if (HasError) {
+ OS << "\n<error parsing>\n";
+ return;
+ }
+
+ if (HasContent) {
+ OS << " Version = " << Version << '\n';
+ dumpCUList(OS);
+ dumpAddressArea(OS);
+ dumpSymbolTable(OS);
+ dumpConstantPool(OS);
+ }
+}
+
+bool DWARFGdbIndex::parseImpl(DataExtractor Data) {
+ uint32_t Offset = 0;
+
+ // Only version 7 is supported at this moment.
+ Version = Data.getU32(&Offset);
+ if (Version != 7)
+ return false;
+
+ CuListOffset = Data.getU32(&Offset);
+ uint32_t CuTypesOffset = Data.getU32(&Offset);
+ AddressAreaOffset = Data.getU32(&Offset);
+ SymbolTableOffset = Data.getU32(&Offset);
+ ConstantPoolOffset = Data.getU32(&Offset);
+
+ if (Offset != CuListOffset)
+ return false;
+
+ uint32_t CuListSize = (CuTypesOffset - CuListOffset) / 16;
+ CuList.reserve(CuListSize);
+ for (uint32_t i = 0; i < CuListSize; ++i) {
+ uint64_t CuOffset = Data.getU64(&Offset);
+ uint64_t CuLength = Data.getU64(&Offset);
+ CuList.push_back({CuOffset, CuLength});
+ }
+
+ // CU Types are no longer needed as DWARF skeleton type units never made it
+ // into the standard.
+ uint32_t CuTypesListSize = (AddressAreaOffset - CuTypesOffset) / 24;
+ if (CuTypesListSize != 0)
+ return false;
+
+ uint32_t AddressAreaSize = (SymbolTableOffset - AddressAreaOffset) / 20;
+ AddressArea.reserve(AddressAreaSize);
+ for (uint32_t i = 0; i < AddressAreaSize; ++i) {
+ uint64_t LowAddress = Data.getU64(&Offset);
+ uint64_t HighAddress = Data.getU64(&Offset);
+ uint32_t CuIndex = Data.getU32(&Offset);
+ AddressArea.push_back({LowAddress, HighAddress, CuIndex});
+ }
+
+ // The symbol table. This is an open addressed hash table. The size of the
+ // hash table is always a power of 2.
+ // Each slot in the hash table consists of a pair of offset_type values. The
+ // first value is the offset of the symbol's name in the constant pool. The
+ // second value is the offset of the CU vector in the constant pool.
+ // If both values are 0, then this slot in the hash table is empty. This is ok
+ // because while 0 is a valid constant pool index, it cannot be a valid index
+ // for both a string and a CU vector.
+ uint32_t SymTableSize = (ConstantPoolOffset - SymbolTableOffset) / 8;
+ SymbolTable.reserve(SymTableSize);
+ uint32_t CuVectorsTotal = 0;
+ for (uint32_t i = 0; i < SymTableSize; ++i) {
+ uint32_t NameOffset = Data.getU32(&Offset);
+ uint32_t CuVecOffset = Data.getU32(&Offset);
+ SymbolTable.push_back({NameOffset, CuVecOffset});
+ if (NameOffset || CuVecOffset)
+ ++CuVectorsTotal;
+ }
+
+ // The constant pool. CU vectors are stored first, followed by strings.
+ // The first value is the number of CU indices in the vector. Each subsequent
+ // value is the index and symbol attributes of a CU in the CU list.
+ for (uint32_t i = 0; i < CuVectorsTotal; ++i) {
+ ConstantPoolVectors.emplace_back(0, SmallVector<uint32_t, 0>());
+ auto &Vec = ConstantPoolVectors.back();
+ Vec.first = Offset - ConstantPoolOffset;
+
+ uint32_t Num = Data.getU32(&Offset);
+ for (uint32_t j = 0; j < Num; ++j)
+ Vec.second.push_back(Data.getU32(&Offset));
+ }
+
+ ConstantPoolStrings = Data.getData().drop_front(Offset);
+ StringPoolOffset = Offset;
+ return true;
+}
+
+void DWARFGdbIndex::parse(DataExtractor Data) {
+ HasContent = !Data.getData().empty();
+ HasError = HasContent && !parseImpl(Data);
+}
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp
index 766e8ac..88fb203 100644
--- a/contrib/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp
@@ -8,6 +8,8 @@
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
+#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
+#include "llvm/Support/Dwarf.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
@@ -22,19 +24,29 @@ bool DWARFTypeUnit::extractImpl(DataExtractor debug_info,
return TypeOffset < getLength();
}
-void DWARFTypeUnit::dump(raw_ostream &OS) {
+void DWARFTypeUnit::dump(raw_ostream &OS, bool SummarizeTypes) {
+ DWARFDie TD = getDIEForOffset(TypeOffset + getOffset());
+ const char *Name = TD.getAttributeValueAsString(llvm::dwarf::DW_AT_name, "");
+
+ if (SummarizeTypes) {
+ OS << "name = '" << Name << "'"
+ << " type_signature = " << format("0x%16" PRIx64, TypeHash)
+ << " length = " << format("0x%08x", getLength()) << '\n';
+ return;
+ }
+
OS << format("0x%08x", getOffset()) << ": Type Unit:"
<< " length = " << format("0x%08x", getLength())
<< " version = " << format("0x%04x", getVersion())
<< " abbr_offset = " << format("0x%04x", getAbbreviations()->getOffset())
<< " addr_size = " << format("0x%02x", getAddressByteSize())
+ << " name = '" << Name << "'"
<< " type_signature = " << format("0x%16" PRIx64, TypeHash)
<< " type_offset = " << format("0x%04x", TypeOffset)
- << " (next unit at " << format("0x%08x", getNextUnitOffset())
- << ")\n";
+ << " (next unit at " << format("0x%08x", getNextUnitOffset()) << ")\n";
- if (const DWARFDebugInfoEntryMinimal *TU = getUnitDIE(false))
- TU->dump(OS, this, -1U);
+ if (DWARFDie TU = getUnitDIE(false))
+ TU.dump(OS, -1U);
else
OS << "<type unit can't be parsed!>\n\n";
}
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
index 13c2b50..ee2c569 100644
--- a/contrib/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
@@ -7,14 +7,25 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
-#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
-#include "llvm/Support/Dwarf.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/Path.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
#include <cstdio>
+#include <vector>
namespace llvm {
+
using namespace dwarf;
void DWARFUnitSectionBase::parse(DWARFContext &C, const DWARFSection &Section) {
@@ -49,8 +60,7 @@ DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section,
clear();
}
-DWARFUnit::~DWARFUnit() {
-}
+DWARFUnit::~DWARFUnit() = default;
bool DWARFUnit::getAddrOffsetSectionItem(uint32_t Index,
uint64_t &Result) const {
@@ -121,7 +131,7 @@ bool DWARFUnit::extract(DataExtractor debug_info, uint32_t *offset_ptr) {
bool DWARFUnit::extractRangeList(uint32_t RangeListOffset,
DWARFDebugRangeList &RangeList) const {
// Require that compile unit is extracted.
- assert(DieArray.size() > 0);
+ assert(!DieArray.empty());
DataExtractor RangesData(RangeSection, isLittleEndian, AddrSize);
uint32_t ActualRangeListOffset = RangeSectionBase + RangeListOffset;
return RangeList.extract(RangesData, &ActualRangeListOffset);
@@ -141,53 +151,16 @@ void DWARFUnit::clear() {
}
const char *DWARFUnit::getCompilationDir() {
- extractDIEsIfNeeded(true);
- if (DieArray.empty())
- return nullptr;
- return DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, nullptr);
+ return getUnitDIE().getAttributeValueAsString(DW_AT_comp_dir, nullptr);
}
-uint64_t DWARFUnit::getDWOId() {
- extractDIEsIfNeeded(true);
- const uint64_t FailValue = -1ULL;
- if (DieArray.empty())
- return FailValue;
- return DieArray[0]
- .getAttributeValueAsUnsignedConstant(this, DW_AT_GNU_dwo_id, FailValue);
-}
-
-void DWARFUnit::setDIERelations() {
- if (DieArray.size() <= 1)
- return;
-
- std::vector<DWARFDebugInfoEntryMinimal *> ParentChain;
- DWARFDebugInfoEntryMinimal *SiblingChain = nullptr;
- for (auto &DIE : DieArray) {
- if (SiblingChain) {
- SiblingChain->setSibling(&DIE);
- }
- if (const DWARFAbbreviationDeclaration *AbbrDecl =
- DIE.getAbbreviationDeclarationPtr()) {
- // Normal DIE.
- if (AbbrDecl->hasChildren()) {
- ParentChain.push_back(&DIE);
- SiblingChain = nullptr;
- } else {
- SiblingChain = &DIE;
- }
- } else {
- // NULL entry terminates the sibling chain.
- SiblingChain = ParentChain.back();
- ParentChain.pop_back();
- }
- }
- assert(SiblingChain == nullptr || SiblingChain == &DieArray[0]);
- assert(ParentChain.empty());
+Optional<uint64_t> DWARFUnit::getDWOId() {
+ return getUnitDIE().getAttributeValueAsUnsignedConstant(DW_AT_GNU_dwo_id);
}
void DWARFUnit::extractDIEsToVector(
bool AppendCUDie, bool AppendNonCUDies,
- std::vector<DWARFDebugInfoEntryMinimal> &Dies) const {
+ std::vector<DWARFDebugInfoEntry> &Dies) const {
if (!AppendCUDie && !AppendNonCUDies)
return;
@@ -195,11 +168,13 @@ void DWARFUnit::extractDIEsToVector(
// next compilation unit header.
uint32_t DIEOffset = Offset + getHeaderSize();
uint32_t NextCUOffset = getNextUnitOffset();
- DWARFDebugInfoEntryMinimal DIE;
+ DWARFDebugInfoEntry DIE;
+ DataExtractor DebugInfoData = getDebugInfoExtractor();
uint32_t Depth = 0;
bool IsCUDie = true;
- while (DIEOffset < NextCUOffset && DIE.extractFast(this, &DIEOffset)) {
+ while (DIE.extractFast(*this, &DIEOffset, DebugInfoData, NextCUOffset,
+ Depth)) {
if (IsCUDie) {
if (AppendCUDie)
Dies.push_back(DIE);
@@ -237,11 +212,11 @@ void DWARFUnit::extractDIEsToVector(
}
size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) {
- if ((CUDieOnly && DieArray.size() > 0) ||
+ if ((CUDieOnly && !DieArray.empty()) ||
DieArray.size() > 1)
return 0; // Already parsed.
- bool HasCUDie = DieArray.size() > 0;
+ bool HasCUDie = !DieArray.empty();
extractDIEsToVector(!HasCUDie, !CUDieOnly, DieArray);
if (DieArray.empty())
@@ -249,25 +224,27 @@ size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) {
// If CU DIE was just parsed, copy several attribute values from it.
if (!HasCUDie) {
- uint64_t BaseAddr =
- DieArray[0].getAttributeValueAsAddress(this, DW_AT_low_pc, -1ULL);
- if (BaseAddr == -1ULL)
- BaseAddr = DieArray[0].getAttributeValueAsAddress(this, DW_AT_entry_pc, 0);
- setBaseAddress(BaseAddr);
- AddrOffsetSectionBase = DieArray[0].getAttributeValueAsSectionOffset(
- this, DW_AT_GNU_addr_base, 0);
- RangeSectionBase = DieArray[0].getAttributeValueAsSectionOffset(
- this, DW_AT_ranges_base, 0);
+ DWARFDie UnitDie = getUnitDIE();
+ auto BaseAddr = UnitDie.getAttributeValueAsAddress(DW_AT_low_pc);
+ if (!BaseAddr)
+ BaseAddr = UnitDie.getAttributeValueAsAddress(DW_AT_entry_pc);
+ if (BaseAddr)
+ setBaseAddress(*BaseAddr);
+ AddrOffsetSectionBase =
+ UnitDie.getAttributeValueAsSectionOffset(DW_AT_GNU_addr_base)
+ .getValueOr(0);
+ RangeSectionBase =
+ UnitDie.getAttributeValueAsSectionOffset(DW_AT_rnglists_base)
+ .getValueOr(0);
// Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for
// skeleton CU DIE, so that DWARF users not aware of it are not broken.
}
- setDIERelations();
return DieArray.size();
}
DWARFUnit::DWOHolder::DWOHolder(StringRef DWOPath)
- : DWOFile(), DWOContext(), DWOU(nullptr) {
+ : DWOU(nullptr) {
auto Obj = object::ObjectFile::createObjectFile(DWOPath);
if (!Obj) {
// TODO: Actually report errors helpfully.
@@ -286,15 +263,15 @@ bool DWARFUnit::parseDWO() {
return false;
if (DWO.get())
return false;
- extractDIEsIfNeeded(true);
- if (DieArray.empty())
+ DWARFDie UnitDie = getUnitDIE();
+ if (!UnitDie)
return false;
const char *DWOFileName =
- DieArray[0].getAttributeValueAsString(this, DW_AT_GNU_dwo_name, nullptr);
+ UnitDie.getAttributeValueAsString(DW_AT_GNU_dwo_name, nullptr);
if (!DWOFileName)
return false;
const char *CompilationDir =
- DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, nullptr);
+ UnitDie.getAttributeValueAsString(DW_AT_comp_dir, nullptr);
SmallString<16> AbsolutePath;
if (sys::path::is_relative(DWOFileName) && CompilationDir != nullptr) {
sys::path::append(AbsolutePath, CompilationDir);
@@ -309,8 +286,8 @@ bool DWARFUnit::parseDWO() {
}
// Share .debug_addr and .debug_ranges section with compile unit in .dwo
DWOCU->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase);
- uint32_t DWORangesBase = DieArray[0].getRangesBaseAttribute(this, 0);
- DWOCU->setRangesSection(RangeSection, DWORangesBase);
+ auto DWORangesBase = UnitDie.getRangesBaseAttribute();
+ DWOCU->setRangesSection(RangeSection, DWORangesBase ? *DWORangesBase : 0);
return true;
}
@@ -323,7 +300,7 @@ void DWARFUnit::clearDIEs(bool KeepCUDie) {
// contents which will cause just the internal pointers to be swapped
// so that when temporary vector goes out of scope, it will destroy the
// contents.
- std::vector<DWARFDebugInfoEntryMinimal> TmpArray;
+ std::vector<DWARFDebugInfoEntry> TmpArray;
DieArray.swap(TmpArray);
// Save at least the compile unit DIE
if (KeepCUDie)
@@ -332,11 +309,11 @@ void DWARFUnit::clearDIEs(bool KeepCUDie) {
}
void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) {
- const auto *U = getUnitDIE();
- if (U == nullptr)
+ DWARFDie UnitDie = getUnitDIE();
+ if (!UnitDie)
return;
// First, check if unit DIE describes address ranges for the whole unit.
- const auto &CUDIERanges = U->getAddressRanges(this);
+ const auto &CUDIERanges = UnitDie.getAddressRanges();
if (!CUDIERanges.empty()) {
CURanges.insert(CURanges.end(), CUDIERanges.begin(), CUDIERanges.end());
return;
@@ -349,7 +326,7 @@ void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) {
// up parsing the DWARF and then throwing them all away to keep memory usage
// down.
const bool ClearDIEs = extractDIEsIfNeeded(false) > 1;
- DieArray[0].collectChildrenAddressRanges(this, CURanges);
+ getUnitDIE().collectChildrenAddressRanges(CURanges);
// Collect address ranges from DIEs in .dwo if necessary.
bool DWOCreated = parseDWO();
@@ -364,36 +341,37 @@ void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) {
clearDIEs(true);
}
-const DWARFDebugInfoEntryMinimal *
+DWARFDie
DWARFUnit::getSubprogramForAddress(uint64_t Address) {
extractDIEsIfNeeded(false);
- for (const DWARFDebugInfoEntryMinimal &DIE : DieArray) {
+ for (const DWARFDebugInfoEntry &D : DieArray) {
+ DWARFDie DIE(this, &D);
if (DIE.isSubprogramDIE() &&
- DIE.addressRangeContainsAddress(this, Address)) {
- return &DIE;
+ DIE.addressRangeContainsAddress(Address)) {
+ return DIE;
}
}
- return nullptr;
+ return DWARFDie();
}
-DWARFDebugInfoEntryInlinedChain
-DWARFUnit::getInlinedChainForAddress(uint64_t Address) {
+void
+DWARFUnit::getInlinedChainForAddress(uint64_t Address,
+ SmallVectorImpl<DWARFDie> &InlinedChain) {
// First, find a subprogram that contains the given address (the root
// of inlined chain).
- const DWARFUnit *ChainCU = nullptr;
- const DWARFDebugInfoEntryMinimal *SubprogramDIE;
+ DWARFDie SubprogramDIE;
// Try to look for subprogram DIEs in the DWO file.
parseDWO();
- if (DWO) {
- if ((SubprogramDIE = DWO->getUnit()->getSubprogramForAddress(Address)))
- ChainCU = DWO->getUnit();
- } else if ((SubprogramDIE = getSubprogramForAddress(Address)))
- ChainCU = this;
+ if (DWO)
+ SubprogramDIE = DWO->getUnit()->getSubprogramForAddress(Address);
+ else
+ SubprogramDIE = getSubprogramForAddress(Address);
// Get inlined chain rooted at this subprogram DIE.
- if (!SubprogramDIE)
- return DWARFDebugInfoEntryInlinedChain();
- return SubprogramDIE->getInlinedChainForAddress(ChainCU, Address);
+ if (SubprogramDIE)
+ SubprogramDIE.getInlinedChainForAddress(Address, InlinedChain);
+ else
+ InlinedChain.clear();
}
const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context,
@@ -403,4 +381,43 @@ const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context,
assert(Kind == DW_SECT_TYPES);
return Context.getTUIndex();
}
+
+DWARFDie DWARFUnit::getParent(const DWARFDebugInfoEntry *Die) {
+ if (!Die)
+ return DWARFDie();
+ const uint32_t Depth = Die->getDepth();
+ // Unit DIEs always have a depth of zero and never have parents.
+ if (Depth == 0)
+ return DWARFDie();
+ // Depth of 1 always means parent is the compile/type unit.
+ if (Depth == 1)
+ return getUnitDIE();
+ // Look for previous DIE with a depth that is one less than the Die's depth.
+ const uint32_t ParentDepth = Depth - 1;
+ for (uint32_t I = getDIEIndex(Die) - 1; I > 0; --I) {
+ if (DieArray[I].getDepth() == ParentDepth)
+ return DWARFDie(this, &DieArray[I]);
+ }
+ return DWARFDie();
}
+
+DWARFDie DWARFUnit::getSibling(const DWARFDebugInfoEntry *Die) {
+ if (!Die)
+ return DWARFDie();
+ uint32_t Depth = Die->getDepth();
+ // Unit DIEs always have a depth of zero and never have siblings.
+ if (Depth == 0)
+ return DWARFDie();
+ // NULL DIEs don't have siblings.
+ if (Die->getAbbreviationDeclarationPtr() == nullptr)
+ return DWARFDie();
+
+ // Find the next DIE whose depth is the same as the Die's depth.
+ for (size_t I=getDIEIndex(Die)+1, EndIdx = DieArray.size(); I<EndIdx; ++I) {
+ if (DieArray[I].getDepth() == Depth)
+ return DWARFDie(this, &DieArray[I]);
+ }
+ return DWARFDie();
+}
+
+} // end namespace llvm
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/MsfBuilder.cpp b/contrib/llvm/lib/DebugInfo/MSF/MSFBuilder.cpp
index 16b086b..5b1b5d8 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/Raw/MsfBuilder.cpp
+++ b/contrib/llvm/lib/DebugInfo/MSF/MSFBuilder.cpp
@@ -1,4 +1,3 @@
-//===- MSFBuilder.cpp - MSF Directory & Metadata Builder --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,12 +6,11 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/DebugInfo/PDB/Raw/MsfBuilder.h"
-#include "llvm/DebugInfo/PDB/Raw/RawError.h"
+#include "llvm/DebugInfo/MSF/MSFBuilder.h"
+#include "llvm/DebugInfo/MSF/MSFError.h"
using namespace llvm;
-using namespace llvm::pdb;
-using namespace llvm::pdb::msf;
+using namespace llvm::msf;
using namespace llvm::support;
namespace {
@@ -21,12 +19,14 @@ const uint32_t kFreePageMap0Block = 1;
const uint32_t kFreePageMap1Block = 2;
const uint32_t kNumReservedPages = 3;
+const uint32_t kDefaultFreePageMap = kFreePageMap0Block;
const uint32_t kDefaultBlockMapAddr = kNumReservedPages;
}
-MsfBuilder::MsfBuilder(uint32_t BlockSize, uint32_t MinBlockCount, bool CanGrow,
+MSFBuilder::MSFBuilder(uint32_t BlockSize, uint32_t MinBlockCount, bool CanGrow,
BumpPtrAllocator &Allocator)
- : Allocator(Allocator), IsGrowable(CanGrow), BlockSize(BlockSize),
+ : Allocator(Allocator), IsGrowable(CanGrow),
+ FreePageMap(kDefaultFreePageMap), BlockSize(BlockSize),
MininumBlocks(MinBlockCount), BlockMapAddr(kDefaultBlockMapAddr),
FreeBlocks(MinBlockCount, true) {
FreeBlocks[kSuperBlockBlock] = false;
@@ -35,48 +35,49 @@ MsfBuilder::MsfBuilder(uint32_t BlockSize, uint32_t MinBlockCount, bool CanGrow,
FreeBlocks[BlockMapAddr] = false;
}
-Expected<MsfBuilder> MsfBuilder::create(BumpPtrAllocator &Allocator,
+Expected<MSFBuilder> MSFBuilder::create(BumpPtrAllocator &Allocator,
uint32_t BlockSize,
uint32_t MinBlockCount, bool CanGrow) {
- if (!msf::isValidBlockSize(BlockSize))
- return make_error<RawError>(raw_error_code::unspecified,
+ if (!isValidBlockSize(BlockSize))
+ return make_error<MSFError>(msf_error_code::invalid_format,
"The requested block size is unsupported");
- return MsfBuilder(BlockSize,
+ return MSFBuilder(BlockSize,
std::max(MinBlockCount, msf::getMinimumBlockCount()),
CanGrow, Allocator);
}
-Error MsfBuilder::setBlockMapAddr(uint32_t Addr) {
+Error MSFBuilder::setBlockMapAddr(uint32_t Addr) {
if (Addr == BlockMapAddr)
return Error::success();
if (Addr >= FreeBlocks.size()) {
if (!IsGrowable)
- return make_error<RawError>(raw_error_code::unspecified,
+ return make_error<MSFError>(msf_error_code::insufficient_buffer,
"Cannot grow the number of blocks");
- FreeBlocks.resize(Addr + 1);
+ FreeBlocks.resize(Addr + 1, true);
}
if (!isBlockFree(Addr))
- return make_error<RawError>(raw_error_code::unspecified,
- "Attempt to reuse an allocated block");
+ return make_error<MSFError>(
+ msf_error_code::block_in_use,
+ "Requested block map address is already in use");
FreeBlocks[BlockMapAddr] = true;
FreeBlocks[Addr] = false;
BlockMapAddr = Addr;
return Error::success();
}
-void MsfBuilder::setFreePageMap(uint32_t Fpm) { FreePageMap = Fpm; }
+void MSFBuilder::setFreePageMap(uint32_t Fpm) { FreePageMap = Fpm; }
-void MsfBuilder::setUnknown1(uint32_t Unk1) { Unknown1 = Unk1; }
+void MSFBuilder::setUnknown1(uint32_t Unk1) { Unknown1 = Unk1; }
-Error MsfBuilder::setDirectoryBlocksHint(ArrayRef<uint32_t> DirBlocks) {
+Error MSFBuilder::setDirectoryBlocksHint(ArrayRef<uint32_t> DirBlocks) {
for (auto B : DirectoryBlocks)
FreeBlocks[B] = true;
for (auto B : DirBlocks) {
if (!isBlockFree(B)) {
- return make_error<RawError>(raw_error_code::unspecified,
+ return make_error<MSFError>(msf_error_code::unspecified,
"Attempt to reuse an allocated block");
}
FreeBlocks[B] = false;
@@ -86,7 +87,7 @@ Error MsfBuilder::setDirectoryBlocksHint(ArrayRef<uint32_t> DirBlocks) {
return Error::success();
}
-Error MsfBuilder::allocateBlocks(uint32_t NumBlocks,
+Error MSFBuilder::allocateBlocks(uint32_t NumBlocks,
MutableArrayRef<uint32_t> Blocks) {
if (NumBlocks == 0)
return Error::success();
@@ -94,7 +95,7 @@ Error MsfBuilder::allocateBlocks(uint32_t NumBlocks,
uint32_t NumFreeBlocks = FreeBlocks.count();
if (NumFreeBlocks < NumBlocks) {
if (!IsGrowable)
- return make_error<RawError>(raw_error_code::unspecified,
+ return make_error<MSFError>(msf_error_code::insufficient_buffer,
"There are no free Blocks in the file");
uint32_t AllocBlocks = NumBlocks - NumFreeBlocks;
FreeBlocks.resize(AllocBlocks + FreeBlocks.size(), true);
@@ -113,32 +114,33 @@ Error MsfBuilder::allocateBlocks(uint32_t NumBlocks,
return Error::success();
}
-uint32_t MsfBuilder::getNumUsedBlocks() const {
+uint32_t MSFBuilder::getNumUsedBlocks() const {
return getTotalBlockCount() - getNumFreeBlocks();
}
-uint32_t MsfBuilder::getNumFreeBlocks() const { return FreeBlocks.count(); }
+uint32_t MSFBuilder::getNumFreeBlocks() const { return FreeBlocks.count(); }
-uint32_t MsfBuilder::getTotalBlockCount() const { return FreeBlocks.size(); }
+uint32_t MSFBuilder::getTotalBlockCount() const { return FreeBlocks.size(); }
-bool MsfBuilder::isBlockFree(uint32_t Idx) const { return FreeBlocks[Idx]; }
+bool MSFBuilder::isBlockFree(uint32_t Idx) const { return FreeBlocks[Idx]; }
-Error MsfBuilder::addStream(uint32_t Size, ArrayRef<uint32_t> Blocks) {
+Expected<uint32_t> MSFBuilder::addStream(uint32_t Size,
+ ArrayRef<uint32_t> Blocks) {
// Add a new stream mapped to the specified blocks. Verify that the specified
// blocks are both necessary and sufficient for holding the requested number
// of bytes, and verify that all requested blocks are free.
uint32_t ReqBlocks = bytesToBlocks(Size, BlockSize);
if (ReqBlocks != Blocks.size())
- return make_error<RawError>(
- raw_error_code::unspecified,
+ return make_error<MSFError>(
+ msf_error_code::invalid_format,
"Incorrect number of blocks for requested stream size");
for (auto Block : Blocks) {
if (Block >= FreeBlocks.size())
FreeBlocks.resize(Block + 1, true);
if (!FreeBlocks.test(Block))
- return make_error<RawError>(
- raw_error_code::unspecified,
+ return make_error<MSFError>(
+ msf_error_code::unspecified,
"Attempt to re-use an already allocated block");
}
// Mark all the blocks occupied by the new stream as not free.
@@ -146,20 +148,20 @@ Error MsfBuilder::addStream(uint32_t Size, ArrayRef<uint32_t> Blocks) {
FreeBlocks.reset(Block);
}
StreamData.push_back(std::make_pair(Size, Blocks));
- return Error::success();
+ return StreamData.size() - 1;
}
-Error MsfBuilder::addStream(uint32_t Size) {
+Expected<uint32_t> MSFBuilder::addStream(uint32_t Size) {
uint32_t ReqBlocks = bytesToBlocks(Size, BlockSize);
std::vector<uint32_t> NewBlocks;
NewBlocks.resize(ReqBlocks);
if (auto EC = allocateBlocks(ReqBlocks, NewBlocks))
- return EC;
+ return std::move(EC);
StreamData.push_back(std::make_pair(Size, NewBlocks));
- return Error::success();
+ return StreamData.size() - 1;
}
-Error MsfBuilder::setStreamSize(uint32_t Idx, uint32_t Size) {
+Error MSFBuilder::setStreamSize(uint32_t Idx, uint32_t Size) {
uint32_t OldSize = getStreamSize(Idx);
if (OldSize == Size)
return Error::success();
@@ -192,17 +194,17 @@ Error MsfBuilder::setStreamSize(uint32_t Idx, uint32_t Size) {
return Error::success();
}
-uint32_t MsfBuilder::getNumStreams() const { return StreamData.size(); }
+uint32_t MSFBuilder::getNumStreams() const { return StreamData.size(); }
-uint32_t MsfBuilder::getStreamSize(uint32_t StreamIdx) const {
+uint32_t MSFBuilder::getStreamSize(uint32_t StreamIdx) const {
return StreamData[StreamIdx].first;
}
-ArrayRef<uint32_t> MsfBuilder::getStreamBlocks(uint32_t StreamIdx) const {
+ArrayRef<uint32_t> MSFBuilder::getStreamBlocks(uint32_t StreamIdx) const {
return StreamData[StreamIdx].second;
}
-uint32_t MsfBuilder::computeDirectoryByteSize() const {
+uint32_t MSFBuilder::computeDirectoryByteSize() const {
// The directory has the following layout, where each item is a ulittle32_t:
// NumStreams
// StreamSizes[NumStreams]
@@ -218,18 +220,19 @@ uint32_t MsfBuilder::computeDirectoryByteSize() const {
return Size;
}
-Expected<Layout> MsfBuilder::build() {
- Layout L;
- L.SB = Allocator.Allocate<SuperBlock>();
- std::memcpy(L.SB->MagicBytes, Magic, sizeof(Magic));
- L.SB->BlockMapAddr = BlockMapAddr;
- L.SB->BlockSize = BlockSize;
- L.SB->NumDirectoryBytes = computeDirectoryByteSize();
- L.SB->FreeBlockMapBlock = FreePageMap;
- L.SB->Unknown1 = Unknown1;
-
- uint32_t NumDirectoryBlocks =
- bytesToBlocks(L.SB->NumDirectoryBytes, BlockSize);
+Expected<MSFLayout> MSFBuilder::build() {
+ SuperBlock *SB = Allocator.Allocate<SuperBlock>();
+ MSFLayout L;
+ L.SB = SB;
+
+ std::memcpy(SB->MagicBytes, Magic, sizeof(Magic));
+ SB->BlockMapAddr = BlockMapAddr;
+ SB->BlockSize = BlockSize;
+ SB->NumDirectoryBytes = computeDirectoryByteSize();
+ SB->FreeBlockMapBlock = FreePageMap;
+ SB->Unknown1 = Unknown1;
+
+ uint32_t NumDirectoryBlocks = bytesToBlocks(SB->NumDirectoryBytes, BlockSize);
if (NumDirectoryBlocks > DirectoryBlocks.size()) {
// Our hint wasn't enough to satisfy the entire directory. Allocate
// remaining pages.
@@ -249,9 +252,9 @@ Expected<Layout> MsfBuilder::build() {
}
// Don't set the number of blocks in the file until after allocating Blocks
- // for
- // the directory, since the allocation might cause the file to need to grow.
- L.SB->NumBlocks = FreeBlocks.size();
+ // for the directory, since the allocation might cause the file to need to
+ // grow.
+ SB->NumBlocks = FreeBlocks.size();
ulittle32_t *DirBlocks = Allocator.Allocate<ulittle32_t>(NumDirectoryBlocks);
std::uninitialized_copy_n(DirectoryBlocks.begin(), NumDirectoryBlocks,
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/MsfCommon.cpp b/contrib/llvm/lib/DebugInfo/MSF/MSFCommon.cpp
index 5d97f33..fdab788 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/Raw/MsfCommon.cpp
+++ b/contrib/llvm/lib/DebugInfo/MSF/MSFCommon.cpp
@@ -1,4 +1,4 @@
-//===- MsfCommon.cpp - Common types and functions for MSF files -*- C++ -*-===//
+//===- MSFCommon.cpp - Common types and functions for MSF files -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,25 +7,25 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/DebugInfo/PDB/Raw/MsfCommon.h"
-#include "llvm/DebugInfo/PDB/Raw/RawError.h"
+#include "llvm/DebugInfo/MSF/MSFCommon.h"
+#include "llvm/DebugInfo/MSF/MSFError.h"
using namespace llvm;
-using namespace llvm::pdb::msf;
+using namespace llvm::msf;
-Error llvm::pdb::msf::validateSuperBlock(const SuperBlock &SB) {
+Error llvm::msf::validateSuperBlock(const SuperBlock &SB) {
// Check the magic bytes.
if (std::memcmp(SB.MagicBytes, Magic, sizeof(Magic)) != 0)
- return make_error<RawError>(raw_error_code::corrupt_file,
+ return make_error<MSFError>(msf_error_code::invalid_format,
"MSF magic header doesn't match");
if (!isValidBlockSize(SB.BlockSize))
- return make_error<RawError>(raw_error_code::corrupt_file,
+ return make_error<MSFError>(msf_error_code::invalid_format,
"Unsupported block size.");
// We don't support directories whose sizes aren't a multiple of four bytes.
if (SB.NumDirectoryBytes % sizeof(support::ulittle32_t) != 0)
- return make_error<RawError>(raw_error_code::corrupt_file,
+ return make_error<MSFError>(msf_error_code::invalid_format,
"Directory size is not multiple of 4.");
// The number of blocks which comprise the directory is a simple function of
@@ -37,12 +37,21 @@ Error llvm::pdb::msf::validateSuperBlock(const SuperBlock &SB) {
// block numbers. It is unclear what would happen if the number of blocks
// couldn't fit on a single block.
if (NumDirectoryBlocks > SB.BlockSize / sizeof(support::ulittle32_t))
- return make_error<RawError>(raw_error_code::corrupt_file,
+ return make_error<MSFError>(msf_error_code::invalid_format,
"Too many directory blocks.");
if (SB.BlockMapAddr == 0)
- return make_error<RawError>(raw_error_code::corrupt_file,
+ return make_error<MSFError>(msf_error_code::invalid_format,
"Block 0 is reserved");
+ if (SB.BlockMapAddr >= SB.NumBlocks)
+ return make_error<MSFError>(msf_error_code::invalid_format,
+ "Block map address is invalid.");
+
+ if (SB.FreeBlockMapBlock != 1 && SB.FreeBlockMapBlock != 2)
+ return make_error<MSFError>(
+ msf_error_code::invalid_format,
+ "The free block map isn't at block 1 or block 2.");
+
return Error::success();
}
diff --git a/contrib/llvm/lib/DebugInfo/MSF/MSFError.cpp b/contrib/llvm/lib/DebugInfo/MSF/MSFError.cpp
new file mode 100644
index 0000000..1b8294e
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/MSF/MSFError.cpp
@@ -0,0 +1,70 @@
+//===- MSFError.cpp - Error extensions for MSF files ------------*- 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/MSF/MSFError.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ManagedStatic.h"
+
+using namespace llvm;
+using namespace llvm::msf;
+
+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 MSFErrorCategory : public std::error_category {
+public:
+ const char *name() const noexcept override { return "llvm.msf"; }
+
+ std::string message(int Condition) const override {
+ switch (static_cast<msf_error_code>(Condition)) {
+ case msf_error_code::unspecified:
+ return "An unknown error has occurred.";
+ case msf_error_code::insufficient_buffer:
+ return "The buffer is not large enough to read the requested number of "
+ "bytes.";
+ case msf_error_code::not_writable:
+ return "The specified stream is not writable.";
+ case msf_error_code::no_stream:
+ return "The specified stream does not exist.";
+ case msf_error_code::invalid_format:
+ return "The data is in an unexpected format.";
+ case msf_error_code::block_in_use:
+ return "The block is already in use.";
+ }
+ llvm_unreachable("Unrecognized msf_error_code");
+ }
+};
+} // end anonymous namespace
+
+static ManagedStatic<MSFErrorCategory> Category;
+
+char MSFError::ID = 0;
+
+MSFError::MSFError(msf_error_code C) : MSFError(C, "") {}
+
+MSFError::MSFError(const std::string &Context)
+ : MSFError(msf_error_code::unspecified, Context) {}
+
+MSFError::MSFError(msf_error_code C, const std::string &Context) : Code(C) {
+ ErrMsg = "MSF Error: ";
+ std::error_code EC = convertToErrorCode();
+ if (Code != msf_error_code::unspecified)
+ ErrMsg += EC.message() + " ";
+ if (!Context.empty())
+ ErrMsg += Context;
+}
+
+void MSFError::log(raw_ostream &OS) const { OS << ErrMsg << "\n"; }
+
+const std::string &MSFError::getErrorMessage() const { return ErrMsg; }
+
+std::error_code MSFError::convertToErrorCode() const {
+ return std::error_code(static_cast<int>(Code), *Category);
+}
diff --git a/contrib/llvm/lib/DebugInfo/MSF/MappedBlockStream.cpp b/contrib/llvm/lib/DebugInfo/MSF/MappedBlockStream.cpp
new file mode 100644
index 0000000..e52c88a
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/MSF/MappedBlockStream.cpp
@@ -0,0 +1,415 @@
+//===- MappedBlockStream.cpp - Reads stream data from an MSF file ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+
+#include "llvm/DebugInfo/MSF/IMSFFile.h"
+#include "llvm/DebugInfo/MSF/MSFCommon.h"
+#include "llvm/DebugInfo/MSF/MSFError.h"
+#include "llvm/DebugInfo/MSF/MSFStreamLayout.h"
+
+using namespace llvm;
+using namespace llvm::msf;
+
+namespace {
+template <typename Base> class MappedBlockStreamImpl : public Base {
+public:
+ template <typename... Args>
+ MappedBlockStreamImpl(Args &&... Params)
+ : Base(std::forward<Args>(Params)...) {}
+};
+}
+
+static void initializeFpmStreamLayout(const MSFLayout &Layout,
+ MSFStreamLayout &FpmLayout) {
+ uint32_t NumFpmIntervals = msf::getNumFpmIntervals(Layout);
+ support::ulittle32_t FpmBlock = Layout.SB->FreeBlockMapBlock;
+ assert(FpmBlock == 1 || FpmBlock == 2);
+ while (NumFpmIntervals > 0) {
+ FpmLayout.Blocks.push_back(FpmBlock);
+ FpmBlock += msf::getFpmIntervalLength(Layout);
+ --NumFpmIntervals;
+ }
+ FpmLayout.Length = msf::getFullFpmByteSize(Layout);
+}
+
+typedef std::pair<uint32_t, uint32_t> Interval;
+static Interval intersect(const Interval &I1, const Interval &I2) {
+ return std::make_pair(std::max(I1.first, I2.first),
+ std::min(I1.second, I2.second));
+}
+
+MappedBlockStream::MappedBlockStream(uint32_t BlockSize, uint32_t NumBlocks,
+ const MSFStreamLayout &Layout,
+ const ReadableStream &MsfData)
+ : BlockSize(BlockSize), NumBlocks(NumBlocks), StreamLayout(Layout),
+ MsfData(MsfData) {}
+
+std::unique_ptr<MappedBlockStream>
+MappedBlockStream::createStream(uint32_t BlockSize, uint32_t NumBlocks,
+ const MSFStreamLayout &Layout,
+ const ReadableStream &MsfData) {
+ return llvm::make_unique<MappedBlockStreamImpl<MappedBlockStream>>(
+ BlockSize, NumBlocks, Layout, MsfData);
+}
+
+std::unique_ptr<MappedBlockStream>
+MappedBlockStream::createIndexedStream(const MSFLayout &Layout,
+ const ReadableStream &MsfData,
+ uint32_t StreamIndex) {
+ assert(StreamIndex < Layout.StreamMap.size() && "Invalid stream index");
+ MSFStreamLayout SL;
+ SL.Blocks = Layout.StreamMap[StreamIndex];
+ SL.Length = Layout.StreamSizes[StreamIndex];
+ return llvm::make_unique<MappedBlockStreamImpl<MappedBlockStream>>(
+ Layout.SB->BlockSize, Layout.SB->NumBlocks, SL, MsfData);
+}
+
+std::unique_ptr<MappedBlockStream>
+MappedBlockStream::createDirectoryStream(const MSFLayout &Layout,
+ const ReadableStream &MsfData) {
+ MSFStreamLayout SL;
+ SL.Blocks = Layout.DirectoryBlocks;
+ SL.Length = Layout.SB->NumDirectoryBytes;
+ return createStream(Layout.SB->BlockSize, Layout.SB->NumBlocks, SL, MsfData);
+}
+
+std::unique_ptr<MappedBlockStream>
+MappedBlockStream::createFpmStream(const MSFLayout &Layout,
+ const ReadableStream &MsfData) {
+ MSFStreamLayout SL;
+ initializeFpmStreamLayout(Layout, SL);
+ return createStream(Layout.SB->BlockSize, Layout.SB->NumBlocks, SL, MsfData);
+}
+
+Error MappedBlockStream::readBytes(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) const {
+ // Make sure we aren't trying to read beyond the end of the stream.
+ if (Size > StreamLayout.Length)
+ return make_error<MSFError>(msf_error_code::insufficient_buffer);
+ if (Offset > StreamLayout.Length - Size)
+ return make_error<MSFError>(msf_error_code::insufficient_buffer);
+
+ if (tryReadContiguously(Offset, Size, Buffer))
+ return Error::success();
+
+ auto CacheIter = CacheMap.find(Offset);
+ if (CacheIter != CacheMap.end()) {
+ // Try to find an alloc that was large enough for this request.
+ for (auto &Entry : CacheIter->second) {
+ if (Entry.size() >= Size) {
+ Buffer = Entry.slice(0, Size);
+ return Error::success();
+ }
+ }
+ }
+
+ // We couldn't find a buffer that started at the correct offset (the most
+ // common scenario). Try to see if there is a buffer that starts at some
+ // other offset but overlaps the desired range.
+ for (auto &CacheItem : CacheMap) {
+ Interval RequestExtent = std::make_pair(Offset, Offset + Size);
+
+ // We already checked this one on the fast path above.
+ if (CacheItem.first == Offset)
+ continue;
+ // If the initial extent of the cached item is beyond the ending extent
+ // of the request, there is no overlap.
+ if (CacheItem.first >= Offset + Size)
+ continue;
+
+ // We really only have to check the last item in the list, since we append
+ // in order of increasing length.
+ if (CacheItem.second.empty())
+ continue;
+
+ auto CachedAlloc = CacheItem.second.back();
+ // If the initial extent of the request is beyond the ending extent of
+ // the cached item, there is no overlap.
+ Interval CachedExtent =
+ std::make_pair(CacheItem.first, CacheItem.first + CachedAlloc.size());
+ if (RequestExtent.first >= CachedExtent.first + CachedExtent.second)
+ continue;
+
+ Interval Intersection = intersect(CachedExtent, RequestExtent);
+ // Only use this if the entire request extent is contained in the cached
+ // extent.
+ if (Intersection != RequestExtent)
+ continue;
+
+ uint32_t CacheRangeOffset =
+ AbsoluteDifference(CachedExtent.first, Intersection.first);
+ Buffer = CachedAlloc.slice(CacheRangeOffset, Size);
+ return Error::success();
+ }
+
+ // Otherwise allocate a large enough buffer in the pool, memcpy the data
+ // into it, and return an ArrayRef to that. Do not touch existing pool
+ // allocations, as existing clients may be holding a pointer which must
+ // not be invalidated.
+ uint8_t *WriteBuffer = static_cast<uint8_t *>(Pool.Allocate(Size, 8));
+ if (auto EC = readBytes(Offset, MutableArrayRef<uint8_t>(WriteBuffer, Size)))
+ return EC;
+
+ if (CacheIter != CacheMap.end()) {
+ CacheIter->second.emplace_back(WriteBuffer, Size);
+ } else {
+ std::vector<CacheEntry> List;
+ List.emplace_back(WriteBuffer, Size);
+ CacheMap.insert(std::make_pair(Offset, List));
+ }
+ Buffer = ArrayRef<uint8_t>(WriteBuffer, Size);
+ return Error::success();
+}
+
+Error MappedBlockStream::readLongestContiguousChunk(
+ uint32_t Offset, ArrayRef<uint8_t> &Buffer) const {
+ // Make sure we aren't trying to read beyond the end of the stream.
+ if (Offset >= StreamLayout.Length)
+ return make_error<MSFError>(msf_error_code::insufficient_buffer);
+ uint32_t First = Offset / BlockSize;
+ uint32_t Last = First;
+
+ while (Last < NumBlocks - 1) {
+ if (StreamLayout.Blocks[Last] != StreamLayout.Blocks[Last + 1] - 1)
+ break;
+ ++Last;
+ }
+
+ uint32_t OffsetInFirstBlock = Offset % BlockSize;
+ uint32_t BytesFromFirstBlock = BlockSize - OffsetInFirstBlock;
+ uint32_t BlockSpan = Last - First + 1;
+ uint32_t ByteSpan = BytesFromFirstBlock + (BlockSpan - 1) * BlockSize;
+
+ ArrayRef<uint8_t> BlockData;
+ uint32_t MsfOffset = blockToOffset(StreamLayout.Blocks[First], BlockSize);
+ if (auto EC = MsfData.readBytes(MsfOffset, BlockSize, BlockData))
+ return EC;
+
+ BlockData = BlockData.drop_front(OffsetInFirstBlock);
+ Buffer = ArrayRef<uint8_t>(BlockData.data(), ByteSpan);
+ return Error::success();
+}
+
+uint32_t MappedBlockStream::getLength() const { return StreamLayout.Length; }
+
+bool MappedBlockStream::tryReadContiguously(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) const {
+ if (Size == 0) {
+ Buffer = ArrayRef<uint8_t>();
+ return true;
+ }
+ // Attempt to fulfill the request with a reference directly into the stream.
+ // This can work even if the request crosses a block boundary, provided that
+ // all subsequent blocks are contiguous. For example, a 10k read with a 4k
+ // block size can be filled with a reference if, from the starting offset,
+ // 3 blocks in a row are contiguous.
+ uint32_t BlockNum = Offset / BlockSize;
+ uint32_t OffsetInBlock = Offset % BlockSize;
+ uint32_t BytesFromFirstBlock = std::min(Size, BlockSize - OffsetInBlock);
+ uint32_t NumAdditionalBlocks =
+ llvm::alignTo(Size - BytesFromFirstBlock, BlockSize) / BlockSize;
+
+ uint32_t RequiredContiguousBlocks = NumAdditionalBlocks + 1;
+ uint32_t E = StreamLayout.Blocks[BlockNum];
+ for (uint32_t I = 0; I < RequiredContiguousBlocks; ++I, ++E) {
+ if (StreamLayout.Blocks[I + BlockNum] != E)
+ return false;
+ }
+
+ // Read out the entire block where the requested offset starts. Then drop
+ // bytes from the beginning so that the actual starting byte lines up with
+ // the requested starting byte. Then, since we know this is a contiguous
+ // cross-block span, explicitly resize the ArrayRef to cover the entire
+ // request length.
+ ArrayRef<uint8_t> BlockData;
+ uint32_t FirstBlockAddr = StreamLayout.Blocks[BlockNum];
+ uint32_t MsfOffset = blockToOffset(FirstBlockAddr, BlockSize);
+ if (auto EC = MsfData.readBytes(MsfOffset, BlockSize, BlockData)) {
+ consumeError(std::move(EC));
+ return false;
+ }
+ BlockData = BlockData.drop_front(OffsetInBlock);
+ Buffer = ArrayRef<uint8_t>(BlockData.data(), Size);
+ return true;
+}
+
+Error MappedBlockStream::readBytes(uint32_t Offset,
+ MutableArrayRef<uint8_t> Buffer) const {
+ uint32_t BlockNum = Offset / BlockSize;
+ uint32_t OffsetInBlock = Offset % BlockSize;
+
+ // Make sure we aren't trying to read beyond the end of the stream.
+ if (Buffer.size() > StreamLayout.Length)
+ return make_error<MSFError>(msf_error_code::insufficient_buffer);
+ if (Offset > StreamLayout.Length - Buffer.size())
+ return make_error<MSFError>(msf_error_code::insufficient_buffer);
+
+ uint32_t BytesLeft = Buffer.size();
+ uint32_t BytesWritten = 0;
+ uint8_t *WriteBuffer = Buffer.data();
+ while (BytesLeft > 0) {
+ uint32_t StreamBlockAddr = StreamLayout.Blocks[BlockNum];
+
+ ArrayRef<uint8_t> BlockData;
+ uint32_t Offset = blockToOffset(StreamBlockAddr, BlockSize);
+ if (auto EC = MsfData.readBytes(Offset, BlockSize, BlockData))
+ return EC;
+
+ const uint8_t *ChunkStart = BlockData.data() + OffsetInBlock;
+ uint32_t BytesInChunk = std::min(BytesLeft, BlockSize - OffsetInBlock);
+ ::memcpy(WriteBuffer + BytesWritten, ChunkStart, BytesInChunk);
+
+ BytesWritten += BytesInChunk;
+ BytesLeft -= BytesInChunk;
+ ++BlockNum;
+ OffsetInBlock = 0;
+ }
+
+ return Error::success();
+}
+
+uint32_t MappedBlockStream::getNumBytesCopied() const {
+ return static_cast<uint32_t>(Pool.getBytesAllocated());
+}
+
+void MappedBlockStream::invalidateCache() { CacheMap.shrink_and_clear(); }
+
+void MappedBlockStream::fixCacheAfterWrite(uint32_t Offset,
+ ArrayRef<uint8_t> Data) const {
+ // If this write overlapped a read which previously came from the pool,
+ // someone may still be holding a pointer to that alloc which is now invalid.
+ // Compute the overlapping range and update the cache entry, so any
+ // outstanding buffers are automatically updated.
+ for (const auto &MapEntry : CacheMap) {
+ // If the end of the written extent precedes the beginning of the cached
+ // extent, ignore this map entry.
+ if (Offset + Data.size() < MapEntry.first)
+ continue;
+ for (const auto &Alloc : MapEntry.second) {
+ // If the end of the cached extent precedes the beginning of the written
+ // extent, ignore this alloc.
+ if (MapEntry.first + Alloc.size() < Offset)
+ continue;
+
+ // If we get here, they are guaranteed to overlap.
+ Interval WriteInterval = std::make_pair(Offset, Offset + Data.size());
+ Interval CachedInterval =
+ std::make_pair(MapEntry.first, MapEntry.first + Alloc.size());
+ // If they overlap, we need to write the new data into the overlapping
+ // range.
+ auto Intersection = intersect(WriteInterval, CachedInterval);
+ assert(Intersection.first <= Intersection.second);
+
+ uint32_t Length = Intersection.second - Intersection.first;
+ uint32_t SrcOffset =
+ AbsoluteDifference(WriteInterval.first, Intersection.first);
+ uint32_t DestOffset =
+ AbsoluteDifference(CachedInterval.first, Intersection.first);
+ ::memcpy(Alloc.data() + DestOffset, Data.data() + SrcOffset, Length);
+ }
+ }
+}
+
+WritableMappedBlockStream::WritableMappedBlockStream(
+ uint32_t BlockSize, uint32_t NumBlocks, const MSFStreamLayout &Layout,
+ const WritableStream &MsfData)
+ : ReadInterface(BlockSize, NumBlocks, Layout, MsfData),
+ WriteInterface(MsfData) {}
+
+std::unique_ptr<WritableMappedBlockStream>
+WritableMappedBlockStream::createStream(uint32_t BlockSize, uint32_t NumBlocks,
+ const MSFStreamLayout &Layout,
+ const WritableStream &MsfData) {
+ return llvm::make_unique<MappedBlockStreamImpl<WritableMappedBlockStream>>(
+ BlockSize, NumBlocks, Layout, MsfData);
+}
+
+std::unique_ptr<WritableMappedBlockStream>
+WritableMappedBlockStream::createIndexedStream(const MSFLayout &Layout,
+ const WritableStream &MsfData,
+ uint32_t StreamIndex) {
+ assert(StreamIndex < Layout.StreamMap.size() && "Invalid stream index");
+ MSFStreamLayout SL;
+ SL.Blocks = Layout.StreamMap[StreamIndex];
+ SL.Length = Layout.StreamSizes[StreamIndex];
+ return createStream(Layout.SB->BlockSize, Layout.SB->NumBlocks, SL, MsfData);
+}
+
+std::unique_ptr<WritableMappedBlockStream>
+WritableMappedBlockStream::createDirectoryStream(
+ const MSFLayout &Layout, const WritableStream &MsfData) {
+ MSFStreamLayout SL;
+ SL.Blocks = Layout.DirectoryBlocks;
+ SL.Length = Layout.SB->NumDirectoryBytes;
+ return createStream(Layout.SB->BlockSize, Layout.SB->NumBlocks, SL, MsfData);
+}
+
+std::unique_ptr<WritableMappedBlockStream>
+WritableMappedBlockStream::createFpmStream(const MSFLayout &Layout,
+ const WritableStream &MsfData) {
+ MSFStreamLayout SL;
+ initializeFpmStreamLayout(Layout, SL);
+ return createStream(Layout.SB->BlockSize, Layout.SB->NumBlocks, SL, MsfData);
+}
+
+Error WritableMappedBlockStream::readBytes(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) const {
+ return ReadInterface.readBytes(Offset, Size, Buffer);
+}
+
+Error WritableMappedBlockStream::readLongestContiguousChunk(
+ uint32_t Offset, ArrayRef<uint8_t> &Buffer) const {
+ return ReadInterface.readLongestContiguousChunk(Offset, Buffer);
+}
+
+uint32_t WritableMappedBlockStream::getLength() const {
+ return ReadInterface.getLength();
+}
+
+Error WritableMappedBlockStream::writeBytes(uint32_t Offset,
+ ArrayRef<uint8_t> Buffer) const {
+ // Make sure we aren't trying to write beyond the end of the stream.
+ if (Buffer.size() > getStreamLength())
+ return make_error<MSFError>(msf_error_code::insufficient_buffer);
+
+ if (Offset > getStreamLayout().Length - Buffer.size())
+ return make_error<MSFError>(msf_error_code::insufficient_buffer);
+
+ uint32_t BlockNum = Offset / getBlockSize();
+ uint32_t OffsetInBlock = Offset % getBlockSize();
+
+ uint32_t BytesLeft = Buffer.size();
+ uint32_t BytesWritten = 0;
+ while (BytesLeft > 0) {
+ uint32_t StreamBlockAddr = getStreamLayout().Blocks[BlockNum];
+ uint32_t BytesToWriteInChunk =
+ std::min(BytesLeft, getBlockSize() - OffsetInBlock);
+
+ const uint8_t *Chunk = Buffer.data() + BytesWritten;
+ ArrayRef<uint8_t> ChunkData(Chunk, BytesToWriteInChunk);
+ uint32_t MsfOffset = blockToOffset(StreamBlockAddr, getBlockSize());
+ MsfOffset += OffsetInBlock;
+ if (auto EC = WriteInterface.writeBytes(MsfOffset, ChunkData))
+ return EC;
+
+ BytesLeft -= BytesToWriteInChunk;
+ BytesWritten += BytesToWriteInChunk;
+ ++BlockNum;
+ OffsetInBlock = 0;
+ }
+
+ ReadInterface.fixCacheAfterWrite(Offset, Buffer);
+
+ return Error::success();
+}
+
+Error WritableMappedBlockStream::commit() const {
+ return WriteInterface.commit();
+}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/StreamReader.cpp b/contrib/llvm/lib/DebugInfo/MSF/StreamReader.cpp
index 64e4548..b85fd14 100644
--- a/contrib/llvm/lib/DebugInfo/CodeView/StreamReader.cpp
+++ b/contrib/llvm/lib/DebugInfo/MSF/StreamReader.cpp
@@ -7,15 +7,15 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/DebugInfo/CodeView/StreamReader.h"
+#include "llvm/DebugInfo/MSF/StreamReader.h"
-#include "llvm/DebugInfo/CodeView/CodeViewError.h"
-#include "llvm/DebugInfo/CodeView/StreamRef.h"
+#include "llvm/DebugInfo/MSF/MSFError.h"
+#include "llvm/DebugInfo/MSF/StreamRef.h"
using namespace llvm;
-using namespace llvm::codeview;
+using namespace llvm::msf;
-StreamReader::StreamReader(StreamRef S) : Stream(S), Offset(0) {}
+StreamReader::StreamReader(ReadableStreamRef S) : Stream(S), Offset(0) {}
Error StreamReader::readLongestContiguousChunk(ArrayRef<uint8_t> &Buffer) {
if (auto EC = Stream.readLongestContiguousChunk(Offset, Buffer))
@@ -31,6 +31,14 @@ Error StreamReader::readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size) {
return Error::success();
}
+Error StreamReader::readInteger(uint8_t &Dest) {
+ const uint8_t *P;
+ if (auto EC = readObject(P))
+ return EC;
+ Dest = *P;
+ return Error::success();
+}
+
Error StreamReader::readInteger(uint16_t &Dest) {
const support::ulittle16_t *P;
if (auto EC = readObject(P))
@@ -47,6 +55,46 @@ Error StreamReader::readInteger(uint32_t &Dest) {
return Error::success();
}
+Error StreamReader::readInteger(uint64_t &Dest) {
+ const support::ulittle64_t *P;
+ if (auto EC = readObject(P))
+ return EC;
+ Dest = *P;
+ return Error::success();
+}
+
+Error StreamReader::readInteger(int8_t &Dest) {
+ const int8_t *P;
+ if (auto EC = readObject(P))
+ return EC;
+ Dest = *P;
+ return Error::success();
+}
+
+Error StreamReader::readInteger(int16_t &Dest) {
+ const support::little16_t *P;
+ if (auto EC = readObject(P))
+ return EC;
+ Dest = *P;
+ return Error::success();
+}
+
+Error StreamReader::readInteger(int32_t &Dest) {
+ const support::little32_t *P;
+ if (auto EC = readObject(P))
+ return EC;
+ Dest = *P;
+ return Error::success();
+}
+
+Error StreamReader::readInteger(int64_t &Dest) {
+ const support::little64_t *P;
+ if (auto EC = readObject(P))
+ return EC;
+ Dest = *P;
+ return Error::success();
+}
+
Error StreamReader::readZeroString(StringRef &Dest) {
uint32_t Length = 0;
// First compute the length of the string by reading 1 byte at a time.
@@ -80,14 +128,29 @@ Error StreamReader::readFixedString(StringRef &Dest, uint32_t Length) {
return Error::success();
}
-Error StreamReader::readStreamRef(StreamRef &Ref) {
+Error StreamReader::readStreamRef(ReadableStreamRef &Ref) {
return readStreamRef(Ref, bytesRemaining());
}
-Error StreamReader::readStreamRef(StreamRef &Ref, uint32_t Length) {
+Error StreamReader::readStreamRef(ReadableStreamRef &Ref, uint32_t Length) {
if (bytesRemaining() < Length)
- return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
+ return make_error<MSFError>(msf_error_code::insufficient_buffer);
Ref = Stream.slice(Offset, Length);
Offset += Length;
return Error::success();
}
+
+Error StreamReader::skip(uint32_t Amount) {
+ if (Amount > bytesRemaining())
+ return make_error<MSFError>(msf_error_code::insufficient_buffer);
+ Offset += Amount;
+ return Error::success();
+}
+
+uint8_t StreamReader::peek() const {
+ ArrayRef<uint8_t> Buffer;
+ auto EC = Stream.readBytes(Offset, 1, Buffer);
+ assert(!EC && "Cannot peek an empty buffer!");
+ llvm::consumeError(std::move(EC));
+ return Buffer[0];
+}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/StreamWriter.cpp b/contrib/llvm/lib/DebugInfo/MSF/StreamWriter.cpp
index f61c6b5..cdae7c5 100644
--- a/contrib/llvm/lib/DebugInfo/CodeView/StreamWriter.cpp
+++ b/contrib/llvm/lib/DebugInfo/MSF/StreamWriter.cpp
@@ -7,16 +7,16 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/DebugInfo/CodeView/StreamWriter.h"
+#include "llvm/DebugInfo/MSF/StreamWriter.h"
-#include "llvm/DebugInfo/CodeView/CodeViewError.h"
-#include "llvm/DebugInfo/CodeView/StreamReader.h"
-#include "llvm/DebugInfo/CodeView/StreamRef.h"
+#include "llvm/DebugInfo/MSF/MSFError.h"
+#include "llvm/DebugInfo/MSF/StreamReader.h"
+#include "llvm/DebugInfo/MSF/StreamRef.h"
using namespace llvm;
-using namespace llvm::codeview;
+using namespace llvm::msf;
-StreamWriter::StreamWriter(StreamRef S) : Stream(S), Offset(0) {}
+StreamWriter::StreamWriter(WritableStreamRef S) : Stream(S), Offset(0) {}
Error StreamWriter::writeBytes(ArrayRef<uint8_t> Buffer) {
if (auto EC = Stream.writeBytes(Offset, Buffer))
@@ -25,6 +25,8 @@ Error StreamWriter::writeBytes(ArrayRef<uint8_t> Buffer) {
return Error::success();
}
+Error StreamWriter::writeInteger(uint8_t Int) { return writeObject(Int); }
+
Error StreamWriter::writeInteger(uint16_t Int) {
return writeObject(support::ulittle16_t(Int));
}
@@ -33,6 +35,24 @@ Error StreamWriter::writeInteger(uint32_t Int) {
return writeObject(support::ulittle32_t(Int));
}
+Error StreamWriter::writeInteger(uint64_t Int) {
+ return writeObject(support::ulittle64_t(Int));
+}
+
+Error StreamWriter::writeInteger(int8_t Int) { return writeObject(Int); }
+
+Error StreamWriter::writeInteger(int16_t Int) {
+ return writeObject(support::little16_t(Int));
+}
+
+Error StreamWriter::writeInteger(int32_t Int) {
+ return writeObject(support::little32_t(Int));
+}
+
+Error StreamWriter::writeInteger(int64_t Int) {
+ return writeObject(support::little64_t(Int));
+}
+
Error StreamWriter::writeZeroString(StringRef Str) {
if (auto EC = writeFixedString(Str))
return EC;
@@ -51,14 +71,15 @@ Error StreamWriter::writeFixedString(StringRef Str) {
return Error::success();
}
-Error StreamWriter::writeStreamRef(StreamRef Ref) {
+Error StreamWriter::writeStreamRef(ReadableStreamRef Ref) {
if (auto EC = writeStreamRef(Ref, Ref.getLength()))
return EC;
- Offset += Ref.getLength();
+ // Don't increment Offset here, it is done by the overloaded call to
+ // writeStreamRef.
return Error::success();
}
-Error StreamWriter::writeStreamRef(StreamRef Ref, uint32_t Length) {
+Error StreamWriter::writeStreamRef(ReadableStreamRef Ref, uint32_t Length) {
Ref = Ref.slice(0, Length);
StreamReader SrcReader(Ref);
diff --git a/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAError.cpp b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAError.cpp
index 1d72a92..0da877b 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAError.cpp
+++ b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAError.cpp
@@ -10,7 +10,7 @@ using namespace llvm::pdb;
// deal with the Error value directly, rather than converting to error_code.
class DIAErrorCategory : public std::error_category {
public:
- const char *name() const LLVM_NOEXCEPT override { return "llvm.pdb.dia"; }
+ const char *name() const noexcept override { return "llvm.pdb.dia"; }
std::string message(int Condition) const override {
switch (static_cast<dia_error_code>(Condition)) {
@@ -38,21 +38,20 @@ char DIAError::ID = 0;
DIAError::DIAError(dia_error_code C) : DIAError(C, "") {}
-DIAError::DIAError(const std::string &Context)
+DIAError::DIAError(StringRef Context)
: DIAError(dia_error_code::unspecified, Context) {}
-DIAError::DIAError(dia_error_code C, const std::string &Context) : Code(C) {
+DIAError::DIAError(dia_error_code C, StringRef Context) : Code(C) {
ErrMsg = "DIA Error: ";
std::error_code EC = convertToErrorCode();
- if (Code != dia_error_code::unspecified)
- ErrMsg += EC.message() + " ";
+ ErrMsg += EC.message() + " ";
if (!Context.empty())
ErrMsg += Context;
}
void DIAError::log(raw_ostream &OS) const { OS << ErrMsg << "\n"; }
-const std::string &DIAError::getErrorMessage() const { return ErrMsg; }
+StringRef DIAError::getErrorMessage() const { return ErrMsg; }
std::error_code DIAError::convertToErrorCode() const {
return std::error_code(static_cast<int>(Code), *Category);
diff --git a/contrib/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp
index fa224af..6ecf335 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp
+++ b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp
@@ -20,31 +20,36 @@
#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
#include "llvm/Support/ConvertUTF.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
using namespace llvm;
using namespace llvm::pdb;
-namespace {
-
-Error ErrorFromHResult(HRESULT Result) {
+static Error ErrorFromHResult(HRESULT Result, StringRef Context) {
switch (Result) {
case E_PDB_NOT_FOUND:
- return make_error<GenericError>(generic_error_code::invalid_path);
+ return make_error<GenericError>(generic_error_code::invalid_path, Context);
case E_PDB_FORMAT:
- return make_error<DIAError>(dia_error_code::invalid_file_format);
+ return make_error<DIAError>(dia_error_code::invalid_file_format, Context);
case E_INVALIDARG:
- return make_error<DIAError>(dia_error_code::invalid_parameter);
+ return make_error<DIAError>(dia_error_code::invalid_parameter, Context);
case E_UNEXPECTED:
- return make_error<DIAError>(dia_error_code::already_loaded);
+ return make_error<DIAError>(dia_error_code::already_loaded, Context);
case E_PDB_INVALID_SIG:
case E_PDB_INVALID_AGE:
- return make_error<DIAError>(dia_error_code::debug_info_mismatch);
- default:
- return make_error<DIAError>(dia_error_code::unspecified);
+ return make_error<DIAError>(dia_error_code::debug_info_mismatch, Context);
+ default: {
+ std::string S;
+ raw_string_ostream OS(S);
+ OS << "HRESULT: " << format_hex(static_cast<DWORD>(Result), 10, true)
+ << ": " << Context;
+ return make_error<DIAError>(dia_error_code::unspecified, OS.str());
+ }
}
}
-Error LoadDIA(CComPtr<IDiaDataSource> &DiaDataSource) {
+static Error LoadDIA(CComPtr<IDiaDataSource> &DiaDataSource) {
if (SUCCEEDED(CoCreateInstance(CLSID_DiaSource, nullptr, CLSCTX_INPROC_SERVER,
IID_IDiaDataSource,
reinterpret_cast<LPVOID *>(&DiaDataSource))))
@@ -55,12 +60,11 @@ Error LoadDIA(CComPtr<IDiaDataSource> &DiaDataSource) {
#if !defined(_MSC_VER)
return llvm::make_error<GenericError>(
"DIA is only supported when using MSVC.");
-#endif
-
+#else
const wchar_t *msdia_dll = nullptr;
-#if _MSC_VER == 1900
+#if _MSC_VER >= 1900 && _MSC_VER < 2000
msdia_dll = L"msdia140.dll"; // VS2015
-#elif _MSC_VER == 1800
+#elif _MSC_VER >= 1800
msdia_dll = L"msdia120.dll"; // VS2013
#else
#error "Unknown Visual Studio version."
@@ -69,10 +73,9 @@ Error LoadDIA(CComPtr<IDiaDataSource> &DiaDataSource) {
HRESULT HR;
if (FAILED(HR = NoRegCoCreate(msdia_dll, CLSID_DiaSource, IID_IDiaDataSource,
reinterpret_cast<LPVOID *>(&DiaDataSource))))
- return ErrorFromHResult(HR);
+ return ErrorFromHResult(HR, "Calling NoRegCoCreate");
return Error::success();
-}
-
+#endif
}
DIASession::DIASession(CComPtr<IDiaSession> DiaSession) : Session(DiaSession) {}
@@ -93,10 +96,10 @@ Error DIASession::createFromPdb(StringRef Path,
const wchar_t *Path16Str = reinterpret_cast<const wchar_t*>(Path16.data());
HRESULT HR;
if (FAILED(HR = DiaDataSource->loadDataFromPdb(Path16Str)))
- return ErrorFromHResult(HR);
+ return ErrorFromHResult(HR, "Calling loadDataFromPdb");
if (FAILED(HR = DiaDataSource->openSession(&DiaSession)))
- return ErrorFromHResult(HR);
+ return ErrorFromHResult(HR, "Calling openSession");
Session.reset(new DIASession(DiaSession));
return Error::success();
@@ -118,10 +121,10 @@ Error DIASession::createFromExe(StringRef Path,
const wchar_t *Path16Str = reinterpret_cast<const wchar_t *>(Path16.data());
HRESULT HR;
if (FAILED(HR = DiaDataSource->loadDataForExe(Path16Str, nullptr, nullptr)))
- return ErrorFromHResult(HR);
+ return ErrorFromHResult(HR, "Calling loadDataForExe");
if (FAILED(HR = DiaDataSource->openSession(&DiaSession)))
- return ErrorFromHResult(HR);
+ return ErrorFromHResult(HR, "Calling openSession");
Session.reset(new DIASession(DiaSession));
return Error::success();
diff --git a/contrib/llvm/lib/DebugInfo/PDB/GenericError.cpp b/contrib/llvm/lib/DebugInfo/PDB/GenericError.cpp
index 34e1799..789f3b8 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/GenericError.cpp
+++ b/contrib/llvm/lib/DebugInfo/PDB/GenericError.cpp
@@ -20,7 +20,7 @@ namespace {
// deal with the Error value directly, rather than converting to error_code.
class GenericErrorCategory : public std::error_category {
public:
- const char *name() const LLVM_NOEXCEPT override { return "llvm.pdb"; }
+ const char *name() const noexcept override { return "llvm.pdb"; }
std::string message(int Condition) const override {
switch (static_cast<generic_error_code>(Condition)) {
@@ -45,11 +45,10 @@ char GenericError::ID = 0;
GenericError::GenericError(generic_error_code C) : GenericError(C, "") {}
-GenericError::GenericError(const std::string &Context)
+GenericError::GenericError(StringRef Context)
: GenericError(generic_error_code::unspecified, Context) {}
-GenericError::GenericError(generic_error_code C, const std::string &Context)
- : Code(C) {
+GenericError::GenericError(generic_error_code C, StringRef Context) : Code(C) {
ErrMsg = "PDB Error: ";
std::error_code EC = convertToErrorCode();
if (Code != generic_error_code::unspecified)
@@ -60,7 +59,7 @@ GenericError::GenericError(generic_error_code C, const std::string &Context)
void GenericError::log(raw_ostream &OS) const { OS << ErrMsg << "\n"; }
-const std::string &GenericError::getErrorMessage() const { return ErrMsg; }
+StringRef GenericError::getErrorMessage() const { return ErrMsg; }
std::error_code GenericError::convertToErrorCode() const {
return std::error_code(static_cast<int>(Code), *Category);
diff --git a/contrib/llvm/lib/DebugInfo/PDB/IPDBSourceFile.cpp b/contrib/llvm/lib/DebugInfo/PDB/IPDBSourceFile.cpp
index 46b422f..8cb1fbe 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/IPDBSourceFile.cpp
+++ b/contrib/llvm/lib/DebugInfo/PDB/IPDBSourceFile.cpp
@@ -1,4 +1,4 @@
-//===- IPDBSourceFile.cpp - base interface for a PDB source file *- C++ -*-===//
+//===- IPDBSourceFile.cpp - base interface for a PDB source file ----------===//
//
// The LLVM Compiler Infrastructure
//
@@ -8,15 +8,17 @@
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
-
#include "llvm/DebugInfo/PDB/PDBExtras.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
+#include <cstdint>
+#include <string>
using namespace llvm;
using namespace llvm::pdb;
-IPDBSourceFile::~IPDBSourceFile() {}
+IPDBSourceFile::~IPDBSourceFile() = default;
void IPDBSourceFile::dump(raw_ostream &OS, int Indent) const {
OS.indent(Indent);
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDB.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDB.cpp
index 69a908e..0d72059 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/PDB.cpp
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDB.cpp
@@ -14,7 +14,7 @@
#include "llvm/DebugInfo/PDB/GenericError.h"
#include "llvm/DebugInfo/PDB/IPDBSession.h"
#include "llvm/DebugInfo/PDB/PDB.h"
-#if HAVE_DIA_SDK
+#if LLVM_ENABLE_DIA_SDK
#include "llvm/DebugInfo/PDB/DIA/DIASession.h"
#endif
#include "llvm/DebugInfo/PDB/Raw/RawSession.h"
@@ -30,7 +30,7 @@ Error llvm::pdb::loadDataForPDB(PDB_ReaderType Type, StringRef Path,
if (Type == PDB_ReaderType::Raw)
return RawSession::createFromPdb(Path, Session);
-#if HAVE_DIA_SDK
+#if LLVM_ENABLE_DIA_SDK
return DIASession::createFromPdb(Path, Session);
#else
return llvm::make_error<GenericError>("DIA is not installed on the system");
@@ -43,7 +43,7 @@ Error llvm::pdb::loadDataForEXE(PDB_ReaderType Type, StringRef Path,
if (Type == PDB_ReaderType::Raw)
return RawSession::createFromExe(Path, Session);
-#if HAVE_DIA_SDK
+#if LLVM_ENABLE_DIA_SDK
return DIASession::createFromExe(Path, Session);
#else
return llvm::make_error<GenericError>("DIA is not installed on the system");
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBContext.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBContext.cpp
index 7732302..94b81ec 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/PDBContext.cpp
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBContext.cpp
@@ -29,8 +29,8 @@ PDBContext::PDBContext(const COFFObjectFile &Object,
Session->setLoadAddress(ImageBase.get());
}
-void PDBContext::dump(raw_ostream &OS, DIDumpType DumpType,
- bool DumpEH) {}
+void PDBContext::dump(raw_ostream &OS, DIDumpType DumpType, bool DumpEH,
+ bool SummarizeTypes) {}
DILineInfo PDBContext::getLineInfoForAddress(uint64_t Address,
DILineInfoSpecifier Specifier) {
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp
index a347c67..541fcda 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp
@@ -15,15 +15,14 @@
#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
#include "llvm/DebugInfo/PDB/IPDBSession.h"
-#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
using namespace llvm;
using namespace llvm::pdb;
-IPDBSession::~IPDBSession() {}
+IPDBSession::~IPDBSession() = default;
-IPDBDataStream::~IPDBDataStream() {}
+IPDBDataStream::~IPDBDataStream() = default;
-IPDBRawSymbol::~IPDBRawSymbol() {}
+IPDBRawSymbol::~IPDBRawSymbol() = default;
-IPDBLineNumber::~IPDBLineNumber() {}
+IPDBLineNumber::~IPDBLineNumber() = default;
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymDumper.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymDumper.cpp
index 9450a98..2f81931 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymDumper.cpp
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymDumper.cpp
@@ -20,7 +20,7 @@ using namespace llvm::pdb;
PDBSymDumper::PDBSymDumper(bool ShouldRequireImpl)
: RequireImpl(ShouldRequireImpl) {}
-PDBSymDumper::~PDBSymDumper() {}
+PDBSymDumper::~PDBSymDumper() = default;
void PDBSymDumper::dump(const PDBSymbolAnnotation &Symbol) {
PDB_SYMDUMP_UNREACHABLE(PDBSymbolAnnotation)
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp
index 78b3afc..633e11a 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp
@@ -8,9 +8,9 @@
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/PDB/PDBSymbol.h"
-
#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBExtras.h"
#include "llvm/DebugInfo/PDB/PDBSymbolAnnotation.h"
#include "llvm/DebugInfo/PDB/PDBSymbolBlock.h"
#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
@@ -42,12 +42,9 @@
#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h"
#include "llvm/DebugInfo/PDB/PDBSymbolUnknown.h"
#include "llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h"
-#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
-#include <memory>
-#include <utility>
-
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+#include <algorithm>
#include <memory>
-#include <utility>
using namespace llvm;
using namespace llvm::pdb;
@@ -56,7 +53,7 @@ PDBSymbol::PDBSymbol(const IPDBSession &PDBSession,
std::unique_ptr<IPDBRawSymbol> Symbol)
: Session(PDBSession), RawSymbol(std::move(Symbol)) {}
-PDBSymbol::~PDBSymbol() {}
+PDBSymbol::~PDBSymbol() = default;
#define FACTORY_SYMTAG_CASE(Tag, Type) \
case PDB_SymType::Tag: \
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp b/contrib/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp
index 3c0586c..4f4a0cf 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp
+++ b/contrib/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp
@@ -7,13 +7,13 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/MSF/StreamArray.h"
+#include "llvm/DebugInfo/MSF/StreamReader.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
#include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
-
-#include "llvm/DebugInfo/CodeView/StreamArray.h"
-#include "llvm/DebugInfo/CodeView/StreamReader.h"
-#include "llvm/DebugInfo/CodeView/StreamWriter.h"
#include "llvm/DebugInfo/PDB/Raw/ISectionContribVisitor.h"
-#include "llvm/DebugInfo/PDB/Raw/IndexedStreamData.h"
#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
#include "llvm/DebugInfo/PDB/Raw/ModInfo.h"
#include "llvm/DebugInfo/PDB/Raw/NameHashTable.h"
@@ -22,49 +22,17 @@
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
#include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
#include "llvm/Object/COFF.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
using namespace llvm;
using namespace llvm::codeview;
+using namespace llvm::msf;
using namespace llvm::pdb;
using namespace llvm::support;
-namespace {
-// Some of the values are stored in bitfields. Since this needs to be portable
-// across compilers and architectures (big / little endian in particular) we
-// can't use the actual structures below, but must instead do the shifting
-// and masking ourselves. The struct definitions are provided for reference.
-
-// struct DbiFlags {
-// uint16_t IncrementalLinking : 1; // True if linked incrementally
-// uint16_t IsStripped : 1; // True if private symbols were stripped.
-// uint16_t HasCTypes : 1; // True if linked with /debug:ctypes.
-// uint16_t Reserved : 13;
-//};
-const uint16_t FlagIncrementalMask = 0x0001;
-const uint16_t FlagStrippedMask = 0x0002;
-const uint16_t FlagHasCTypesMask = 0x0004;
-
-// struct DbiBuildNo {
-// uint16_t MinorVersion : 8;
-// uint16_t MajorVersion : 7;
-// uint16_t NewVersionFormat : 1;
-//};
-const uint16_t BuildMinorMask = 0x00FF;
-const uint16_t BuildMinorShift = 0;
-
-const uint16_t BuildMajorMask = 0x7F00;
-const uint16_t BuildMajorShift = 8;
-
-struct FileInfoSubstreamHeader {
- ulittle16_t NumModules; // Total # of modules, should match number of
- // records in the ModuleInfo substream.
- ulittle16_t NumSourceFiles; // Total # of source files. This value is not
- // accurate because PDB actually supports more
- // than 64k source files, so we ignore it and
- // compute the value from other stream fields.
-};
-}
-
template <typename ContribType>
static Error loadSectionContribs(FixedStreamArray<ContribType> &Output,
StreamReader &Reader) {
@@ -81,15 +49,14 @@ static Error loadSectionContribs(FixedStreamArray<ContribType> &Output,
DbiStream::DbiStream(PDBFile &File, std::unique_ptr<MappedBlockStream> Stream)
: Pdb(File), Stream(std::move(Stream)), Header(nullptr) {
- static_assert(sizeof(HeaderInfo) == 64, "Invalid HeaderInfo size!");
}
-DbiStream::~DbiStream() {}
+DbiStream::~DbiStream() = default;
Error DbiStream::reload() {
StreamReader Reader(*Stream);
- if (Stream->getLength() < sizeof(HeaderInfo))
+ if (Stream->getLength() < sizeof(DbiStreamHeader))
return make_error<RawError>(raw_error_code::corrupt_file,
"DBI Stream does not contain a header.");
if (auto EC = Reader.readObject(Header))
@@ -116,7 +83,7 @@ Error DbiStream::reload() {
"DBI Age does not match PDB Age.");
if (Stream->getLength() !=
- sizeof(HeaderInfo) + Header->ModiSubstreamSize +
+ sizeof(DbiStreamHeader) + Header->ModiSubstreamSize +
Header->SecContrSubstreamSize + Header->SectionMapSize +
Header->FileInfoSize + Header->TypeServerSize +
Header->OptionalDbgHdrSize + Header->ECSubstreamSize)
@@ -142,14 +109,11 @@ Error DbiStream::reload() {
return make_error<RawError>(raw_error_code::corrupt_file,
"DBI type server substream not aligned.");
- // Since each ModInfo in the stream is a variable length, we have to iterate
- // them to know how many there actually are.
- VarStreamArray<ModInfo> ModInfoArray;
- if (auto EC = Reader.readArray(ModInfoArray, Header->ModiSubstreamSize))
+ if (auto EC =
+ Reader.readStreamRef(ModInfoSubstream, Header->ModiSubstreamSize))
+ return EC;
+ if (auto EC = initializeModInfoArray())
return EC;
- for (auto &Info : ModInfoArray) {
- ModuleInfos.emplace_back(Info);
- }
if (auto EC = Reader.readStreamRef(SecContrSubstream,
Header->SecContrSubstreamSize))
@@ -209,25 +173,27 @@ uint16_t DbiStream::getGlobalSymbolStreamIndex() const {
uint16_t DbiStream::getFlags() const { return Header->Flags; }
bool DbiStream::isIncrementallyLinked() const {
- return (Header->Flags & FlagIncrementalMask) != 0;
+ return (Header->Flags & DbiFlags::FlagIncrementalMask) != 0;
}
bool DbiStream::hasCTypes() const {
- return (Header->Flags & FlagHasCTypesMask) != 0;
+ return (Header->Flags & DbiFlags::FlagHasCTypesMask) != 0;
}
bool DbiStream::isStripped() const {
- return (Header->Flags & FlagStrippedMask) != 0;
+ return (Header->Flags & DbiFlags::FlagStrippedMask) != 0;
}
uint16_t DbiStream::getBuildNumber() const { return Header->BuildNumber; }
uint16_t DbiStream::getBuildMajorVersion() const {
- return (Header->BuildNumber & BuildMajorMask) >> BuildMajorShift;
+ return (Header->BuildNumber & DbiBuildNo::BuildMajorMask) >>
+ DbiBuildNo::BuildMajorShift;
}
uint16_t DbiStream::getBuildMinorVersion() const {
- return (Header->BuildNumber & BuildMinorMask) >> BuildMinorShift;
+ return (Header->BuildNumber & DbiBuildNo::BuildMinorMask) >>
+ DbiBuildNo::BuildMinorShift;
}
uint16_t DbiStream::getPdbDllRbld() const { return Header->PdbDllRbld; }
@@ -243,21 +209,20 @@ PDB_Machine DbiStream::getMachineType() const {
return static_cast<PDB_Machine>(Machine);
}
-codeview::FixedStreamArray<object::coff_section>
-DbiStream::getSectionHeaders() {
+msf::FixedStreamArray<object::coff_section> DbiStream::getSectionHeaders() {
return SectionHeaders;
}
-codeview::FixedStreamArray<object::FpoData> DbiStream::getFpoRecords() {
+msf::FixedStreamArray<object::FpoData> DbiStream::getFpoRecords() {
return FpoRecords;
}
ArrayRef<ModuleInfoEx> DbiStream::modules() const { return ModuleInfos; }
-codeview::FixedStreamArray<SecMapEntry> DbiStream::getSectionMap() const {
+msf::FixedStreamArray<SecMapEntry> DbiStream::getSectionMap() const {
return SectionMap;
}
-void llvm::pdb::DbiStream::visitSectionContributions(
+void DbiStream::visitSectionContributions(
ISectionContribVisitor &Visitor) const {
if (SectionContribVersion == DbiSecContribVer60) {
for (auto &SC : SectionContribs)
@@ -285,6 +250,24 @@ Error DbiStream::initializeSectionContributionData() {
"Unsupported DBI Section Contribution version");
}
+Error DbiStream::initializeModInfoArray() {
+ if (ModInfoSubstream.getLength() == 0)
+ return Error::success();
+
+ // Since each ModInfo in the stream is a variable length, we have to iterate
+ // them to know how many there actually are.
+ StreamReader Reader(ModInfoSubstream);
+
+ VarStreamArray<ModInfo> ModInfoArray;
+ if (auto EC = Reader.readArray(ModInfoArray, ModInfoSubstream.getLength()))
+ return EC;
+ for (auto &Info : ModInfoArray) {
+ ModuleInfos.emplace_back(Info);
+ }
+
+ return Error::success();
+}
+
// Initializes this->SectionHeaders.
Error DbiStream::initializeSectionHeadersData() {
if (DbgStreams.size() == 0)
@@ -294,22 +277,21 @@ Error DbiStream::initializeSectionHeadersData() {
if (StreamNum >= Pdb.getNumStreams())
return make_error<RawError>(raw_error_code::no_stream);
- auto SHS = MappedBlockStream::createIndexedStream(StreamNum, Pdb);
- if (!SHS)
- return SHS.takeError();
+ auto SHS = MappedBlockStream::createIndexedStream(
+ Pdb.getMsfLayout(), Pdb.getMsfBuffer(), StreamNum);
- size_t StreamLen = (*SHS)->getLength();
+ size_t StreamLen = SHS->getLength();
if (StreamLen % sizeof(object::coff_section))
return make_error<RawError>(raw_error_code::corrupt_file,
"Corrupted section header stream.");
size_t NumSections = StreamLen / sizeof(object::coff_section);
- codeview::StreamReader Reader(**SHS);
+ msf::StreamReader Reader(*SHS);
if (auto EC = Reader.readArray(SectionHeaders, NumSections))
return make_error<RawError>(raw_error_code::corrupt_file,
"Could not read a bitmap.");
- SectionHeaderStream = std::move(*SHS);
+ SectionHeaderStream = std::move(SHS);
return Error::success();
}
@@ -321,27 +303,26 @@ Error DbiStream::initializeFpoRecords() {
uint32_t StreamNum = getDebugStreamIndex(DbgHeaderType::NewFPO);
// This means there is no FPO data.
- if (StreamNum == InvalidStreamIndex)
+ if (StreamNum == kInvalidStreamIndex)
return Error::success();
if (StreamNum >= Pdb.getNumStreams())
return make_error<RawError>(raw_error_code::no_stream);
- auto FS = MappedBlockStream::createIndexedStream(StreamNum, Pdb);
- if (!FS)
- return FS.takeError();
+ auto FS = MappedBlockStream::createIndexedStream(
+ Pdb.getMsfLayout(), Pdb.getMsfBuffer(), StreamNum);
- size_t StreamLen = (*FS)->getLength();
+ size_t StreamLen = FS->getLength();
if (StreamLen % sizeof(object::FpoData))
return make_error<RawError>(raw_error_code::corrupt_file,
"Corrupted New FPO stream.");
size_t NumRecords = StreamLen / sizeof(object::FpoData);
- codeview::StreamReader Reader(**FS);
+ msf::StreamReader Reader(*FS);
if (auto EC = Reader.readArray(FpoRecords, NumRecords))
return make_error<RawError>(raw_error_code::corrupt_file,
"Corrupted New FPO stream.");
- FpoStream = std::move(*FS);
+ FpoStream = std::move(FS);
return Error::success();
}
@@ -359,18 +340,6 @@ Error DbiStream::initializeSectionMapData() {
}
Error DbiStream::initializeFileInfo() {
- // The layout of the FileInfoSubstream is like this:
- // struct {
- // ulittle16_t NumModules;
- // ulittle16_t NumSourceFiles;
- // ulittle16_t ModIndices[NumModules];
- // ulittle16_t ModFileCounts[NumModules];
- // ulittle32_t FileNameOffsets[NumSourceFiles];
- // char Names[][NumSourceFiles];
- // };
- // with the caveat that `NumSourceFiles` cannot be trusted, so
- // it is computed by summing `ModFileCounts`.
- //
if (FileInfoSubstream.getLength() == 0)
return Error::success();
@@ -437,7 +406,10 @@ Error DbiStream::initializeFileInfo() {
}
uint32_t DbiStream::getDebugStreamIndex(DbgHeaderType Type) const {
- return DbgStreams[static_cast<uint16_t>(Type)];
+ uint16_t T = static_cast<uint16_t>(Type);
+ if (T >= DbgStreams.size())
+ return kInvalidStreamIndex;
+ return DbgStreams[T];
}
Expected<StringRef> DbiStream::getFileNameForIndex(uint32_t Index) const {
@@ -452,11 +424,3 @@ Expected<StringRef> DbiStream::getFileNameForIndex(uint32_t Index) const {
return std::move(EC);
return Name;
}
-
-Error DbiStream::commit() {
- StreamWriter Writer(*Stream);
- if (auto EC = Writer.writeObject(*Header))
- return EC;
-
- return Error::success();
-}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp
index 34ff8ae..1d5b8d6 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp
+++ b/contrib/llvm/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp
@@ -9,18 +9,28 @@
#include "llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h"
-#include "llvm/DebugInfo/CodeView/StreamWriter.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/DebugInfo/MSF/MSFBuilder.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/MSF/StreamWriter.h"
#include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
-#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Support/COFF.h"
using namespace llvm;
using namespace llvm::codeview;
+using namespace llvm::msf;
using namespace llvm::pdb;
-DbiStreamBuilder::DbiStreamBuilder()
- : Age(1), BuildNumber(0), PdbDllVersion(0), PdbDllRbld(0), Flags(0),
- MachineType(PDB_Machine::x86) {}
+namespace {
+class ModiSubstreamBuilder {};
+}
+
+DbiStreamBuilder::DbiStreamBuilder(msf::MSFBuilder &Msf)
+ : Msf(Msf), Allocator(Msf.getAllocator()), Age(1), BuildNumber(0),
+ PdbDllVersion(0), PdbDllRbld(0), Flags(0), MachineType(PDB_Machine::x86),
+ Header(nullptr), DbgStreams((int)DbgHeaderType::Max) {}
void DbiStreamBuilder::setVersionHeader(PdbRaw_DbiVer V) { VerHeader = V; }
@@ -36,24 +46,207 @@ void DbiStreamBuilder::setFlags(uint16_t F) { Flags = F; }
void DbiStreamBuilder::setMachineType(PDB_Machine M) { MachineType = M; }
+void DbiStreamBuilder::setSectionContribs(ArrayRef<SectionContrib> Arr) {
+ SectionContribs = Arr;
+}
+
+void DbiStreamBuilder::setSectionMap(ArrayRef<SecMapEntry> SecMap) {
+ SectionMap = SecMap;
+}
+
+Error DbiStreamBuilder::addDbgStream(pdb::DbgHeaderType Type,
+ ArrayRef<uint8_t> Data) {
+ if (DbgStreams[(int)Type].StreamNumber)
+ return make_error<RawError>(raw_error_code::duplicate_entry,
+ "The specified stream type already exists");
+ auto ExpectedIndex = Msf.addStream(Data.size());
+ if (!ExpectedIndex)
+ return ExpectedIndex.takeError();
+ uint32_t Index = std::move(*ExpectedIndex);
+ DbgStreams[(int)Type].Data = Data;
+ DbgStreams[(int)Type].StreamNumber = Index;
+ return Error::success();
+}
+
uint32_t DbiStreamBuilder::calculateSerializedLength() const {
// For now we only support serializing the header.
- return sizeof(DbiStream::HeaderInfo);
-}
-
-Expected<std::unique_ptr<DbiStream>> DbiStreamBuilder::build(PDBFile &File) {
- if (!VerHeader.hasValue())
- return make_error<RawError>(raw_error_code::unspecified,
- "Missing DBI Stream Version");
-
- auto DbiS = MappedBlockStream::createIndexedStream(StreamDBI, File);
- if (!DbiS)
- return DbiS.takeError();
- auto DS = std::move(*DbiS);
- DbiStream::HeaderInfo *H =
- static_cast<DbiStream::HeaderInfo *>(DS->getAllocator().Allocate(
- sizeof(DbiStream::HeaderInfo),
- llvm::AlignOf<DbiStream::HeaderInfo>::Alignment));
+ return sizeof(DbiStreamHeader) + calculateFileInfoSubstreamSize() +
+ calculateModiSubstreamSize() + calculateSectionContribsStreamSize() +
+ calculateSectionMapStreamSize() + calculateDbgStreamsSize();
+}
+
+Error DbiStreamBuilder::addModuleInfo(StringRef ObjFile, StringRef Module) {
+ auto Entry = llvm::make_unique<ModuleInfo>();
+ ModuleInfo *M = Entry.get();
+ Entry->Mod = Module;
+ Entry->Obj = ObjFile;
+ auto Result = ModuleInfos.insert(std::make_pair(Module, std::move(Entry)));
+ if (!Result.second)
+ return make_error<RawError>(raw_error_code::duplicate_entry,
+ "The specified module already exists");
+ ModuleInfoList.push_back(M);
+ return Error::success();
+}
+
+Error DbiStreamBuilder::addModuleSourceFile(StringRef Module, StringRef File) {
+ auto ModIter = ModuleInfos.find(Module);
+ if (ModIter == ModuleInfos.end())
+ return make_error<RawError>(raw_error_code::no_entry,
+ "The specified module was not found");
+ uint32_t Index = SourceFileNames.size();
+ SourceFileNames.insert(std::make_pair(File, Index));
+ auto &ModEntry = *ModIter;
+ ModEntry.second->SourceFiles.push_back(File);
+ return Error::success();
+}
+
+uint32_t DbiStreamBuilder::calculateModiSubstreamSize() const {
+ uint32_t Size = 0;
+ for (const auto &M : ModuleInfoList) {
+ Size += sizeof(ModuleInfoHeader);
+ Size += M->Mod.size() + 1;
+ Size += M->Obj.size() + 1;
+ }
+ return alignTo(Size, sizeof(uint32_t));
+}
+
+uint32_t DbiStreamBuilder::calculateSectionContribsStreamSize() const {
+ if (SectionContribs.empty())
+ return 0;
+ return sizeof(enum PdbRaw_DbiSecContribVer) +
+ sizeof(SectionContribs[0]) * SectionContribs.size();
+}
+
+uint32_t DbiStreamBuilder::calculateSectionMapStreamSize() const {
+ if (SectionMap.empty())
+ return 0;
+ return sizeof(SecMapHeader) + sizeof(SecMapEntry) * SectionMap.size();
+}
+
+uint32_t DbiStreamBuilder::calculateFileInfoSubstreamSize() const {
+ uint32_t Size = 0;
+ Size += sizeof(ulittle16_t); // NumModules
+ Size += sizeof(ulittle16_t); // NumSourceFiles
+ Size += ModuleInfoList.size() * sizeof(ulittle16_t); // ModIndices
+ Size += ModuleInfoList.size() * sizeof(ulittle16_t); // ModFileCounts
+ uint32_t NumFileInfos = 0;
+ for (const auto &M : ModuleInfoList)
+ NumFileInfos += M->SourceFiles.size();
+ Size += NumFileInfos * sizeof(ulittle32_t); // FileNameOffsets
+ Size += calculateNamesBufferSize();
+ return alignTo(Size, sizeof(uint32_t));
+}
+
+uint32_t DbiStreamBuilder::calculateNamesBufferSize() const {
+ uint32_t Size = 0;
+ for (const auto &F : SourceFileNames) {
+ Size += F.getKeyLength() + 1; // Names[I];
+ }
+ return Size;
+}
+
+uint32_t DbiStreamBuilder::calculateDbgStreamsSize() const {
+ return DbgStreams.size() * sizeof(uint16_t);
+}
+
+Error DbiStreamBuilder::generateModiSubstream() {
+ uint32_t Size = calculateModiSubstreamSize();
+ auto Data = Allocator.Allocate<uint8_t>(Size);
+
+ ModInfoBuffer = MutableByteStream(MutableArrayRef<uint8_t>(Data, Size));
+
+ StreamWriter ModiWriter(ModInfoBuffer);
+ for (const auto &M : ModuleInfoList) {
+ ModuleInfoHeader Layout = {};
+ Layout.ModDiStream = kInvalidStreamIndex;
+ Layout.NumFiles = M->SourceFiles.size();
+ if (auto EC = ModiWriter.writeObject(Layout))
+ return EC;
+ if (auto EC = ModiWriter.writeZeroString(M->Mod))
+ return EC;
+ if (auto EC = ModiWriter.writeZeroString(M->Obj))
+ return EC;
+ }
+ if (ModiWriter.bytesRemaining() > sizeof(uint32_t))
+ return make_error<RawError>(raw_error_code::invalid_format,
+ "Unexpected bytes in Modi Stream Data");
+ return Error::success();
+}
+
+Error DbiStreamBuilder::generateFileInfoSubstream() {
+ uint32_t Size = calculateFileInfoSubstreamSize();
+ uint32_t NameSize = calculateNamesBufferSize();
+ auto Data = Allocator.Allocate<uint8_t>(Size);
+ uint32_t NamesOffset = Size - NameSize;
+
+ FileInfoBuffer = MutableByteStream(MutableArrayRef<uint8_t>(Data, Size));
+
+ WritableStreamRef MetadataBuffer =
+ WritableStreamRef(FileInfoBuffer).keep_front(NamesOffset);
+ StreamWriter MetadataWriter(MetadataBuffer);
+
+ uint16_t ModiCount = std::min<uint32_t>(UINT16_MAX, ModuleInfos.size());
+ uint16_t FileCount = std::min<uint32_t>(UINT16_MAX, SourceFileNames.size());
+ if (auto EC = MetadataWriter.writeInteger(ModiCount)) // NumModules
+ return EC;
+ if (auto EC = MetadataWriter.writeInteger(FileCount)) // NumSourceFiles
+ return EC;
+ for (uint16_t I = 0; I < ModiCount; ++I) {
+ if (auto EC = MetadataWriter.writeInteger(I)) // Mod Indices
+ return EC;
+ }
+ for (const auto MI : ModuleInfoList) {
+ FileCount = static_cast<uint16_t>(MI->SourceFiles.size());
+ if (auto EC = MetadataWriter.writeInteger(FileCount)) // Mod File Counts
+ return EC;
+ }
+
+ // Before writing the FileNameOffsets array, write the NamesBuffer array.
+ // A side effect of this is that this will actually compute the various
+ // file name offsets, so we can then go back and write the FileNameOffsets
+ // array to the other substream.
+ NamesBuffer = WritableStreamRef(FileInfoBuffer).drop_front(NamesOffset);
+ StreamWriter NameBufferWriter(NamesBuffer);
+ for (auto &Name : SourceFileNames) {
+ Name.second = NameBufferWriter.getOffset();
+ if (auto EC = NameBufferWriter.writeZeroString(Name.getKey()))
+ return EC;
+ }
+
+ for (const auto MI : ModuleInfoList) {
+ for (StringRef Name : MI->SourceFiles) {
+ auto Result = SourceFileNames.find(Name);
+ if (Result == SourceFileNames.end())
+ return make_error<RawError>(raw_error_code::no_entry,
+ "The source file was not found.");
+ if (auto EC = MetadataWriter.writeInteger(Result->second))
+ return EC;
+ }
+ }
+
+ if (NameBufferWriter.bytesRemaining() > 0)
+ return make_error<RawError>(raw_error_code::invalid_format,
+ "The names buffer contained unexpected data.");
+
+ if (MetadataWriter.bytesRemaining() > sizeof(uint32_t))
+ return make_error<RawError>(
+ raw_error_code::invalid_format,
+ "The metadata buffer contained unexpected data.");
+
+ return Error::success();
+}
+
+Error DbiStreamBuilder::finalize() {
+ if (Header)
+ return Error::success();
+
+ DbiStreamHeader *H = Allocator.Allocate<DbiStreamHeader>();
+
+ if (auto EC = generateModiSubstream())
+ return EC;
+ if (auto EC = generateFileInfoSubstream())
+ return EC;
+
H->VersionHeader = *VerHeader;
H->VersionSignature = -1;
H->Age = Age;
@@ -64,18 +257,156 @@ Expected<std::unique_ptr<DbiStream>> DbiStreamBuilder::build(PDBFile &File) {
H->MachineType = static_cast<uint16_t>(MachineType);
H->ECSubstreamSize = 0;
- H->FileInfoSize = 0;
- H->ModiSubstreamSize = 0;
- H->OptionalDbgHdrSize = 0;
- H->SecContrSubstreamSize = 0;
- H->SectionMapSize = 0;
+ H->FileInfoSize = FileInfoBuffer.getLength();
+ H->ModiSubstreamSize = ModInfoBuffer.getLength();
+ H->OptionalDbgHdrSize = DbgStreams.size() * sizeof(uint16_t);
+ H->SecContrSubstreamSize = calculateSectionContribsStreamSize();
+ H->SectionMapSize = calculateSectionMapStreamSize();
H->TypeServerSize = 0;
- H->SymRecordStreamIndex = DbiStream::InvalidStreamIndex;
- H->PublicSymbolStreamIndex = DbiStream::InvalidStreamIndex;
- H->MFCTypeServerIndex = DbiStream::InvalidStreamIndex;
- H->GlobalSymbolStreamIndex = DbiStream::InvalidStreamIndex;
-
- auto Dbi = llvm::make_unique<DbiStream>(File, std::move(DS));
- Dbi->Header = H;
- return std::move(Dbi);
+ H->SymRecordStreamIndex = kInvalidStreamIndex;
+ H->PublicSymbolStreamIndex = kInvalidStreamIndex;
+ H->MFCTypeServerIndex = kInvalidStreamIndex;
+ H->GlobalSymbolStreamIndex = kInvalidStreamIndex;
+
+ Header = H;
+ return Error::success();
+}
+
+Error DbiStreamBuilder::finalizeMsfLayout() {
+ uint32_t Length = calculateSerializedLength();
+ if (auto EC = Msf.setStreamSize(StreamDBI, Length))
+ return EC;
+ return Error::success();
+}
+
+static uint16_t toSecMapFlags(uint32_t Flags) {
+ uint16_t Ret = 0;
+ if (Flags & COFF::IMAGE_SCN_MEM_READ)
+ Ret |= static_cast<uint16_t>(OMFSegDescFlags::Read);
+ if (Flags & COFF::IMAGE_SCN_MEM_WRITE)
+ Ret |= static_cast<uint16_t>(OMFSegDescFlags::Write);
+ if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
+ Ret |= static_cast<uint16_t>(OMFSegDescFlags::Execute);
+ if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
+ Ret |= static_cast<uint16_t>(OMFSegDescFlags::Execute);
+ if (!(Flags & COFF::IMAGE_SCN_MEM_16BIT))
+ Ret |= static_cast<uint16_t>(OMFSegDescFlags::AddressIs32Bit);
+
+ // This seems always 1.
+ Ret |= static_cast<uint16_t>(OMFSegDescFlags::IsSelector);
+
+ return Ret;
+}
+
+// A utility function to create Section Contributions
+// for a given input sections.
+std::vector<SectionContrib> DbiStreamBuilder::createSectionContribs(
+ ArrayRef<object::coff_section> SecHdrs) {
+ std::vector<SectionContrib> Ret;
+
+ // Create a SectionContrib for each input section.
+ for (auto &Sec : SecHdrs) {
+ Ret.emplace_back();
+ auto &Entry = Ret.back();
+ memset(&Entry, 0, sizeof(Entry));
+
+ Entry.Off = Sec.PointerToRawData;
+ Entry.Size = Sec.SizeOfRawData;
+ Entry.Characteristics = Sec.Characteristics;
+ }
+ return Ret;
+}
+
+// A utility function to create a Section Map for a given list of COFF sections.
+//
+// A Section Map seem to be a copy of a COFF section list in other format.
+// I don't know why a PDB file contains both a COFF section header and
+// a Section Map, but it seems it must be present in a PDB.
+std::vector<SecMapEntry> DbiStreamBuilder::createSectionMap(
+ ArrayRef<llvm::object::coff_section> SecHdrs) {
+ std::vector<SecMapEntry> Ret;
+ int Idx = 0;
+
+ auto Add = [&]() -> SecMapEntry & {
+ Ret.emplace_back();
+ auto &Entry = Ret.back();
+ memset(&Entry, 0, sizeof(Entry));
+
+ Entry.Frame = Idx + 1;
+
+ // We don't know the meaning of these fields yet.
+ Entry.SecName = UINT16_MAX;
+ Entry.ClassName = UINT16_MAX;
+
+ return Entry;
+ };
+
+ for (auto &Hdr : SecHdrs) {
+ auto &Entry = Add();
+ Entry.Flags = toSecMapFlags(Hdr.Characteristics);
+ Entry.SecByteLength = Hdr.VirtualSize;
+ ++Idx;
+ }
+
+ // The last entry is for absolute symbols.
+ auto &Entry = Add();
+ Entry.Flags = static_cast<uint16_t>(OMFSegDescFlags::AddressIs32Bit) |
+ static_cast<uint16_t>(OMFSegDescFlags::IsAbsoluteAddress);
+ Entry.SecByteLength = UINT32_MAX;
+
+ return Ret;
+}
+
+Error DbiStreamBuilder::commit(const msf::MSFLayout &Layout,
+ const msf::WritableStream &Buffer) {
+ if (auto EC = finalize())
+ return EC;
+
+ auto InfoS =
+ WritableMappedBlockStream::createIndexedStream(Layout, Buffer, StreamDBI);
+
+ StreamWriter Writer(*InfoS);
+ if (auto EC = Writer.writeObject(*Header))
+ return EC;
+
+ if (auto EC = Writer.writeStreamRef(ModInfoBuffer))
+ return EC;
+
+ if (!SectionContribs.empty()) {
+ if (auto EC = Writer.writeEnum(DbiSecContribVer60))
+ return EC;
+ if (auto EC = Writer.writeArray(SectionContribs))
+ return EC;
+ }
+
+ if (!SectionMap.empty()) {
+ ulittle16_t Size = static_cast<ulittle16_t>(SectionMap.size());
+ SecMapHeader SMHeader = {Size, Size};
+ if (auto EC = Writer.writeObject(SMHeader))
+ return EC;
+ if (auto EC = Writer.writeArray(SectionMap))
+ return EC;
+ }
+
+ if (auto EC = Writer.writeStreamRef(FileInfoBuffer))
+ return EC;
+
+ for (auto &Stream : DbgStreams)
+ if (auto EC = Writer.writeInteger(Stream.StreamNumber))
+ return EC;
+
+ for (auto &Stream : DbgStreams) {
+ if (Stream.StreamNumber == kInvalidStreamIndex)
+ continue;
+ auto WritableStream = WritableMappedBlockStream::createIndexedStream(
+ Layout, Buffer, Stream.StreamNumber);
+ StreamWriter DbgStreamWriter(*WritableStream);
+ if (auto EC = DbgStreamWriter.writeArray(Stream.Data))
+ return EC;
+ }
+
+ if (Writer.bytesRemaining() > 0)
+ return make_error<RawError>(raw_error_code::invalid_format,
+ "Unexpected bytes found in DBI Stream");
+ return Error::success();
}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/GSI.cpp b/contrib/llvm/lib/DebugInfo/PDB/Raw/GSI.cpp
new file mode 100644
index 0000000..6ecbb5c
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/Raw/GSI.cpp
@@ -0,0 +1,93 @@
+//===- GSI.cpp - Common Functions for GlobalsStream and PublicsStream ----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "GSI.h"
+
+#include "llvm/DebugInfo/MSF/StreamArray.h"
+#include "llvm/DebugInfo/MSF/StreamReader.h"
+#include "llvm/DebugInfo/PDB/Raw/RawError.h"
+#include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
+
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace pdb {
+
+static Error checkHashHdrVersion(const GSIHashHeader *HashHdr) {
+ if (HashHdr->VerHdr != GSIHashHeader::HdrVersion)
+ return make_error<RawError>(
+ raw_error_code::feature_unsupported,
+ "Encountered unsupported globals stream version.");
+
+ return Error::success();
+}
+
+Error readGSIHashBuckets(
+ msf::FixedStreamArray<support::ulittle32_t> &HashBuckets,
+ const GSIHashHeader *HashHdr, msf::StreamReader &Reader) {
+ if (auto EC = checkHashHdrVersion(HashHdr))
+ return EC;
+
+ // Before the actual hash buckets, there is a bitmap of length determined by
+ // IPHR_HASH.
+ ArrayRef<uint8_t> Bitmap;
+ size_t BitmapSizeInBits = alignTo(IPHR_HASH + 1, 32);
+ uint32_t NumBitmapEntries = BitmapSizeInBits / 8;
+ if (auto EC = Reader.readBytes(Bitmap, NumBitmapEntries))
+ return joinErrors(std::move(EC),
+ make_error<RawError>(raw_error_code::corrupt_file,
+ "Could not read a bitmap."));
+ uint32_t NumBuckets = 0;
+ for (uint8_t B : Bitmap)
+ NumBuckets += countPopulation(B);
+
+ // Hash buckets follow.
+ if (auto EC = Reader.readArray(HashBuckets, NumBuckets))
+ return joinErrors(std::move(EC),
+ make_error<RawError>(raw_error_code::corrupt_file,
+ "Hash buckets corrupted."));
+
+ return Error::success();
+}
+
+Error readGSIHashHeader(const GSIHashHeader *&HashHdr,
+ msf::StreamReader &Reader) {
+ if (Reader.readObject(HashHdr))
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Stream does not contain a GSIHashHeader.");
+
+ if (HashHdr->VerSignature != GSIHashHeader::HdrSignature)
+ return make_error<RawError>(
+ raw_error_code::feature_unsupported,
+ "GSIHashHeader signature (0xffffffff) not found.");
+
+ return Error::success();
+}
+
+Error readGSIHashRecords(msf::FixedStreamArray<PSHashRecord> &HashRecords,
+ const GSIHashHeader *HashHdr,
+ msf::StreamReader &Reader) {
+ if (auto EC = checkHashHdrVersion(HashHdr))
+ return EC;
+
+ // HashHdr->HrSize specifies the number of bytes of PSHashRecords we have.
+ // Verify that we can read them all.
+ if (HashHdr->HrSize % sizeof(PSHashRecord))
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Invalid HR array size.");
+ uint32_t NumHashRecords = HashHdr->HrSize / sizeof(PSHashRecord);
+ if (auto EC = Reader.readArray(HashRecords, NumHashRecords))
+ return joinErrors(std::move(EC),
+ make_error<RawError>(raw_error_code::corrupt_file,
+ "Error reading hash records."));
+
+ return Error::success();
+}
+}
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/GSI.h b/contrib/llvm/lib/DebugInfo/PDB/Raw/GSI.h
new file mode 100644
index 0000000..82cebd9
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/Raw/GSI.h
@@ -0,0 +1,70 @@
+//===- GSI.h - Common Declarations for GlobalsStream and PublicsStream ----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// The data structures defined in this file are based on the reference
+// implementation which is available at
+// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h
+//
+// When you are reading the reference source code, you'd find the
+// information below useful.
+//
+// - ppdb1->m_fMinimalDbgInfo seems to be always true.
+// - SMALLBUCKETS macro is defined.
+//
+// The reference doesn't compile, so I learned just by reading code.
+// It's not guaranteed to be correct.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_DEBUGINFO_PDB_RAW_GSI_H
+#define LLVM_LIB_DEBUGINFO_PDB_RAW_GSI_H
+
+#include "llvm/DebugInfo/MSF/StreamArray.h"
+#include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
+
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+
+namespace msf {
+class StreamReader;
+}
+
+namespace pdb {
+
+/// From https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.cpp
+static const unsigned IPHR_HASH = 4096;
+
+/// Header of the hash tables found in the globals and publics sections.
+/// Based on GSIHashHeader in
+/// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h
+struct GSIHashHeader {
+ enum : unsigned {
+ HdrSignature = ~0U,
+ HdrVersion = 0xeffe0000 + 19990810,
+ };
+ support::ulittle32_t VerSignature;
+ support::ulittle32_t VerHdr;
+ support::ulittle32_t HrSize;
+ support::ulittle32_t NumBuckets;
+};
+
+Error readGSIHashBuckets(
+ msf::FixedStreamArray<support::ulittle32_t> &HashBuckets,
+ const GSIHashHeader *HashHdr, msf::StreamReader &Reader);
+Error readGSIHashHeader(const GSIHashHeader *&HashHdr,
+ msf::StreamReader &Reader);
+Error readGSIHashRecords(msf::FixedStreamArray<PSHashRecord> &HashRecords,
+ const GSIHashHeader *HashHdr,
+ msf::StreamReader &Reader);
+}
+}
+
+#endif
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/GlobalsStream.cpp b/contrib/llvm/lib/DebugInfo/PDB/Raw/GlobalsStream.cpp
new file mode 100644
index 0000000..31afc92
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/Raw/GlobalsStream.cpp
@@ -0,0 +1,42 @@
+//===- GlobalsStream.cpp - PDB Index of Symbols by Name ---- ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "GSI.h"
+#include "llvm/DebugInfo/MSF/StreamReader.h"
+#include "llvm/DebugInfo/PDB/Raw/GlobalsStream.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+
+using namespace llvm;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+
+GlobalsStream::GlobalsStream(std::unique_ptr<MappedBlockStream> Stream)
+ : Stream(std::move(Stream)) {}
+
+GlobalsStream::~GlobalsStream() = default;
+
+Error GlobalsStream::reload() {
+ StreamReader Reader(*Stream);
+
+ const GSIHashHeader *HashHdr;
+ if (auto EC = readGSIHashHeader(HashHdr, Reader))
+ return EC;
+
+ if (auto EC = readGSIHashRecords(HashRecords, HashHdr, Reader))
+ return EC;
+
+ if (auto EC = readGSIHashBuckets(HashBuckets, HashHdr, Reader))
+ return EC;
+ NumBuckets = HashBuckets.size();
+
+ return Error::success();
+}
+
+Error GlobalsStream::commit() { return Error::success(); }
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/Hash.cpp b/contrib/llvm/lib/DebugInfo/PDB/Raw/Hash.cpp
index 23cb557..b9f685e 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/Raw/Hash.cpp
+++ b/contrib/llvm/lib/DebugInfo/PDB/Raw/Hash.cpp
@@ -11,6 +11,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/Endian.h"
+#include "llvm/Support/JamCRC.h"
using namespace llvm;
using namespace llvm::support;
@@ -73,59 +74,13 @@ uint32_t pdb::hashStringV2(StringRef Str) {
Hash ^= (Hash >> 6);
}
- return Hash * 1664525L + 1013904223L;
+ return Hash * 1664525U + 1013904223U;
}
-static const uint32_t V8HashTable[] = {
- 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
- 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
- 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
- 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
- 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
- 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
- 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
- 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
- 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
- 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
- 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
- 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
- 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
- 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
- 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
- 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
- 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
- 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
- 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
- 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
- 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
- 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
- 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
- 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
- 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
- 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
- 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
- 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
- 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
- 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
- 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
- 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
- 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
- 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
- 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
- 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
- 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
- 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
- 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
- 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
- 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
- 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
- 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D,
-};
-
// Corresponds to `SigForPbCb` in langapi/shared/crc32.h.
uint32_t pdb::hashBufferV8(ArrayRef<uint8_t> Buf) {
- uint32_t Hash = 0;
- for (uint8_t Byte : Buf)
- Hash = (Hash >> 8) ^ V8HashTable[(Hash & 0xff) ^ Byte];
- return Hash;
+ JamCRC JC(/*Init=*/0U);
+ JC.update(makeArrayRef<char>(reinterpret_cast<const char *>(Buf.data()),
+ Buf.size()));
+ return JC.getCRC();
}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/IndexedStreamData.cpp b/contrib/llvm/lib/DebugInfo/PDB/Raw/IndexedStreamData.cpp
deleted file mode 100644
index 9bd16ea..0000000
--- a/contrib/llvm/lib/DebugInfo/PDB/Raw/IndexedStreamData.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-//===- IndexedStreamData.cpp - Standard PDB Stream Data ---------*- 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/PDB/Raw/IndexedStreamData.h"
-#include "llvm/DebugInfo/PDB/Raw/IPDBFile.h"
-
-using namespace llvm;
-using namespace llvm::pdb;
-
-IndexedStreamData::IndexedStreamData(uint32_t StreamIdx, const IPDBFile &File)
- : StreamIdx(StreamIdx), File(File) {}
-
-uint32_t IndexedStreamData::getLength() {
- return File.getStreamByteSize(StreamIdx);
-}
-
-ArrayRef<support::ulittle32_t> IndexedStreamData::getStreamBlocks() {
- return File.getStreamBlockList(StreamIdx);
-}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/InfoStream.cpp b/contrib/llvm/lib/DebugInfo/PDB/Raw/InfoStream.cpp
index c33a764..f19535d 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/Raw/InfoStream.cpp
+++ b/contrib/llvm/lib/DebugInfo/PDB/Raw/InfoStream.cpp
@@ -10,24 +10,25 @@
#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/DebugInfo/CodeView/StreamReader.h"
-#include "llvm/DebugInfo/CodeView/StreamWriter.h"
-#include "llvm/DebugInfo/PDB/Raw/IndexedStreamData.h"
+#include "llvm/DebugInfo/MSF/StreamReader.h"
+#include "llvm/DebugInfo/MSF/StreamWriter.h"
#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
+#include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
using namespace llvm;
using namespace llvm::codeview;
+using namespace llvm::msf;
using namespace llvm::pdb;
InfoStream::InfoStream(std::unique_ptr<MappedBlockStream> Stream)
: Stream(std::move(Stream)) {}
Error InfoStream::reload() {
- codeview::StreamReader Reader(*Stream);
+ StreamReader Reader(*Stream);
- const HeaderInfo *H;
+ const InfoStreamHeader *H;
if (auto EC = Reader.readObject(H))
return joinErrors(
std::move(EC),
@@ -74,17 +75,3 @@ uint32_t InfoStream::getSignature() const { return Signature; }
uint32_t InfoStream::getAge() const { return Age; }
PDB_UniqueId InfoStream::getGuid() const { return Guid; }
-
-Error InfoStream::commit() {
- StreamWriter Writer(*Stream);
-
- HeaderInfo H;
- H.Age = Age;
- H.Signature = Signature;
- H.Version = Version;
- H.Guid = Guid;
- if (auto EC = Writer.writeObject(H))
- return EC;
-
- return NamedStreams.commit(Writer);
-}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/InfoStreamBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Raw/InfoStreamBuilder.cpp
index 7be9cc3..73fbf85 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/Raw/InfoStreamBuilder.cpp
+++ b/contrib/llvm/lib/DebugInfo/PDB/Raw/InfoStreamBuilder.cpp
@@ -9,16 +9,20 @@
#include "llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h"
-#include "llvm/DebugInfo/CodeView/StreamWriter.h"
+#include "llvm/DebugInfo/MSF/MSFBuilder.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/MSF/StreamWriter.h"
#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
-#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
+#include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
using namespace llvm;
using namespace llvm::codeview;
+using namespace llvm::msf;
using namespace llvm::pdb;
-InfoStreamBuilder::InfoStreamBuilder() {}
+InfoStreamBuilder::InfoStreamBuilder(msf::MSFBuilder &Msf)
+ : Msf(Msf), Ver(PdbRaw_ImplVer::PdbImplVC70), Sig(-1), Age(0) {}
void InfoStreamBuilder::setVersion(PdbRaw_ImplVer V) { Ver = V; }
@@ -33,35 +37,29 @@ NameMapBuilder &InfoStreamBuilder::getNamedStreamsBuilder() {
}
uint32_t InfoStreamBuilder::calculateSerializedLength() const {
- return sizeof(InfoStream::HeaderInfo) +
- NamedStreams.calculateSerializedLength();
+ return sizeof(InfoStreamHeader) + NamedStreams.calculateSerializedLength();
}
-Expected<std::unique_ptr<InfoStream>> InfoStreamBuilder::build(PDBFile &File) {
- if (!Ver.hasValue())
- return make_error<RawError>(raw_error_code::unspecified,
- "Missing PDB Stream Version");
- if (!Sig.hasValue())
- return make_error<RawError>(raw_error_code::unspecified,
- "Missing PDB Stream Signature");
- if (!Age.hasValue())
- return make_error<RawError>(raw_error_code::unspecified,
- "Missing PDB Stream Age");
- if (!Guid.hasValue())
- return make_error<RawError>(raw_error_code::unspecified,
- "Missing PDB Stream Guid");
+Error InfoStreamBuilder::finalizeMsfLayout() {
+ uint32_t Length = calculateSerializedLength();
+ if (auto EC = Msf.setStreamSize(StreamPDB, Length))
+ return EC;
+ return Error::success();
+}
+
+Error InfoStreamBuilder::commit(const msf::MSFLayout &Layout,
+ const msf::WritableStream &Buffer) const {
+ auto InfoS =
+ WritableMappedBlockStream::createIndexedStream(Layout, Buffer, StreamPDB);
+ StreamWriter Writer(*InfoS);
+
+ InfoStreamHeader H;
+ H.Age = Age;
+ H.Signature = Sig;
+ H.Version = Ver;
+ H.Guid = Guid;
+ if (auto EC = Writer.writeObject(H))
+ return EC;
- auto InfoS = MappedBlockStream::createIndexedStream(StreamPDB, File);
- if (!InfoS)
- return InfoS.takeError();
- auto Info = llvm::make_unique<InfoStream>(std::move(*InfoS));
- Info->Version = *Ver;
- Info->Signature = *Sig;
- Info->Age = *Age;
- Info->Guid = *Guid;
- auto NS = NamedStreams.build();
- if (!NS)
- return NS.takeError();
- Info->NamedStreams = **NS;
- return std::move(Info);
+ return NamedStreams.commit(Writer);
}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/MappedBlockStream.cpp b/contrib/llvm/lib/DebugInfo/PDB/Raw/MappedBlockStream.cpp
deleted file mode 100644
index 92b2048..0000000
--- a/contrib/llvm/lib/DebugInfo/PDB/Raw/MappedBlockStream.cpp
+++ /dev/null
@@ -1,310 +0,0 @@
-//===- MappedBlockStream.cpp - Reads stream data from a PDBFile -----------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
-#include "llvm/DebugInfo/PDB/Raw/DirectoryStreamData.h"
-#include "llvm/DebugInfo/PDB/Raw/IPDBStreamData.h"
-#include "llvm/DebugInfo/PDB/Raw/IndexedStreamData.h"
-#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
-#include "llvm/DebugInfo/PDB/Raw/RawError.h"
-
-using namespace llvm;
-using namespace llvm::pdb;
-
-namespace {
-// This exists so that we can use make_unique while still keeping the
-// constructor of MappedBlockStream private, forcing users to go through
-// the `create` interface.
-class MappedBlockStreamImpl : public MappedBlockStream {
-public:
- MappedBlockStreamImpl(std::unique_ptr<IPDBStreamData> Data,
- const IPDBFile &File)
- : MappedBlockStream(std::move(Data), File) {}
-};
-}
-
-typedef std::pair<uint32_t, uint32_t> Interval;
-static Interval intersect(const Interval &I1, const Interval &I2) {
- return std::make_pair(std::max(I1.first, I2.first),
- std::min(I1.second, I2.second));
-}
-
-MappedBlockStream::MappedBlockStream(std::unique_ptr<IPDBStreamData> Data,
- const IPDBFile &Pdb)
- : Pdb(Pdb), Data(std::move(Data)) {}
-
-Error MappedBlockStream::readBytes(uint32_t Offset, uint32_t Size,
- ArrayRef<uint8_t> &Buffer) const {
- // Make sure we aren't trying to read beyond the end of the stream.
- if (Size > Data->getLength())
- return make_error<RawError>(raw_error_code::insufficient_buffer);
- if (Offset > Data->getLength() - Size)
- return make_error<RawError>(raw_error_code::insufficient_buffer);
-
- if (tryReadContiguously(Offset, Size, Buffer))
- return Error::success();
-
- auto CacheIter = CacheMap.find(Offset);
- if (CacheIter != CacheMap.end()) {
- // Try to find an alloc that was large enough for this request.
- for (auto &Entry : CacheIter->second) {
- if (Entry.size() >= Size) {
- Buffer = Entry.slice(0, Size);
- return Error::success();
- }
- }
- }
-
- // We couldn't find a buffer that started at the correct offset (the most
- // common scenario). Try to see if there is a buffer that starts at some
- // other offset but overlaps the desired range.
- for (auto &CacheItem : CacheMap) {
- Interval RequestExtent = std::make_pair(Offset, Offset + Size);
-
- // We already checked this one on the fast path above.
- if (CacheItem.first == Offset)
- continue;
- // If the initial extent of the cached item is beyond the ending extent
- // of the request, there is no overlap.
- if (CacheItem.first >= Offset + Size)
- continue;
-
- // We really only have to check the last item in the list, since we append
- // in order of increasing length.
- if (CacheItem.second.empty())
- continue;
-
- auto CachedAlloc = CacheItem.second.back();
- // If the initial extent of the request is beyond the ending extent of
- // the cached item, there is no overlap.
- Interval CachedExtent =
- std::make_pair(CacheItem.first, CacheItem.first + CachedAlloc.size());
- if (RequestExtent.first >= CachedExtent.first + CachedExtent.second)
- continue;
-
- Interval Intersection = intersect(CachedExtent, RequestExtent);
- // Only use this if the entire request extent is contained in the cached
- // extent.
- if (Intersection != RequestExtent)
- continue;
-
- uint32_t CacheRangeOffset =
- AbsoluteDifference(CachedExtent.first, Intersection.first);
- Buffer = CachedAlloc.slice(CacheRangeOffset, Size);
- return Error::success();
- }
-
- // Otherwise allocate a large enough buffer in the pool, memcpy the data
- // into it, and return an ArrayRef to that. Do not touch existing pool
- // allocations, as existing clients may be holding a pointer which must
- // not be invalidated.
- uint8_t *WriteBuffer = static_cast<uint8_t *>(Pool.Allocate(Size, 8));
- if (auto EC = readBytes(Offset, MutableArrayRef<uint8_t>(WriteBuffer, Size)))
- return EC;
-
- if (CacheIter != CacheMap.end()) {
- CacheIter->second.emplace_back(WriteBuffer, Size);
- } else {
- std::vector<CacheEntry> List;
- List.emplace_back(WriteBuffer, Size);
- CacheMap.insert(std::make_pair(Offset, List));
- }
- Buffer = ArrayRef<uint8_t>(WriteBuffer, Size);
- return Error::success();
-}
-
-Error MappedBlockStream::readLongestContiguousChunk(
- uint32_t Offset, ArrayRef<uint8_t> &Buffer) const {
- // Make sure we aren't trying to read beyond the end of the stream.
- if (Offset >= Data->getLength())
- return make_error<RawError>(raw_error_code::insufficient_buffer);
- uint32_t First = Offset / Pdb.getBlockSize();
- uint32_t Last = First;
-
- auto BlockList = Data->getStreamBlocks();
- while (Last < Pdb.getBlockCount() - 1) {
- if (BlockList[Last] != BlockList[Last + 1] - 1)
- break;
- ++Last;
- }
-
- uint32_t OffsetInFirstBlock = Offset % Pdb.getBlockSize();
- uint32_t BytesFromFirstBlock = Pdb.getBlockSize() - OffsetInFirstBlock;
- uint32_t BlockSpan = Last - First + 1;
- uint32_t ByteSpan =
- BytesFromFirstBlock + (BlockSpan - 1) * Pdb.getBlockSize();
- auto Result = Pdb.getBlockData(BlockList[First], Pdb.getBlockSize());
- if (!Result)
- return Result.takeError();
- Buffer = Result->drop_front(OffsetInFirstBlock);
- Buffer = ArrayRef<uint8_t>(Buffer.data(), ByteSpan);
- return Error::success();
-}
-
-uint32_t MappedBlockStream::getLength() const { return Data->getLength(); }
-
-Error MappedBlockStream::commit() const { return Error::success(); }
-
-bool MappedBlockStream::tryReadContiguously(uint32_t Offset, uint32_t Size,
- ArrayRef<uint8_t> &Buffer) const {
- // Attempt to fulfill the request with a reference directly into the stream.
- // This can work even if the request crosses a block boundary, provided that
- // all subsequent blocks are contiguous. For example, a 10k read with a 4k
- // block size can be filled with a reference if, from the starting offset,
- // 3 blocks in a row are contiguous.
- uint32_t BlockNum = Offset / Pdb.getBlockSize();
- uint32_t OffsetInBlock = Offset % Pdb.getBlockSize();
- uint32_t BytesFromFirstBlock =
- std::min(Size, Pdb.getBlockSize() - OffsetInBlock);
- uint32_t NumAdditionalBlocks =
- llvm::alignTo(Size - BytesFromFirstBlock, Pdb.getBlockSize()) /
- Pdb.getBlockSize();
-
- auto BlockList = Data->getStreamBlocks();
- uint32_t RequiredContiguousBlocks = NumAdditionalBlocks + 1;
- uint32_t E = BlockList[BlockNum];
- for (uint32_t I = 0; I < RequiredContiguousBlocks; ++I, ++E) {
- if (BlockList[I + BlockNum] != E)
- return false;
- }
-
- uint32_t FirstBlockAddr = BlockList[BlockNum];
- auto Result = Pdb.getBlockData(FirstBlockAddr, Pdb.getBlockSize());
- if (!Result) {
- consumeError(Result.takeError());
- return false;
- }
- auto Data = Result->drop_front(OffsetInBlock);
- Buffer = ArrayRef<uint8_t>(Data.data(), Size);
- return true;
-}
-
-Error MappedBlockStream::readBytes(uint32_t Offset,
- MutableArrayRef<uint8_t> Buffer) const {
- uint32_t BlockNum = Offset / Pdb.getBlockSize();
- uint32_t OffsetInBlock = Offset % Pdb.getBlockSize();
-
- // Make sure we aren't trying to read beyond the end of the stream.
- if (Buffer.size() > Data->getLength())
- return make_error<RawError>(raw_error_code::insufficient_buffer);
- if (Offset > Data->getLength() - Buffer.size())
- return make_error<RawError>(raw_error_code::insufficient_buffer);
-
- uint32_t BytesLeft = Buffer.size();
- uint32_t BytesWritten = 0;
- uint8_t *WriteBuffer = Buffer.data();
- auto BlockList = Data->getStreamBlocks();
- while (BytesLeft > 0) {
- uint32_t StreamBlockAddr = BlockList[BlockNum];
-
- auto Result = Pdb.getBlockData(StreamBlockAddr, Pdb.getBlockSize());
- if (!Result)
- return Result.takeError();
-
- auto Data = *Result;
- const uint8_t *ChunkStart = Data.data() + OffsetInBlock;
- uint32_t BytesInChunk =
- std::min(BytesLeft, Pdb.getBlockSize() - OffsetInBlock);
- ::memcpy(WriteBuffer + BytesWritten, ChunkStart, BytesInChunk);
-
- BytesWritten += BytesInChunk;
- BytesLeft -= BytesInChunk;
- ++BlockNum;
- OffsetInBlock = 0;
- }
-
- return Error::success();
-}
-
-Error MappedBlockStream::writeBytes(uint32_t Offset,
- ArrayRef<uint8_t> Buffer) const {
- // Make sure we aren't trying to write beyond the end of the stream.
- if (Buffer.size() > Data->getLength())
- return make_error<RawError>(raw_error_code::insufficient_buffer);
-
- if (Offset > Data->getLength() - Buffer.size())
- return make_error<RawError>(raw_error_code::insufficient_buffer);
-
- uint32_t BlockNum = Offset / Pdb.getBlockSize();
- uint32_t OffsetInBlock = Offset % Pdb.getBlockSize();
-
- uint32_t BytesLeft = Buffer.size();
- auto BlockList = Data->getStreamBlocks();
- uint32_t BytesWritten = 0;
- while (BytesLeft > 0) {
- uint32_t StreamBlockAddr = BlockList[BlockNum];
- uint32_t BytesToWriteInChunk =
- std::min(BytesLeft, Pdb.getBlockSize() - OffsetInBlock);
-
- const uint8_t *Chunk = Buffer.data() + BytesWritten;
- ArrayRef<uint8_t> ChunkData(Chunk, BytesToWriteInChunk);
- if (auto EC = Pdb.setBlockData(StreamBlockAddr, OffsetInBlock, ChunkData))
- return EC;
-
- BytesLeft -= BytesToWriteInChunk;
- BytesWritten += BytesToWriteInChunk;
- ++BlockNum;
- OffsetInBlock = 0;
- }
-
- // If this write overlapped a read which previously came from the pool,
- // someone may still be holding a pointer to that alloc which is now invalid.
- // Compute the overlapping range and update the cache entry, so any
- // outstanding buffers are automatically updated.
- for (const auto &MapEntry : CacheMap) {
- // If the end of the written extent precedes the beginning of the cached
- // extent, ignore this map entry.
- if (Offset + BytesWritten < MapEntry.first)
- continue;
- for (const auto &Alloc : MapEntry.second) {
- // If the end of the cached extent precedes the beginning of the written
- // extent, ignore this alloc.
- if (MapEntry.first + Alloc.size() < Offset)
- continue;
-
- // If we get here, they are guaranteed to overlap.
- Interval WriteInterval = std::make_pair(Offset, Offset + BytesWritten);
- Interval CachedInterval =
- std::make_pair(MapEntry.first, MapEntry.first + Alloc.size());
- // If they overlap, we need to write the new data into the overlapping
- // range.
- auto Intersection = intersect(WriteInterval, CachedInterval);
- assert(Intersection.first <= Intersection.second);
-
- uint32_t Length = Intersection.second - Intersection.first;
- uint32_t SrcOffset =
- AbsoluteDifference(WriteInterval.first, Intersection.first);
- uint32_t DestOffset =
- AbsoluteDifference(CachedInterval.first, Intersection.first);
- ::memcpy(Alloc.data() + DestOffset, Buffer.data() + SrcOffset, Length);
- }
- }
-
- return Error::success();
-}
-
-uint32_t MappedBlockStream::getNumBytesCopied() const {
- return static_cast<uint32_t>(Pool.getBytesAllocated());
-}
-
-Expected<std::unique_ptr<MappedBlockStream>>
-MappedBlockStream::createIndexedStream(uint32_t StreamIdx,
- const IPDBFile &File) {
- if (StreamIdx >= File.getNumStreams())
- return make_error<RawError>(raw_error_code::no_stream);
-
- auto Data = llvm::make_unique<IndexedStreamData>(StreamIdx, File);
- return llvm::make_unique<MappedBlockStreamImpl>(std::move(Data), File);
-}
-
-Expected<std::unique_ptr<MappedBlockStream>>
-MappedBlockStream::createDirectoryStream(const PDBFile &File) {
- auto Data = llvm::make_unique<DirectoryStreamData>(File);
- return llvm::make_unique<MappedBlockStreamImpl>(std::move(Data), File);
-}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/ModInfo.cpp b/contrib/llvm/lib/DebugInfo/PDB/Raw/ModInfo.cpp
index bae135f..b34d770 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/Raw/ModInfo.cpp
+++ b/contrib/llvm/lib/DebugInfo/PDB/Raw/ModInfo.cpp
@@ -7,76 +7,27 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/DebugInfo/MSF/StreamReader.h"
#include "llvm/DebugInfo/PDB/Raw/ModInfo.h"
-
-#include "llvm/DebugInfo/CodeView/StreamReader.h"
-#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MathExtras.h"
+#include <cstdint>
using namespace llvm;
+using namespace llvm::msf;
using namespace llvm::pdb;
using namespace llvm::support;
-namespace {
-
-struct SCBytes {
- ulittle16_t Section;
- char Padding1[2];
- little32_t Offset;
- little32_t Size;
- ulittle32_t Characteristics;
- ulittle16_t ModuleIndex;
- char Padding2[2];
- ulittle32_t DataCrc;
- ulittle32_t RelocCrc;
-};
-
-// struct Flags {
-// uint16_t fWritten : 1; // True if ModInfo is dirty
-// uint16_t fECEnabled : 1; // Is EC symbolic info present? (What is EC?)
-// uint16_t unused : 6; // Reserved
-// uint16_t iTSM : 8; // Type Server Index for this module
-//};
-const uint16_t HasECFlagMask = 0x2;
-
-const uint16_t TypeServerIndexMask = 0xFF00;
-const uint16_t TypeServerIndexShift = 8;
-}
+ModInfo::ModInfo() = default;
+
+ModInfo::ModInfo(const ModInfo &Info) = default;
-struct ModInfo::FileLayout {
- ulittle32_t Mod; // Currently opened module. This field is a
- // pointer in the reference implementation, but
- // that won't work on 64-bit systems, and anyway
- // it doesn't make sense to read a pointer from a
- // file. For now it is unused, so just ignore it.
- SCBytes SC; // First section contribution of this module.
- ulittle16_t Flags; // See Flags definition.
- ulittle16_t ModDiStream; // Stream Number of module debug info
- ulittle32_t SymBytes; // Size of local symbol debug info in above stream
- ulittle32_t LineBytes; // Size of line number debug info in above stream
- ulittle32_t C13Bytes; // Size of C13 line number info in above stream
- ulittle16_t NumFiles; // Number of files contributing to this module
- char Padding1[2]; // Padding so the next field is 4-byte aligned.
- ulittle32_t FileNameOffs; // array of [0..NumFiles) DBI name buffer offsets.
- // This field is a pointer in the reference
- // implementation, but as with `Mod`, we ignore it
- // for now since it is unused.
- ulittle32_t SrcFileNameNI; // Name Index for src file name
- ulittle32_t PdbFilePathNI; // Name Index for path to compiler PDB
- // Null terminated Module name
- // Null terminated Obj File Name
-};
-
-ModInfo::ModInfo() : Layout(nullptr) {}
-
-ModInfo::ModInfo(const ModInfo &Info)
- : ModuleName(Info.ModuleName), ObjFileName(Info.ObjFileName),
- Layout(Info.Layout) {}
-
-ModInfo::~ModInfo() {}
-
-Error ModInfo::initialize(codeview::StreamRef Stream, ModInfo &Info) {
- codeview::StreamReader Reader(Stream);
+ModInfo::~ModInfo() = default;
+
+Error ModInfo::initialize(ReadableStreamRef Stream, ModInfo &Info) {
+ StreamReader Reader(Stream);
if (auto EC = Reader.readObject(Info.Layout))
return EC;
@@ -88,10 +39,13 @@ Error ModInfo::initialize(codeview::StreamRef Stream, ModInfo &Info) {
return Error::success();
}
-bool ModInfo::hasECInfo() const { return (Layout->Flags & HasECFlagMask) != 0; }
+bool ModInfo::hasECInfo() const {
+ return (Layout->Flags & ModInfoFlags::HasECFlagMask) != 0;
+}
uint16_t ModInfo::getTypeServerIndex() const {
- return (Layout->Flags & TypeServerIndexMask) >> TypeServerIndexShift;
+ return (Layout->Flags & ModInfoFlags::TypeServerIndexMask) >>
+ ModInfoFlags::TypeServerIndexShift;
}
uint16_t ModInfo::getModuleStreamIndex() const { return Layout->ModDiStream; }
@@ -121,7 +75,7 @@ StringRef ModInfo::getObjFileName() const { return ObjFileName; }
uint32_t ModInfo::getRecordLength() const {
uint32_t M = ModuleName.str().size() + 1;
uint32_t O = ObjFileName.str().size() + 1;
- uint32_t Size = sizeof(FileLayout) + M + O;
- Size = llvm::alignTo(Size, 4);
+ uint32_t Size = sizeof(ModuleInfoHeader) + M + O;
+ Size = alignTo(Size, 4);
return Size;
}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/ModStream.cpp b/contrib/llvm/lib/DebugInfo/PDB/Raw/ModStream.cpp
index 3415fcd..0ffc5b7 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/Raw/ModStream.cpp
+++ b/contrib/llvm/lib/DebugInfo/PDB/Raw/ModStream.cpp
@@ -7,39 +7,43 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/DebugInfo/PDB/Raw/ModStream.h"
-
-#include "llvm/DebugInfo/CodeView/StreamReader.h"
-#include "llvm/DebugInfo/PDB/Raw/IndexedStreamData.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/MSF/StreamReader.h"
+#include "llvm/DebugInfo/MSF/StreamRef.h"
#include "llvm/DebugInfo/PDB/Raw/ModInfo.h"
+#include "llvm/DebugInfo/PDB/Raw/ModStream.h"
#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
#include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+#include <cstdint>
using namespace llvm;
+using namespace llvm::msf;
using namespace llvm::pdb;
ModStream::ModStream(const ModInfo &Module,
std::unique_ptr<MappedBlockStream> Stream)
: Mod(Module), Stream(std::move(Stream)) {}
-ModStream::~ModStream() {}
+ModStream::~ModStream() = default;
Error ModStream::reload() {
- codeview::StreamReader Reader(*Stream);
+ StreamReader Reader(*Stream);
uint32_t SymbolSize = Mod.getSymbolDebugInfoByteSize();
uint32_t C11Size = Mod.getLineInfoByteSize();
uint32_t C13Size = Mod.getC13LineInfoByteSize();
if (C11Size > 0 && C13Size > 0)
- return llvm::make_error<RawError>(raw_error_code::corrupt_file,
- "Module has both C11 and C13 line info");
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Module has both C11 and C13 line info");
- codeview::StreamRef S;
+ ReadableStreamRef S;
- uint32_t SymbolSubstreamSig = 0;
- if (auto EC = Reader.readInteger(SymbolSubstreamSig))
+ if (auto EC = Reader.readInteger(Signature))
return EC;
if (auto EC = Reader.readArray(SymbolsSubstream, SymbolSize - 4))
return EC;
@@ -49,7 +53,7 @@ Error ModStream::reload() {
if (auto EC = Reader.readStreamRef(C13LinesSubstream, C13Size))
return EC;
- codeview::StreamReader LineReader(C13LinesSubstream);
+ StreamReader LineReader(C13LinesSubstream);
if (auto EC = LineReader.readArray(LineInfo, LineReader.bytesRemaining()))
return EC;
@@ -59,8 +63,8 @@ Error ModStream::reload() {
if (auto EC = Reader.readStreamRef(GlobalRefsSubstream, GlobalRefsSize))
return EC;
if (Reader.bytesRemaining() > 0)
- return llvm::make_error<RawError>(raw_error_code::corrupt_file,
- "Unexpected bytes in module stream.");
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Unexpected bytes in module stream.");
return Error::success();
}
@@ -69,14 +73,13 @@ iterator_range<codeview::CVSymbolArray::Iterator>
ModStream::symbols(bool *HadError) const {
// It's OK if the stream is empty.
if (SymbolsSubstream.getUnderlyingStream().getLength() == 0)
- return llvm::make_range(SymbolsSubstream.end(), SymbolsSubstream.end());
- return llvm::make_range(SymbolsSubstream.begin(HadError),
- SymbolsSubstream.end());
+ return make_range(SymbolsSubstream.end(), SymbolsSubstream.end());
+ return make_range(SymbolsSubstream.begin(HadError), SymbolsSubstream.end());
}
iterator_range<codeview::ModuleSubstreamArray::Iterator>
ModStream::lines(bool *HadError) const {
- return llvm::make_range(LineInfo.begin(HadError), LineInfo.end());
+ return make_range(LineInfo.begin(HadError), LineInfo.end());
}
Error ModStream::commit() { return Error::success(); }
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/NameHashTable.cpp b/contrib/llvm/lib/DebugInfo/PDB/Raw/NameHashTable.cpp
index ae4ebf2..84cccb35 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/Raw/NameHashTable.cpp
+++ b/contrib/llvm/lib/DebugInfo/PDB/Raw/NameHashTable.cpp
@@ -10,18 +10,19 @@
#include "llvm/DebugInfo/PDB/Raw/NameHashTable.h"
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/DebugInfo/CodeView/StreamReader.h"
+#include "llvm/DebugInfo/MSF/StreamReader.h"
#include "llvm/DebugInfo/PDB/Raw/Hash.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
#include "llvm/Support/Endian.h"
using namespace llvm;
+using namespace llvm::msf;
using namespace llvm::support;
using namespace llvm::pdb;
NameHashTable::NameHashTable() : Signature(0), HashVersion(0), NameCount(0) {}
-Error NameHashTable::load(codeview::StreamReader &Stream) {
+Error NameHashTable::load(StreamReader &Stream) {
struct Header {
support::ulittle32_t Signature;
support::ulittle32_t HashVersion;
@@ -72,7 +73,7 @@ StringRef NameHashTable::getStringForID(uint32_t ID) const {
// the starting offset of the string we're looking for. So just seek into
// the desired offset and a read a null terminated stream from that offset.
StringRef Result;
- codeview::StreamReader NameReader(NamesBuffer);
+ StreamReader NameReader(NamesBuffer);
NameReader.setOffset(ID);
if (auto EC = NameReader.readZeroString(Result))
consumeError(std::move(EC));
@@ -98,7 +99,6 @@ uint32_t NameHashTable::getIDForString(StringRef Str) const {
return IDs[0];
}
-codeview::FixedStreamArray<support::ulittle32_t>
-NameHashTable::name_ids() const {
+FixedStreamArray<support::ulittle32_t> NameHashTable::name_ids() const {
return IDs;
}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/NameMap.cpp b/contrib/llvm/lib/DebugInfo/PDB/Raw/NameMap.cpp
index b8a4eb7..0f55f58 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/Raw/NameMap.cpp
+++ b/contrib/llvm/lib/DebugInfo/PDB/Raw/NameMap.cpp
@@ -7,20 +7,24 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/DebugInfo/PDB/Raw/NameMap.h"
#include "llvm/ADT/SparseBitVector.h"
-#include "llvm/DebugInfo/CodeView/StreamReader.h"
-#include "llvm/DebugInfo/CodeView/StreamWriter.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/DebugInfo/MSF/StreamReader.h"
+#include "llvm/DebugInfo/PDB/Raw/NameMap.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+#include <cstdint>
using namespace llvm;
-using namespace llvm::codeview;
+using namespace llvm::msf;
using namespace llvm::pdb;
-NameMap::NameMap() {}
-
-Error NameMap::load(codeview::StreamReader &Stream) {
+NameMap::NameMap() = default;
+Error NameMap::load(StreamReader &Stream) {
// This is some sort of weird string-set/hash table encoded in the stream.
// It starts with the number of bytes in the table.
uint32_t NumberOfBytes;
@@ -145,63 +149,9 @@ Error NameMap::load(codeview::StreamReader &Stream) {
return Error::success();
}
-Error NameMap::commit(codeview::StreamWriter &Writer) {
- // The first field is the number of bytes of string data. So add
- // up the length of all strings plus a null terminator for each
- // one.
- uint32_t NumBytes = 0;
- for (auto B = Mapping.begin(), E = Mapping.end(); B != E; ++B) {
- NumBytes += B->getKeyLength() + 1;
- }
-
- if (auto EC = Writer.writeInteger(NumBytes)) // Number of bytes of string data
- return EC;
- // Now all of the string data itself.
- for (auto B = Mapping.begin(), E = Mapping.end(); B != E; ++B) {
- if (auto EC = Writer.writeZeroString(B->getKey()))
- return EC;
- }
-
- if (auto EC = Writer.writeInteger(Mapping.size())) // Hash Size
- return EC;
-
- if (auto EC = Writer.writeInteger(Mapping.size())) // Max Number of Strings
- return EC;
-
- if (auto EC = Writer.writeInteger(Mapping.size())) // Num Present Words
- return EC;
-
- // For each entry in the mapping, write a bit mask which represents a bucket
- // to store it in. We don't use this, so the value we write isn't important
- // to us, it just has to be there.
- for (auto B = Mapping.begin(), E = Mapping.end(); B != E; ++B) {
- if (auto EC = Writer.writeInteger(1U))
- return EC;
- }
-
- if (auto EC = Writer.writeInteger(0U)) // Num Deleted Words
- return EC;
-
- // Mappings of each word.
- uint32_t OffsetSoFar = 0;
- for (auto B = Mapping.begin(), E = Mapping.end(); B != E; ++B) {
- // This is a list of key value pairs where the key is the offset into the
- // strings buffer, and the value is a stream number. Write each pair.
- if (auto EC = Writer.writeInteger(OffsetSoFar))
- return EC;
-
- if (auto EC = Writer.writeInteger(B->second))
- return EC;
-
- OffsetSoFar += B->getKeyLength() + 1;
- }
-
- return Error::success();
-}
-
iterator_range<StringMapConstIterator<uint32_t>> NameMap::entries() const {
- return llvm::make_range<StringMapConstIterator<uint32_t>>(Mapping.begin(),
- Mapping.end());
+ return make_range<StringMapConstIterator<uint32_t>>(Mapping.begin(),
+ Mapping.end());
}
bool NameMap::tryGetValue(StringRef Name, uint32_t &Value) const {
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/NameMapBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Raw/NameMapBuilder.cpp
index 41c6c2c..f570d59 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/Raw/NameMapBuilder.cpp
+++ b/contrib/llvm/lib/DebugInfo/PDB/Raw/NameMapBuilder.cpp
@@ -7,15 +7,19 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/DebugInfo/PDB/Raw/NameMapBuilder.h"
-
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/MSF/StreamWriter.h"
#include "llvm/DebugInfo/PDB/Raw/NameMap.h"
+#include "llvm/DebugInfo/PDB/Raw/NameMapBuilder.h"
#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+#include <cstdint>
using namespace llvm;
using namespace llvm::pdb;
-NameMapBuilder::NameMapBuilder() {}
+NameMapBuilder::NameMapBuilder() = default;
void NameMapBuilder::addMapping(StringRef Name, uint32_t Mapping) {
StringDataBytes += Name.size() + 1;
@@ -48,3 +52,57 @@ uint32_t NameMapBuilder::calculateSerializedLength() const {
return TotalLength;
}
+
+Error NameMapBuilder::commit(msf::StreamWriter &Writer) const {
+ // The first field is the number of bytes of string data. So add
+ // up the length of all strings plus a null terminator for each
+ // one.
+ uint32_t NumBytes = 0;
+ for (auto B = Map.begin(), E = Map.end(); B != E; ++B) {
+ NumBytes += B->getKeyLength() + 1;
+ }
+
+ if (auto EC = Writer.writeInteger(NumBytes)) // Number of bytes of string data
+ return EC;
+ // Now all of the string data itself.
+ for (auto B = Map.begin(), E = Map.end(); B != E; ++B) {
+ if (auto EC = Writer.writeZeroString(B->getKey()))
+ return EC;
+ }
+
+ if (auto EC = Writer.writeInteger(Map.size())) // Hash Size
+ return EC;
+
+ if (auto EC = Writer.writeInteger(Map.size())) // Max Number of Strings
+ return EC;
+
+ if (auto EC = Writer.writeInteger(Map.size())) // Num Present Words
+ return EC;
+
+ // For each entry in the mapping, write a bit mask which represents a bucket
+ // to store it in. We don't use this, so the value we write isn't important
+ // to us, it just has to be there.
+ for (auto B = Map.begin(), E = Map.end(); B != E; ++B) {
+ if (auto EC = Writer.writeInteger(1U))
+ return EC;
+ }
+
+ if (auto EC = Writer.writeInteger(0U)) // Num Deleted Words
+ return EC;
+
+ // Mappings of each word.
+ uint32_t OffsetSoFar = 0;
+ for (auto B = Map.begin(), E = Map.end(); B != E; ++B) {
+ // This is a list of key value pairs where the key is the offset into the
+ // strings buffer, and the value is a stream number. Write each pair.
+ if (auto EC = Writer.writeInteger(OffsetSoFar))
+ return EC;
+
+ if (auto EC = Writer.writeInteger(B->second))
+ return EC;
+
+ OffsetSoFar += B->getKeyLength() + 1;
+ }
+
+ return Error::success();
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp b/contrib/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp
index 9501675..5349151 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp
+++ b/contrib/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp
@@ -7,68 +7,84 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
-
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/DebugInfo/CodeView/StreamArray.h"
-#include "llvm/DebugInfo/CodeView/StreamInterface.h"
-#include "llvm/DebugInfo/CodeView/StreamReader.h"
-#include "llvm/DebugInfo/CodeView/StreamWriter.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/MSF/MSFCommon.h"
+#include "llvm/DebugInfo/MSF/StreamArray.h"
+#include "llvm/DebugInfo/MSF/StreamInterface.h"
+#include "llvm/DebugInfo/MSF/StreamReader.h"
#include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
-#include "llvm/DebugInfo/PDB/Raw/DirectoryStreamData.h"
-#include "llvm/DebugInfo/PDB/Raw/IndexedStreamData.h"
+#include "llvm/DebugInfo/PDB/Raw/GlobalsStream.h"
#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
#include "llvm/DebugInfo/PDB/Raw/NameHashTable.h"
+#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
#include "llvm/DebugInfo/PDB/Raw/PublicsStream.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
#include "llvm/DebugInfo/PDB/Raw/SymbolStream.h"
#include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
#include "llvm/Support/Endian.h"
-#include "llvm/Support/FileOutputBuffer.h"
-#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
using namespace llvm;
using namespace llvm::codeview;
+using namespace llvm::msf;
using namespace llvm::pdb;
namespace {
typedef FixedStreamArray<support::ulittle32_t> ulittle_array;
-}
+} // end anonymous namespace
-PDBFile::PDBFile(std::unique_ptr<StreamInterface> PdbFileBuffer)
- : Buffer(std::move(PdbFileBuffer)), SB(nullptr) {}
+PDBFile::PDBFile(std::unique_ptr<ReadableStream> PdbFileBuffer,
+ BumpPtrAllocator &Allocator)
+ : Allocator(Allocator), Buffer(std::move(PdbFileBuffer)) {}
-PDBFile::~PDBFile() {}
+PDBFile::~PDBFile() = default;
-uint32_t PDBFile::getBlockSize() const { return SB->BlockSize; }
+uint32_t PDBFile::getBlockSize() const { return ContainerLayout.SB->BlockSize; }
-uint32_t PDBFile::getFreeBlockMapBlock() const { return SB->FreeBlockMapBlock; }
+uint32_t PDBFile::getFreeBlockMapBlock() const {
+ return ContainerLayout.SB->FreeBlockMapBlock;
+}
-uint32_t PDBFile::getBlockCount() const { return SB->NumBlocks; }
+uint32_t PDBFile::getBlockCount() const {
+ return ContainerLayout.SB->NumBlocks;
+}
-uint32_t PDBFile::getNumDirectoryBytes() const { return SB->NumDirectoryBytes; }
+uint32_t PDBFile::getNumDirectoryBytes() const {
+ return ContainerLayout.SB->NumDirectoryBytes;
+}
-uint32_t PDBFile::getBlockMapIndex() const { return SB->BlockMapAddr; }
+uint32_t PDBFile::getBlockMapIndex() const {
+ return ContainerLayout.SB->BlockMapAddr;
+}
-uint32_t PDBFile::getUnknown1() const { return SB->Unknown1; }
+uint32_t PDBFile::getUnknown1() const { return ContainerLayout.SB->Unknown1; }
uint32_t PDBFile::getNumDirectoryBlocks() const {
- return msf::bytesToBlocks(SB->NumDirectoryBytes, SB->BlockSize);
+ return msf::bytesToBlocks(ContainerLayout.SB->NumDirectoryBytes,
+ ContainerLayout.SB->BlockSize);
}
uint64_t PDBFile::getBlockMapOffset() const {
- return (uint64_t)SB->BlockMapAddr * SB->BlockSize;
+ return (uint64_t)ContainerLayout.SB->BlockMapAddr *
+ ContainerLayout.SB->BlockSize;
}
-uint32_t PDBFile::getNumStreams() const { return StreamSizes.size(); }
+uint32_t PDBFile::getNumStreams() const {
+ return ContainerLayout.StreamSizes.size();
+}
uint32_t PDBFile::getStreamByteSize(uint32_t StreamIndex) const {
- return StreamSizes[StreamIndex];
+ return ContainerLayout.StreamSizes[StreamIndex];
}
ArrayRef<support::ulittle32_t>
PDBFile::getStreamBlockList(uint32_t StreamIndex) const {
- return StreamMap[StreamIndex];
+ return ContainerLayout.StreamMap[StreamIndex];
}
uint32_t PDBFile::getFileSize() const { return Buffer->getLength(); }
@@ -85,41 +101,72 @@ Expected<ArrayRef<uint8_t>> PDBFile::getBlockData(uint32_t BlockIndex,
Error PDBFile::setBlockData(uint32_t BlockIndex, uint32_t Offset,
ArrayRef<uint8_t> Data) const {
- if (Offset >= getBlockSize())
- return make_error<RawError>(
- raw_error_code::invalid_block_address,
- "setBlockData attempted to write out of block bounds.");
- if (Data.size() > getBlockSize() - Offset)
- return make_error<RawError>(
- raw_error_code::invalid_block_address,
- "setBlockData attempted to write out of block bounds.");
-
- uint64_t StreamBlockOffset = msf::blockToOffset(BlockIndex, getBlockSize());
- StreamBlockOffset += Offset;
- return Buffer->writeBytes(StreamBlockOffset, Data);
+ return make_error<RawError>(raw_error_code::not_writable,
+ "PDBFile is immutable");
}
Error PDBFile::parseFileHeaders() {
StreamReader Reader(*Buffer);
+ // Initialize SB.
+ const msf::SuperBlock *SB = nullptr;
if (auto EC = Reader.readObject(SB)) {
consumeError(std::move(EC));
return make_error<RawError>(raw_error_code::corrupt_file,
"Does not contain superblock");
}
- if (auto EC = setSuperBlock(SB))
+ if (auto EC = msf::validateSuperBlock(*SB))
+ return EC;
+
+ if (Buffer->getLength() % SB->BlockSize != 0)
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "File size is not a multiple of block size");
+ ContainerLayout.SB = SB;
+
+ // Initialize Free Page Map.
+ ContainerLayout.FreePageMap.resize(SB->NumBlocks);
+ // The Fpm exists either at block 1 or block 2 of the MSF. However, this
+ // allows for a maximum of getBlockSize() * 8 blocks bits in the Fpm, and
+ // thusly an equal number of total blocks in the file. For a block size
+ // of 4KiB (very common), this would yield 32KiB total blocks in file, for a
+ // maximum file size of 32KiB * 4KiB = 128MiB. Obviously this won't do, so
+ // the Fpm is split across the file at `getBlockSize()` intervals. As a
+ // result, every block whose index is of the form |{1,2} + getBlockSize() * k|
+ // for any non-negative integer k is an Fpm block. In theory, we only really
+ // need to reserve blocks of the form |{1,2} + getBlockSize() * 8 * k|, but
+ // current versions of the MSF format already expect the Fpm to be arranged
+ // at getBlockSize() intervals, so we have to be compatible.
+ // See the function fpmPn() for more information:
+ // https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/msf/msf.cpp#L489
+ auto FpmStream = MappedBlockStream::createFpmStream(ContainerLayout, *Buffer);
+ StreamReader FpmReader(*FpmStream);
+ ArrayRef<uint8_t> FpmBytes;
+ if (auto EC = FpmReader.readBytes(FpmBytes,
+ msf::getFullFpmByteSize(ContainerLayout)))
return EC;
+ uint32_t BlocksRemaining = getBlockCount();
+ uint32_t BI = 0;
+ for (auto Byte : FpmBytes) {
+ uint32_t BlocksThisByte = std::min(BlocksRemaining, 8U);
+ for (uint32_t I = 0; I < BlocksThisByte; ++I) {
+ if (Byte & (1 << I))
+ ContainerLayout.FreePageMap[BI] = true;
+ --BlocksRemaining;
+ ++BI;
+ }
+ }
Reader.setOffset(getBlockMapOffset());
- if (auto EC = Reader.readArray(DirectoryBlocks, getNumDirectoryBlocks()))
+ if (auto EC = Reader.readArray(ContainerLayout.DirectoryBlocks,
+ getNumDirectoryBlocks()))
return EC;
return Error::success();
}
Error PDBFile::parseStreamData() {
- assert(SB);
+ assert(ContainerLayout.SB);
if (DirectoryStream)
return Error::success();
@@ -130,21 +177,20 @@ Error PDBFile::parseStreamData() {
// is exactly what we are attempting to parse. By specifying a custom
// subclass of IPDBStreamData which only accesses the fields that have already
// been parsed, we can avoid this and reuse MappedBlockStream.
- auto DS = MappedBlockStream::createDirectoryStream(*this);
- if (!DS)
- return DS.takeError();
- StreamReader Reader(**DS);
+ auto DS = MappedBlockStream::createDirectoryStream(ContainerLayout, *Buffer);
+ StreamReader Reader(*DS);
if (auto EC = Reader.readInteger(NumStreams))
return EC;
- if (auto EC = Reader.readArray(StreamSizes, NumStreams))
+ if (auto EC = Reader.readArray(ContainerLayout.StreamSizes, NumStreams))
return EC;
for (uint32_t I = 0; I < NumStreams; ++I) {
uint32_t StreamSize = getStreamByteSize(I);
// FIXME: What does StreamSize ~0U mean?
uint64_t NumExpectedStreamBlocks =
- StreamSize == UINT32_MAX ? 0 : msf::bytesToBlocks(StreamSize,
- SB->BlockSize);
+ StreamSize == UINT32_MAX
+ ? 0
+ : msf::bytesToBlocks(StreamSize, ContainerLayout.SB->BlockSize);
// For convenience, we store the block array contiguously. This is because
// if someone calls setStreamMap(), it is more convenient to be able to call
@@ -156,29 +202,46 @@ Error PDBFile::parseStreamData() {
if (auto EC = Reader.readArray(Blocks, NumExpectedStreamBlocks))
return EC;
for (uint32_t Block : Blocks) {
- uint64_t BlockEndOffset = (uint64_t)(Block + 1) * SB->BlockSize;
+ uint64_t BlockEndOffset =
+ (uint64_t)(Block + 1) * ContainerLayout.SB->BlockSize;
if (BlockEndOffset > getFileSize())
return make_error<RawError>(raw_error_code::corrupt_file,
"Stream block map is corrupt.");
}
- StreamMap.push_back(Blocks);
+ ContainerLayout.StreamMap.push_back(Blocks);
}
// We should have read exactly SB->NumDirectoryBytes bytes.
assert(Reader.bytesRemaining() == 0);
- DirectoryStream = std::move(*DS);
+ DirectoryStream = std::move(DS);
return Error::success();
}
-llvm::ArrayRef<support::ulittle32_t> PDBFile::getDirectoryBlockArray() const {
- return DirectoryBlocks;
+ArrayRef<support::ulittle32_t> PDBFile::getDirectoryBlockArray() const {
+ return ContainerLayout.DirectoryBlocks;
+}
+
+Expected<GlobalsStream &> PDBFile::getPDBGlobalsStream() {
+ if (!Globals) {
+ auto DbiS = getPDBDbiStream();
+ if (!DbiS)
+ return DbiS.takeError();
+
+ auto GlobalS = safelyCreateIndexedStream(
+ ContainerLayout, *Buffer, DbiS->getGlobalSymbolStreamIndex());
+ if (!GlobalS) return GlobalS.takeError();
+ auto TempGlobals = llvm::make_unique<GlobalsStream>(std::move(*GlobalS));
+ if (auto EC = TempGlobals->reload())
+ return std::move(EC);
+ Globals = std::move(TempGlobals);
+ }
+ return *Globals;
}
Expected<InfoStream &> PDBFile::getPDBInfoStream() {
if (!Info) {
- auto InfoS = MappedBlockStream::createIndexedStream(StreamPDB, *this);
- if (!InfoS)
- return InfoS.takeError();
+ auto InfoS = safelyCreateIndexedStream(ContainerLayout, *Buffer, StreamPDB);
+ if (!InfoS) return InfoS.takeError();
auto TempInfo = llvm::make_unique<InfoStream>(std::move(*InfoS));
if (auto EC = TempInfo->reload())
return std::move(EC);
@@ -189,9 +252,8 @@ Expected<InfoStream &> PDBFile::getPDBInfoStream() {
Expected<DbiStream &> PDBFile::getPDBDbiStream() {
if (!Dbi) {
- auto DbiS = MappedBlockStream::createIndexedStream(StreamDBI, *this);
- if (!DbiS)
- return DbiS.takeError();
+ auto DbiS = safelyCreateIndexedStream(ContainerLayout, *Buffer, StreamDBI);
+ if (!DbiS) return DbiS.takeError();
auto TempDbi = llvm::make_unique<DbiStream>(*this, std::move(*DbiS));
if (auto EC = TempDbi->reload())
return std::move(EC);
@@ -202,9 +264,8 @@ Expected<DbiStream &> PDBFile::getPDBDbiStream() {
Expected<TpiStream &> PDBFile::getPDBTpiStream() {
if (!Tpi) {
- auto TpiS = MappedBlockStream::createIndexedStream(StreamTPI, *this);
- if (!TpiS)
- return TpiS.takeError();
+ auto TpiS = safelyCreateIndexedStream(ContainerLayout, *Buffer, StreamTPI);
+ if (!TpiS) return TpiS.takeError();
auto TempTpi = llvm::make_unique<TpiStream>(*this, std::move(*TpiS));
if (auto EC = TempTpi->reload())
return std::move(EC);
@@ -215,9 +276,8 @@ Expected<TpiStream &> PDBFile::getPDBTpiStream() {
Expected<TpiStream &> PDBFile::getPDBIpiStream() {
if (!Ipi) {
- auto IpiS = MappedBlockStream::createIndexedStream(StreamIPI, *this);
- if (!IpiS)
- return IpiS.takeError();
+ auto IpiS = safelyCreateIndexedStream(ContainerLayout, *Buffer, StreamIPI);
+ if (!IpiS) return IpiS.takeError();
auto TempIpi = llvm::make_unique<TpiStream>(*this, std::move(*IpiS));
if (auto EC = TempIpi->reload())
return std::move(EC);
@@ -232,12 +292,9 @@ Expected<PublicsStream &> PDBFile::getPDBPublicsStream() {
if (!DbiS)
return DbiS.takeError();
- uint32_t PublicsStreamNum = DbiS->getPublicSymbolStreamIndex();
-
- auto PublicS =
- MappedBlockStream::createIndexedStream(PublicsStreamNum, *this);
- if (!PublicS)
- return PublicS.takeError();
+ auto PublicS = safelyCreateIndexedStream(
+ ContainerLayout, *Buffer, DbiS->getPublicSymbolStreamIndex());
+ if (!PublicS) return PublicS.takeError();
auto TempPublics =
llvm::make_unique<PublicsStream>(*this, std::move(*PublicS));
if (auto EC = TempPublics->reload())
@@ -254,11 +311,10 @@ Expected<SymbolStream &> PDBFile::getPDBSymbolStream() {
return DbiS.takeError();
uint32_t SymbolStreamNum = DbiS->getSymRecordStreamIndex();
-
auto SymbolS =
- MappedBlockStream::createIndexedStream(SymbolStreamNum, *this);
- if (!SymbolS)
- return SymbolS.takeError();
+ safelyCreateIndexedStream(ContainerLayout, *Buffer, SymbolStreamNum);
+ if (!SymbolS) return SymbolS.takeError();
+
auto TempSymbols = llvm::make_unique<SymbolStream>(std::move(*SymbolS));
if (auto EC = TempSymbols->reload())
return std::move(EC);
@@ -275,14 +331,9 @@ Expected<NameHashTable &> PDBFile::getStringTable() {
uint32_t NameStreamIndex = IS->getNamedStreamIndex("/names");
- if (NameStreamIndex == 0)
- return make_error<RawError>(raw_error_code::no_stream);
- if (NameStreamIndex >= getNumStreams())
- return make_error<RawError>(raw_error_code::no_stream);
-
- auto NS = MappedBlockStream::createIndexedStream(NameStreamIndex, *this);
- if (!NS)
- return NS.takeError();
+ auto NS =
+ safelyCreateIndexedStream(ContainerLayout, *Buffer, NameStreamIndex);
+ if (!NS) return NS.takeError();
StreamReader Reader(**NS);
auto N = llvm::make_unique<NameHashTable>();
@@ -294,72 +345,47 @@ Expected<NameHashTable &> PDBFile::getStringTable() {
return *StringTable;
}
-Error PDBFile::setSuperBlock(const msf::SuperBlock *Block) {
- if (auto EC = msf::validateSuperBlock(*Block))
- return EC;
-
- if (Buffer->getLength() % SB->BlockSize != 0)
- return make_error<RawError>(raw_error_code::corrupt_file,
- "File size is not a multiple of block size");
+bool PDBFile::hasPDBDbiStream() const { return StreamDBI < getNumStreams(); }
- SB = Block;
- return Error::success();
+bool PDBFile::hasPDBGlobalsStream() {
+ auto DbiS = getPDBDbiStream();
+ if (!DbiS) return false;
+ return DbiS->getGlobalSymbolStreamIndex() < getNumStreams();
}
-Error PDBFile::commit() {
- StreamWriter Writer(*Buffer);
-
- if (auto EC = Writer.writeObject(*SB))
- return EC;
- Writer.setOffset(getBlockMapOffset());
- if (auto EC = Writer.writeArray(DirectoryBlocks))
- return EC;
-
- auto DS = MappedBlockStream::createDirectoryStream(*this);
- if (!DS)
- return DS.takeError();
- auto DirStream = std::move(*DS);
- StreamWriter DW(*DirStream);
- if (auto EC = DW.writeInteger(this->getNumStreams()))
- return EC;
-
- if (auto EC = DW.writeArray(StreamSizes))
- return EC;
-
- for (const auto &Blocks : StreamMap) {
- if (auto EC = DW.writeArray(Blocks))
- return EC;
- }
-
- if (Info) {
- if (auto EC = Info->commit())
- return EC;
- }
+bool PDBFile::hasPDBInfoStream() { return StreamPDB < getNumStreams(); }
- if (Dbi) {
- if (auto EC = Dbi->commit())
- return EC;
- }
+bool PDBFile::hasPDBIpiStream() const { return StreamIPI < getNumStreams(); }
- if (Symbols) {
- if (auto EC = Symbols->commit())
- return EC;
- }
+bool PDBFile::hasPDBPublicsStream() {
+ auto DbiS = getPDBDbiStream();
+ if (!DbiS) return false;
+ return DbiS->getPublicSymbolStreamIndex() < getNumStreams();
+}
- if (Publics) {
- if (auto EC = Publics->commit())
- return EC;
- }
+bool PDBFile::hasPDBSymbolStream() {
+ auto DbiS = getPDBDbiStream();
+ if (!DbiS) return false;
+ return DbiS->getSymRecordStreamIndex() < getNumStreams();
+}
- if (Tpi) {
- if (auto EC = Tpi->commit())
- return EC;
- }
+bool PDBFile::hasPDBTpiStream() const { return StreamTPI < getNumStreams(); }
- if (Ipi) {
- if (auto EC = Ipi->commit())
- return EC;
- }
+bool PDBFile::hasStringTable() {
+ auto IS = getPDBInfoStream();
+ if (!IS) return false;
+ return IS->getNamedStreamIndex("/names") < getNumStreams();
+}
- return Buffer->commit();
+/// Wrapper around MappedBlockStream::createIndexedStream()
+/// that checks if a stream with that index actually exists.
+/// If it does not, the return value will have an MSFError with
+/// code msf_error_code::no_stream. Else, the return value will
+/// contain the stream returned by createIndexedStream().
+Expected<std::unique_ptr<MappedBlockStream>> PDBFile::safelyCreateIndexedStream(
+ const MSFLayout &Layout, const ReadableStream &MsfData,
+ uint32_t StreamIndex) const {
+ if (StreamIndex >= getNumStreams())
+ return make_error<RawError>(raw_error_code::no_stream);
+ return MappedBlockStream::createIndexedStream(Layout, MsfData, StreamIndex);
}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp
index 9063fd6..6fec0e3 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp
+++ b/contrib/llvm/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp
@@ -11,92 +11,138 @@
#include "llvm/ADT/BitVector.h"
-#include "llvm/DebugInfo/CodeView/StreamInterface.h"
-#include "llvm/DebugInfo/CodeView/StreamWriter.h"
+#include "llvm/DebugInfo/MSF/MSFBuilder.h"
+#include "llvm/DebugInfo/MSF/StreamInterface.h"
+#include "llvm/DebugInfo/MSF/StreamWriter.h"
+#include "llvm/DebugInfo/PDB/GenericError.h"
#include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
#include "llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
#include "llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
+#include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
+#include "llvm/DebugInfo/PDB/Raw/TpiStreamBuilder.h"
using namespace llvm;
using namespace llvm::codeview;
+using namespace llvm::msf;
using namespace llvm::pdb;
using namespace llvm::support;
-PDBFileBuilder::PDBFileBuilder(
- std::unique_ptr<codeview::StreamInterface> FileBuffer)
- : File(llvm::make_unique<PDBFile>(std::move(FileBuffer))) {}
+PDBFileBuilder::PDBFileBuilder(BumpPtrAllocator &Allocator)
+ : Allocator(Allocator) {}
-Error PDBFileBuilder::initialize(const msf::SuperBlock &Super) {
- auto ExpectedMsf =
- MsfBuilder::create(File->Allocator, Super.BlockSize, Super.NumBlocks);
+Error PDBFileBuilder::initialize(uint32_t BlockSize) {
+ auto ExpectedMsf = MSFBuilder::create(Allocator, BlockSize);
if (!ExpectedMsf)
return ExpectedMsf.takeError();
-
- auto &MsfResult = *ExpectedMsf;
- if (auto EC = MsfResult.setBlockMapAddr(Super.BlockMapAddr))
- return EC;
- Msf = llvm::make_unique<MsfBuilder>(std::move(MsfResult));
- Msf->setFreePageMap(Super.FreeBlockMapBlock);
- Msf->setUnknown1(Super.Unknown1);
+ Msf = llvm::make_unique<MSFBuilder>(std::move(*ExpectedMsf));
return Error::success();
}
-MsfBuilder &PDBFileBuilder::getMsfBuilder() { return *Msf; }
+MSFBuilder &PDBFileBuilder::getMsfBuilder() { return *Msf; }
InfoStreamBuilder &PDBFileBuilder::getInfoBuilder() {
if (!Info)
- Info = llvm::make_unique<InfoStreamBuilder>();
+ Info = llvm::make_unique<InfoStreamBuilder>(*Msf);
return *Info;
}
DbiStreamBuilder &PDBFileBuilder::getDbiBuilder() {
if (!Dbi)
- Dbi = llvm::make_unique<DbiStreamBuilder>();
+ Dbi = llvm::make_unique<DbiStreamBuilder>(*Msf);
return *Dbi;
}
-Expected<std::unique_ptr<PDBFile>> PDBFileBuilder::build() {
+TpiStreamBuilder &PDBFileBuilder::getTpiBuilder() {
+ if (!Tpi)
+ Tpi = llvm::make_unique<TpiStreamBuilder>(*Msf, StreamTPI);
+ return *Tpi;
+}
+
+TpiStreamBuilder &PDBFileBuilder::getIpiBuilder() {
+ if (!Ipi)
+ Ipi = llvm::make_unique<TpiStreamBuilder>(*Msf, StreamIPI);
+ return *Ipi;
+}
+
+Expected<msf::MSFLayout> PDBFileBuilder::finalizeMsfLayout() const {
if (Info) {
- uint32_t Length = Info->calculateSerializedLength();
- if (auto EC = Msf->setStreamSize(StreamPDB, Length))
+ if (auto EC = Info->finalizeMsfLayout())
return std::move(EC);
}
if (Dbi) {
- uint32_t Length = Dbi->calculateSerializedLength();
- if (auto EC = Msf->setStreamSize(StreamDBI, Length))
+ if (auto EC = Dbi->finalizeMsfLayout())
return std::move(EC);
}
+ if (Tpi) {
+ if (auto EC = Tpi->finalizeMsfLayout())
+ return std::move(EC);
+ }
+ if (Ipi) {
+ if (auto EC = Ipi->finalizeMsfLayout())
+ return std::move(EC);
+ }
+
+ return Msf->build();
+}
- auto ExpectedLayout = Msf->build();
+Error PDBFileBuilder::commit(StringRef Filename) {
+ auto ExpectedLayout = finalizeMsfLayout();
if (!ExpectedLayout)
return ExpectedLayout.takeError();
+ auto &Layout = *ExpectedLayout;
- const msf::Layout &L = *ExpectedLayout;
- File->StreamMap = L.StreamMap;
- File->StreamSizes = L.StreamSizes;
- File->DirectoryBlocks = L.DirectoryBlocks;
- File->SB = L.SB;
+ uint64_t Filesize = Layout.SB->BlockSize * Layout.SB->NumBlocks;
+ auto OutFileOrError = FileOutputBuffer::create(Filename, Filesize);
+ if (OutFileOrError.getError())
+ return llvm::make_error<pdb::GenericError>(generic_error_code::invalid_path,
+ Filename);
+ FileBufferByteStream Buffer(std::move(*OutFileOrError));
+ StreamWriter Writer(Buffer);
+
+ if (auto EC = Writer.writeObject(*Layout.SB))
+ return EC;
+ uint32_t BlockMapOffset =
+ msf::blockToOffset(Layout.SB->BlockMapAddr, Layout.SB->BlockSize);
+ Writer.setOffset(BlockMapOffset);
+ if (auto EC = Writer.writeArray(Layout.DirectoryBlocks))
+ return EC;
+
+ auto DirStream =
+ WritableMappedBlockStream::createDirectoryStream(Layout, Buffer);
+ StreamWriter DW(*DirStream);
+ if (auto EC =
+ DW.writeInteger(static_cast<uint32_t>(Layout.StreamSizes.size())))
+ return EC;
+
+ if (auto EC = DW.writeArray(Layout.StreamSizes))
+ return EC;
+
+ for (const auto &Blocks : Layout.StreamMap) {
+ if (auto EC = DW.writeArray(Blocks))
+ return EC;
+ }
if (Info) {
- auto ExpectedInfo = Info->build(*File);
- if (!ExpectedInfo)
- return ExpectedInfo.takeError();
- File->Info = std::move(*ExpectedInfo);
+ if (auto EC = Info->commit(Layout, Buffer))
+ return EC;
}
if (Dbi) {
- auto ExpectedDbi = Dbi->build(*File);
- if (!ExpectedDbi)
- return ExpectedDbi.takeError();
- File->Dbi = std::move(*ExpectedDbi);
+ if (auto EC = Dbi->commit(Layout, Buffer))
+ return EC;
}
- if (File->Info && File->Dbi && File->Info->getAge() != File->Dbi->getAge())
- return llvm::make_error<RawError>(
- raw_error_code::corrupt_file,
- "PDB Stream Age doesn't match Dbi Stream Age!");
+ if (Tpi) {
+ if (auto EC = Tpi->commit(Layout, Buffer))
+ return EC;
+ }
+
+ if (Ipi) {
+ if (auto EC = Ipi->commit(Layout, Buffer))
+ return EC;
+ }
- return std::move(File);
+ return Buffer.commit();
}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/PublicsStream.cpp b/contrib/llvm/lib/DebugInfo/PDB/Raw/PublicsStream.cpp
index af3d2d0..b31f605 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/Raw/PublicsStream.cpp
+++ b/contrib/llvm/lib/DebugInfo/PDB/Raw/PublicsStream.cpp
@@ -22,30 +22,25 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/DebugInfo/PDB/Raw/PublicsStream.h"
-
-#include "llvm/DebugInfo/CodeView/CodeView.h"
-#include "llvm/DebugInfo/CodeView/StreamReader.h"
-#include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/PDB/Raw/IndexedStreamData.h"
-#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
+#include "GSI.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/MSF/StreamReader.h"
#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
-#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
+#include "llvm/DebugInfo/PDB/Raw/PublicsStream.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
#include "llvm/DebugInfo/PDB/Raw/SymbolStream.h"
-
-#include "llvm/ADT/BitVector.h"
#include "llvm/Support/Endian.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+#include <cstdint>
using namespace llvm;
+using namespace llvm::msf;
using namespace llvm::support;
using namespace llvm::pdb;
-
-static const unsigned IPHR_HASH = 4096;
-
// This is PSGSIHDR struct defined in
// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h
struct PublicsStream::HeaderInfo {
@@ -59,23 +54,11 @@ struct PublicsStream::HeaderInfo {
ulittle32_t NumSections;
};
-// This is GSIHashHdr.
-struct PublicsStream::GSIHashHeader {
- enum : unsigned {
- HdrSignature = ~0U,
- HdrVersion = 0xeffe0000 + 19990810,
- };
- ulittle32_t VerSignature;
- ulittle32_t VerHdr;
- ulittle32_t HrSize;
- ulittle32_t NumBuckets;
-};
-
PublicsStream::PublicsStream(PDBFile &File,
std::unique_ptr<MappedBlockStream> Stream)
: Pdb(File), Stream(std::move(Stream)) {}
-PublicsStream::~PublicsStream() {}
+PublicsStream::~PublicsStream() = default;
uint32_t PublicsStream::getSymHash() const { return Header->SymHash; }
uint32_t PublicsStream::getAddrMap() const { return Header->AddrMap; }
@@ -86,7 +69,7 @@ uint32_t PublicsStream::getAddrMap() const { return Header->AddrMap; }
// we skip over the hash table which we believe contains information about
// public symbols.
Error PublicsStream::reload() {
- codeview::StreamReader Reader(*Stream);
+ StreamReader Reader(*Stream);
// Check stream size.
if (Reader.bytesRemaining() < sizeof(HeaderInfo) + sizeof(GSIHashHeader))
@@ -98,40 +81,15 @@ Error PublicsStream::reload() {
return make_error<RawError>(raw_error_code::corrupt_file,
"Publics Stream does not contain a header.");
- if (Reader.readObject(HashHdr))
- return make_error<RawError>(raw_error_code::corrupt_file,
- "Publics Stream does not contain a header.");
+ if (auto EC = readGSIHashHeader(HashHdr, Reader))
+ return EC;
- // An array of HashRecord follows. Read them.
- if (HashHdr->HrSize % sizeof(PSHashRecord))
- return make_error<RawError>(raw_error_code::corrupt_file,
- "Invalid HR array size.");
- uint32_t NumHashRecords = HashHdr->HrSize / sizeof(PSHashRecord);
- if (auto EC = Reader.readArray(HashRecords, NumHashRecords))
- return joinErrors(std::move(EC),
- make_error<RawError>(raw_error_code::corrupt_file,
- "Could not read an HR array"));
+ if (auto EC = readGSIHashRecords(HashRecords, HashHdr, Reader))
+ return EC;
- // A bitmap of a fixed length follows.
- size_t BitmapSizeInBits = alignTo(IPHR_HASH + 1, 32);
- uint32_t NumBitmapEntries = BitmapSizeInBits / 8;
- if (auto EC = Reader.readBytes(Bitmap, NumBitmapEntries))
- return joinErrors(std::move(EC),
- make_error<RawError>(raw_error_code::corrupt_file,
- "Could not read a bitmap."));
- for (uint8_t B : Bitmap)
- NumBuckets += countPopulation(B);
-
- // We don't yet understand the following data structures completely,
- // but we at least know the types and sizes. Here we are trying
- // to read the stream till end so that we at least can detect
- // corrupted streams.
-
- // Hash buckets follow.
- if (auto EC = Reader.readArray(HashBuckets, NumBuckets))
- return joinErrors(std::move(EC),
- make_error<RawError>(raw_error_code::corrupt_file,
- "Hash buckets corrupted."));
+ if (auto EC = readGSIHashBuckets(HashBuckets, HashHdr, Reader))
+ return EC;
+ NumBuckets = HashBuckets.size();
// Something called "address map" follows.
uint32_t NumAddressMapEntries = Header->AddrMap / sizeof(uint32_t);
@@ -163,7 +121,7 @@ PublicsStream::getSymbols(bool *HadError) const {
auto SymbolS = Pdb.getPDBSymbolStream();
if (SymbolS.takeError()) {
codeview::CVSymbolArray::Iterator Iter;
- return llvm::make_range(Iter, Iter);
+ return make_range(Iter, Iter);
}
SymbolStream &SS = SymbolS.get();
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/RawError.cpp b/contrib/llvm/lib/DebugInfo/PDB/Raw/RawError.cpp
index eb169f7..f4a5057 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/Raw/RawError.cpp
+++ b/contrib/llvm/lib/DebugInfo/PDB/Raw/RawError.cpp
@@ -11,7 +11,7 @@ namespace {
// deal with the Error value directly, rather than converting to error_code.
class RawErrorCategory : public std::error_category {
public:
- const char *name() const LLVM_NOEXCEPT override { return "llvm.pdb.raw"; }
+ const char *name() const noexcept override { return "llvm.pdb.raw"; }
std::string message(int Condition) const override {
switch (static_cast<raw_error_code>(Condition)) {
@@ -19,6 +19,8 @@ public:
return "An unknown error has occurred.";
case raw_error_code::feature_unsupported:
return "The feature is unsupported by the implementation.";
+ case raw_error_code::invalid_format:
+ return "The record is in an unexpected format.";
case raw_error_code::corrupt_file:
return "The PDB file is corrupt.";
case raw_error_code::insufficient_buffer:
@@ -30,6 +32,10 @@ public:
return "The specified item does not exist in the array.";
case raw_error_code::invalid_block_address:
return "The specified block address is not valid.";
+ case raw_error_code::duplicate_entry:
+ return "The entry already exists.";
+ case raw_error_code::no_entry:
+ return "The entry does not exist.";
case raw_error_code::not_writable:
return "The PDB does not support writing.";
case raw_error_code::invalid_tpi_hash:
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/RawSession.cpp b/contrib/llvm/lib/DebugInfo/PDB/Raw/RawSession.cpp
index 455d331..cd3a206 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/Raw/RawSession.cpp
+++ b/contrib/llvm/lib/DebugInfo/PDB/Raw/RawSession.cpp
@@ -7,10 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/DebugInfo/PDB/Raw/RawSession.h"
-
-#include "llvm/DebugInfo/CodeView/ByteStream.h"
-#include "llvm/DebugInfo/CodeView/StreamInterface.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/MSF/ByteStream.h"
#include "llvm/DebugInfo/PDB/GenericError.h"
#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
@@ -18,59 +16,51 @@
#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
-
+#include "llvm/DebugInfo/PDB/Raw/RawSession.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/MemoryBuffer.h"
+#include <algorithm>
+#include <memory>
using namespace llvm;
+using namespace llvm::msf;
using namespace llvm::pdb;
-namespace {
-// We need a class which behaves like an immutable ByteStream, but whose data
-// is backed by an llvm::MemoryBuffer. It also needs to own the underlying
-// MemoryBuffer, so this simple adapter is a good way to achieve that.
-class InputByteStream : public codeview::ByteStream<false> {
-public:
- explicit InputByteStream(std::unique_ptr<MemoryBuffer> Buffer)
- : ByteStream(ArrayRef<uint8_t>(Buffer->getBuffer().bytes_begin(),
- Buffer->getBuffer().bytes_end())),
- MemBuffer(std::move(Buffer)) {}
-
- std::unique_ptr<MemoryBuffer> MemBuffer;
-};
-}
-
-RawSession::RawSession(std::unique_ptr<PDBFile> PdbFile)
- : Pdb(std::move(PdbFile)) {}
+RawSession::RawSession(std::unique_ptr<PDBFile> PdbFile,
+ std::unique_ptr<BumpPtrAllocator> Allocator)
+ : Pdb(std::move(PdbFile)), Allocator(std::move(Allocator)) {}
-RawSession::~RawSession() {}
+RawSession::~RawSession() = default;
Error RawSession::createFromPdb(StringRef Path,
std::unique_ptr<IPDBSession> &Session) {
-
ErrorOr<std::unique_ptr<MemoryBuffer>> ErrorOrBuffer =
MemoryBuffer::getFileOrSTDIN(Path, /*FileSize=*/-1,
/*RequiresNullTerminator=*/false);
if (!ErrorOrBuffer)
- return llvm::make_error<GenericError>(generic_error_code::invalid_path);
+ return make_error<GenericError>(generic_error_code::invalid_path);
std::unique_ptr<MemoryBuffer> Buffer = std::move(*ErrorOrBuffer);
- auto Stream = llvm::make_unique<InputByteStream>(std::move(Buffer));
+ auto Stream = llvm::make_unique<MemoryBufferByteStream>(std::move(Buffer));
- std::unique_ptr<PDBFile> File(new PDBFile(std::move(Stream)));
+ auto Allocator = llvm::make_unique<BumpPtrAllocator>();
+ auto File = llvm::make_unique<PDBFile>(std::move(Stream), *Allocator);
if (auto EC = File->parseFileHeaders())
return EC;
if (auto EC = File->parseStreamData())
return EC;
- Session.reset(new RawSession(std::move(File)));
+ Session =
+ llvm::make_unique<RawSession>(std::move(File), std::move(Allocator));
return Error::success();
}
Error RawSession::createFromExe(StringRef Path,
std::unique_ptr<IPDBSession> &Session) {
- return llvm::make_error<RawError>(raw_error_code::feature_unsupported);
+ return make_error<RawError>(raw_error_code::feature_unsupported);
}
uint64_t RawSession::getLoadAddress() const { return 0; }
@@ -103,26 +93,26 @@ RawSession::findLineNumbersByAddress(uint64_t Address, uint32_t Length) const {
std::unique_ptr<IPDBEnumSourceFiles>
RawSession::findSourceFiles(const PDBSymbolCompiland *Compiland,
- llvm::StringRef Pattern,
+ StringRef Pattern,
PDB_NameSearchFlags Flags) const {
return nullptr;
}
std::unique_ptr<IPDBSourceFile>
RawSession::findOneSourceFile(const PDBSymbolCompiland *Compiland,
- llvm::StringRef Pattern,
+ StringRef Pattern,
PDB_NameSearchFlags Flags) const {
return nullptr;
}
std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>>
-RawSession::findCompilandsForSourceFile(llvm::StringRef Pattern,
+RawSession::findCompilandsForSourceFile(StringRef Pattern,
PDB_NameSearchFlags Flags) const {
return nullptr;
}
std::unique_ptr<PDBSymbolCompiland>
-RawSession::findOneCompilandForSourceFile(llvm::StringRef Pattern,
+RawSession::findOneCompilandForSourceFile(StringRef Pattern,
PDB_NameSearchFlags Flags) const {
return nullptr;
}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/SymbolStream.cpp b/contrib/llvm/lib/DebugInfo/PDB/Raw/SymbolStream.cpp
index 41b2a64..2f3ac34 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/Raw/SymbolStream.cpp
+++ b/contrib/llvm/lib/DebugInfo/PDB/Raw/SymbolStream.cpp
@@ -10,10 +10,9 @@
#include "llvm/DebugInfo/PDB/Raw/SymbolStream.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
-#include "llvm/DebugInfo/CodeView/StreamReader.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/PDB/Raw/IndexedStreamData.h"
-#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/MSF/StreamReader.h"
#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
@@ -21,6 +20,7 @@
#include "llvm/Support/Endian.h"
using namespace llvm;
+using namespace llvm::msf;
using namespace llvm::support;
using namespace llvm::pdb;
@@ -30,7 +30,7 @@ SymbolStream::SymbolStream(std::unique_ptr<MappedBlockStream> Stream)
SymbolStream::~SymbolStream() {}
Error SymbolStream::reload() {
- codeview::StreamReader Reader(*Stream);
+ StreamReader Reader(*Stream);
if (auto EC = Reader.readArray(SymbolRecords, Stream->getLength()))
return EC;
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/TpiHashing.cpp b/contrib/llvm/lib/DebugInfo/PDB/Raw/TpiHashing.cpp
new file mode 100644
index 0000000..6c3ddb3
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/Raw/TpiHashing.cpp
@@ -0,0 +1,110 @@
+//===- TpiHashing.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/PDB/Raw/TpiHashing.h"
+
+#include "llvm/DebugInfo/PDB/Raw/Hash.h"
+#include "llvm/DebugInfo/PDB/Raw/RawError.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+// Corresponds to `fUDTAnon`.
+template <typename T> static bool isAnonymous(T &Rec) {
+ StringRef Name = Rec.getName();
+ return Name == "<unnamed-tag>" || Name == "__unnamed" ||
+ Name.endswith("::<unnamed-tag>") || Name.endswith("::__unnamed");
+}
+
+// Computes a hash for a given TPI record.
+template <typename T>
+static uint32_t getTpiHash(T &Rec, ArrayRef<uint8_t> FullRecord) {
+ auto Opts = static_cast<uint16_t>(Rec.getOptions());
+
+ bool ForwardRef =
+ Opts & static_cast<uint16_t>(ClassOptions::ForwardReference);
+ bool Scoped = Opts & static_cast<uint16_t>(ClassOptions::Scoped);
+ bool UniqueName = Opts & static_cast<uint16_t>(ClassOptions::HasUniqueName);
+ bool IsAnon = UniqueName && isAnonymous(Rec);
+
+ if (!ForwardRef && !Scoped && !IsAnon)
+ return hashStringV1(Rec.getName());
+ if (!ForwardRef && UniqueName && !IsAnon)
+ return hashStringV1(Rec.getUniqueName());
+ return hashBufferV8(FullRecord);
+}
+
+template <typename T> static uint32_t getSourceLineHash(T &Rec) {
+ char Buf[4];
+ support::endian::write32le(Buf, Rec.getUDT().getIndex());
+ return hashStringV1(StringRef(Buf, 4));
+}
+
+void TpiHashUpdater::visitKnownRecordImpl(CVType &CVR,
+ UdtSourceLineRecord &Rec) {
+ CVR.Hash = getSourceLineHash(Rec);
+}
+
+void TpiHashUpdater::visitKnownRecordImpl(CVType &CVR,
+ UdtModSourceLineRecord &Rec) {
+ CVR.Hash = getSourceLineHash(Rec);
+}
+
+void TpiHashUpdater::visitKnownRecordImpl(CVType &CVR, ClassRecord &Rec) {
+ CVR.Hash = getTpiHash(Rec, CVR.data());
+}
+
+void TpiHashUpdater::visitKnownRecordImpl(CVType &CVR, EnumRecord &Rec) {
+ CVR.Hash = getTpiHash(Rec, CVR.data());
+}
+
+void TpiHashUpdater::visitKnownRecordImpl(CVType &CVR, UnionRecord &Rec) {
+ CVR.Hash = getTpiHash(Rec, CVR.data());
+}
+
+Error TpiHashVerifier::visitKnownRecord(CVType &CVR, UdtSourceLineRecord &Rec) {
+ return verifySourceLine(Rec.getUDT());
+}
+
+Error TpiHashVerifier::visitKnownRecord(CVType &CVR,
+ UdtModSourceLineRecord &Rec) {
+ return verifySourceLine(Rec.getUDT());
+}
+
+Error TpiHashVerifier::visitKnownRecord(CVType &CVR, ClassRecord &Rec) {
+ if (getTpiHash(Rec, CVR.data()) % NumHashBuckets != HashValues[Index])
+ return errorInvalidHash();
+ return Error::success();
+}
+Error TpiHashVerifier::visitKnownRecord(CVType &CVR, EnumRecord &Rec) {
+ if (getTpiHash(Rec, CVR.data()) % NumHashBuckets != HashValues[Index])
+ return errorInvalidHash();
+ return Error::success();
+}
+Error TpiHashVerifier::visitKnownRecord(CVType &CVR, UnionRecord &Rec) {
+ if (getTpiHash(Rec, CVR.data()) % NumHashBuckets != HashValues[Index])
+ return errorInvalidHash();
+ return Error::success();
+}
+
+Error TpiHashVerifier::verifySourceLine(codeview::TypeIndex TI) {
+ char Buf[4];
+ support::endian::write32le(Buf, TI.getIndex());
+ uint32_t Hash = hashStringV1(StringRef(Buf, 4));
+ if (Hash % NumHashBuckets != HashValues[Index])
+ return errorInvalidHash();
+ return Error::success();
+}
+
+Error TpiHashVerifier::visitTypeBegin(CVType &Rec) {
+ ++Index;
+ RawRecord = Rec;
+ return Error::success();
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp b/contrib/llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp
index 5617e57..a1167cd 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp
+++ b/contrib/llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp
@@ -7,155 +7,55 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
-
+#include "llvm/ADT/iterator_range.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
-#include "llvm/DebugInfo/CodeView/CodeView.h"
-#include "llvm/DebugInfo/CodeView/StreamReader.h"
-#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/PDB/Raw/Hash.h"
-#include "llvm/DebugInfo/PDB/Raw/IndexedStreamData.h"
-#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/MSF/StreamReader.h"
#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
#include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
-
+#include "llvm/DebugInfo/PDB/Raw/TpiHashing.h"
+#include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+#include <cstdint>
+#include <vector>
using namespace llvm;
using namespace llvm::codeview;
using namespace llvm::support;
+using namespace llvm::msf;
using namespace llvm::pdb;
-namespace {
-const uint32_t MinHashBuckets = 0x1000;
-const uint32_t MaxHashBuckets = 0x40000;
-}
-
-// This corresponds to `HDR` in PDB/dbi/tpi.h.
-struct TpiStream::HeaderInfo {
- struct EmbeddedBuf {
- little32_t Off;
- ulittle32_t Length;
- };
-
- ulittle32_t Version;
- ulittle32_t HeaderSize;
- ulittle32_t TypeIndexBegin;
- ulittle32_t TypeIndexEnd;
- ulittle32_t TypeRecordBytes;
-
- // The following members correspond to `TpiHash` in PDB/dbi/tpi.h.
- ulittle16_t HashStreamIndex;
- ulittle16_t HashAuxStreamIndex;
- ulittle32_t HashKeySize;
- ulittle32_t NumHashBuckets;
-
- EmbeddedBuf HashValueBuffer;
- EmbeddedBuf IndexOffsetBuffer;
- EmbeddedBuf HashAdjBuffer;
-};
-
TpiStream::TpiStream(const PDBFile &File,
std::unique_ptr<MappedBlockStream> Stream)
: Pdb(File), Stream(std::move(Stream)) {}
-TpiStream::~TpiStream() {}
-
-// Corresponds to `fUDTAnon`.
-template <typename T> static bool isAnonymous(T &Rec) {
- StringRef Name = Rec.getName();
- return Name == "<unnamed-tag>" || Name == "__unnamed" ||
- Name.endswith("::<unnamed-tag>") || Name.endswith("::__unnamed");
-}
-
-// Computes a hash for a given TPI record.
-template <typename T>
-static uint32_t getTpiHash(T &Rec, const CVRecord<TypeLeafKind> &RawRec) {
- auto Opts = static_cast<uint16_t>(Rec.getOptions());
-
- bool ForwardRef =
- Opts & static_cast<uint16_t>(ClassOptions::ForwardReference);
- bool Scoped = Opts & static_cast<uint16_t>(ClassOptions::Scoped);
- bool UniqueName = Opts & static_cast<uint16_t>(ClassOptions::HasUniqueName);
- bool IsAnon = UniqueName && isAnonymous(Rec);
-
- if (!ForwardRef && !Scoped && !IsAnon)
- return hashStringV1(Rec.getName());
- if (!ForwardRef && UniqueName && !IsAnon)
- return hashStringV1(Rec.getUniqueName());
- return hashBufferV8(RawRec.RawData);
-}
-
-namespace {
-class TpiHashVerifier : public TypeVisitorCallbacks {
-public:
- TpiHashVerifier(FixedStreamArray<support::ulittle32_t> &HashValues,
- uint32_t NumHashBuckets)
- : HashValues(HashValues), NumHashBuckets(NumHashBuckets) {}
-
- Error visitUdtSourceLine(UdtSourceLineRecord &Rec) override {
- return verifySourceLine(Rec);
- }
-
- Error visitUdtModSourceLine(UdtModSourceLineRecord &Rec) override {
- return verifySourceLine(Rec);
- }
-
- Error visitClass(ClassRecord &Rec) override { return verify(Rec); }
- Error visitEnum(EnumRecord &Rec) override { return verify(Rec); }
- Error visitUnion(UnionRecord &Rec) override { return verify(Rec); }
-
- Error visitTypeBegin(const CVRecord<TypeLeafKind> &Rec) override {
- ++Index;
- RawRecord = &Rec;
- return Error::success();
- }
-
-private:
- template <typename T> Error verify(T &Rec) {
- uint32_t Hash = getTpiHash(Rec, *RawRecord);
- if (Hash % NumHashBuckets != HashValues[Index])
- return errorInvalidHash();
- return Error::success();
- }
-
- template <typename T> Error verifySourceLine(T &Rec) {
- char Buf[4];
- support::endian::write32le(Buf, Rec.getUDT().getIndex());
- uint32_t Hash = hashStringV1(StringRef(Buf, 4));
- if (Hash % NumHashBuckets != HashValues[Index])
- return errorInvalidHash();
- return Error::success();
- }
-
- Error errorInvalidHash() {
- return make_error<RawError>(
- raw_error_code::invalid_tpi_hash,
- "Type index is 0x" + utohexstr(TypeIndex::FirstNonSimpleIndex + Index));
- }
-
- FixedStreamArray<support::ulittle32_t> HashValues;
- const CVRecord<TypeLeafKind> *RawRecord;
- uint32_t NumHashBuckets;
- uint32_t Index = -1;
-};
-}
+TpiStream::~TpiStream() = default;
// Verifies that a given type record matches with a given hash value.
// Currently we only verify SRC_LINE records.
Error TpiStream::verifyHashValues() {
TpiHashVerifier Verifier(HashValues, Header->NumHashBuckets);
- CVTypeVisitor Visitor(Verifier);
+ TypeDeserializer Deserializer;
+
+ TypeVisitorCallbackPipeline Pipeline;
+ Pipeline.addCallbackToPipeline(Deserializer);
+ Pipeline.addCallbackToPipeline(Verifier);
+
+ CVTypeVisitor Visitor(Pipeline);
return Visitor.visitTypeStream(TypeRecords);
}
Error TpiStream::reload() {
StreamReader Reader(*Stream);
- if (Reader.bytesRemaining() < sizeof(HeaderInfo))
+ if (Reader.bytesRemaining() < sizeof(TpiStreamHeader))
return make_error<RawError>(raw_error_code::corrupt_file,
"TPI Stream does not contain a header.");
@@ -167,7 +67,7 @@ Error TpiStream::reload() {
return make_error<RawError>(raw_error_code::corrupt_file,
"Unsupported TPI Version.");
- if (Header->HeaderSize != sizeof(HeaderInfo))
+ if (Header->HeaderSize != sizeof(TpiStreamHeader))
return make_error<RawError>(raw_error_code::corrupt_file,
"Corrupt TPI Header size.");
@@ -175,8 +75,8 @@ Error TpiStream::reload() {
return make_error<RawError>(raw_error_code::corrupt_file,
"TPI Stream expected 4 byte hash key size.");
- if (Header->NumHashBuckets < MinHashBuckets ||
- Header->NumHashBuckets > MaxHashBuckets)
+ if (Header->NumHashBuckets < MinTpiHashBuckets ||
+ Header->NumHashBuckets > MaxTpiHashBuckets)
return make_error<RawError>(raw_error_code::corrupt_file,
"TPI Stream Invalid number of hash buckets.");
@@ -185,43 +85,47 @@ Error TpiStream::reload() {
return EC;
// Hash indices, hash values, etc come from the hash stream.
- if (Header->HashStreamIndex >= Pdb.getNumStreams())
- return make_error<RawError>(raw_error_code::corrupt_file,
- "Invalid TPI hash stream index.");
-
- auto HS =
- MappedBlockStream::createIndexedStream(Header->HashStreamIndex, Pdb);
- if (!HS)
- return HS.takeError();
- StreamReader HSR(**HS);
-
- uint32_t NumHashValues = Header->HashValueBuffer.Length / sizeof(ulittle32_t);
- if (NumHashValues != NumTypeRecords())
- return make_error<RawError>(
- raw_error_code::corrupt_file,
- "TPI hash count does not match with the number of type records.");
- HSR.setOffset(Header->HashValueBuffer.Off);
- if (auto EC = HSR.readArray(HashValues, NumHashValues))
- return EC;
-
- HSR.setOffset(Header->IndexOffsetBuffer.Off);
- uint32_t NumTypeIndexOffsets =
- Header->IndexOffsetBuffer.Length / sizeof(TypeIndexOffset);
- if (auto EC = HSR.readArray(TypeIndexOffsets, NumTypeIndexOffsets))
- return EC;
-
- HSR.setOffset(Header->HashAdjBuffer.Off);
- uint32_t NumHashAdjustments =
- Header->HashAdjBuffer.Length / sizeof(TypeIndexOffset);
- if (auto EC = HSR.readArray(HashAdjustments, NumHashAdjustments))
- return EC;
-
- HashStream = std::move(*HS);
-
- // TPI hash table is a parallel array for the type records.
- // Verify that the hash values match with type records.
- if (auto EC = verifyHashValues())
- return EC;
+ if (Header->HashStreamIndex != kInvalidStreamIndex) {
+ if (Header->HashStreamIndex >= Pdb.getNumStreams())
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Invalid TPI hash stream index.");
+
+ auto HS = MappedBlockStream::createIndexedStream(
+ Pdb.getMsfLayout(), Pdb.getMsfBuffer(), Header->HashStreamIndex);
+ StreamReader HSR(*HS);
+
+ uint32_t NumHashValues =
+ Header->HashValueBuffer.Length / sizeof(ulittle32_t);
+ if (NumHashValues != NumTypeRecords())
+ return make_error<RawError>(
+ raw_error_code::corrupt_file,
+ "TPI hash count does not match with the number of type records.");
+ HSR.setOffset(Header->HashValueBuffer.Off);
+ if (auto EC = HSR.readArray(HashValues, NumHashValues))
+ return EC;
+ std::vector<ulittle32_t> HashValueList;
+ for (auto I : HashValues)
+ HashValueList.push_back(I);
+
+ HSR.setOffset(Header->IndexOffsetBuffer.Off);
+ uint32_t NumTypeIndexOffsets =
+ Header->IndexOffsetBuffer.Length / sizeof(TypeIndexOffset);
+ if (auto EC = HSR.readArray(TypeIndexOffsets, NumTypeIndexOffsets))
+ return EC;
+
+ HSR.setOffset(Header->HashAdjBuffer.Off);
+ uint32_t NumHashAdjustments =
+ Header->HashAdjBuffer.Length / sizeof(TypeIndexOffset);
+ if (auto EC = HSR.readArray(HashAdjustments, NumHashAdjustments))
+ return EC;
+
+ HashStream = std::move(HS);
+
+ // TPI hash table is a parallel array for the type records.
+ // Verify that the hash values match with type records.
+ if (auto EC = verifyHashValues())
+ return EC;
+ }
return Error::success();
}
@@ -267,7 +171,7 @@ TpiStream::getHashAdjustments() const {
iterator_range<CVTypeArray::Iterator>
TpiStream::types(bool *HadError) const {
- return llvm::make_range(TypeRecords.begin(HadError), TypeRecords.end());
+ return make_range(TypeRecords.begin(HadError), TypeRecords.end());
}
Error TpiStream::commit() { return Error::success(); }
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/TpiStreamBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Raw/TpiStreamBuilder.cpp
new file mode 100644
index 0000000..c769321
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/Raw/TpiStreamBuilder.cpp
@@ -0,0 +1,145 @@
+//===- TpiStreamBuilder.cpp - -------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/MSF/ByteStream.h"
+#include "llvm/DebugInfo/MSF/MSFBuilder.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/MSF/StreamArray.h"
+#include "llvm/DebugInfo/MSF/StreamReader.h"
+#include "llvm/DebugInfo/MSF/StreamWriter.h"
+#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Raw/RawError.h"
+#include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
+#include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
+#include "llvm/DebugInfo/PDB/Raw/TpiStreamBuilder.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+#include <cstdint>
+
+using namespace llvm;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+using namespace llvm::support;
+
+TpiStreamBuilder::TpiStreamBuilder(MSFBuilder &Msf, uint32_t StreamIdx)
+ : Msf(Msf), Allocator(Msf.getAllocator()), Header(nullptr), Idx(StreamIdx) {
+}
+
+TpiStreamBuilder::~TpiStreamBuilder() = default;
+
+void TpiStreamBuilder::setVersionHeader(PdbRaw_TpiVer Version) {
+ VerHeader = Version;
+}
+
+void TpiStreamBuilder::addTypeRecord(const codeview::CVType &Record) {
+ TypeRecords.push_back(Record);
+ TypeRecordStream.setItems(TypeRecords);
+}
+
+Error TpiStreamBuilder::finalize() {
+ if (Header)
+ return Error::success();
+
+ TpiStreamHeader *H = Allocator.Allocate<TpiStreamHeader>();
+
+ uint32_t Count = TypeRecords.size();
+ uint32_t HashBufferSize = calculateHashBufferSize();
+
+ H->Version = *VerHeader;
+ H->HeaderSize = sizeof(TpiStreamHeader);
+ H->TypeIndexBegin = codeview::TypeIndex::FirstNonSimpleIndex;
+ H->TypeIndexEnd = H->TypeIndexBegin + Count;
+ H->TypeRecordBytes = TypeRecordStream.getLength();
+
+ H->HashStreamIndex = HashStreamIndex;
+ H->HashAuxStreamIndex = kInvalidStreamIndex;
+ H->HashKeySize = sizeof(ulittle32_t);
+ H->NumHashBuckets = MinTpiHashBuckets;
+
+ // Recall that hash values go into a completely different stream identified by
+ // the `HashStreamIndex` field of the `TpiStreamHeader`. Therefore, the data
+ // begins at offset 0 of this independent stream.
+ H->HashValueBuffer.Off = 0;
+ H->HashValueBuffer.Length = HashBufferSize;
+ H->HashAdjBuffer.Off = H->HashValueBuffer.Off + H->HashValueBuffer.Length;
+ H->HashAdjBuffer.Length = 0;
+ H->IndexOffsetBuffer.Off = H->HashAdjBuffer.Off + H->HashAdjBuffer.Length;
+ H->IndexOffsetBuffer.Length = 0;
+
+ Header = H;
+ return Error::success();
+}
+
+uint32_t TpiStreamBuilder::calculateSerializedLength() const {
+ return sizeof(TpiStreamHeader) + TypeRecordStream.getLength();
+}
+
+uint32_t TpiStreamBuilder::calculateHashBufferSize() const {
+ if (TypeRecords.empty() || !TypeRecords[0].Hash.hasValue())
+ return 0;
+ return TypeRecords.size() * sizeof(ulittle32_t);
+}
+
+Error TpiStreamBuilder::finalizeMsfLayout() {
+ uint32_t Length = calculateSerializedLength();
+ if (auto EC = Msf.setStreamSize(Idx, Length))
+ return EC;
+
+ uint32_t HashBufferSize = calculateHashBufferSize();
+
+ if (HashBufferSize == 0)
+ return Error::success();
+
+ auto ExpectedIndex = Msf.addStream(HashBufferSize);
+ if (!ExpectedIndex)
+ return ExpectedIndex.takeError();
+ HashStreamIndex = *ExpectedIndex;
+ ulittle32_t *H = Allocator.Allocate<ulittle32_t>(TypeRecords.size());
+ MutableArrayRef<ulittle32_t> HashBuffer(H, TypeRecords.size());
+ for (uint32_t I = 0; I < TypeRecords.size(); ++I) {
+ HashBuffer[I] = *TypeRecords[I].Hash % MinTpiHashBuckets;
+ }
+ ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(HashBuffer.data()),
+ HashBufferSize);
+ HashValueStream = llvm::make_unique<ByteStream>(Bytes);
+ return Error::success();
+}
+
+Error TpiStreamBuilder::commit(const msf::MSFLayout &Layout,
+ const msf::WritableStream &Buffer) {
+ if (auto EC = finalize())
+ return EC;
+
+ auto InfoS =
+ WritableMappedBlockStream::createIndexedStream(Layout, Buffer, Idx);
+
+ StreamWriter Writer(*InfoS);
+ if (auto EC = Writer.writeObject(*Header))
+ return EC;
+
+ auto RecordArray = VarStreamArray<codeview::CVType>(TypeRecordStream);
+ if (auto EC = Writer.writeArray(RecordArray))
+ return EC;
+
+ if (HashStreamIndex != kInvalidStreamIndex) {
+ auto HVS = WritableMappedBlockStream::createIndexedStream(Layout, Buffer,
+ HashStreamIndex);
+ StreamWriter HW(*HVS);
+ if (auto EC = HW.writeStreamRef(*HashValueStream))
+ return EC;
+ }
+
+ return Error::success();
+}
diff --git a/contrib/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp b/contrib/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
index adbe0cb..7e56859 100644
--- a/contrib/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
+++ b/contrib/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
@@ -391,10 +391,11 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) {
// If this is a COFF object containing PDB info, use a PDBContext to
// symbolize. Otherwise, use DWARF.
if (auto CoffObject = dyn_cast<COFFObjectFile>(Objects.first)) {
- const debug_pdb_info *PDBInfo;
+ const codeview::DebugInfo *DebugInfo;
StringRef PDBFileName;
- auto EC = CoffObject->getDebugPDBInfo(PDBInfo, PDBFileName);
- if (!EC && PDBInfo != nullptr) {
+ auto EC = CoffObject->getDebugPDBInfo(DebugInfo, PDBFileName);
+ if (!EC && DebugInfo != nullptr && !PDBFileName.empty()) {
+#if 0
using namespace pdb;
std::unique_ptr<IPDBSession> Session;
if (auto Err = loadDataForEXE(PDB_ReaderType::DIA,
@@ -404,6 +405,11 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) {
return std::move(Err);
}
Context.reset(new PDBContext(*CoffObject, std::move(Session)));
+#else
+ return make_error<StringError>(
+ "PDB support not compiled in",
+ std::make_error_code(std::errc::not_supported));
+#endif
}
}
if (!Context)
OpenPOWER on IntegriCloud