summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/DebugInfo/PDB/Raw/ModInfo.h62
-rw-r--r--llvm/include/llvm/DebugInfo/PDB/Raw/PDBDbiStream.h5
-rw-r--r--llvm/lib/DebugInfo/PDB/CMakeLists.txt1
-rw-r--r--llvm/lib/DebugInfo/PDB/Raw/ModInfo.cpp142
-rw-r--r--llvm/lib/DebugInfo/PDB/Raw/PDBDbiStream.cpp20
-rw-r--r--llvm/test/DebugInfo/PDB/pdbdump-headers.test24
-rw-r--r--llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp23
7 files changed, 275 insertions, 2 deletions
diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/ModInfo.h b/llvm/include/llvm/DebugInfo/PDB/Raw/ModInfo.h
new file mode 100644
index 00000000000..8a7efd0af38
--- /dev/null
+++ b/llvm/include/llvm/DebugInfo/PDB/Raw/ModInfo.h
@@ -0,0 +1,62 @@
+//===- ModInfo.h - PDB module information -----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_RAW_MODINFO_H
+#define LLVM_DEBUGINFO_PDB_RAW_MODINFO_H
+
+#include "llvm/ADT/StringRef.h"
+
+#include <stdint.h>
+
+namespace llvm {
+class PDBFile;
+
+class ModInfo {
+private:
+ struct FileLayout;
+
+public:
+ ModInfo(const uint8_t *Bytes);
+ ~ModInfo();
+
+ bool hasECInfo() const;
+ uint16_t getTypeServerIndex() const;
+ uint16_t getModuleStreamIndex() const;
+ uint32_t getSymbolDebugInfoByteSize() const;
+ uint32_t getLineInfoByteSize() const;
+ uint32_t getC13LineInfoByteSize() const;
+ uint32_t getNumberOfFiles() const;
+ uint32_t getSourceFileNameIndex() const;
+ uint32_t getPdbFilePathNameIndex() const;
+
+ llvm::StringRef getModuleName() const;
+ llvm::StringRef getObjFileName() const;
+
+private:
+ const FileLayout *Layout;
+};
+
+class ModInfoIterator {
+public:
+ ModInfoIterator(const uint8_t *Stream);
+ ModInfoIterator(const ModInfoIterator &Other);
+
+ ModInfo operator*();
+ ModInfoIterator &operator++();
+ ModInfoIterator operator++(int);
+ bool operator==(const ModInfoIterator &Other);
+ bool operator!=(const ModInfoIterator &Other);
+ ModInfoIterator &operator=(const ModInfoIterator &Other);
+
+private:
+ const uint8_t *Bytes;
+};
+}
+
+#endif
diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/PDBDbiStream.h b/llvm/include/llvm/DebugInfo/PDB/Raw/PDBDbiStream.h
index f9d4f30353d..179797f2be8 100644
--- a/llvm/include/llvm/DebugInfo/PDB/Raw/PDBDbiStream.h
+++ b/llvm/include/llvm/DebugInfo/PDB/Raw/PDBDbiStream.h
@@ -11,6 +11,7 @@
#define LLVM_DEBUGINFO_PDB_RAW_PDBDBISTREAM_H
#include "llvm/DebugInfo/PDB/PDBTypes.h"
+#include "llvm/DebugInfo/PDB/Raw/ModInfo.h"
#include "llvm/DebugInfo/PDB/Raw/PDBRawConstants.h"
#include "llvm/DebugInfo/PDB/Raw/PDBStream.h"
#include "llvm/Support/Endian.h"
@@ -42,9 +43,13 @@ public:
PDB_Machine getMachineType() const;
+ llvm::iterator_range<ModInfoIterator> modules() const;
+
private:
PDBFile &Pdb;
PDBStream Stream;
+
+ std::vector<uint8_t> ModInfoSubstream;
std::unique_ptr<HeaderInfo> Header;
};
}
diff --git a/llvm/lib/DebugInfo/PDB/CMakeLists.txt b/llvm/lib/DebugInfo/PDB/CMakeLists.txt
index 24a9e8bf6f5..b98c37bfbc8 100644
--- a/llvm/lib/DebugInfo/PDB/CMakeLists.txt
+++ b/llvm/lib/DebugInfo/PDB/CMakeLists.txt
@@ -27,6 +27,7 @@ if(HAVE_DIA_SDK)
endif()
add_pdb_impl_folder(Raw
+ Raw/ModInfo.cpp
Raw/PDBFile.cpp
Raw/PDBDbiStream.cpp
Raw/PDBInfoStream.cpp
diff --git a/llvm/lib/DebugInfo/PDB/Raw/ModInfo.cpp b/llvm/lib/DebugInfo/PDB/Raw/ModInfo.cpp
new file mode 100644
index 00000000000..4634cb08245
--- /dev/null
+++ b/llvm/lib/DebugInfo/PDB/Raw/ModInfo.cpp
@@ -0,0 +1,142 @@
+//===- ModInfo.cpp - PDB module information -------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Raw/ModInfo.h"
+#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
+#include "llvm/Support/Endian.h"
+
+using namespace llvm;
+using namespace llvm::support;
+
+namespace {
+struct SCBytes {
+ ulittle16_t Section;
+ char Padding1[2];
+ little32_t Offset;
+ little32_t Size;
+ ulittle32_t Characteristics;
+ ulittle16_t ModuleIndex;
+ char Padding2[2];
+ ulittle32_t DataCrc;
+ ulittle32_t RelocCrc;
+};
+
+// struct Flags {
+// uint16_t fWritten : 1; // True if ModInfo is dirty
+// uint16_t fECEnabled : 1; // Is EC symbolic info present? (What is EC?)
+// uint16_t unused : 6; // Reserved
+// uint16_t iTSM : 8; // Type Server Index for this module
+//};
+const uint16_t HasECFlagMask = 0x2;
+
+const uint16_t TypeServerIndexMask = 0xFF00;
+const uint16_t TypeServerIndexShift = 8;
+}
+
+struct ModInfo::FileLayout {
+ ulittle32_t Mod; // Currently opened module. This field is a
+ // pointer in the reference implementation, but
+ // that won't work on 64-bit systems, and anyway
+ // it doesn't make sense to read a pointer from a
+ // file. For now it is unused, so just ignore it.
+ SCBytes SC; // First section contribution of this module.
+ ulittle16_t Flags; // See Flags definition.
+ ulittle16_t ModDiStream; // Stream Number of module debug info
+ ulittle32_t SymBytes; // Size of local symbol debug info in above stream
+ ulittle32_t LineBytes; // Size of line number debug info in above stream
+ ulittle32_t C13Bytes; // Size of C13 line number info in above stream
+ ulittle16_t NumFiles; // Number of files contributing to this module
+ char Padding1[2]; // Padding so the next field is 4-byte aligned.
+ ulittle32_t FileNameOffs; // array of [0..NumFiles) DBI name buffer offsets.
+ // This field is a pointer in the reference
+ // implementation, but as with `Mod`, we ignore it
+ // for now since it is unused.
+ ulittle32_t SrcFileNameNI; // Name Index for src file name
+ ulittle32_t PdbFilePathNI; // Name Index for path to compiler PDB
+ char VarInfo[1]; // Module name followed by Obj File Name
+
+ StringRef getModuleName() const { return StringRef(VarInfo); }
+
+ StringRef getObjectFileName() const {
+ return StringRef(getModuleName().end() + 1);
+ }
+};
+
+ModInfo::ModInfo(const uint8_t *Bytes)
+ : Layout(reinterpret_cast<const FileLayout *>(Bytes)) {}
+
+ModInfo::~ModInfo() {}
+
+bool ModInfo::hasECInfo() const { return (Layout->Flags & HasECFlagMask) != 0; }
+
+uint16_t ModInfo::getTypeServerIndex() const {
+ return (Layout->Flags & TypeServerIndexMask) >> TypeServerIndexShift;
+}
+
+uint16_t ModInfo::getModuleStreamIndex() const { return Layout->ModDiStream; }
+
+uint32_t ModInfo::getSymbolDebugInfoByteSize() const {
+ return Layout->SymBytes;
+}
+
+uint32_t ModInfo::getLineInfoByteSize() const { return Layout->LineBytes; }
+
+uint32_t ModInfo::getC13LineInfoByteSize() const { return Layout->C13Bytes; }
+
+uint32_t ModInfo::getNumberOfFiles() const { return Layout->NumFiles; }
+
+uint32_t ModInfo::getSourceFileNameIndex() const {
+ return Layout->SrcFileNameNI;
+}
+
+uint32_t ModInfo::getPdbFilePathNameIndex() const {
+ return Layout->PdbFilePathNI;
+}
+
+llvm::StringRef ModInfo::getModuleName() const {
+ return Layout->getModuleName();
+}
+
+llvm::StringRef ModInfo::getObjFileName() const {
+ return Layout->getObjectFileName();
+}
+
+ModInfoIterator::ModInfoIterator(const uint8_t *Stream) : Bytes(Stream) {}
+
+ModInfoIterator::ModInfoIterator(const ModInfoIterator &Other)
+ : Bytes(Other.Bytes) {}
+
+ModInfo ModInfoIterator::operator*() { return ModInfo(Bytes); }
+
+ModInfoIterator &ModInfoIterator::operator++() {
+ StringRef Obj = ModInfo(Bytes).getObjFileName();
+ Bytes = Obj.bytes_end() + 1;
+ Bytes = reinterpret_cast<const uint8_t *>(llvm::alignAddr(Bytes, 4));
+
+ return *this;
+}
+
+ModInfoIterator ModInfoIterator::operator++(int) {
+ ModInfoIterator Copy(*this);
+ ++(*this);
+ return Copy;
+}
+
+bool ModInfoIterator::operator==(const ModInfoIterator &Other) {
+ return Bytes == Other.Bytes;
+}
+
+bool ModInfoIterator::operator!=(const ModInfoIterator &Other) {
+ return !(*this == Other);
+}
+
+ModInfoIterator &ModInfoIterator::operator=(const ModInfoIterator &Other) {
+ Bytes = Other.Bytes;
+ return *this;
+}
diff --git a/llvm/lib/DebugInfo/PDB/Raw/PDBDbiStream.cpp b/llvm/lib/DebugInfo/PDB/Raw/PDBDbiStream.cpp
index 40eb567d167..db84192bc36 100644
--- a/llvm/lib/DebugInfo/PDB/Raw/PDBDbiStream.cpp
+++ b/llvm/lib/DebugInfo/PDB/Raw/PDBDbiStream.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/PDB/Raw/PDBDbiStream.h"
+#include "llvm/DebugInfo/PDB/Raw/ModInfo.h"
#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
#include "llvm/DebugInfo/PDB/Raw/PDBInfoStream.h"
#include "llvm/DebugInfo/PDB/Raw/PDBRawConstants.h"
@@ -84,8 +85,10 @@ std::error_code PDBDbiStream::reload() {
if (Header->VersionSignature != -1)
return std::make_error_code(std::errc::illegal_byte_sequence);
- // Prior to VC50 an old style header was used. We don't support this.
- if (Header->VersionHeader < PdbDbiV50)
+ // Require at least version 7, which should be present in all PDBs
+ // produced in the last decade and allows us to avoid having to
+ // special case all kinds of complicated arcane formats.
+ if (Header->VersionHeader < PdbDbiV70)
return std::make_error_code(std::errc::not_supported);
if (Header->Age != Pdb.getPDBInfoStream().getAge())
@@ -98,6 +101,14 @@ std::error_code PDBDbiStream::reload() {
Header->OptionalDbgHdrSize + Header->ECSubstreamSize)
return std::make_error_code(std::errc::illegal_byte_sequence);
+ if (Header->ModiSubstreamSize % sizeof(uint32_t) != 0)
+ return std::make_error_code(std::errc::illegal_byte_sequence);
+
+ ModInfoSubstream.resize(Header->ModiSubstreamSize);
+ if (auto EC =
+ Stream.readBytes(&ModInfoSubstream[0], Header->ModiSubstreamSize))
+ return EC;
+
return std::error_code();
}
@@ -138,3 +149,8 @@ PDB_Machine PDBDbiStream::getMachineType() const {
uint16_t Machine = Header->MachineType;
return static_cast<PDB_Machine>(Machine);
}
+
+llvm::iterator_range<ModInfoIterator> PDBDbiStream::modules() const {
+ return llvm::make_range(ModInfoIterator(&ModInfoSubstream.front()),
+ ModInfoIterator(&ModInfoSubstream.back() + 1));
+}
diff --git a/llvm/test/DebugInfo/PDB/pdbdump-headers.test b/llvm/test/DebugInfo/PDB/pdbdump-headers.test
index 4bb05cb0f8e..1932378fe06 100644
--- a/llvm/test/DebugInfo/PDB/pdbdump-headers.test
+++ b/llvm/test/DebugInfo/PDB/pdbdump-headers.test
@@ -28,3 +28,27 @@
; CHECK-NEXT: Number of Symbols: 8
; CHECK-NEXT: Toolchain Version: 12.0
; CHECK-NEXT: mspdb120.dll version: 12.0.31101
+
+; CHECK: Modules:
+; CHECK-NEXT: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj
+; CHECK-NEXT: Debug Stream Index: 12
+; CHECK-NEXT: Object File: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj
+; CHECK-NEXT: Num Files: 1
+; CHECK-NEXT: Source File Name Idx: 0
+; CHECK-NEXT: Pdb File Name Idx: 0
+; CHECK-NEXT: Line Info Byte Size: 0
+; CHECK-NEXT: C13 Line Info Byte Size: 88
+; CHECK-NEXT: Symbol Byte Size: 208
+; CHECK-NEXT: Type Server Index: 0
+; CHECK-NEXT: Has EC Info: 0
+; CHECK-NEXT: * Linker *
+; CHECK-NEXT: Debug Stream Index: 14
+; CHECK-NEXT: Object File:
+; CHECK-NEXT: Num Files: 0
+; CHECK-NEXT: Source File Name Idx: 0
+; CHECK-NEXT: Pdb File Name Idx: 1
+; CHECK-NEXT: Line Info Byte Size: 0
+; CHECK-NEXT: C13 Line Info Byte Size: 0
+; CHECK-NEXT: Symbol Byte Size: 516
+; CHECK-NEXT: Type Server Index: 0
+; CHECK-NEXT: Has EC Info: 0
diff --git a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
index 4f24e058f21..e051c85c5dc 100644
--- a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
+++ b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
@@ -35,6 +35,7 @@
#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
#include "llvm/DebugInfo/PDB/PDBSymbolThunk.h"
+#include "llvm/DebugInfo/PDB/Raw/ModInfo.h"
#include "llvm/DebugInfo/PDB/Raw/PDBDbiStream.h"
#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
#include "llvm/DebugInfo/PDB/Raw/PDBInfoStream.h"
@@ -278,6 +279,28 @@ static void dumpStructure(RawSession &RS) {
outs() << "Toolchain Version: " << Major << "." << Minor << '\n';
outs() << "mspdb" << Major << Minor << ".dll version: " << Major << "."
<< Minor << "." << DbiStream.getPdbDllVersion() << '\n';
+
+ outs() << "Modules: \n";
+ for (auto Modi : DbiStream.modules()) {
+ outs() << Modi.getModuleName() << '\n';
+ outs().indent(4) << "Debug Stream Index: " << Modi.getModuleStreamIndex()
+ << '\n';
+ outs().indent(4) << "Object File: " << Modi.getObjFileName() << '\n';
+ outs().indent(4) << "Num Files: " << Modi.getNumberOfFiles() << '\n';
+ outs().indent(4) << "Source File Name Idx: "
+ << Modi.getSourceFileNameIndex() << '\n';
+ outs().indent(4) << "Pdb File Name Idx: " << Modi.getPdbFilePathNameIndex()
+ << '\n';
+ outs().indent(4) << "Line Info Byte Size: " << Modi.getLineInfoByteSize()
+ << '\n';
+ outs().indent(4) << "C13 Line Info Byte Size: "
+ << Modi.getC13LineInfoByteSize() << '\n';
+ outs().indent(4) << "Symbol Byte Size: "
+ << Modi.getSymbolDebugInfoByteSize() << '\n';
+ outs().indent(4) << "Type Server Index: " << Modi.getTypeServerIndex()
+ << '\n';
+ outs().indent(4) << "Has EC Info: " << Modi.hasECInfo() << '\n';
+ }
}
static void dumpInput(StringRef Path) {
OpenPOWER on IntegriCloud