aboutsummaryrefslogtreecommitdiff
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/EnumTables.cpp28
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.cpp107
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugFragment.cpp16
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugFragmentRecord.cpp84
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugFragmentVisitor.cpp52
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.cpp123
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugLineFragment.cpp161
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugUnknownFragment.cpp10
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/ModuleSubstream.cpp43
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/ModuleSubstreamVisitor.cpp106
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/StringTable.cpp71
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp25
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/TypeDatabase.cpp4
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp273
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp513
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugPubTable.cpp2
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp6
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp5
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp277
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptor.cpp (renamed from contrib/llvm/lib/DebugInfo/PDB/Native/ModInfo.cpp)46
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp (renamed from contrib/llvm/lib/DebugInfo/PDB/Native/ModInfoBuilder.cpp)118
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Native/DbiStream.cpp15
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp15
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp (renamed from contrib/llvm/lib/DebugInfo/PDB/Native/ModStream.cpp)40
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStreamBuilder.cpp0
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp15
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp25
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp134
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp133
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Native/StringTable.cpp109
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Native/StringTableBuilder.cpp102
-rw-r--r--contrib/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp7
32 files changed, 1990 insertions, 675 deletions
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/EnumTables.cpp b/contrib/llvm/lib/DebugInfo/CodeView/EnumTables.cpp
index 0e20bcb27ec9..fc6008ba66de 100644
--- a/contrib/llvm/lib/DebugInfo/CodeView/EnumTables.cpp
+++ b/contrib/llvm/lib/DebugInfo/CodeView/EnumTables.cpp
@@ -245,20 +245,20 @@ static const EnumEntry<uint32_t> FrameProcSymFlagNames[] = {
};
static const EnumEntry<uint32_t> ModuleSubstreamKindNames[] = {
- CV_ENUM_CLASS_ENT(ModuleSubstreamKind, None),
- CV_ENUM_CLASS_ENT(ModuleSubstreamKind, Symbols),
- CV_ENUM_CLASS_ENT(ModuleSubstreamKind, Lines),
- CV_ENUM_CLASS_ENT(ModuleSubstreamKind, StringTable),
- CV_ENUM_CLASS_ENT(ModuleSubstreamKind, FileChecksums),
- CV_ENUM_CLASS_ENT(ModuleSubstreamKind, FrameData),
- CV_ENUM_CLASS_ENT(ModuleSubstreamKind, InlineeLines),
- CV_ENUM_CLASS_ENT(ModuleSubstreamKind, CrossScopeImports),
- CV_ENUM_CLASS_ENT(ModuleSubstreamKind, CrossScopeExports),
- CV_ENUM_CLASS_ENT(ModuleSubstreamKind, ILLines),
- CV_ENUM_CLASS_ENT(ModuleSubstreamKind, FuncMDTokenMap),
- CV_ENUM_CLASS_ENT(ModuleSubstreamKind, TypeMDTokenMap),
- CV_ENUM_CLASS_ENT(ModuleSubstreamKind, MergedAssemblyInput),
- CV_ENUM_CLASS_ENT(ModuleSubstreamKind, CoffSymbolRVA),
+ CV_ENUM_CLASS_ENT(ModuleDebugFragmentKind, None),
+ CV_ENUM_CLASS_ENT(ModuleDebugFragmentKind, Symbols),
+ CV_ENUM_CLASS_ENT(ModuleDebugFragmentKind, Lines),
+ CV_ENUM_CLASS_ENT(ModuleDebugFragmentKind, StringTable),
+ CV_ENUM_CLASS_ENT(ModuleDebugFragmentKind, FileChecksums),
+ CV_ENUM_CLASS_ENT(ModuleDebugFragmentKind, FrameData),
+ CV_ENUM_CLASS_ENT(ModuleDebugFragmentKind, InlineeLines),
+ CV_ENUM_CLASS_ENT(ModuleDebugFragmentKind, CrossScopeImports),
+ CV_ENUM_CLASS_ENT(ModuleDebugFragmentKind, CrossScopeExports),
+ CV_ENUM_CLASS_ENT(ModuleDebugFragmentKind, ILLines),
+ CV_ENUM_CLASS_ENT(ModuleDebugFragmentKind, FuncMDTokenMap),
+ CV_ENUM_CLASS_ENT(ModuleDebugFragmentKind, TypeMDTokenMap),
+ CV_ENUM_CLASS_ENT(ModuleDebugFragmentKind, MergedAssemblyInput),
+ CV_ENUM_CLASS_ENT(ModuleDebugFragmentKind, CoffSymbolRVA),
};
static const EnumEntry<uint16_t> ExportSymFlagNames[] = {
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.cpp b/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.cpp
new file mode 100644
index 000000000000..42f0afc3e2d7
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.cpp
@@ -0,0 +1,107 @@
+//===- ModuleDebugFileChecksumFragment.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/ModuleDebugFileChecksumFragment.h"
+
+#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/DebugInfo/CodeView/StringTable.h"
+#include "llvm/Support/BinaryStreamReader.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+struct FileChecksumEntryHeader {
+ using ulittle32_t = support::ulittle32_t;
+
+ ulittle32_t FileNameOffset; // Byte offset of filename in global string table.
+ uint8_t ChecksumSize; // Number of bytes of checksum.
+ uint8_t ChecksumKind; // FileChecksumKind
+ // Checksum bytes follow.
+};
+
+Error llvm::VarStreamArrayExtractor<FileChecksumEntry>::extract(
+ BinaryStreamRef Stream, uint32_t &Len, FileChecksumEntry &Item) {
+ BinaryStreamReader Reader(Stream);
+
+ const FileChecksumEntryHeader *Header;
+ if (auto EC = Reader.readObject(Header))
+ return EC;
+
+ Item.FileNameOffset = Header->FileNameOffset;
+ Item.Kind = static_cast<FileChecksumKind>(Header->ChecksumKind);
+ if (auto EC = Reader.readBytes(Item.Checksum, Header->ChecksumSize))
+ return EC;
+
+ Len = alignTo(Header->ChecksumSize + sizeof(FileChecksumEntryHeader), 4);
+ return Error::success();
+}
+
+Error ModuleDebugFileChecksumFragmentRef::initialize(
+ BinaryStreamReader Reader) {
+ if (auto EC = Reader.readArray(Checksums, Reader.bytesRemaining()))
+ return EC;
+
+ return Error::success();
+}
+
+ModuleDebugFileChecksumFragment::ModuleDebugFileChecksumFragment(
+ StringTable &Strings)
+ : ModuleDebugFragment(ModuleDebugFragmentKind::FileChecksums),
+ Strings(Strings) {}
+
+void ModuleDebugFileChecksumFragment::addChecksum(StringRef FileName,
+ FileChecksumKind Kind,
+ ArrayRef<uint8_t> Bytes) {
+ FileChecksumEntry Entry;
+ if (!Bytes.empty()) {
+ uint8_t *Copy = Storage.Allocate<uint8_t>(Bytes.size());
+ ::memcpy(Copy, Bytes.data(), Bytes.size());
+ Entry.Checksum = makeArrayRef(Copy, Bytes.size());
+ }
+
+ Entry.FileNameOffset = Strings.insert(FileName);
+ Entry.Kind = Kind;
+ Checksums.push_back(Entry);
+
+ // This maps the offset of this string in the string table to the offset
+ // of this checksum entry in the checksum buffer.
+ OffsetMap[Entry.FileNameOffset] = SerializedSize;
+ assert(SerializedSize % 4 == 0);
+
+ uint32_t Len = alignTo(sizeof(FileChecksumEntryHeader) + Bytes.size(), 4);
+ SerializedSize += Len;
+}
+
+uint32_t ModuleDebugFileChecksumFragment::calculateSerializedLength() {
+ return SerializedSize;
+}
+
+Error ModuleDebugFileChecksumFragment::commit(BinaryStreamWriter &Writer) {
+ for (const auto &FC : Checksums) {
+ FileChecksumEntryHeader Header;
+ Header.ChecksumKind = uint8_t(FC.Kind);
+ Header.ChecksumSize = FC.Checksum.size();
+ Header.FileNameOffset = FC.FileNameOffset;
+ if (auto EC = Writer.writeObject(Header))
+ return EC;
+ if (auto EC = Writer.writeArray(makeArrayRef(FC.Checksum)))
+ return EC;
+ if (auto EC = Writer.padToAlignment(4))
+ return EC;
+ }
+ return Error::success();
+}
+
+uint32_t
+ModuleDebugFileChecksumFragment::mapChecksumOffset(StringRef FileName) const {
+ uint32_t Offset = Strings.getStringId(FileName);
+ auto Iter = OffsetMap.find(Offset);
+ assert(Iter != OffsetMap.end());
+ return Iter->second;
+}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugFragment.cpp b/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugFragment.cpp
new file mode 100644
index 000000000000..2af1917413da
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugFragment.cpp
@@ -0,0 +1,16 @@
+//===- ModuleDebugFragment.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/ModuleDebugFragment.h"
+
+using namespace llvm::codeview;
+
+ModuleDebugFragmentRef::~ModuleDebugFragmentRef() {}
+
+ModuleDebugFragment::~ModuleDebugFragment() {}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugFragmentRecord.cpp b/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugFragmentRecord.cpp
new file mode 100644
index 000000000000..b2543de78069
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugFragmentRecord.cpp
@@ -0,0 +1,84 @@
+//===- ModuleDebugFragmentRecord.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/ModuleDebugFragmentRecord.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h"
+
+#include "llvm/Support/BinaryStreamReader.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+ModuleDebugFragmentRecord::ModuleDebugFragmentRecord()
+ : Kind(ModuleDebugFragmentKind::None) {}
+
+ModuleDebugFragmentRecord::ModuleDebugFragmentRecord(
+ ModuleDebugFragmentKind Kind, BinaryStreamRef Data)
+ : Kind(Kind), Data(Data) {}
+
+Error ModuleDebugFragmentRecord::initialize(BinaryStreamRef Stream,
+ ModuleDebugFragmentRecord &Info) {
+ const ModuleDebugFragmentHeader *Header;
+ BinaryStreamReader Reader(Stream);
+ if (auto EC = Reader.readObject(Header))
+ return EC;
+
+ ModuleDebugFragmentKind Kind =
+ static_cast<ModuleDebugFragmentKind>(uint32_t(Header->Kind));
+ switch (Kind) {
+ case ModuleDebugFragmentKind::FileChecksums:
+ case ModuleDebugFragmentKind::Lines:
+ case ModuleDebugFragmentKind::InlineeLines:
+ break;
+ default:
+ llvm_unreachable("Unexpected debug fragment kind!");
+ }
+ if (auto EC = Reader.readStreamRef(Info.Data, Header->Length))
+ return EC;
+ Info.Kind = Kind;
+ return Error::success();
+}
+
+uint32_t ModuleDebugFragmentRecord::getRecordLength() const {
+ uint32_t Result = sizeof(ModuleDebugFragmentHeader) + Data.getLength();
+ assert(Result % 4 == 0);
+ return Result;
+}
+
+ModuleDebugFragmentKind ModuleDebugFragmentRecord::kind() const { return Kind; }
+
+BinaryStreamRef ModuleDebugFragmentRecord::getRecordData() const {
+ return Data;
+}
+
+ModuleDebugFragmentRecordBuilder::ModuleDebugFragmentRecordBuilder(
+ ModuleDebugFragmentKind Kind, ModuleDebugFragment &Frag)
+ : Kind(Kind), Frag(Frag) {}
+
+uint32_t ModuleDebugFragmentRecordBuilder::calculateSerializedLength() {
+ uint32_t Size = sizeof(ModuleDebugFragmentHeader) +
+ alignTo(Frag.calculateSerializedLength(), 4);
+ return Size;
+}
+
+Error ModuleDebugFragmentRecordBuilder::commit(BinaryStreamWriter &Writer) {
+ ModuleDebugFragmentHeader Header;
+ Header.Kind = uint32_t(Kind);
+ Header.Length =
+ calculateSerializedLength() - sizeof(ModuleDebugFragmentHeader);
+
+ if (auto EC = Writer.writeObject(Header))
+ return EC;
+ if (auto EC = Frag.commit(Writer))
+ return EC;
+ if (auto EC = Writer.padToAlignment(4))
+ return EC;
+
+ return Error::success();
+}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugFragmentVisitor.cpp b/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugFragmentVisitor.cpp
new file mode 100644
index 000000000000..dc591f3990e2
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugFragmentVisitor.cpp
@@ -0,0 +1,52 @@
+//===- ModuleDebugFragmentVisitor.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/ModuleDebugFragmentVisitor.h"
+
+#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/BinaryStreamRef.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+Error llvm::codeview::visitModuleDebugFragment(
+ const ModuleDebugFragmentRecord &R, ModuleDebugFragmentVisitor &V) {
+ BinaryStreamReader Reader(R.getRecordData());
+ switch (R.kind()) {
+ case ModuleDebugFragmentKind::Lines: {
+ ModuleDebugLineFragmentRef Fragment;
+ if (auto EC = Fragment.initialize(Reader))
+ return EC;
+
+ return V.visitLines(Fragment);
+ }
+ case ModuleDebugFragmentKind::FileChecksums: {
+ ModuleDebugFileChecksumFragmentRef Fragment;
+ if (auto EC = Fragment.initialize(Reader))
+ return EC;
+
+ return V.visitFileChecksums(Fragment);
+ }
+ case ModuleDebugFragmentKind::InlineeLines: {
+ ModuleDebugInlineeLineFragmentRef Fragment;
+ if (auto EC = Fragment.initialize(Reader))
+ return EC;
+ return V.visitInlineeLines(Fragment);
+ }
+ default: {
+ ModuleDebugUnknownFragmentRef Fragment(R.kind(), R.getRecordData());
+ return V.visitUnknown(Fragment);
+ }
+ }
+}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.cpp b/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.cpp
new file mode 100644
index 000000000000..cb6a8478797f
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.cpp
@@ -0,0 +1,123 @@
+//===- ModuleDebugInlineeLineFragment.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/ModuleDebugInlineeLinesFragment.h"
+
+#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h"
+#include "llvm/DebugInfo/CodeView/StringTable.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+Error VarStreamArrayExtractor<InlineeSourceLine>::extract(
+ BinaryStreamRef Stream, uint32_t &Len, InlineeSourceLine &Item,
+ bool HasExtraFiles) {
+ BinaryStreamReader Reader(Stream);
+
+ if (auto EC = Reader.readObject(Item.Header))
+ return EC;
+
+ if (HasExtraFiles) {
+ uint32_t ExtraFileCount;
+ if (auto EC = Reader.readInteger(ExtraFileCount))
+ return EC;
+ if (auto EC = Reader.readArray(Item.ExtraFiles, ExtraFileCount))
+ return EC;
+ }
+
+ Len = Reader.getOffset();
+ return Error::success();
+}
+
+ModuleDebugInlineeLineFragmentRef::ModuleDebugInlineeLineFragmentRef()
+ : ModuleDebugFragmentRef(ModuleDebugFragmentKind::InlineeLines) {}
+
+Error ModuleDebugInlineeLineFragmentRef::initialize(BinaryStreamReader Reader) {
+ if (auto EC = Reader.readEnum(Signature))
+ return EC;
+
+ if (auto EC =
+ Reader.readArray(Lines, Reader.bytesRemaining(), hasExtraFiles()))
+ return EC;
+
+ assert(Reader.bytesRemaining() == 0);
+ return Error::success();
+}
+
+bool ModuleDebugInlineeLineFragmentRef::hasExtraFiles() const {
+ return Signature == InlineeLinesSignature::ExtraFiles;
+}
+
+ModuleDebugInlineeLineFragment::ModuleDebugInlineeLineFragment(
+ ModuleDebugFileChecksumFragment &Checksums, bool HasExtraFiles)
+ : ModuleDebugFragment(ModuleDebugFragmentKind::InlineeLines),
+ Checksums(Checksums), HasExtraFiles(HasExtraFiles) {}
+
+uint32_t ModuleDebugInlineeLineFragment::calculateSerializedLength() {
+ // 4 bytes for the signature
+ uint32_t Size = sizeof(InlineeLinesSignature);
+
+ // one header for each entry.
+ Size += Entries.size() * sizeof(InlineeSourceLineHeader);
+ if (HasExtraFiles) {
+ // If extra files are enabled, one count for each entry.
+ Size += Entries.size() * sizeof(uint32_t);
+
+ // And one file id for each file.
+ Size += ExtraFileCount * sizeof(uint32_t);
+ }
+ assert(Size % 4 == 0);
+ return Size;
+}
+
+Error ModuleDebugInlineeLineFragment::commit(BinaryStreamWriter &Writer) {
+ InlineeLinesSignature Sig = InlineeLinesSignature::Normal;
+ if (HasExtraFiles)
+ Sig = InlineeLinesSignature::ExtraFiles;
+
+ if (auto EC = Writer.writeEnum(Sig))
+ return EC;
+
+ for (const auto &E : Entries) {
+ if (auto EC = Writer.writeObject(E.Header))
+ return EC;
+
+ if (!HasExtraFiles)
+ continue;
+
+ if (auto EC = Writer.writeInteger<uint32_t>(E.ExtraFiles.size()))
+ return EC;
+ if (auto EC = Writer.writeArray(makeArrayRef(E.ExtraFiles)))
+ return EC;
+ }
+
+ return Error::success();
+}
+
+void ModuleDebugInlineeLineFragment::addExtraFile(StringRef FileName) {
+ uint32_t Offset = Checksums.mapChecksumOffset(FileName);
+
+ auto &Entry = Entries.back();
+ Entry.ExtraFiles.push_back(ulittle32_t(Offset));
+ ++ExtraFileCount;
+}
+
+void ModuleDebugInlineeLineFragment::addInlineSite(TypeIndex FuncId,
+ StringRef FileName,
+ uint32_t SourceLine) {
+ uint32_t Offset = Checksums.mapChecksumOffset(FileName);
+
+ Entries.emplace_back();
+ auto &Entry = Entries.back();
+ Entry.Header.FileID = Offset;
+ Entry.Header.SourceLineNum = SourceLine;
+ Entry.Header.Inlinee = FuncId;
+}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugLineFragment.cpp b/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugLineFragment.cpp
new file mode 100644
index 000000000000..e0ee934709ba
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugLineFragment.cpp
@@ -0,0 +1,161 @@
+//===- ModuleDebugLineFragment.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/ModuleDebugLineFragment.h"
+
+#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h"
+#include "llvm/DebugInfo/CodeView/StringTable.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+Error LineColumnExtractor::extract(BinaryStreamRef Stream, uint32_t &Len,
+ LineColumnEntry &Item,
+ const LineFragmentHeader *Header) {
+ using namespace codeview;
+ const LineBlockFragmentHeader *BlockHeader;
+ BinaryStreamReader Reader(Stream);
+ if (auto EC = Reader.readObject(BlockHeader))
+ return EC;
+ bool HasColumn = Header->Flags & uint16_t(LF_HaveColumns);
+ uint32_t LineInfoSize =
+ BlockHeader->NumLines *
+ (sizeof(LineNumberEntry) + (HasColumn ? sizeof(ColumnNumberEntry) : 0));
+ if (BlockHeader->BlockSize < sizeof(LineBlockFragmentHeader))
+ return make_error<CodeViewError>(cv_error_code::corrupt_record,
+ "Invalid line block record size");
+ uint32_t Size = BlockHeader->BlockSize - sizeof(LineBlockFragmentHeader);
+ if (LineInfoSize > Size)
+ return make_error<CodeViewError>(cv_error_code::corrupt_record,
+ "Invalid line block record size");
+ // The value recorded in BlockHeader->BlockSize includes the size of
+ // LineBlockFragmentHeader.
+ Len = BlockHeader->BlockSize;
+ Item.NameIndex = BlockHeader->NameIndex;
+ if (auto EC = Reader.readArray(Item.LineNumbers, BlockHeader->NumLines))
+ return EC;
+ if (HasColumn) {
+ if (auto EC = Reader.readArray(Item.Columns, BlockHeader->NumLines))
+ return EC;
+ }
+ return Error::success();
+}
+
+ModuleDebugLineFragmentRef::ModuleDebugLineFragmentRef()
+ : ModuleDebugFragmentRef(ModuleDebugFragmentKind::Lines) {}
+
+Error ModuleDebugLineFragmentRef::initialize(BinaryStreamReader Reader) {
+ if (auto EC = Reader.readObject(Header))
+ return EC;
+
+ if (auto EC =
+ Reader.readArray(LinesAndColumns, Reader.bytesRemaining(), Header))
+ return EC;
+
+ return Error::success();
+}
+
+bool ModuleDebugLineFragmentRef::hasColumnInfo() const {
+ return !!(Header->Flags & LF_HaveColumns);
+}
+
+ModuleDebugLineFragment::ModuleDebugLineFragment(
+ ModuleDebugFileChecksumFragment &Checksums, StringTable &Strings)
+ : ModuleDebugFragment(ModuleDebugFragmentKind::Lines),
+ Checksums(Checksums) {}
+
+void ModuleDebugLineFragment::createBlock(StringRef FileName) {
+ uint32_t Offset = Checksums.mapChecksumOffset(FileName);
+
+ Blocks.emplace_back(Offset);
+}
+
+void ModuleDebugLineFragment::addLineInfo(uint32_t Offset,
+ const LineInfo &Line) {
+ Block &B = Blocks.back();
+ LineNumberEntry LNE;
+ LNE.Flags = Line.getRawData();
+ LNE.Offset = Offset;
+ B.Lines.push_back(LNE);
+}
+
+void ModuleDebugLineFragment::addLineAndColumnInfo(uint32_t Offset,
+ const LineInfo &Line,
+ uint32_t ColStart,
+ uint32_t ColEnd) {
+ Block &B = Blocks.back();
+ assert(B.Lines.size() == B.Columns.size());
+
+ addLineInfo(Offset, Line);
+ ColumnNumberEntry CNE;
+ CNE.StartColumn = ColStart;
+ CNE.EndColumn = ColEnd;
+ B.Columns.push_back(CNE);
+}
+
+Error ModuleDebugLineFragment::commit(BinaryStreamWriter &Writer) {
+ LineFragmentHeader Header;
+ Header.CodeSize = CodeSize;
+ Header.Flags = hasColumnInfo() ? LF_HaveColumns : 0;
+ Header.RelocOffset = RelocOffset;
+ Header.RelocSegment = RelocSegment;
+
+ if (auto EC = Writer.writeObject(Header))
+ return EC;
+
+ for (const auto &B : Blocks) {
+ LineBlockFragmentHeader BlockHeader;
+ assert(B.Lines.size() == B.Columns.size() || B.Columns.empty());
+
+ BlockHeader.NumLines = B.Lines.size();
+ BlockHeader.BlockSize = sizeof(LineBlockFragmentHeader);
+ BlockHeader.BlockSize += BlockHeader.NumLines * sizeof(LineNumberEntry);
+ if (hasColumnInfo())
+ BlockHeader.BlockSize += BlockHeader.NumLines * sizeof(ColumnNumberEntry);
+ BlockHeader.NameIndex = B.ChecksumBufferOffset;
+ if (auto EC = Writer.writeObject(BlockHeader))
+ return EC;
+
+ if (auto EC = Writer.writeArray(makeArrayRef(B.Lines)))
+ return EC;
+
+ if (hasColumnInfo()) {
+ if (auto EC = Writer.writeArray(makeArrayRef(B.Columns)))
+ return EC;
+ }
+ }
+ return Error::success();
+}
+
+uint32_t ModuleDebugLineFragment::calculateSerializedLength() {
+ uint32_t Size = sizeof(LineFragmentHeader);
+ for (const auto &B : Blocks) {
+ Size += sizeof(LineBlockFragmentHeader);
+ Size += B.Lines.size() * sizeof(LineNumberEntry);
+ if (hasColumnInfo())
+ Size += B.Columns.size() * sizeof(ColumnNumberEntry);
+ }
+ return Size;
+}
+
+void ModuleDebugLineFragment::setRelocationAddress(uint16_t Segment,
+ uint16_t Offset) {
+ RelocOffset = Offset;
+ RelocSegment = Segment;
+}
+
+void ModuleDebugLineFragment::setCodeSize(uint32_t Size) { CodeSize = Size; }
+
+void ModuleDebugLineFragment::setFlags(LineFlags Flags) { this->Flags = Flags; }
+
+bool ModuleDebugLineFragment::hasColumnInfo() const {
+ return Flags & LF_HaveColumns;
+}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugUnknownFragment.cpp b/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugUnknownFragment.cpp
new file mode 100644
index 000000000000..9fd2cb8ed3e8
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugUnknownFragment.cpp
@@ -0,0 +1,10 @@
+//===- ModuleDebugUnknownFragment.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/ModuleDebugUnknownFragment.h" \ No newline at end of file
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/ModuleSubstream.cpp b/contrib/llvm/lib/DebugInfo/CodeView/ModuleSubstream.cpp
deleted file mode 100644
index 69a7c59116cf..000000000000
--- a/contrib/llvm/lib/DebugInfo/CodeView/ModuleSubstream.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-//===- ModuleSubstream.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/ModuleSubstream.h"
-
-#include "llvm/Support/BinaryStreamReader.h"
-
-using namespace llvm;
-using namespace llvm::codeview;
-
-ModuleSubstream::ModuleSubstream() : Kind(ModuleSubstreamKind::None) {}
-
-ModuleSubstream::ModuleSubstream(ModuleSubstreamKind Kind, BinaryStreamRef Data)
- : Kind(Kind), Data(Data) {}
-
-Error ModuleSubstream::initialize(BinaryStreamRef Stream,
- ModuleSubstream &Info) {
- const ModuleSubsectionHeader *Header;
- BinaryStreamReader Reader(Stream);
- if (auto EC = Reader.readObject(Header))
- return EC;
-
- ModuleSubstreamKind Kind =
- static_cast<ModuleSubstreamKind>(uint32_t(Header->Kind));
- if (auto EC = Reader.readStreamRef(Info.Data, Header->Length))
- return EC;
- Info.Kind = Kind;
- return Error::success();
-}
-
-uint32_t ModuleSubstream::getRecordLength() const {
- return sizeof(ModuleSubsectionHeader) + Data.getLength();
-}
-
-ModuleSubstreamKind ModuleSubstream::getSubstreamKind() const { return Kind; }
-
-BinaryStreamRef ModuleSubstream::getRecordData() const { return Data; }
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/ModuleSubstreamVisitor.cpp b/contrib/llvm/lib/DebugInfo/CodeView/ModuleSubstreamVisitor.cpp
deleted file mode 100644
index e490a78cadbc..000000000000
--- a/contrib/llvm/lib/DebugInfo/CodeView/ModuleSubstreamVisitor.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-//===- ModuleSubstreamVisitor.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/ModuleSubstreamVisitor.h"
-#include "llvm/Support/BinaryStreamReader.h"
-#include "llvm/Support/BinaryStreamRef.h"
-
-using namespace llvm;
-using namespace llvm::codeview;
-
-Error IModuleSubstreamVisitor::visitSymbols(BinaryStreamRef Data) {
- return visitUnknown(ModuleSubstreamKind::Symbols, Data);
-}
-Error IModuleSubstreamVisitor::visitLines(BinaryStreamRef Data,
- const LineSubstreamHeader *Header,
- const LineInfoArray &Lines) {
- return visitUnknown(ModuleSubstreamKind::Lines, Data);
-}
-Error IModuleSubstreamVisitor::visitStringTable(BinaryStreamRef Data) {
- return visitUnknown(ModuleSubstreamKind::StringTable, Data);
-}
-Error IModuleSubstreamVisitor::visitFileChecksums(
- BinaryStreamRef Data, const FileChecksumArray &Checksums) {
- return visitUnknown(ModuleSubstreamKind::FileChecksums, Data);
-}
-Error IModuleSubstreamVisitor::visitFrameData(BinaryStreamRef Data) {
- return visitUnknown(ModuleSubstreamKind::FrameData, Data);
-}
-Error IModuleSubstreamVisitor::visitInlineeLines(BinaryStreamRef Data) {
- return visitUnknown(ModuleSubstreamKind::InlineeLines, Data);
-}
-Error IModuleSubstreamVisitor::visitCrossScopeImports(BinaryStreamRef Data) {
- return visitUnknown(ModuleSubstreamKind::CrossScopeExports, Data);
-}
-Error IModuleSubstreamVisitor::visitCrossScopeExports(BinaryStreamRef Data) {
- return visitUnknown(ModuleSubstreamKind::CrossScopeImports, Data);
-}
-Error IModuleSubstreamVisitor::visitILLines(BinaryStreamRef Data) {
- return visitUnknown(ModuleSubstreamKind::ILLines, Data);
-}
-Error IModuleSubstreamVisitor::visitFuncMDTokenMap(BinaryStreamRef Data) {
- return visitUnknown(ModuleSubstreamKind::FuncMDTokenMap, Data);
-}
-Error IModuleSubstreamVisitor::visitTypeMDTokenMap(BinaryStreamRef Data) {
- return visitUnknown(ModuleSubstreamKind::TypeMDTokenMap, Data);
-}
-Error IModuleSubstreamVisitor::visitMergedAssemblyInput(BinaryStreamRef Data) {
- return visitUnknown(ModuleSubstreamKind::MergedAssemblyInput, Data);
-}
-Error IModuleSubstreamVisitor::visitCoffSymbolRVA(BinaryStreamRef Data) {
- return visitUnknown(ModuleSubstreamKind::CoffSymbolRVA, Data);
-}
-
-Error llvm::codeview::visitModuleSubstream(const ModuleSubstream &R,
- IModuleSubstreamVisitor &V) {
- switch (R.getSubstreamKind()) {
- case ModuleSubstreamKind::Symbols:
- return V.visitSymbols(R.getRecordData());
- case ModuleSubstreamKind::Lines: {
- BinaryStreamReader Reader(R.getRecordData());
- const LineSubstreamHeader *Header;
- if (auto EC = Reader.readObject(Header))
- return EC;
- VarStreamArrayExtractor<LineColumnEntry> E(Header);
- LineInfoArray LineInfos(E);
- if (auto EC = Reader.readArray(LineInfos, Reader.bytesRemaining()))
- return EC;
- return V.visitLines(R.getRecordData(), Header, LineInfos);
- }
- case ModuleSubstreamKind::StringTable:
- return V.visitStringTable(R.getRecordData());
- case ModuleSubstreamKind::FileChecksums: {
- BinaryStreamReader Reader(R.getRecordData());
- FileChecksumArray Checksums;
- if (auto EC = Reader.readArray(Checksums, Reader.bytesRemaining()))
- return EC;
- return V.visitFileChecksums(R.getRecordData(), Checksums);
- }
- case ModuleSubstreamKind::FrameData:
- return V.visitFrameData(R.getRecordData());
- case ModuleSubstreamKind::InlineeLines:
- return V.visitInlineeLines(R.getRecordData());
- case ModuleSubstreamKind::CrossScopeImports:
- return V.visitCrossScopeImports(R.getRecordData());
- case ModuleSubstreamKind::CrossScopeExports:
- return V.visitCrossScopeExports(R.getRecordData());
- case ModuleSubstreamKind::ILLines:
- return V.visitILLines(R.getRecordData());
- case ModuleSubstreamKind::FuncMDTokenMap:
- return V.visitFuncMDTokenMap(R.getRecordData());
- case ModuleSubstreamKind::TypeMDTokenMap:
- return V.visitTypeMDTokenMap(R.getRecordData());
- case ModuleSubstreamKind::MergedAssemblyInput:
- return V.visitMergedAssemblyInput(R.getRecordData());
- case ModuleSubstreamKind::CoffSymbolRVA:
- return V.visitCoffSymbolRVA(R.getRecordData());
- default:
- return V.visitUnknown(R.getSubstreamKind(), R.getRecordData());
- }
-}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/StringTable.cpp b/contrib/llvm/lib/DebugInfo/CodeView/StringTable.cpp
new file mode 100644
index 000000000000..21f11204686b
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/StringTable.cpp
@@ -0,0 +1,71 @@
+//===- StringTable.cpp - CodeView String Table Reader/Writer ----*- 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/StringTable.h"
+
+#include "llvm/Support/BinaryStream.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+StringTableRef::StringTableRef() {}
+
+Error StringTableRef::initialize(BinaryStreamRef Contents) {
+ Stream = Contents;
+ return Error::success();
+}
+
+Expected<StringRef> StringTableRef::getString(uint32_t Offset) const {
+ BinaryStreamReader Reader(Stream);
+ Reader.setOffset(Offset);
+ StringRef Result;
+ if (auto EC = Reader.readCString(Result))
+ return std::move(EC);
+ return Result;
+}
+
+uint32_t StringTable::insert(StringRef S) {
+ auto P = Strings.insert({S, StringSize});
+
+ // If a given string didn't exist in the string table, we want to increment
+ // the string table size.
+ if (P.second)
+ StringSize += S.size() + 1; // +1 for '\0'
+ return P.first->second;
+}
+
+uint32_t StringTable::calculateSerializedSize() const { return StringSize; }
+
+Error StringTable::commit(BinaryStreamWriter &Writer) const {
+ assert(Writer.bytesRemaining() == StringSize);
+ uint32_t MaxOffset = 1;
+
+ for (auto &Pair : Strings) {
+ StringRef S = Pair.getKey();
+ uint32_t Offset = Pair.getValue();
+ Writer.setOffset(Offset);
+ if (auto EC = Writer.writeCString(S))
+ return EC;
+ MaxOffset = std::max<uint32_t>(MaxOffset, Offset + S.size() + 1);
+ }
+
+ Writer.setOffset(MaxOffset);
+ assert(Writer.bytesRemaining() == 0);
+ return Error::success();
+}
+
+uint32_t StringTable::size() const { return Strings.size(); }
+
+uint32_t StringTable::getStringId(StringRef S) const {
+ auto P = Strings.find(S);
+ assert(P != Strings.end());
+ return P->second;
+}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp b/contrib/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp
index 134471e81cac..5395e4349b28 100644
--- a/contrib/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp
+++ b/contrib/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp
@@ -13,6 +13,7 @@
#include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
#include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
#include "llvm/DebugInfo/CodeView/EnumTables.h"
+#include "llvm/DebugInfo/CodeView/StringTable.h"
#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
#include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
@@ -369,14 +370,14 @@ Error CVSymbolDumperImpl::visitKnownRecord(
DictScope S(W, "DefRangeSubfield");
if (ObjDelegate) {
- StringRef StringTable = ObjDelegate->getStringTable();
- auto ProgramStringTableOffset = DefRangeSubfield.Program;
- if (ProgramStringTableOffset >= StringTable.size())
+ StringTableRef Strings = ObjDelegate->getStringTable();
+ auto ExpectedProgram = Strings.getString(DefRangeSubfield.Program);
+ if (!ExpectedProgram) {
+ consumeError(ExpectedProgram.takeError());
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.printString("Program", *ExpectedProgram);
}
W.printNumber("OffsetInParent", DefRangeSubfield.OffsetInParent);
printLocalVariableAddrRange(DefRangeSubfield.Range,
@@ -390,14 +391,14 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
DictScope S(W, "DefRange");
if (ObjDelegate) {
- StringRef StringTable = ObjDelegate->getStringTable();
- auto ProgramStringTableOffset = DefRange.Program;
- if (ProgramStringTableOffset >= StringTable.size())
+ StringTableRef Strings = ObjDelegate->getStringTable();
+ auto ExpectedProgram = Strings.getString(DefRange.Program);
+ if (!ExpectedProgram) {
+ consumeError(ExpectedProgram.takeError());
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.printString("Program", *ExpectedProgram);
}
printLocalVariableAddrRange(DefRange.Range, DefRange.getRelocationOffset());
printLocalVariableAddrGap(DefRange.Gaps);
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/TypeDatabase.cpp b/contrib/llvm/lib/DebugInfo/CodeView/TypeDatabase.cpp
index f9ded6ce2a86..efaba4646ffe 100644
--- a/contrib/llvm/lib/DebugInfo/CodeView/TypeDatabase.cpp
+++ b/contrib/llvm/lib/DebugInfo/CodeView/TypeDatabase.cpp
@@ -110,6 +110,10 @@ const CVType &TypeDatabase::getTypeRecord(TypeIndex Index) const {
return TypeRecords[Index.getIndex() - TypeIndex::FirstNonSimpleIndex];
}
+CVType &TypeDatabase::getTypeRecord(TypeIndex Index) {
+ return TypeRecords[Index.getIndex() - TypeIndex::FirstNonSimpleIndex];
+}
+
bool TypeDatabase::containsTypeIndex(TypeIndex Index) const {
uint32_t I = Index.getIndex() - TypeIndex::FirstNonSimpleIndex;
return I < CVUDTNames.size();
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
index 7e8d04672c03..573d37d77fee 100644
--- a/contrib/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -7,17 +7,17 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
-#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
-#include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
@@ -29,6 +29,7 @@
#include "llvm/DebugInfo/DWARF/DWARFGdbIndex.h"
#include "llvm/DebugInfo/DWARF/DWARFSection.h"
#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
+#include "llvm/DebugInfo/DWARF/DWARFVerifier.h"
#include "llvm/Object/Decompressor.h"
#include "llvm/Object/MachO.h"
#include "llvm/Object/ObjectFile.h"
@@ -42,6 +43,8 @@
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cstdint>
+#include <map>
+#include <set>
#include <string>
#include <utility>
#include <vector>
@@ -284,6 +287,268 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType, bool DumpEH,
getStringSection(), isLittleEndian());
}
+DWARFDie DWARFContext::getDIEForOffset(uint32_t Offset) {
+ parseCompileUnits();
+ if (auto *CU = CUs.getUnitForOffset(Offset))
+ return CU->getDIEForOffset(Offset);
+ return DWARFDie();
+}
+
+namespace {
+
+class Verifier {
+ raw_ostream &OS;
+ DWARFContext &DCtx;
+public:
+ Verifier(raw_ostream &S, DWARFContext &D) : OS(S), DCtx(D) {}
+
+ bool HandleDebugInfo() {
+ bool Success = true;
+ // A map that tracks all references (converted absolute references) so we
+ // can verify each reference points to a valid DIE and not an offset that
+ // lies between to valid DIEs.
+ std::map<uint64_t, std::set<uint32_t>> ReferenceToDIEOffsets;
+
+ OS << "Verifying .debug_info...\n";
+ for (const auto &CU : DCtx.compile_units()) {
+ unsigned NumDies = CU->getNumDIEs();
+ for (unsigned I = 0; I < NumDies; ++I) {
+ auto Die = CU->getDIEAtIndex(I);
+ const auto Tag = Die.getTag();
+ if (Tag == DW_TAG_null)
+ continue;
+ for (auto AttrValue : Die.attributes()) {
+ const auto Attr = AttrValue.Attr;
+ const auto Form = AttrValue.Value.getForm();
+ switch (Attr) {
+ case DW_AT_ranges:
+ // Make sure the offset in the DW_AT_ranges attribute is valid.
+ if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) {
+ if (*SectionOffset >= DCtx.getRangeSection().Data.size()) {
+ Success = false;
+ OS << "error: DW_AT_ranges offset is beyond .debug_ranges "
+ "bounds:\n";
+ Die.dump(OS, 0);
+ OS << "\n";
+ }
+ } else {
+ Success = false;
+ OS << "error: DIE has invalid DW_AT_ranges encoding:\n";
+ Die.dump(OS, 0);
+ OS << "\n";
+ }
+ break;
+ case DW_AT_stmt_list:
+ // Make sure the offset in the DW_AT_stmt_list attribute is valid.
+ if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) {
+ if (*SectionOffset >= DCtx.getLineSection().Data.size()) {
+ Success = false;
+ OS << "error: DW_AT_stmt_list offset is beyond .debug_line "
+ "bounds: "
+ << format("0x%08" PRIx32, *SectionOffset) << "\n";
+ CU->getUnitDIE().dump(OS, 0);
+ OS << "\n";
+ }
+ } else {
+ Success = false;
+ OS << "error: DIE has invalid DW_AT_stmt_list encoding:\n";
+ Die.dump(OS, 0);
+ OS << "\n";
+ }
+ break;
+
+ default:
+ break;
+ }
+ switch (Form) {
+ case DW_FORM_ref1:
+ case DW_FORM_ref2:
+ case DW_FORM_ref4:
+ case DW_FORM_ref8:
+ case DW_FORM_ref_udata: {
+ // Verify all CU relative references are valid CU offsets.
+ Optional<uint64_t> RefVal = AttrValue.Value.getAsReference();
+ assert(RefVal);
+ if (RefVal) {
+ auto DieCU = Die.getDwarfUnit();
+ auto CUSize = DieCU->getNextUnitOffset() - DieCU->getOffset();
+ auto CUOffset = AttrValue.Value.getRawUValue();
+ if (CUOffset >= CUSize) {
+ Success = false;
+ OS << "error: " << FormEncodingString(Form) << " CU offset "
+ << format("0x%08" PRIx32, CUOffset)
+ << " is invalid (must be less than CU size of "
+ << format("0x%08" PRIx32, CUSize) << "):\n";
+ Die.dump(OS, 0);
+ OS << "\n";
+ } else {
+ // Valid reference, but we will verify it points to an actual
+ // DIE later.
+ ReferenceToDIEOffsets[*RefVal].insert(Die.getOffset());
+ }
+ }
+ break;
+ }
+ case DW_FORM_ref_addr: {
+ // Verify all absolute DIE references have valid offsets in the
+ // .debug_info section.
+ Optional<uint64_t> RefVal = AttrValue.Value.getAsReference();
+ assert(RefVal);
+ if (RefVal) {
+ if(*RefVal >= DCtx.getInfoSection().Data.size()) {
+ Success = false;
+ OS << "error: DW_FORM_ref_addr offset beyond .debug_info "
+ "bounds:\n";
+ Die.dump(OS, 0);
+ OS << "\n";
+ } else {
+ // Valid reference, but we will verify it points to an actual
+ // DIE later.
+ ReferenceToDIEOffsets[*RefVal].insert(Die.getOffset());
+ }
+ }
+ break;
+ }
+ case DW_FORM_strp: {
+ auto SecOffset = AttrValue.Value.getAsSectionOffset();
+ assert(SecOffset); // DW_FORM_strp is a section offset.
+ if (SecOffset && *SecOffset >= DCtx.getStringSection().size()) {
+ Success = false;
+ OS << "error: DW_FORM_strp offset beyond .debug_str bounds:\n";
+ Die.dump(OS, 0);
+ OS << "\n";
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ // Take all references and make sure they point to an actual DIE by
+ // getting the DIE by offset and emitting an error
+ OS << "Verifying .debug_info references...\n";
+ for (auto Pair: ReferenceToDIEOffsets) {
+ auto Die = DCtx.getDIEForOffset(Pair.first);
+ if (Die)
+ continue;
+ Success = false;
+ OS << "error: invalid DIE reference " << format("0x%08" PRIx64, Pair.first)
+ << ". Offset is in between DIEs:\n";
+ for (auto Offset: Pair.second) {
+ auto ReferencingDie = DCtx.getDIEForOffset(Offset);
+ ReferencingDie.dump(OS, 0);
+ OS << "\n";
+ }
+ OS << "\n";
+ }
+ return Success;
+ }
+
+ bool HandleDebugLine() {
+ std::map<uint64_t, DWARFDie> StmtListToDie;
+ bool Success = true;
+ OS << "Verifying .debug_line...\n";
+ for (const auto &CU : DCtx.compile_units()) {
+ uint32_t LineTableOffset = 0;
+ auto CUDie = CU->getUnitDIE();
+ auto StmtFormValue = CUDie.find(DW_AT_stmt_list);
+ if (!StmtFormValue) {
+ // No line table for this compile unit.
+ continue;
+ }
+ // Get the attribute value as a section offset. No need to produce an
+ // error here if the encoding isn't correct because we validate this in
+ // the .debug_info verifier.
+ if (auto StmtSectionOffset = toSectionOffset(StmtFormValue)) {
+ LineTableOffset = *StmtSectionOffset;
+ if (LineTableOffset >= DCtx.getLineSection().Data.size()) {
+ // Make sure we don't get a valid line table back if the offset
+ // is wrong.
+ assert(DCtx.getLineTableForUnit(CU.get()) == nullptr);
+ // Skip this line table as it isn't valid. No need to create an error
+ // here because we validate this in the .debug_info verifier.
+ continue;
+ } else {
+ auto Iter = StmtListToDie.find(LineTableOffset);
+ if (Iter != StmtListToDie.end()) {
+ Success = false;
+ OS << "error: two compile unit DIEs, "
+ << format("0x%08" PRIx32, Iter->second.getOffset()) << " and "
+ << format("0x%08" PRIx32, CUDie.getOffset())
+ << ", have the same DW_AT_stmt_list section offset:\n";
+ Iter->second.dump(OS, 0);
+ CUDie.dump(OS, 0);
+ OS << '\n';
+ // Already verified this line table before, no need to do it again.
+ continue;
+ }
+ StmtListToDie[LineTableOffset] = CUDie;
+ }
+ }
+ auto LineTable = DCtx.getLineTableForUnit(CU.get());
+ if (!LineTable) {
+ Success = false;
+ OS << "error: .debug_line[" << format("0x%08" PRIx32, LineTableOffset)
+ << "] was not able to be parsed for CU:\n";
+ CUDie.dump(OS, 0);
+ OS << '\n';
+ continue;
+ }
+ uint32_t MaxFileIndex = LineTable->Prologue.FileNames.size();
+ uint64_t PrevAddress = 0;
+ uint32_t RowIndex = 0;
+ for (const auto &Row : LineTable->Rows) {
+ if (Row.Address < PrevAddress) {
+ Success = false;
+ OS << "error: .debug_line[" << format("0x%08" PRIx32, LineTableOffset)
+ << "] row[" << RowIndex
+ << "] decreases in address from previous row:\n";
+
+ DWARFDebugLine::Row::dumpTableHeader(OS);
+ if (RowIndex > 0)
+ LineTable->Rows[RowIndex - 1].dump(OS);
+ Row.dump(OS);
+ OS << '\n';
+ }
+
+ if (Row.File > MaxFileIndex) {
+ Success = false;
+ OS << "error: .debug_line[" << format("0x%08" PRIx32, LineTableOffset)
+ << "][" << RowIndex << "] has invalid file index " << Row.File
+ << " (valid values are [1," << MaxFileIndex << "]):\n";
+ DWARFDebugLine::Row::dumpTableHeader(OS);
+ Row.dump(OS);
+ OS << '\n';
+ }
+ if (Row.EndSequence)
+ PrevAddress = 0;
+ else
+ PrevAddress = Row.Address;
+ ++RowIndex;
+ }
+ }
+ return Success;
+ }
+};
+
+} // anonymous namespace
+
+bool DWARFContext::verify(raw_ostream &OS, DIDumpType DumpType) {
+ bool Success = true;
+ DWARFVerifier verifier(OS, *this);
+ if (DumpType == DIDT_All || DumpType == DIDT_Info) {
+ if (!verifier.handleDebugInfo())
+ Success = false;
+ }
+ if (DumpType == DIDT_All || DumpType == DIDT_Line) {
+ if (!verifier.handleDebugLine())
+ Success = false;
+ }
+ return Success;
+}
const DWARFUnitIndex &DWARFContext::getCUIndex() {
if (CUIndex)
return *CUIndex;
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
index ff6ed9c6741d..f32e8fe76357 100644
--- a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
@@ -7,9 +7,10 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
-#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
+#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/Format.h"
@@ -26,11 +27,19 @@ using namespace llvm;
using namespace dwarf;
typedef DILineInfoSpecifier::FileLineInfoKind FileLineInfoKind;
+namespace {
+struct ContentDescriptor {
+ dwarf::LineNumberEntryFormat Type;
+ dwarf::Form Form;
+};
+typedef SmallVector<ContentDescriptor, 4> ContentDescriptors;
+} // end anonmyous namespace
DWARFDebugLine::Prologue::Prologue() { clear(); }
void DWARFDebugLine::Prologue::clear() {
TotalLength = Version = PrologueLength = 0;
+ AddressSize = SegSelectorSize = 0;
MinInstLength = MaxOpsPerInst = DefaultIsStmt = LineBase = LineRange = 0;
OpcodeBase = 0;
IsDWARF64 = false;
@@ -43,6 +52,8 @@ void DWARFDebugLine::Prologue::dump(raw_ostream &OS) const {
OS << "Line table prologue:\n"
<< format(" total_length: 0x%8.8" PRIx64 "\n", TotalLength)
<< format(" version: %u\n", Version)
+ << format(Version >= 5 ? " address_size: %u\n" : "", AddressSize)
+ << format(Version >= 5 ? " seg_select_size: %u\n" : "", SegSelectorSize)
<< format(" prologue_length: 0x%8.8" PRIx64 "\n", PrologueLength)
<< format(" min_inst_length: %u\n", MinInstLength)
<< format(Version >= 4 ? "max_ops_per_inst: %u\n" : "", MaxOpsPerInst)
@@ -51,95 +62,210 @@ void DWARFDebugLine::Prologue::dump(raw_ostream &OS) const {
<< format(" line_range: %u\n", LineRange)
<< format(" opcode_base: %u\n", OpcodeBase);
- for (uint32_t i = 0; i < StandardOpcodeLengths.size(); ++i)
+ for (uint32_t I = 0; I != StandardOpcodeLengths.size(); ++I)
OS << format("standard_opcode_lengths[%s] = %u\n",
- LNStandardString(i + 1).data(), StandardOpcodeLengths[i]);
+ LNStandardString(I + 1).data(), StandardOpcodeLengths[I]);
if (!IncludeDirectories.empty())
- for (uint32_t i = 0; i < IncludeDirectories.size(); ++i)
- OS << format("include_directories[%3u] = '", i + 1)
- << IncludeDirectories[i] << "'\n";
+ for (uint32_t I = 0; I != IncludeDirectories.size(); ++I)
+ OS << format("include_directories[%3u] = '", I + 1)
+ << IncludeDirectories[I] << "'\n";
if (!FileNames.empty()) {
OS << " Dir Mod Time File Len File Name\n"
<< " ---- ---------- ---------- -----------"
"----------------\n";
- for (uint32_t i = 0; i < FileNames.size(); ++i) {
- const FileNameEntry &fileEntry = FileNames[i];
- OS << format("file_names[%3u] %4" PRIu64 " ", i + 1, fileEntry.DirIdx)
- << format("0x%8.8" PRIx64 " 0x%8.8" PRIx64 " ", fileEntry.ModTime,
- fileEntry.Length)
- << fileEntry.Name << '\n';
+ for (uint32_t I = 0; I != FileNames.size(); ++I) {
+ const FileNameEntry &FileEntry = FileNames[I];
+ OS << format("file_names[%3u] %4" PRIu64 " ", I + 1, FileEntry.DirIdx)
+ << format("0x%8.8" PRIx64 " 0x%8.8" PRIx64 " ", FileEntry.ModTime,
+ FileEntry.Length)
+ << FileEntry.Name << '\n';
}
}
}
-bool DWARFDebugLine::Prologue::parse(DataExtractor debug_line_data,
- uint32_t *offset_ptr) {
- const uint64_t prologue_offset = *offset_ptr;
+// Parse v2-v4 directory and file tables.
+static void
+parseV2DirFileTables(DataExtractor DebugLineData, uint32_t *OffsetPtr,
+ uint64_t EndPrologueOffset,
+ std::vector<StringRef> &IncludeDirectories,
+ std::vector<DWARFDebugLine::FileNameEntry> &FileNames) {
+ while (*OffsetPtr < EndPrologueOffset) {
+ StringRef S = DebugLineData.getCStrRef(OffsetPtr);
+ if (S.empty())
+ break;
+ IncludeDirectories.push_back(S);
+ }
+
+ while (*OffsetPtr < EndPrologueOffset) {
+ StringRef Name = DebugLineData.getCStrRef(OffsetPtr);
+ if (Name.empty())
+ break;
+ DWARFDebugLine::FileNameEntry FileEntry;
+ FileEntry.Name = Name;
+ FileEntry.DirIdx = DebugLineData.getULEB128(OffsetPtr);
+ FileEntry.ModTime = DebugLineData.getULEB128(OffsetPtr);
+ FileEntry.Length = DebugLineData.getULEB128(OffsetPtr);
+ FileNames.push_back(FileEntry);
+ }
+}
+
+// Parse v5 directory/file entry content descriptions.
+// Returns the descriptors, or an empty vector if we did not find a path or
+// ran off the end of the prologue.
+static ContentDescriptors
+parseV5EntryFormat(DataExtractor DebugLineData, uint32_t *OffsetPtr,
+ uint64_t EndPrologueOffset) {
+ ContentDescriptors Descriptors;
+ int FormatCount = DebugLineData.getU8(OffsetPtr);
+ bool HasPath = false;
+ for (int I = 0; I != FormatCount; ++I) {
+ if (*OffsetPtr >= EndPrologueOffset)
+ return ContentDescriptors();
+ ContentDescriptor Descriptor;
+ Descriptor.Type =
+ dwarf::LineNumberEntryFormat(DebugLineData.getULEB128(OffsetPtr));
+ Descriptor.Form = dwarf::Form(DebugLineData.getULEB128(OffsetPtr));
+ if (Descriptor.Type == dwarf::DW_LNCT_path)
+ HasPath = true;
+ Descriptors.push_back(Descriptor);
+ }
+ return HasPath ? Descriptors : ContentDescriptors();
+}
+
+static bool
+parseV5DirFileTables(DataExtractor DebugLineData, uint32_t *OffsetPtr,
+ uint64_t EndPrologueOffset,
+ std::vector<StringRef> &IncludeDirectories,
+ std::vector<DWARFDebugLine::FileNameEntry> &FileNames) {
+ // Get the directory entry description.
+ ContentDescriptors DirDescriptors =
+ parseV5EntryFormat(DebugLineData, OffsetPtr, EndPrologueOffset);
+ if (DirDescriptors.empty())
+ return false;
+
+ // Get the directory entries, according to the format described above.
+ int DirEntryCount = DebugLineData.getU8(OffsetPtr);
+ for (int I = 0; I != DirEntryCount; ++I) {
+ if (*OffsetPtr >= EndPrologueOffset)
+ return false;
+ for (auto Descriptor : DirDescriptors) {
+ DWARFFormValue Value(Descriptor.Form);
+ switch (Descriptor.Type) {
+ case DW_LNCT_path:
+ if (!Value.extractValue(DebugLineData, OffsetPtr, nullptr))
+ return false;
+ IncludeDirectories.push_back(Value.getAsCString().getValue());
+ break;
+ default:
+ if (!Value.skipValue(DebugLineData, OffsetPtr, nullptr))
+ return false;
+ }
+ }
+ }
+
+ // Get the file entry description.
+ ContentDescriptors FileDescriptors =
+ parseV5EntryFormat(DebugLineData, OffsetPtr, EndPrologueOffset);
+ if (FileDescriptors.empty())
+ return false;
+
+ // Get the file entries, according to the format described above.
+ int FileEntryCount = DebugLineData.getU8(OffsetPtr);
+ for (int I = 0; I != FileEntryCount; ++I) {
+ if (*OffsetPtr >= EndPrologueOffset)
+ return false;
+ DWARFDebugLine::FileNameEntry FileEntry;
+ for (auto Descriptor : FileDescriptors) {
+ DWARFFormValue Value(Descriptor.Form);
+ if (!Value.extractValue(DebugLineData, OffsetPtr, nullptr))
+ return false;
+ switch (Descriptor.Type) {
+ case DW_LNCT_path:
+ FileEntry.Name = Value.getAsCString().getValue();
+ break;
+ case DW_LNCT_directory_index:
+ FileEntry.DirIdx = Value.getAsUnsignedConstant().getValue();
+ break;
+ case DW_LNCT_timestamp:
+ FileEntry.ModTime = Value.getAsUnsignedConstant().getValue();
+ break;
+ case DW_LNCT_size:
+ FileEntry.Length = Value.getAsUnsignedConstant().getValue();
+ break;
+ // FIXME: Add MD5
+ default:
+ break;
+ }
+ }
+ FileNames.push_back(FileEntry);
+ }
+ return true;
+}
+
+bool DWARFDebugLine::Prologue::parse(DataExtractor DebugLineData,
+ uint32_t *OffsetPtr) {
+ const uint64_t PrologueOffset = *OffsetPtr;
clear();
- TotalLength = debug_line_data.getU32(offset_ptr);
+ TotalLength = DebugLineData.getU32(OffsetPtr);
if (TotalLength == UINT32_MAX) {
IsDWARF64 = true;
- TotalLength = debug_line_data.getU64(offset_ptr);
+ TotalLength = DebugLineData.getU64(OffsetPtr);
} else if (TotalLength > 0xffffff00) {
return false;
}
- Version = debug_line_data.getU16(offset_ptr);
+ Version = DebugLineData.getU16(OffsetPtr);
if (Version < 2)
return false;
- PrologueLength =
- debug_line_data.getUnsigned(offset_ptr, sizeofPrologueLength());
- const uint64_t end_prologue_offset = PrologueLength + *offset_ptr;
- MinInstLength = debug_line_data.getU8(offset_ptr);
+ if (Version >= 5) {
+ AddressSize = DebugLineData.getU8(OffsetPtr);
+ SegSelectorSize = DebugLineData.getU8(OffsetPtr);
+ }
+
+ PrologueLength = DebugLineData.getUnsigned(OffsetPtr, sizeofPrologueLength());
+ const uint64_t EndPrologueOffset = PrologueLength + *OffsetPtr;
+ MinInstLength = DebugLineData.getU8(OffsetPtr);
if (Version >= 4)
- MaxOpsPerInst = debug_line_data.getU8(offset_ptr);
- DefaultIsStmt = debug_line_data.getU8(offset_ptr);
- LineBase = debug_line_data.getU8(offset_ptr);
- LineRange = debug_line_data.getU8(offset_ptr);
- OpcodeBase = debug_line_data.getU8(offset_ptr);
+ MaxOpsPerInst = DebugLineData.getU8(OffsetPtr);
+ DefaultIsStmt = DebugLineData.getU8(OffsetPtr);
+ LineBase = DebugLineData.getU8(OffsetPtr);
+ LineRange = DebugLineData.getU8(OffsetPtr);
+ OpcodeBase = DebugLineData.getU8(OffsetPtr);
StandardOpcodeLengths.reserve(OpcodeBase - 1);
- for (uint32_t i = 1; i < OpcodeBase; ++i) {
- uint8_t op_len = debug_line_data.getU8(offset_ptr);
- StandardOpcodeLengths.push_back(op_len);
- }
-
- while (*offset_ptr < end_prologue_offset) {
- const char *s = debug_line_data.getCStr(offset_ptr);
- if (s && s[0])
- IncludeDirectories.push_back(s);
- else
- break;
+ for (uint32_t I = 1; I < OpcodeBase; ++I) {
+ uint8_t OpLen = DebugLineData.getU8(OffsetPtr);
+ StandardOpcodeLengths.push_back(OpLen);
}
- while (*offset_ptr < end_prologue_offset) {
- const char *name = debug_line_data.getCStr(offset_ptr);
- if (name && name[0]) {
- FileNameEntry fileEntry;
- fileEntry.Name = name;
- fileEntry.DirIdx = debug_line_data.getULEB128(offset_ptr);
- fileEntry.ModTime = debug_line_data.getULEB128(offset_ptr);
- fileEntry.Length = debug_line_data.getULEB128(offset_ptr);
- FileNames.push_back(fileEntry);
- } else {
- break;
+ if (Version >= 5) {
+ if (!parseV5DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset,
+ IncludeDirectories, FileNames)) {
+ fprintf(stderr,
+ "warning: parsing line table prologue at 0x%8.8" PRIx64
+ " found an invalid directory or file table description at"
+ " 0x%8.8" PRIx64 "\n", PrologueOffset, (uint64_t)*OffsetPtr);
+ return false;
}
- }
-
- if (*offset_ptr != end_prologue_offset) {
- fprintf(stderr, "warning: parsing line table prologue at 0x%8.8" PRIx64
- " should have ended at 0x%8.8" PRIx64
- " but it ended at 0x%8.8" PRIx64 "\n",
- prologue_offset, end_prologue_offset, (uint64_t)*offset_ptr);
+ } else
+ parseV2DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset,
+ IncludeDirectories, FileNames);
+
+ if (*OffsetPtr != EndPrologueOffset) {
+ fprintf(stderr,
+ "warning: parsing line table prologue at 0x%8.8" PRIx64
+ " should have ended at 0x%8.8" PRIx64
+ " but it ended at 0x%8.8" PRIx64 "\n",
+ PrologueOffset, EndPrologueOffset, (uint64_t)*OffsetPtr);
return false;
}
return true;
}
-DWARFDebugLine::Row::Row(bool default_is_stmt) { reset(default_is_stmt); }
+DWARFDebugLine::Row::Row(bool DefaultIsStmt) { reset(DefaultIsStmt); }
void DWARFDebugLine::Row::postAppend() {
BasicBlock = false;
@@ -147,20 +273,26 @@ void DWARFDebugLine::Row::postAppend() {
EpilogueBegin = false;
}
-void DWARFDebugLine::Row::reset(bool default_is_stmt) {
+void DWARFDebugLine::Row::reset(bool DefaultIsStmt) {
Address = 0;
Line = 1;
Column = 0;
File = 1;
Isa = 0;
Discriminator = 0;
- IsStmt = default_is_stmt;
+ IsStmt = DefaultIsStmt;
BasicBlock = false;
EndSequence = false;
PrologueEnd = false;
EpilogueBegin = false;
}
+void DWARFDebugLine::Row::dumpTableHeader(raw_ostream &OS) {
+ OS << "Address Line Column File ISA Discriminator Flags\n"
+ << "------------------ ------ ------ ------ --- ------------- "
+ "-------------\n";
+}
+
void DWARFDebugLine::Row::dump(raw_ostream &OS) const {
OS << format("0x%16.16" PRIx64 " %6u %6u", Address, Line, Column)
<< format(" %6u %3u %13u ", File, Isa, Discriminator)
@@ -187,9 +319,7 @@ void DWARFDebugLine::LineTable::dump(raw_ostream &OS) const {
OS << '\n';
if (!Rows.empty()) {
- OS << "Address Line Column File ISA Discriminator Flags\n"
- << "------------------ ------ ------ ------ --- ------------- "
- "-------------\n";
+ Row::dumpTableHeader(OS);
for (const Row &R : Rows) {
R.dump(OS);
}
@@ -212,7 +342,7 @@ void DWARFDebugLine::ParsingState::resetRowAndSequence() {
Sequence.reset();
}
-void DWARFDebugLine::ParsingState::appendRowToMatrix(uint32_t offset) {
+void DWARFDebugLine::ParsingState::appendRowToMatrix(uint32_t Offset) {
if (Sequence.Empty) {
// Record the beginning of instruction sequence.
Sequence.Empty = false;
@@ -233,56 +363,56 @@ void DWARFDebugLine::ParsingState::appendRowToMatrix(uint32_t offset) {
}
const DWARFDebugLine::LineTable *
-DWARFDebugLine::getLineTable(uint32_t offset) const {
- LineTableConstIter pos = LineTableMap.find(offset);
- if (pos != LineTableMap.end())
- return &pos->second;
+DWARFDebugLine::getLineTable(uint32_t Offset) const {
+ LineTableConstIter Pos = LineTableMap.find(Offset);
+ if (Pos != LineTableMap.end())
+ return &Pos->second;
return nullptr;
}
const DWARFDebugLine::LineTable *
-DWARFDebugLine::getOrParseLineTable(DataExtractor debug_line_data,
- uint32_t offset) {
- std::pair<LineTableIter, bool> pos =
- LineTableMap.insert(LineTableMapTy::value_type(offset, LineTable()));
- LineTable *LT = &pos.first->second;
- if (pos.second) {
- if (!LT->parse(debug_line_data, RelocMap, &offset))
+DWARFDebugLine::getOrParseLineTable(DataExtractor DebugLineData,
+ uint32_t Offset) {
+ std::pair<LineTableIter, bool> Pos =
+ LineTableMap.insert(LineTableMapTy::value_type(Offset, LineTable()));
+ LineTable *LT = &Pos.first->second;
+ if (Pos.second) {
+ if (!LT->parse(DebugLineData, RelocMap, &Offset))
return nullptr;
}
return LT;
}
-bool DWARFDebugLine::LineTable::parse(DataExtractor debug_line_data,
+bool DWARFDebugLine::LineTable::parse(DataExtractor DebugLineData,
const RelocAddrMap *RMap,
- uint32_t *offset_ptr) {
- const uint32_t debug_line_offset = *offset_ptr;
+ uint32_t *OffsetPtr) {
+ const uint32_t DebugLineOffset = *OffsetPtr;
clear();
- if (!Prologue.parse(debug_line_data, offset_ptr)) {
+ if (!Prologue.parse(DebugLineData, OffsetPtr)) {
// Restore our offset and return false to indicate failure!
- *offset_ptr = debug_line_offset;
+ *OffsetPtr = DebugLineOffset;
return false;
}
- const uint32_t end_offset =
- debug_line_offset + Prologue.TotalLength + Prologue.sizeofTotalLength();
+ const uint32_t EndOffset =
+ DebugLineOffset + Prologue.TotalLength + Prologue.sizeofTotalLength();
ParsingState State(this);
- while (*offset_ptr < end_offset) {
- uint8_t opcode = debug_line_data.getU8(offset_ptr);
+ while (*OffsetPtr < EndOffset) {
+ uint8_t Opcode = DebugLineData.getU8(OffsetPtr);
- if (opcode == 0) {
+ if (Opcode == 0) {
// Extended Opcodes always start with a zero opcode followed by
// a uleb128 length so you can skip ones you don't know about
- uint32_t ext_offset = *offset_ptr;
- uint64_t len = debug_line_data.getULEB128(offset_ptr);
- uint32_t arg_size = len - (*offset_ptr - ext_offset);
+ uint32_t ExtOffset = *OffsetPtr;
+ uint64_t Len = DebugLineData.getULEB128(OffsetPtr);
+ uint32_t ArgSize = Len - (*OffsetPtr - ExtOffset);
- uint8_t sub_opcode = debug_line_data.getU8(offset_ptr);
- switch (sub_opcode) {
+ uint8_t SubOpcode = DebugLineData.getU8(OffsetPtr);
+ switch (SubOpcode) {
case DW_LNE_end_sequence:
// Set the end_sequence register of the state machine to true and
// append a row to the matrix using the current values of the
@@ -292,7 +422,7 @@ bool DWARFDebugLine::LineTable::parse(DataExtractor debug_line_data,
// address is that of the byte after the last target machine instruction
// of the sequence.
State.Row.EndSequence = true;
- State.appendRowToMatrix(*offset_ptr);
+ State.appendRowToMatrix(*OffsetPtr);
State.resetRowAndSequence();
break;
@@ -303,9 +433,8 @@ bool DWARFDebugLine::LineTable::parse(DataExtractor debug_line_data,
// relocatable address. All of the other statement program opcodes
// that affect the address register add a delta to it. This instruction
// stores a relocatable value into it instead.
- State.Row.Address =
- getRelocatedValue(debug_line_data, debug_line_data.getAddressSize(),
- offset_ptr, RMap);
+ State.Row.Address = getRelocatedValue(
+ DebugLineData, DebugLineData.getAddressSize(), OffsetPtr, RMap);
break;
case DW_LNE_define_file:
@@ -330,33 +459,33 @@ bool DWARFDebugLine::LineTable::parse(DataExtractor debug_line_data,
// the DW_LNE_define_file instruction. These numbers are used in the
// the file register of the state machine.
{
- FileNameEntry fileEntry;
- fileEntry.Name = debug_line_data.getCStr(offset_ptr);
- fileEntry.DirIdx = debug_line_data.getULEB128(offset_ptr);
- fileEntry.ModTime = debug_line_data.getULEB128(offset_ptr);
- fileEntry.Length = debug_line_data.getULEB128(offset_ptr);
- Prologue.FileNames.push_back(fileEntry);
+ FileNameEntry FileEntry;
+ FileEntry.Name = DebugLineData.getCStr(OffsetPtr);
+ FileEntry.DirIdx = DebugLineData.getULEB128(OffsetPtr);
+ FileEntry.ModTime = DebugLineData.getULEB128(OffsetPtr);
+ FileEntry.Length = DebugLineData.getULEB128(OffsetPtr);
+ Prologue.FileNames.push_back(FileEntry);
}
break;
case DW_LNE_set_discriminator:
- State.Row.Discriminator = debug_line_data.getULEB128(offset_ptr);
+ State.Row.Discriminator = DebugLineData.getULEB128(OffsetPtr);
break;
default:
// Length doesn't include the zero opcode byte or the length itself, but
// it does include the sub_opcode, so we have to adjust for that below
- (*offset_ptr) += arg_size;
+ (*OffsetPtr) += ArgSize;
break;
}
- } else if (opcode < Prologue.OpcodeBase) {
- switch (opcode) {
+ } else if (Opcode < Prologue.OpcodeBase) {
+ switch (Opcode) {
// Standard Opcodes
case DW_LNS_copy:
// Takes no arguments. Append a row to the matrix using the
// current values of the state-machine registers. Then set
// the basic_block register to false.
- State.appendRowToMatrix(*offset_ptr);
+ State.appendRowToMatrix(*OffsetPtr);
break;
case DW_LNS_advance_pc:
@@ -364,25 +493,25 @@ bool DWARFDebugLine::LineTable::parse(DataExtractor debug_line_data,
// min_inst_length field of the prologue, and adds the
// result to the address register of the state machine.
State.Row.Address +=
- debug_line_data.getULEB128(offset_ptr) * Prologue.MinInstLength;
+ DebugLineData.getULEB128(OffsetPtr) * Prologue.MinInstLength;
break;
case DW_LNS_advance_line:
// Takes a single signed LEB128 operand and adds that value to
// the line register of the state machine.
- State.Row.Line += debug_line_data.getSLEB128(offset_ptr);
+ State.Row.Line += DebugLineData.getSLEB128(OffsetPtr);
break;
case DW_LNS_set_file:
// Takes a single unsigned LEB128 operand and stores it in the file
// register of the state machine.
- State.Row.File = debug_line_data.getULEB128(offset_ptr);
+ State.Row.File = DebugLineData.getULEB128(OffsetPtr);
break;
case DW_LNS_set_column:
// Takes a single unsigned LEB128 operand and stores it in the
// column register of the state machine.
- State.Row.Column = debug_line_data.getULEB128(offset_ptr);
+ State.Row.Column = DebugLineData.getULEB128(OffsetPtr);
break;
case DW_LNS_negate_stmt:
@@ -410,10 +539,10 @@ bool DWARFDebugLine::LineTable::parse(DataExtractor debug_line_data,
// than twice that range will it need to use both DW_LNS_advance_pc
// and a special opcode, requiring three or more bytes.
{
- uint8_t adjust_opcode = 255 - Prologue.OpcodeBase;
- uint64_t addr_offset =
- (adjust_opcode / Prologue.LineRange) * Prologue.MinInstLength;
- State.Row.Address += addr_offset;
+ uint8_t AdjustOpcode = 255 - Prologue.OpcodeBase;
+ uint64_t AddrOffset =
+ (AdjustOpcode / Prologue.LineRange) * Prologue.MinInstLength;
+ State.Row.Address += AddrOffset;
}
break;
@@ -427,7 +556,7 @@ bool DWARFDebugLine::LineTable::parse(DataExtractor debug_line_data,
// judge when the computation of a special opcode overflows and
// requires the use of DW_LNS_advance_pc. Such assemblers, however,
// can use DW_LNS_fixed_advance_pc instead, sacrificing compression.
- State.Row.Address += debug_line_data.getU16(offset_ptr);
+ State.Row.Address += DebugLineData.getU16(OffsetPtr);
break;
case DW_LNS_set_prologue_end:
@@ -445,7 +574,7 @@ bool DWARFDebugLine::LineTable::parse(DataExtractor debug_line_data,
case DW_LNS_set_isa:
// Takes a single unsigned LEB128 operand and stores it in the
// column register of the state machine.
- State.Row.Isa = debug_line_data.getULEB128(offset_ptr);
+ State.Row.Isa = DebugLineData.getULEB128(OffsetPtr);
break;
default:
@@ -453,10 +582,10 @@ bool DWARFDebugLine::LineTable::parse(DataExtractor debug_line_data,
// of such opcodes because they are specified in the prologue
// as a multiple of LEB128 operands for each opcode.
{
- assert(opcode - 1U < Prologue.StandardOpcodeLengths.size());
- uint8_t opcode_length = Prologue.StandardOpcodeLengths[opcode - 1];
- for (uint8_t i = 0; i < opcode_length; ++i)
- debug_line_data.getULEB128(offset_ptr);
+ assert(Opcode - 1U < Prologue.StandardOpcodeLengths.size());
+ uint8_t OpcodeLength = Prologue.StandardOpcodeLengths[Opcode - 1];
+ for (uint8_t I = 0; I < OpcodeLength; ++I)
+ DebugLineData.getULEB128(OffsetPtr);
}
break;
}
@@ -494,14 +623,14 @@ bool DWARFDebugLine::LineTable::parse(DataExtractor debug_line_data,
//
// line increment = line_base + (adjusted opcode % line_range)
- uint8_t adjust_opcode = opcode - Prologue.OpcodeBase;
- uint64_t addr_offset =
- (adjust_opcode / Prologue.LineRange) * Prologue.MinInstLength;
- int32_t line_offset =
- Prologue.LineBase + (adjust_opcode % Prologue.LineRange);
- State.Row.Line += line_offset;
- State.Row.Address += addr_offset;
- State.appendRowToMatrix(*offset_ptr);
+ uint8_t AdjustOpcode = Opcode - Prologue.OpcodeBase;
+ uint64_t AddrOffset =
+ (AdjustOpcode / Prologue.LineRange) * Prologue.MinInstLength;
+ int32_t LineOffset =
+ Prologue.LineBase + (AdjustOpcode % Prologue.LineRange);
+ State.Row.Line += LineOffset;
+ State.Row.Address += AddrOffset;
+ State.appendRowToMatrix(*OffsetPtr);
// Reset discriminator to 0.
State.Row.Discriminator = 0;
}
@@ -523,124 +652,122 @@ bool DWARFDebugLine::LineTable::parse(DataExtractor debug_line_data,
// rudimentary sequences for address ranges [0x0, 0xsomething).
}
- return end_offset;
+ return EndOffset;
}
uint32_t
-DWARFDebugLine::LineTable::findRowInSeq(const DWARFDebugLine::Sequence &seq,
- uint64_t address) const {
- if (!seq.containsPC(address))
+DWARFDebugLine::LineTable::findRowInSeq(const DWARFDebugLine::Sequence &Seq,
+ uint64_t Address) const {
+ if (!Seq.containsPC(Address))
return UnknownRowIndex;
// Search for instruction address in the rows describing the sequence.
// Rows are stored in a vector, so we may use arithmetical operations with
// iterators.
- DWARFDebugLine::Row row;
- row.Address = address;
- RowIter first_row = Rows.begin() + seq.FirstRowIndex;
- RowIter last_row = Rows.begin() + seq.LastRowIndex;
- LineTable::RowIter row_pos = std::lower_bound(
- first_row, last_row, row, DWARFDebugLine::Row::orderByAddress);
- if (row_pos == last_row) {
- return seq.LastRowIndex - 1;
+ DWARFDebugLine::Row Row;
+ Row.Address = Address;
+ RowIter FirstRow = Rows.begin() + Seq.FirstRowIndex;
+ RowIter LastRow = Rows.begin() + Seq.LastRowIndex;
+ LineTable::RowIter RowPos = std::lower_bound(
+ FirstRow, LastRow, Row, DWARFDebugLine::Row::orderByAddress);
+ if (RowPos == LastRow) {
+ return Seq.LastRowIndex - 1;
}
- uint32_t index = seq.FirstRowIndex + (row_pos - first_row);
- if (row_pos->Address > address) {
- if (row_pos == first_row)
+ uint32_t Index = Seq.FirstRowIndex + (RowPos - FirstRow);
+ if (RowPos->Address > Address) {
+ if (RowPos == FirstRow)
return UnknownRowIndex;
else
- index--;
+ Index--;
}
- return index;
+ return Index;
}
-uint32_t DWARFDebugLine::LineTable::lookupAddress(uint64_t address) const {
+uint32_t DWARFDebugLine::LineTable::lookupAddress(uint64_t Address) const {
if (Sequences.empty())
return UnknownRowIndex;
// First, find an instruction sequence containing the given address.
- DWARFDebugLine::Sequence sequence;
- sequence.LowPC = address;
- SequenceIter first_seq = Sequences.begin();
- SequenceIter last_seq = Sequences.end();
- SequenceIter seq_pos = std::lower_bound(
- first_seq, last_seq, sequence, DWARFDebugLine::Sequence::orderByLowPC);
- DWARFDebugLine::Sequence found_seq;
- if (seq_pos == last_seq) {
- found_seq = Sequences.back();
- } else if (seq_pos->LowPC == address) {
- found_seq = *seq_pos;
+ DWARFDebugLine::Sequence Sequence;
+ Sequence.LowPC = Address;
+ SequenceIter FirstSeq = Sequences.begin();
+ SequenceIter LastSeq = Sequences.end();
+ SequenceIter SeqPos = std::lower_bound(
+ FirstSeq, LastSeq, Sequence, DWARFDebugLine::Sequence::orderByLowPC);
+ DWARFDebugLine::Sequence FoundSeq;
+ if (SeqPos == LastSeq) {
+ FoundSeq = Sequences.back();
+ } else if (SeqPos->LowPC == Address) {
+ FoundSeq = *SeqPos;
} else {
- if (seq_pos == first_seq)
+ if (SeqPos == FirstSeq)
return UnknownRowIndex;
- found_seq = *(seq_pos - 1);
+ FoundSeq = *(SeqPos - 1);
}
- return findRowInSeq(found_seq, address);
+ return findRowInSeq(FoundSeq, Address);
}
bool DWARFDebugLine::LineTable::lookupAddressRange(
- uint64_t address, uint64_t size, std::vector<uint32_t> &result) const {
+ uint64_t Address, uint64_t Size, std::vector<uint32_t> &Result) const {
if (Sequences.empty())
return false;
- uint64_t end_addr = address + size;
+ uint64_t EndAddr = Address + Size;
// First, find an instruction sequence containing the given address.
- DWARFDebugLine::Sequence sequence;
- sequence.LowPC = address;
- SequenceIter first_seq = Sequences.begin();
- SequenceIter last_seq = Sequences.end();
- SequenceIter seq_pos = std::lower_bound(
- first_seq, last_seq, sequence, DWARFDebugLine::Sequence::orderByLowPC);
- if (seq_pos == last_seq || seq_pos->LowPC != address) {
- if (seq_pos == first_seq)
+ DWARFDebugLine::Sequence Sequence;
+ Sequence.LowPC = Address;
+ SequenceIter FirstSeq = Sequences.begin();
+ SequenceIter LastSeq = Sequences.end();
+ SequenceIter SeqPos = std::lower_bound(
+ FirstSeq, LastSeq, Sequence, DWARFDebugLine::Sequence::orderByLowPC);
+ if (SeqPos == LastSeq || SeqPos->LowPC != Address) {
+ if (SeqPos == FirstSeq)
return false;
- seq_pos--;
+ SeqPos--;
}
- if (!seq_pos->containsPC(address))
+ if (!SeqPos->containsPC(Address))
return false;
- SequenceIter start_pos = seq_pos;
+ SequenceIter StartPos = SeqPos;
// Add the rows from the first sequence to the vector, starting with the
// index we just calculated
- while (seq_pos != last_seq && seq_pos->LowPC < end_addr) {
- const DWARFDebugLine::Sequence &cur_seq = *seq_pos;
+ while (SeqPos != LastSeq && SeqPos->LowPC < EndAddr) {
+ const DWARFDebugLine::Sequence &CurSeq = *SeqPos;
// For the first sequence, we need to find which row in the sequence is the
// first in our range.
- uint32_t first_row_index = cur_seq.FirstRowIndex;
- if (seq_pos == start_pos)
- first_row_index = findRowInSeq(cur_seq, address);
+ uint32_t FirstRowIndex = CurSeq.FirstRowIndex;
+ if (SeqPos == StartPos)
+ FirstRowIndex = findRowInSeq(CurSeq, Address);
// Figure out the last row in the range.
- uint32_t last_row_index = findRowInSeq(cur_seq, end_addr - 1);
- if (last_row_index == UnknownRowIndex)
- last_row_index = cur_seq.LastRowIndex - 1;
+ uint32_t LastRowIndex = findRowInSeq(CurSeq, EndAddr - 1);
+ if (LastRowIndex == UnknownRowIndex)
+ LastRowIndex = CurSeq.LastRowIndex - 1;
- assert(first_row_index != UnknownRowIndex);
- assert(last_row_index != UnknownRowIndex);
+ assert(FirstRowIndex != UnknownRowIndex);
+ assert(LastRowIndex != UnknownRowIndex);
- for (uint32_t i = first_row_index; i <= last_row_index; ++i) {
- result.push_back(i);
+ for (uint32_t I = FirstRowIndex; I <= LastRowIndex; ++I) {
+ Result.push_back(I);
}
- ++seq_pos;
+ ++SeqPos;
}
return true;
}
-bool
-DWARFDebugLine::LineTable::hasFileAtIndex(uint64_t FileIndex) const {
+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 {
+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;
+ StringRef FileName = Entry.Name;
if (Kind != FileLineInfoKind::AbsoluteFilePath ||
sys::path::is_absolute(FileName)) {
Result = FileName;
@@ -649,7 +776,7 @@ DWARFDebugLine::LineTable::getFileNameByIndex(uint64_t FileIndex,
SmallString<16> FilePath;
uint64_t IncludeDirIndex = Entry.DirIdx;
- const char *IncludeDir = "";
+ StringRef IncludeDir;
// Be defensive about the contents of Entry.
if (IncludeDirIndex > 0 &&
IncludeDirIndex <= Prologue.IncludeDirectories.size())
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugPubTable.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugPubTable.cpp
index 662e53d9d7e6..daded255f8c7 100644
--- a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugPubTable.cpp
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugPubTable.cpp
@@ -45,7 +45,7 @@ DWARFDebugPubTable::DWARFDebugPubTable(StringRef Data, bool LittleEndian,
}
void DWARFDebugPubTable::dump(StringRef Name, raw_ostream &OS) const {
- OS << "\n." << Name << " contents: a\n";
+ OS << "\n." << Name << " contents:\n";
for (const Set &S : Sets) {
OS << "length = " << format("0x%08x", S.Length);
OS << " version = " << format("0x%04x", S.Version);
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp
index 28592e4dfb65..7f827de89240 100644
--- a/contrib/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp
@@ -309,8 +309,10 @@ bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const {
}
// 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
- // by mistake.
- return (Form == DW_FORM_data4 || Form == DW_FORM_data8) &&
+ // by mistake. Also accept DW_FORM_strp since this is .debug_str section
+ // offset.
+ return (Form == DW_FORM_data4 || Form == DW_FORM_data8 ||
+ Form == DW_FORM_strp) &&
FC == FC_SectionOffset;
}
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp
index 76354a9b1ddb..0625d01097c9 100644
--- a/contrib/llvm/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp
@@ -39,8 +39,9 @@ void DWARFGdbIndex::dumpAddressArea(raw_ostream &OS) const {
<< '\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);
+ " Low/High address = [0x%llx, 0x%llx) (Size: 0x%llx), CU id = %d\n",
+ Addr.LowAddress, Addr.HighAddress, Addr.HighAddress - Addr.LowAddress,
+ Addr.CuIndex);
}
void DWARFGdbIndex::dumpSymbolTable(raw_ostream &OS) const {
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
new file mode 100644
index 000000000000..9494e876da15
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
@@ -0,0 +1,277 @@
+//===- DWARFVerifier.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/DWARFVerifier.h"
+#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
+#include "llvm/DebugInfo/DWARF/DWARFDie.h"
+#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
+#include "llvm/DebugInfo/DWARF/DWARFSection.h"
+#include "llvm/Support/raw_ostream.h"
+#include <map>
+#include <set>
+#include <vector>
+
+using namespace llvm;
+using namespace dwarf;
+using namespace object;
+
+void DWARFVerifier::verifyDebugInfoAttribute(DWARFDie &Die,
+ DWARFAttribute &AttrValue) {
+ const auto Attr = AttrValue.Attr;
+ switch (Attr) {
+ case DW_AT_ranges:
+ // Make sure the offset in the DW_AT_ranges attribute is valid.
+ if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) {
+ if (*SectionOffset >= DCtx.getRangeSection().Data.size()) {
+ ++NumDebugInfoErrors;
+ OS << "error: DW_AT_ranges offset is beyond .debug_ranges "
+ "bounds:\n";
+ Die.dump(OS, 0);
+ OS << "\n";
+ }
+ } else {
+ ++NumDebugInfoErrors;
+ OS << "error: DIE has invalid DW_AT_ranges encoding:\n";
+ Die.dump(OS, 0);
+ OS << "\n";
+ }
+ break;
+ case DW_AT_stmt_list:
+ // Make sure the offset in the DW_AT_stmt_list attribute is valid.
+ if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) {
+ if (*SectionOffset >= DCtx.getLineSection().Data.size()) {
+ ++NumDebugInfoErrors;
+ OS << "error: DW_AT_stmt_list offset is beyond .debug_line "
+ "bounds: "
+ << format("0x%08" PRIx32, *SectionOffset) << "\n";
+ Die.dump(OS, 0);
+ OS << "\n";
+ }
+ } else {
+ ++NumDebugInfoErrors;
+ OS << "error: DIE has invalid DW_AT_stmt_list encoding:\n";
+ Die.dump(OS, 0);
+ OS << "\n";
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+void DWARFVerifier::verifyDebugInfoForm(DWARFDie &Die,
+ DWARFAttribute &AttrValue) {
+ const auto Form = AttrValue.Value.getForm();
+ switch (Form) {
+ case DW_FORM_ref1:
+ case DW_FORM_ref2:
+ case DW_FORM_ref4:
+ case DW_FORM_ref8:
+ case DW_FORM_ref_udata: {
+ // Verify all CU relative references are valid CU offsets.
+ Optional<uint64_t> RefVal = AttrValue.Value.getAsReference();
+ assert(RefVal);
+ if (RefVal) {
+ auto DieCU = Die.getDwarfUnit();
+ auto CUSize = DieCU->getNextUnitOffset() - DieCU->getOffset();
+ auto CUOffset = AttrValue.Value.getRawUValue();
+ if (CUOffset >= CUSize) {
+ ++NumDebugInfoErrors;
+ OS << "error: " << FormEncodingString(Form) << " CU offset "
+ << format("0x%08" PRIx32, CUOffset)
+ << " is invalid (must be less than CU size of "
+ << format("0x%08" PRIx32, CUSize) << "):\n";
+ Die.dump(OS, 0);
+ OS << "\n";
+ } else {
+ // Valid reference, but we will verify it points to an actual
+ // DIE later.
+ ReferenceToDIEOffsets[*RefVal].insert(Die.getOffset());
+ }
+ }
+ break;
+ }
+ case DW_FORM_ref_addr: {
+ // Verify all absolute DIE references have valid offsets in the
+ // .debug_info section.
+ Optional<uint64_t> RefVal = AttrValue.Value.getAsReference();
+ assert(RefVal);
+ if (RefVal) {
+ if (*RefVal >= DCtx.getInfoSection().Data.size()) {
+ ++NumDebugInfoErrors;
+ OS << "error: DW_FORM_ref_addr offset beyond .debug_info "
+ "bounds:\n";
+ Die.dump(OS, 0);
+ OS << "\n";
+ } else {
+ // Valid reference, but we will verify it points to an actual
+ // DIE later.
+ ReferenceToDIEOffsets[*RefVal].insert(Die.getOffset());
+ }
+ }
+ break;
+ }
+ case DW_FORM_strp: {
+ auto SecOffset = AttrValue.Value.getAsSectionOffset();
+ assert(SecOffset); // DW_FORM_strp is a section offset.
+ if (SecOffset && *SecOffset >= DCtx.getStringSection().size()) {
+ ++NumDebugInfoErrors;
+ OS << "error: DW_FORM_strp offset beyond .debug_str bounds:\n";
+ Die.dump(OS, 0);
+ OS << "\n";
+ }
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+void DWARFVerifier::veifyDebugInfoReferences() {
+ // Take all references and make sure they point to an actual DIE by
+ // getting the DIE by offset and emitting an error
+ OS << "Verifying .debug_info references...\n";
+ for (auto Pair : ReferenceToDIEOffsets) {
+ auto Die = DCtx.getDIEForOffset(Pair.first);
+ if (Die)
+ continue;
+ ++NumDebugInfoErrors;
+ OS << "error: invalid DIE reference " << format("0x%08" PRIx64, Pair.first)
+ << ". Offset is in between DIEs:\n";
+ for (auto Offset : Pair.second) {
+ auto ReferencingDie = DCtx.getDIEForOffset(Offset);
+ ReferencingDie.dump(OS, 0);
+ OS << "\n";
+ }
+ OS << "\n";
+ }
+}
+
+bool DWARFVerifier::handleDebugInfo() {
+ NumDebugInfoErrors = 0;
+ OS << "Verifying .debug_info...\n";
+ for (const auto &CU : DCtx.compile_units()) {
+ unsigned NumDies = CU->getNumDIEs();
+ for (unsigned I = 0; I < NumDies; ++I) {
+ auto Die = CU->getDIEAtIndex(I);
+ const auto Tag = Die.getTag();
+ if (Tag == DW_TAG_null)
+ continue;
+ for (auto AttrValue : Die.attributes()) {
+ verifyDebugInfoAttribute(Die, AttrValue);
+ verifyDebugInfoForm(Die, AttrValue);
+ }
+ }
+ }
+ veifyDebugInfoReferences();
+ return NumDebugInfoErrors == 0;
+}
+
+void DWARFVerifier::verifyDebugLineStmtOffsets() {
+ std::map<uint64_t, DWARFDie> StmtListToDie;
+ for (const auto &CU : DCtx.compile_units()) {
+ auto Die = CU->getUnitDIE();
+ // Get the attribute value as a section offset. No need to produce an
+ // error here if the encoding isn't correct because we validate this in
+ // the .debug_info verifier.
+ auto StmtSectionOffset = toSectionOffset(Die.find(DW_AT_stmt_list));
+ if (!StmtSectionOffset)
+ continue;
+ const uint32_t LineTableOffset = *StmtSectionOffset;
+ auto LineTable = DCtx.getLineTableForUnit(CU.get());
+ if (LineTableOffset < DCtx.getLineSection().Data.size()) {
+ if (!LineTable) {
+ ++NumDebugLineErrors;
+ OS << "error: .debug_line[" << format("0x%08" PRIx32, LineTableOffset)
+ << "] was not able to be parsed for CU:\n";
+ Die.dump(OS, 0);
+ OS << '\n';
+ continue;
+ }
+ } else {
+ // Make sure we don't get a valid line table back if the offset is wrong.
+ assert(LineTable == nullptr);
+ // Skip this line table as it isn't valid. No need to create an error
+ // here because we validate this in the .debug_info verifier.
+ continue;
+ }
+ auto Iter = StmtListToDie.find(LineTableOffset);
+ if (Iter != StmtListToDie.end()) {
+ ++NumDebugLineErrors;
+ OS << "error: two compile unit DIEs, "
+ << format("0x%08" PRIx32, Iter->second.getOffset()) << " and "
+ << format("0x%08" PRIx32, Die.getOffset())
+ << ", have the same DW_AT_stmt_list section offset:\n";
+ Iter->second.dump(OS, 0);
+ Die.dump(OS, 0);
+ OS << '\n';
+ // Already verified this line table before, no need to do it again.
+ continue;
+ }
+ StmtListToDie[LineTableOffset] = Die;
+ }
+}
+
+void DWARFVerifier::verifyDebugLineRows() {
+ for (const auto &CU : DCtx.compile_units()) {
+ auto Die = CU->getUnitDIE();
+ auto LineTable = DCtx.getLineTableForUnit(CU.get());
+ // If there is no line table we will have created an error in the
+ // .debug_info verifier or in verifyDebugLineStmtOffsets().
+ if (!LineTable)
+ continue;
+ uint32_t MaxFileIndex = LineTable->Prologue.FileNames.size();
+ uint64_t PrevAddress = 0;
+ uint32_t RowIndex = 0;
+ for (const auto &Row : LineTable->Rows) {
+ if (Row.Address < PrevAddress) {
+ ++NumDebugLineErrors;
+ OS << "error: .debug_line["
+ << format("0x%08" PRIx32,
+ *toSectionOffset(Die.find(DW_AT_stmt_list)))
+ << "] row[" << RowIndex
+ << "] decreases in address from previous row:\n";
+
+ DWARFDebugLine::Row::dumpTableHeader(OS);
+ if (RowIndex > 0)
+ LineTable->Rows[RowIndex - 1].dump(OS);
+ Row.dump(OS);
+ OS << '\n';
+ }
+
+ if (Row.File > MaxFileIndex) {
+ ++NumDebugLineErrors;
+ OS << "error: .debug_line["
+ << format("0x%08" PRIx32,
+ *toSectionOffset(Die.find(DW_AT_stmt_list)))
+ << "][" << RowIndex << "] has invalid file index " << Row.File
+ << " (valid values are [1," << MaxFileIndex << "]):\n";
+ DWARFDebugLine::Row::dumpTableHeader(OS);
+ Row.dump(OS);
+ OS << '\n';
+ }
+ if (Row.EndSequence)
+ PrevAddress = 0;
+ else
+ PrevAddress = Row.Address;
+ ++RowIndex;
+ }
+ }
+}
+
+bool DWARFVerifier::handleDebugLine() {
+ NumDebugLineErrors = 0;
+ OS << "Verifying .debug_line...\n";
+ verifyDebugLineStmtOffsets();
+ verifyDebugLineRows();
+ return NumDebugLineErrors == 0;
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/ModInfo.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptor.cpp
index 1405286fd088..dabcc3447ee5 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/Native/ModInfo.cpp
+++ b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptor.cpp
@@ -1,4 +1,4 @@
-//===- ModInfo.cpp - PDB module information -------------------------------===//
+//===- DbiModuleDescriptor.cpp - PDB module information -------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/DebugInfo/PDB/Native/ModInfo.h"
+#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
#include "llvm/Support/BinaryStreamReader.h"
#include "llvm/Support/Endian.h"
@@ -19,13 +19,15 @@ using namespace llvm;
using namespace llvm::pdb;
using namespace llvm::support;
-ModInfo::ModInfo() = default;
+DbiModuleDescriptor::DbiModuleDescriptor() = default;
-ModInfo::ModInfo(const ModInfo &Info) = default;
+DbiModuleDescriptor::DbiModuleDescriptor(const DbiModuleDescriptor &Info) =
+ default;
-ModInfo::~ModInfo() = default;
+DbiModuleDescriptor::~DbiModuleDescriptor() = default;
-Error ModInfo::initialize(BinaryStreamRef Stream, ModInfo &Info) {
+Error DbiModuleDescriptor::initialize(BinaryStreamRef Stream,
+ DbiModuleDescriptor &Info) {
BinaryStreamReader Reader(Stream);
if (auto EC = Reader.readObject(Info.Layout))
return EC;
@@ -38,40 +40,48 @@ Error ModInfo::initialize(BinaryStreamRef Stream, ModInfo &Info) {
return Error::success();
}
-bool ModInfo::hasECInfo() const {
+bool DbiModuleDescriptor::hasECInfo() const {
return (Layout->Flags & ModInfoFlags::HasECFlagMask) != 0;
}
-uint16_t ModInfo::getTypeServerIndex() const {
+uint16_t DbiModuleDescriptor::getTypeServerIndex() const {
return (Layout->Flags & ModInfoFlags::TypeServerIndexMask) >>
ModInfoFlags::TypeServerIndexShift;
}
-uint16_t ModInfo::getModuleStreamIndex() const { return Layout->ModDiStream; }
+uint16_t DbiModuleDescriptor::getModuleStreamIndex() const {
+ return Layout->ModDiStream;
+}
-uint32_t ModInfo::getSymbolDebugInfoByteSize() const {
+uint32_t DbiModuleDescriptor::getSymbolDebugInfoByteSize() const {
return Layout->SymBytes;
}
-uint32_t ModInfo::getLineInfoByteSize() const { return Layout->LineBytes; }
+uint32_t DbiModuleDescriptor::getC11LineInfoByteSize() const {
+ return Layout->C11Bytes;
+}
-uint32_t ModInfo::getC13LineInfoByteSize() const { return Layout->C13Bytes; }
+uint32_t DbiModuleDescriptor::getC13LineInfoByteSize() const {
+ return Layout->C13Bytes;
+}
-uint32_t ModInfo::getNumberOfFiles() const { return Layout->NumFiles; }
+uint32_t DbiModuleDescriptor::getNumberOfFiles() const {
+ return Layout->NumFiles;
+}
-uint32_t ModInfo::getSourceFileNameIndex() const {
+uint32_t DbiModuleDescriptor::getSourceFileNameIndex() const {
return Layout->SrcFileNameNI;
}
-uint32_t ModInfo::getPdbFilePathNameIndex() const {
+uint32_t DbiModuleDescriptor::getPdbFilePathNameIndex() const {
return Layout->PdbFilePathNI;
}
-StringRef ModInfo::getModuleName() const { return ModuleName; }
+StringRef DbiModuleDescriptor::getModuleName() const { return ModuleName; }
-StringRef ModInfo::getObjFileName() const { return ObjFileName; }
+StringRef DbiModuleDescriptor::getObjFileName() const { return ObjFileName; }
-uint32_t ModInfo::getRecordLength() const {
+uint32_t DbiModuleDescriptor::getRecordLength() const {
uint32_t M = ModuleName.str().size() + 1;
uint32_t O = ObjFileName.str().size() + 1;
uint32_t Size = sizeof(ModuleInfoHeader) + M + O;
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/ModInfoBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp
index 73c45a953520..867864e47dce 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/Native/ModInfoBuilder.cpp
+++ b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp
@@ -1,4 +1,4 @@
-//===- ModInfoBuilder.cpp - PDB Module Info Stream Creation -----*- C++ -*-===//
+//===- DbiModuleDescriptorBuilder.cpp - PDB Mod Info Creation ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,13 +7,14 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/DebugInfo/PDB/Native/ModInfoBuilder.h"
+#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h"
#include "llvm/DebugInfo/MSF/MSFBuilder.h"
#include "llvm/DebugInfo/MSF/MSFCommon.h"
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
-#include "llvm/DebugInfo/PDB/Native/ModInfo.h"
+#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
#include "llvm/DebugInfo/PDB/Native/RawError.h"
#include "llvm/Support/BinaryItemStream.h"
@@ -35,47 +36,72 @@ template <> struct BinaryItemTraits<CVSymbol> {
};
}
-static uint32_t calculateDiSymbolStreamSize(uint32_t SymbolByteSize) {
+static uint32_t calculateDiSymbolStreamSize(uint32_t SymbolByteSize,
+ uint32_t C13Size) {
uint32_t Size = sizeof(uint32_t); // Signature
Size += SymbolByteSize; // Symbol Data
- Size += 0; // TODO: Layout.LineBytes
- Size += 0; // TODO: Layout.C13Bytes
+ Size += 0; // TODO: Layout.C11Bytes
+ Size += C13Size; // C13 Debug Info Size
Size += sizeof(uint32_t); // GlobalRefs substream size (always 0)
Size += 0; // GlobalRefs substream bytes
return Size;
}
-ModInfoBuilder::ModInfoBuilder(StringRef ModuleName, uint32_t ModIndex,
- msf::MSFBuilder &Msf)
+DbiModuleDescriptorBuilder::DbiModuleDescriptorBuilder(StringRef ModuleName,
+ uint32_t ModIndex,
+ msf::MSFBuilder &Msf)
: MSF(Msf), ModuleName(ModuleName) {
Layout.Mod = ModIndex;
}
-uint16_t ModInfoBuilder::getStreamIndex() const { return Layout.ModDiStream; }
+DbiModuleDescriptorBuilder::~DbiModuleDescriptorBuilder() {}
-void ModInfoBuilder::setObjFileName(StringRef Name) { ObjFileName = Name; }
+uint16_t DbiModuleDescriptorBuilder::getStreamIndex() const {
+ return Layout.ModDiStream;
+}
+
+void DbiModuleDescriptorBuilder::setObjFileName(StringRef Name) {
+ ObjFileName = Name;
+}
-void ModInfoBuilder::addSymbol(CVSymbol Symbol) {
+void DbiModuleDescriptorBuilder::addSymbol(CVSymbol Symbol) {
Symbols.push_back(Symbol);
SymbolByteSize += Symbol.data().size();
}
-void ModInfoBuilder::addSourceFile(StringRef Path) {
+void DbiModuleDescriptorBuilder::addSourceFile(StringRef Path) {
SourceFiles.push_back(Path);
}
-uint32_t ModInfoBuilder::calculateSerializedLength() const {
+uint32_t DbiModuleDescriptorBuilder::calculateC13DebugInfoSize() const {
+ uint32_t Result = 0;
+ for (const auto &Builder : C13Builders) {
+ assert(Builder && "Empty C13 Fragment Builder!");
+ Result += Builder->calculateSerializedLength();
+ }
+ return Result;
+}
+
+uint32_t DbiModuleDescriptorBuilder::calculateSerializedLength() const {
uint32_t L = sizeof(Layout);
uint32_t M = ModuleName.size() + 1;
uint32_t O = ObjFileName.size() + 1;
return alignTo(L + M + O, sizeof(uint32_t));
}
-void ModInfoBuilder::finalize() {
- Layout.C13Bytes = 0;
+template <typename T> struct Foo {
+ explicit Foo(T &&Answer) : Answer(Answer) {}
+
+ T Answer;
+};
+
+template <typename T> Foo<T> makeFoo(T &&t) { return Foo<T>(std::move(t)); }
+
+void DbiModuleDescriptorBuilder::finalize() {
Layout.FileNameOffs = 0; // TODO: Fix this
Layout.Flags = 0; // TODO: Fix this
- Layout.LineBytes = 0;
+ Layout.C11Bytes = 0;
+ Layout.C13Bytes = calculateC13DebugInfoSize();
(void)Layout.Mod; // Set in constructor
(void)Layout.ModDiStream; // Set in finalizeMsfLayout
Layout.NumFiles = SourceFiles.size();
@@ -87,18 +113,20 @@ void ModInfoBuilder::finalize() {
Layout.SymBytes = SymbolByteSize + sizeof(uint32_t);
}
-Error ModInfoBuilder::finalizeMsfLayout() {
+Error DbiModuleDescriptorBuilder::finalizeMsfLayout() {
this->Layout.ModDiStream = kInvalidStreamIndex;
- auto ExpectedSN = MSF.addStream(calculateDiSymbolStreamSize(SymbolByteSize));
+ uint32_t C13Size = calculateC13DebugInfoSize();
+ auto ExpectedSN =
+ MSF.addStream(calculateDiSymbolStreamSize(SymbolByteSize, C13Size));
if (!ExpectedSN)
return ExpectedSN.takeError();
Layout.ModDiStream = *ExpectedSN;
return Error::success();
}
-Error ModInfoBuilder::commit(BinaryStreamWriter &ModiWriter,
- const msf::MSFLayout &MsfLayout,
- WritableBinaryStreamRef MsfBuffer) {
+Error DbiModuleDescriptorBuilder::commit(BinaryStreamWriter &ModiWriter,
+ const msf::MSFLayout &MsfLayout,
+ WritableBinaryStreamRef MsfBuffer) {
// We write the Modi record to the `ModiWriter`, but we additionally write its
// symbol stream to a brand new stream.
if (auto EC = ModiWriter.writeObject(Layout))
@@ -125,7 +153,13 @@ Error ModInfoBuilder::commit(BinaryStreamWriter &ModiWriter,
if (auto EC = SymbolWriter.writeStreamRef(RecordsRef))
return EC;
// TODO: Write C11 Line data
- // TODO: Write C13 Line data
+
+ for (const auto &Builder : C13Builders) {
+ assert(Builder && "Empty C13 Fragment Builder!");
+ if (auto EC = Builder->commit(SymbolWriter))
+ return EC;
+ }
+
// TODO: Figure out what GlobalRefs substream actually is and populate it.
if (auto EC = SymbolWriter.writeInteger<uint32_t>(0))
return EC;
@@ -134,3 +168,43 @@ Error ModInfoBuilder::commit(BinaryStreamWriter &ModiWriter,
}
return Error::success();
}
+
+void DbiModuleDescriptorBuilder::addC13Fragment(
+ std::unique_ptr<ModuleDebugLineFragment> Lines) {
+ ModuleDebugLineFragment &Frag = *Lines;
+
+ // File Checksums have to come first, so push an empty entry on if this
+ // is the first.
+ if (C13Builders.empty())
+ C13Builders.push_back(nullptr);
+
+ this->LineInfo.push_back(std::move(Lines));
+ C13Builders.push_back(
+ llvm::make_unique<ModuleDebugFragmentRecordBuilder>(Frag.kind(), Frag));
+}
+
+void DbiModuleDescriptorBuilder::addC13Fragment(
+ std::unique_ptr<codeview::ModuleDebugInlineeLineFragment> Inlinees) {
+ ModuleDebugInlineeLineFragment &Frag = *Inlinees;
+
+ // File Checksums have to come first, so push an empty entry on if this
+ // is the first.
+ if (C13Builders.empty())
+ C13Builders.push_back(nullptr);
+
+ this->Inlinees.push_back(std::move(Inlinees));
+ C13Builders.push_back(
+ llvm::make_unique<ModuleDebugFragmentRecordBuilder>(Frag.kind(), Frag));
+}
+
+void DbiModuleDescriptorBuilder::setC13FileChecksums(
+ std::unique_ptr<ModuleDebugFileChecksumFragment> Checksums) {
+ assert(!ChecksumInfo && "Can't have more than one checksum info!");
+
+ if (C13Builders.empty())
+ C13Builders.push_back(nullptr);
+
+ ChecksumInfo = std::move(Checksums);
+ C13Builders[0] = llvm::make_unique<ModuleDebugFragmentRecordBuilder>(
+ ChecksumInfo->kind(), *ChecksumInfo);
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/DbiStream.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiStream.cpp
index b9f53578d326..db703809f7c9 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/Native/DbiStream.cpp
+++ b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiStream.cpp
@@ -10,9 +10,9 @@
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
#include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"
#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
-#include "llvm/DebugInfo/PDB/Native/ModInfo.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
#include "llvm/DebugInfo/PDB/Native/RawError.h"
@@ -146,7 +146,7 @@ Error DbiStream::reload() {
if (ECSubstream.getLength() > 0) {
BinaryStreamReader ECReader(ECSubstream);
- if (auto EC = ECNames.load(ECReader))
+ if (auto EC = ECNames.reload(ECReader))
return EC;
}
@@ -252,11 +252,12 @@ Error DbiStream::initializeModInfoArray() {
if (ModInfoSubstream.getLength() == 0)
return Error::success();
- // Since each ModInfo in the stream is a variable length, we have to iterate
+ // Since each DbiModuleDescriptor in the stream is a variable length, we have
+ // to iterate
// them to know how many there actually are.
BinaryStreamReader Reader(ModInfoSubstream);
- VarStreamArray<ModInfo> ModInfoArray;
+ VarStreamArray<DbiModuleDescriptor> ModInfoArray;
if (auto EC = Reader.readArray(ModInfoArray, ModInfoSubstream.getLength()))
return EC;
for (auto &Info : ModInfoArray) {
@@ -371,10 +372,12 @@ Error DbiStream::initializeFileInfo() {
NumSourceFiles += Count;
// This is the array that in the reference implementation corresponds to
- // `ModInfo::FileLayout::FileNameOffs`, which is commented there as being a
+ // `DbiModuleDescriptor::FileLayout::FileNameOffs`, which is commented there
+ // as being a
// pointer. Due to the mentioned problems of pointers causing difficulty
// when reading from the file on 64-bit systems, we continue to ignore that
- // field in `ModInfo`, and instead build a vector of StringRefs and stores
+ // field in `DbiModuleDescriptor`, and instead build a vector of StringRefs
+ // and stores
// them in `ModuleInfoEx`. The value written to and read from the file is
// not used anyway, it is only there as a way to store the offsets for the
// purposes of later accessing the names at runtime.
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp
index a203aea60fe7..c19a2f0d3110 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp
+++ b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp
@@ -12,8 +12,8 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/DebugInfo/MSF/MSFBuilder.h"
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
-#include "llvm/DebugInfo/PDB/Native/ModInfoBuilder.h"
#include "llvm/DebugInfo/PDB/Native/RawError.h"
#include "llvm/Object/COFF.h"
#include "llvm/Support/BinaryStreamWriter.h"
@@ -74,10 +74,11 @@ uint32_t DbiStreamBuilder::calculateSerializedLength() const {
calculateSectionMapStreamSize() + calculateDbgStreamsSize();
}
-Expected<ModInfoBuilder &>
+Expected<DbiModuleDescriptorBuilder &>
DbiStreamBuilder::addModuleInfo(StringRef ModuleName) {
uint32_t Index = ModiList.size();
- auto MIB = llvm::make_unique<ModInfoBuilder>(ModuleName, Index, Msf);
+ auto MIB =
+ llvm::make_unique<DbiModuleDescriptorBuilder>(ModuleName, Index, Msf);
auto M = MIB.get();
auto Result = ModiMap.insert(std::make_pair(ModuleName, std::move(MIB)));
@@ -100,6 +101,14 @@ Error DbiStreamBuilder::addModuleSourceFile(StringRef Module, StringRef File) {
return Error::success();
}
+Expected<uint32_t> DbiStreamBuilder::getSourceFileNameIndex(StringRef File) {
+ auto NameIter = SourceFileNames.find(File);
+ if (NameIter == SourceFileNames.end())
+ return make_error<RawError>(raw_error_code::no_entry,
+ "The specified source file was not found");
+ return NameIter->getValue();
+}
+
uint32_t DbiStreamBuilder::calculateModiSubstreamSize() const {
uint32_t Size = 0;
for (const auto &M : ModiList)
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/ModStream.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp
index e87e2c407593..d7a203746a0d 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/Native/ModStream.cpp
+++ b/contrib/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp
@@ -1,4 +1,4 @@
-//===- ModStream.cpp - PDB Module Info Stream Access ----------------------===//
+//===- ModuleDebugStream.cpp - PDB Module Info Stream Access --------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,10 +7,10 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/DebugInfo/PDB/Native/ModStream.h"
+#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
-#include "llvm/DebugInfo/PDB/Native/ModInfo.h"
+#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/RawError.h"
#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
@@ -21,20 +21,22 @@
#include <cstdint>
using namespace llvm;
+using namespace llvm::codeview;
using namespace llvm::msf;
using namespace llvm::pdb;
-ModStream::ModStream(const ModInfo &Module,
- std::unique_ptr<MappedBlockStream> Stream)
+ModuleDebugStreamRef::ModuleDebugStreamRef(
+ const DbiModuleDescriptor &Module,
+ std::unique_ptr<MappedBlockStream> Stream)
: Mod(Module), Stream(std::move(Stream)) {}
-ModStream::~ModStream() = default;
+ModuleDebugStreamRef::~ModuleDebugStreamRef() = default;
-Error ModStream::reload() {
+Error ModuleDebugStreamRef::reload() {
BinaryStreamReader Reader(*Stream);
uint32_t SymbolSize = Mod.getSymbolDebugInfoByteSize();
- uint32_t C11Size = Mod.getLineInfoByteSize();
+ uint32_t C11Size = Mod.getC11LineInfoByteSize();
uint32_t C13Size = Mod.getC13LineInfoByteSize();
if (C11Size > 0 && C13Size > 0)
@@ -48,13 +50,14 @@ Error ModStream::reload() {
if (auto EC = Reader.readArray(SymbolsSubstream, SymbolSize - 4))
return EC;
- if (auto EC = Reader.readStreamRef(LinesSubstream, C11Size))
+ if (auto EC = Reader.readStreamRef(C11LinesSubstream, C11Size))
return EC;
if (auto EC = Reader.readStreamRef(C13LinesSubstream, C13Size))
return EC;
BinaryStreamReader LineReader(C13LinesSubstream);
- if (auto EC = LineReader.readArray(LineInfo, LineReader.bytesRemaining()))
+ if (auto EC =
+ LineReader.readArray(LinesAndChecksums, LineReader.bytesRemaining()))
return EC;
uint32_t GlobalRefsSize;
@@ -70,20 +73,17 @@ Error ModStream::reload() {
}
iterator_range<codeview::CVSymbolArray::Iterator>
-ModStream::symbols(bool *HadError) const {
- // It's OK if the stream is empty.
- if (SymbolsSubstream.getUnderlyingStream().getLength() == 0)
- return make_range(SymbolsSubstream.end(), SymbolsSubstream.end());
+ModuleDebugStreamRef::symbols(bool *HadError) const {
return make_range(SymbolsSubstream.begin(HadError), SymbolsSubstream.end());
}
-iterator_range<codeview::ModuleSubstreamArray::Iterator>
-ModStream::lines(bool *HadError) const {
- return make_range(LineInfo.begin(HadError), LineInfo.end());
+llvm::iterator_range<ModuleDebugStreamRef::LinesAndChecksumsIterator>
+ModuleDebugStreamRef::linesAndChecksums() const {
+ return make_range(LinesAndChecksums.begin(), LinesAndChecksums.end());
}
-bool ModStream::hasLineInfo() const {
- return C13LinesSubstream.getLength() > 0 || LinesSubstream.getLength() > 0;
+bool ModuleDebugStreamRef::hasLineInfo() const {
+ return C13LinesSubstream.getLength() > 0;
}
-Error ModStream::commit() { return Error::success(); }
+Error ModuleDebugStreamRef::commit() { return Error::success(); }
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStreamBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStreamBuilder.cpp
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStreamBuilder.cpp
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp
index 943e7fa13ab7..859295d2c7d3 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp
+++ b/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp
@@ -15,9 +15,9 @@
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
+#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h"
#include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
#include "llvm/DebugInfo/PDB/Native/RawError.h"
-#include "llvm/DebugInfo/PDB/Native/StringTable.h"
#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
#include "llvm/Support/BinaryStream.h"
@@ -337,8 +337,8 @@ Expected<SymbolStream &> PDBFile::getPDBSymbolStream() {
return *Symbols;
}
-Expected<StringTable &> PDBFile::getStringTable() {
- if (!Strings || !StringTableStream) {
+Expected<PDBStringTable &> PDBFile::getStringTable() {
+ if (!Strings) {
auto IS = getPDBInfoStream();
if (!IS)
return IS.takeError();
@@ -350,12 +350,13 @@ Expected<StringTable &> PDBFile::getStringTable() {
if (!NS)
return NS.takeError();
+ auto N = llvm::make_unique<PDBStringTable>();
BinaryStreamReader Reader(**NS);
- auto N = llvm::make_unique<StringTable>();
- if (auto EC = N->load(Reader))
+ if (auto EC = N->reload(Reader))
return std::move(EC);
- Strings = std::move(N);
+ assert(Reader.bytesRemaining() == 0);
StringTableStream = std::move(*NS);
+ Strings = std::move(N);
}
return *Strings;
}
@@ -389,7 +390,7 @@ bool PDBFile::hasPDBSymbolStream() {
bool PDBFile::hasPDBTpiStream() const { return StreamTPI < getNumStreams(); }
-bool PDBFile::hasStringTable() {
+bool PDBFile::hasPDBStringTable() {
auto IS = getPDBInfoStream();
if (!IS)
return false;
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
index b3c84903bc7e..4dd965c69071 100644
--- a/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
+++ b/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
@@ -17,8 +17,8 @@
#include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
#include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h"
+#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
#include "llvm/DebugInfo/PDB/Native/RawError.h"
-#include "llvm/DebugInfo/PDB/Native/StringTableBuilder.h"
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
#include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h"
#include "llvm/Support/BinaryStream.h"
@@ -67,7 +67,9 @@ TpiStreamBuilder &PDBFileBuilder::getIpiBuilder() {
return *Ipi;
}
-StringTableBuilder &PDBFileBuilder::getStringTableBuilder() { return Strings; }
+PDBStringTableBuilder &PDBFileBuilder::getStringTableBuilder() {
+ return Strings;
+}
Error PDBFileBuilder::addNamedStream(StringRef Name, uint32_t Size) {
auto ExpectedStream = Msf->addStream(Size);
@@ -78,9 +80,9 @@ Error PDBFileBuilder::addNamedStream(StringRef Name, uint32_t Size) {
}
Expected<msf::MSFLayout> PDBFileBuilder::finalizeMsfLayout() {
- uint32_t StringTableSize = Strings.finalize();
+ uint32_t StringsLen = Strings.calculateSerializedSize();
- if (auto EC = addNamedStream("/names", StringTableSize))
+ if (auto EC = addNamedStream("/names", StringsLen))
return std::move(EC);
if (auto EC = addNamedStream("/LinkInfo", 0))
return std::move(EC);
@@ -107,6 +109,13 @@ Expected<msf::MSFLayout> PDBFileBuilder::finalizeMsfLayout() {
return Msf->build();
}
+Expected<uint32_t> PDBFileBuilder::getNamedStreamIndex(StringRef Name) const {
+ uint32_t SN = 0;
+ if (!NamedStreams.get(Name, SN))
+ return llvm::make_error<pdb::RawError>(raw_error_code::no_stream);
+ return SN;
+}
+
Error PDBFileBuilder::commit(StringRef Filename) {
auto ExpectedLayout = finalizeMsfLayout();
if (!ExpectedLayout)
@@ -144,12 +153,12 @@ Error PDBFileBuilder::commit(StringRef Filename) {
return EC;
}
- uint32_t StringTableStreamNo = 0;
- if (!NamedStreams.get("/names", StringTableStreamNo))
- return llvm::make_error<pdb::RawError>(raw_error_code::no_stream);
+ auto ExpectedSN = getNamedStreamIndex("/names");
+ if (!ExpectedSN)
+ return ExpectedSN.takeError();
auto NS = WritableMappedBlockStream::createIndexedStream(Layout, Buffer,
- StringTableStreamNo);
+ *ExpectedSN);
BinaryStreamWriter NSWriter(*NS);
if (auto EC = Strings.commit(NSWriter))
return EC;
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp
new file mode 100644
index 000000000000..e84573fe07b8
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp
@@ -0,0 +1,134 @@
+//===- PDBStringTable.cpp - PDB String Table ---------------------*- 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/Native/PDBStringTable.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/Hash.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/Endian.h"
+
+using namespace llvm;
+using namespace llvm::support;
+using namespace llvm::pdb;
+
+uint32_t PDBStringTable::getByteSize() const { return ByteSize; }
+uint32_t PDBStringTable::getNameCount() const { return NameCount; }
+uint32_t PDBStringTable::getHashVersion() const { return Header->HashVersion; }
+uint32_t PDBStringTable::getSignature() const { return Header->Signature; }
+
+Error PDBStringTable::readHeader(BinaryStreamReader &Reader) {
+ if (auto EC = Reader.readObject(Header))
+ return EC;
+
+ if (Header->Signature != PDBStringTableSignature)
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Invalid hash table signature");
+ if (Header->HashVersion != 1 && Header->HashVersion != 2)
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Unsupported hash version");
+
+ assert(Reader.bytesRemaining() == 0);
+ return Error::success();
+}
+
+Error PDBStringTable::readStrings(BinaryStreamReader &Reader) {
+ BinaryStreamRef Stream;
+ if (auto EC = Reader.readStreamRef(Stream))
+ return EC;
+
+ if (auto EC = Strings.initialize(Stream)) {
+ return joinErrors(std::move(EC),
+ make_error<RawError>(raw_error_code::corrupt_file,
+ "Invalid hash table byte length"));
+ }
+
+ assert(Reader.bytesRemaining() == 0);
+ return Error::success();
+}
+
+Error PDBStringTable::readHashTable(BinaryStreamReader &Reader) {
+ const support::ulittle32_t *HashCount;
+ if (auto EC = Reader.readObject(HashCount))
+ return EC;
+
+ if (auto EC = Reader.readArray(IDs, *HashCount)) {
+ return joinErrors(std::move(EC),
+ make_error<RawError>(raw_error_code::corrupt_file,
+ "Could not read bucket array"));
+ }
+
+ return Error::success();
+}
+
+Error PDBStringTable::readEpilogue(BinaryStreamReader &Reader) {
+ if (auto EC = Reader.readInteger(NameCount))
+ return EC;
+
+ assert(Reader.bytesRemaining() == 0);
+ return Error::success();
+}
+
+Error PDBStringTable::reload(BinaryStreamReader &Reader) {
+
+ BinaryStreamReader SectionReader;
+
+ std::tie(SectionReader, Reader) = Reader.split(sizeof(PDBStringTableHeader));
+ if (auto EC = readHeader(SectionReader))
+ return EC;
+
+ std::tie(SectionReader, Reader) = Reader.split(Header->ByteSize);
+ if (auto EC = readStrings(SectionReader))
+ return EC;
+
+ // We don't know how long the hash table is until we parse it, so let the
+ // function responsible for doing that figure it out.
+ if (auto EC = readHashTable(Reader))
+ return EC;
+
+ std::tie(SectionReader, Reader) = Reader.split(sizeof(uint32_t));
+ if (auto EC = readEpilogue(SectionReader))
+ return EC;
+
+ assert(Reader.bytesRemaining() == 0);
+ return Error::success();
+}
+
+Expected<StringRef> PDBStringTable::getStringForID(uint32_t ID) const {
+ return Strings.getString(ID);
+}
+
+Expected<uint32_t> PDBStringTable::getIDForString(StringRef Str) const {
+ uint32_t Hash =
+ (Header->HashVersion == 1) ? hashStringV1(Str) : hashStringV2(Str);
+ size_t Count = IDs.size();
+ uint32_t Start = Hash % Count;
+ for (size_t I = 0; I < Count; ++I) {
+ // The hash is just a starting point for the search, but if it
+ // doesn't work we should find the string no matter what, because
+ // we iterate the entire array.
+ uint32_t Index = (Start + I) % Count;
+
+ uint32_t ID = IDs[Index];
+ auto ExpectedStr = getStringForID(ID);
+ if (!ExpectedStr)
+ return ExpectedStr.takeError();
+
+ if (*ExpectedStr == Str)
+ return ID;
+ }
+ return make_error<RawError>(raw_error_code::no_entry);
+}
+
+FixedStreamArray<support::ulittle32_t> PDBStringTable::name_ids() const {
+ return IDs;
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp
new file mode 100644
index 000000000000..a472181a4895
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp
@@ -0,0 +1,133 @@
+//===- PDBStringTableBuilder.cpp - PDB String Table -------------*- 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/Native/PDBStringTableBuilder.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/Hash.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Support/Endian.h"
+
+using namespace llvm;
+using namespace llvm::msf;
+using namespace llvm::support;
+using namespace llvm::support::endian;
+using namespace llvm::pdb;
+
+uint32_t PDBStringTableBuilder::insert(StringRef S) {
+ return Strings.insert(S);
+}
+
+static uint32_t computeBucketCount(uint32_t NumStrings) {
+ // The /names stream is basically an on-disk open-addressing hash table.
+ // Hash collisions are resolved by linear probing. We cannot make
+ // utilization 100% because it will make the linear probing extremely
+ // slow. But lower utilization wastes disk space. As a reasonable
+ // load factor, we choose 80%. We need +1 because slot 0 is reserved.
+ return (NumStrings + 1) * 1.25;
+}
+
+uint32_t PDBStringTableBuilder::calculateHashTableSize() const {
+ uint32_t Size = sizeof(uint32_t); // Hash table begins with 4-byte size field.
+ Size += sizeof(uint32_t) * computeBucketCount(Strings.size());
+
+ return Size;
+}
+
+uint32_t PDBStringTableBuilder::calculateSerializedSize() const {
+ uint32_t Size = 0;
+ Size += sizeof(PDBStringTableHeader);
+ Size += Strings.calculateSerializedSize();
+ Size += calculateHashTableSize();
+ Size += sizeof(uint32_t); // The /names stream ends with the string count.
+ return Size;
+}
+
+Error PDBStringTableBuilder::writeHeader(BinaryStreamWriter &Writer) const {
+ // Write a header
+ PDBStringTableHeader H;
+ H.Signature = PDBStringTableSignature;
+ H.HashVersion = 1;
+ H.ByteSize = Strings.calculateSerializedSize();
+ if (auto EC = Writer.writeObject(H))
+ return EC;
+ assert(Writer.bytesRemaining() == 0);
+ return Error::success();
+}
+
+Error PDBStringTableBuilder::writeStrings(BinaryStreamWriter &Writer) const {
+ if (auto EC = Strings.commit(Writer))
+ return EC;
+
+ assert(Writer.bytesRemaining() == 0);
+ return Error::success();
+}
+
+Error PDBStringTableBuilder::writeHashTable(BinaryStreamWriter &Writer) const {
+ // Write a hash table.
+ uint32_t BucketCount = computeBucketCount(Strings.size());
+ if (auto EC = Writer.writeInteger(BucketCount))
+ return EC;
+ std::vector<ulittle32_t> Buckets(BucketCount);
+
+ for (auto &Pair : Strings) {
+ StringRef S = Pair.getKey();
+ uint32_t Offset = Pair.getValue();
+ uint32_t Hash = hashStringV1(S);
+
+ for (uint32_t I = 0; I != BucketCount; ++I) {
+ uint32_t Slot = (Hash + I) % BucketCount;
+ if (Slot == 0)
+ continue; // Skip reserved slot
+ if (Buckets[Slot] != 0)
+ continue;
+ Buckets[Slot] = Offset;
+ break;
+ }
+ }
+
+ if (auto EC = Writer.writeArray(ArrayRef<ulittle32_t>(Buckets)))
+ return EC;
+
+ assert(Writer.bytesRemaining() == 0);
+ return Error::success();
+}
+
+Error PDBStringTableBuilder::writeEpilogue(BinaryStreamWriter &Writer) const {
+ if (auto EC = Writer.writeInteger<uint32_t>(Strings.size()))
+ return EC;
+ assert(Writer.bytesRemaining() == 0);
+ return Error::success();
+}
+
+Error PDBStringTableBuilder::commit(BinaryStreamWriter &Writer) const {
+ BinaryStreamWriter SectionWriter;
+
+ std::tie(SectionWriter, Writer) = Writer.split(sizeof(PDBStringTableHeader));
+ if (auto EC = writeHeader(SectionWriter))
+ return EC;
+
+ std::tie(SectionWriter, Writer) =
+ Writer.split(Strings.calculateSerializedSize());
+ if (auto EC = writeStrings(SectionWriter))
+ return EC;
+
+ std::tie(SectionWriter, Writer) = Writer.split(calculateHashTableSize());
+ if (auto EC = writeHashTable(SectionWriter))
+ return EC;
+
+ std::tie(SectionWriter, Writer) = Writer.split(sizeof(uint32_t));
+ if (auto EC = writeEpilogue(SectionWriter))
+ return EC;
+
+ return Error::success();
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/StringTable.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/StringTable.cpp
deleted file mode 100644
index 7e28389b8383..000000000000
--- a/contrib/llvm/lib/DebugInfo/PDB/Native/StringTable.cpp
+++ /dev/null
@@ -1,109 +0,0 @@
-//===- StringTable.cpp - PDB String Table -----------------------*- 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/Native/StringTable.h"
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/DebugInfo/PDB/Native/Hash.h"
-#include "llvm/DebugInfo/PDB/Native/RawError.h"
-#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
-#include "llvm/Support/BinaryStreamReader.h"
-#include "llvm/Support/Endian.h"
-
-using namespace llvm;
-using namespace llvm::support;
-using namespace llvm::pdb;
-
-StringTable::StringTable() {}
-
-Error StringTable::load(BinaryStreamReader &Stream) {
- ByteSize = Stream.getLength();
-
- const StringTableHeader *H;
- if (auto EC = Stream.readObject(H))
- return EC;
-
- if (H->Signature != StringTableSignature)
- return make_error<RawError>(raw_error_code::corrupt_file,
- "Invalid hash table signature");
- if (H->HashVersion != 1 && H->HashVersion != 2)
- return make_error<RawError>(raw_error_code::corrupt_file,
- "Unsupported hash version");
-
- Signature = H->Signature;
- HashVersion = H->HashVersion;
- if (auto EC = Stream.readStreamRef(NamesBuffer, H->ByteSize))
- return joinErrors(std::move(EC),
- make_error<RawError>(raw_error_code::corrupt_file,
- "Invalid hash table byte length"));
-
- const support::ulittle32_t *HashCount;
- if (auto EC = Stream.readObject(HashCount))
- return EC;
-
- if (auto EC = Stream.readArray(IDs, *HashCount))
- return joinErrors(std::move(EC),
- make_error<RawError>(raw_error_code::corrupt_file,
- "Could not read bucket array"));
-
- if (Stream.bytesRemaining() < sizeof(support::ulittle32_t))
- return make_error<RawError>(raw_error_code::corrupt_file,
- "Missing name count");
-
- if (auto EC = Stream.readInteger(NameCount))
- return EC;
-
- if (Stream.bytesRemaining() > 0)
- return make_error<RawError>(raw_error_code::stream_too_long,
- "Unexpected bytes found in string table");
-
- return Error::success();
-}
-
-uint32_t StringTable::getByteSize() const {
- return ByteSize;
-}
-
-StringRef StringTable::getStringForID(uint32_t ID) const {
- if (ID == IDs[0])
- return StringRef();
-
- // NamesBuffer is a buffer of null terminated strings back to back. ID is
- // 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;
- BinaryStreamReader NameReader(NamesBuffer);
- NameReader.setOffset(ID);
- if (auto EC = NameReader.readCString(Result))
- consumeError(std::move(EC));
- return Result;
-}
-
-uint32_t StringTable::getIDForString(StringRef Str) const {
- uint32_t Hash = (HashVersion == 1) ? hashStringV1(Str) : hashStringV2(Str);
- size_t Count = IDs.size();
- uint32_t Start = Hash % Count;
- for (size_t I = 0; I < Count; ++I) {
- // The hash is just a starting point for the search, but if it
- // doesn't work we should find the string no matter what, because
- // we iterate the entire array.
- uint32_t Index = (Start + I) % Count;
-
- uint32_t ID = IDs[Index];
- StringRef S = getStringForID(ID);
- if (S == Str)
- return ID;
- }
- // IDs[0] contains the ID of the "invalid" entry.
- return IDs[0];
-}
-
-FixedStreamArray<support::ulittle32_t> StringTable::name_ids() const {
- return IDs;
-}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/StringTableBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/StringTableBuilder.cpp
deleted file mode 100644
index e0f8370ab608..000000000000
--- a/contrib/llvm/lib/DebugInfo/PDB/Native/StringTableBuilder.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-//===- StringTableBuilder.cpp - PDB String Table ----------------*- 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/Native/StringTableBuilder.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/DebugInfo/PDB/Native/Hash.h"
-#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
-#include "llvm/Support/BinaryStreamWriter.h"
-#include "llvm/Support/Endian.h"
-
-using namespace llvm;
-using namespace llvm::support;
-using namespace llvm::support::endian;
-using namespace llvm::pdb;
-
-uint32_t StringTableBuilder::insert(StringRef S) {
- auto P = Strings.insert({S, StringSize});
-
- // If a given string didn't exist in the string table, we want to increment
- // the string table size.
- if (P.second)
- StringSize += S.size() + 1; // +1 for '\0'
- return P.first->second;
-}
-
-static uint32_t computeBucketCount(uint32_t NumStrings) {
- // The /names stream is basically an on-disk open-addressing hash table.
- // Hash collisions are resolved by linear probing. We cannot make
- // utilization 100% because it will make the linear probing extremely
- // slow. But lower utilization wastes disk space. As a reasonable
- // load factor, we choose 80%. We need +1 because slot 0 is reserved.
- return (NumStrings + 1) * 1.25;
-}
-
-uint32_t StringTableBuilder::finalize() {
- uint32_t Size = 0;
- Size += sizeof(StringTableHeader);
- Size += StringSize;
- Size += sizeof(uint32_t); // Hash table begins with 4-byte size field.
-
- uint32_t BucketCount = computeBucketCount(Strings.size());
- Size += BucketCount * sizeof(uint32_t);
-
- Size +=
- sizeof(uint32_t); // The /names stream ends with the number of strings.
- return Size;
-}
-
-Error StringTableBuilder::commit(BinaryStreamWriter &Writer) const {
- // Write a header
- StringTableHeader H;
- H.Signature = StringTableSignature;
- H.HashVersion = 1;
- H.ByteSize = StringSize;
- if (auto EC = Writer.writeObject(H))
- return EC;
-
- // Write a string table.
- uint32_t StringStart = Writer.getOffset();
- for (auto Pair : Strings) {
- StringRef S = Pair.first;
- uint32_t Offset = Pair.second;
- Writer.setOffset(StringStart + Offset);
- if (auto EC = Writer.writeCString(S))
- return EC;
- }
- Writer.setOffset(StringStart + StringSize);
-
- // Write a hash table.
- uint32_t BucketCount = computeBucketCount(Strings.size());
- if (auto EC = Writer.writeInteger(BucketCount))
- return EC;
- std::vector<ulittle32_t> Buckets(BucketCount);
-
- for (auto Pair : Strings) {
- StringRef S = Pair.first;
- uint32_t Offset = Pair.second;
- uint32_t Hash = hashStringV1(S);
-
- for (uint32_t I = 0; I != BucketCount; ++I) {
- uint32_t Slot = (Hash + I) % BucketCount;
- if (Slot == 0)
- continue; // Skip reserved slot
- if (Buckets[Slot] != 0)
- continue;
- Buckets[Slot] = Offset;
- break;
- }
- }
-
- if (auto EC = Writer.writeArray(ArrayRef<ulittle32_t>(Buckets)))
- return EC;
- if (auto EC = Writer.writeInteger(static_cast<uint32_t>(Strings.size())))
- return EC;
- return Error::success();
-}
diff --git a/contrib/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp b/contrib/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
index 7e56859c40e6..a41a065a983c 100644
--- a/contrib/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
+++ b/contrib/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
@@ -467,8 +467,9 @@ extern "C" char *__cxa_demangle(const char *mangled_name, char *output_buffer,
size_t *length, int *status);
#endif
-std::string LLVMSymbolizer::DemangleName(const std::string &Name,
- const SymbolizableModule *ModInfo) {
+std::string
+LLVMSymbolizer::DemangleName(const std::string &Name,
+ const SymbolizableModule *DbiModuleDescriptor) {
#if !defined(_MSC_VER)
// We can spoil names of symbols with C linkage, so use an heuristic
// approach to check if the name should be demangled.
@@ -496,7 +497,7 @@ std::string LLVMSymbolizer::DemangleName(const std::string &Name,
return (result == 0) ? Name : std::string(DemangledName);
}
#endif
- if (ModInfo && ModInfo->isWin32Module())
+ if (DbiModuleDescriptor && DbiModuleDescriptor->isWin32Module())
return std::string(demanglePE32ExternCFunc(Name));
return Name;
}