<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Mon, May 2, 2016 at 5:28 PM, Zachary Turner via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Author: zturner<br>
Date: Mon May  2 19:28:21 2016<br>
New Revision: 268343<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=268343&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=268343&view=rev</a><br>
Log:<br>
Parse the TPI (type information) stream of PDB files.<br>
<br>
This parses the TPI stream (stream 2) from the PDB file. This stream<br>
contains some header information followed by a series of codeview records.<br>
There is some additional complexity here in that alongside this stream of<br>
codeview records is a serialized hash table in order to efficiently query<br>
the types. We parse the necessary bookkeeping information to allow us to<br>
reconstruct the hash table, but we do not actually construct it yet as<br>
there are still a few things that need to be understood first.<br>
<br>
Differential Revision: <a href="http://reviews.llvm.org/D19840" rel="noreferrer" target="_blank">http://reviews.llvm.org/D19840</a><br>
Reviewed By: ruiu, rnk<br>
<br>
Added:<br>
    llvm/trunk/include/llvm/DebugInfo/PDB/Raw/TpiStream.h<br>
    llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp<br>
Modified:<br>
    llvm/trunk/include/llvm/DebugInfo/PDB/Raw/ByteStream.h<br>
    llvm/trunk/include/llvm/DebugInfo/PDB/Raw/MappedBlockStream.h<br>
    llvm/trunk/include/llvm/DebugInfo/PDB/Raw/PDBFile.h<br>
    llvm/trunk/include/llvm/DebugInfo/PDB/Raw/RawConstants.h<br>
    llvm/trunk/include/llvm/DebugInfo/PDB/Raw/StreamInterface.h<br>
    llvm/trunk/include/llvm/DebugInfo/PDB/Raw/StreamReader.h<br>
    llvm/trunk/lib/DebugInfo/PDB/CMakeLists.txt<br>
    llvm/trunk/lib/DebugInfo/PDB/Raw/ByteStream.cpp<br>
    llvm/trunk/lib/DebugInfo/PDB/Raw/MappedBlockStream.cpp<br>
    llvm/trunk/lib/DebugInfo/PDB/Raw/PDBFile.cpp<br>
    llvm/trunk/lib/DebugInfo/PDB/Raw/StreamReader.cpp<br>
    llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test<br>
    llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp<br>
<br>
Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Raw/ByteStream.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Raw/ByteStream.h?rev=268343&r1=268342&r2=268343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Raw/ByteStream.h?rev=268343&r1=268342&r2=268343&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/DebugInfo/PDB/Raw/ByteStream.h (original)<br>
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Raw/ByteStream.h Mon May  2 19:28:21 2016<br>
@@ -35,6 +35,10 @@ public:<br>
<br>
   std::error_code readBytes(uint32_t Offset,<br>
                             MutableArrayRef<uint8_t> Buffer) const override;<br>
+<br>
+  std::error_code getArrayRef(uint32_t Offset, ArrayRef<uint8_t> &Buffer,<br>
+                              uint32_t Length) const override;<br>
+<br>
   uint32_t getLength() const override;<br>
<br>
   ArrayRef<uint8_t> data() const { return Data; }<br>
<br>
Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Raw/MappedBlockStream.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Raw/MappedBlockStream.h?rev=268343&r1=268342&r2=268343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Raw/MappedBlockStream.h?rev=268343&r1=268342&r2=268343&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/DebugInfo/PDB/Raw/MappedBlockStream.h (original)<br>
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Raw/MappedBlockStream.h Mon May  2 19:28:21 2016<br>
@@ -27,6 +27,9 @@ public:<br>
<br>
   std::error_code readBytes(uint32_t Offset,<br>
                             MutableArrayRef<uint8_t> Buffer) const override;<br>
+  std::error_code getArrayRef(uint32_t Offset, ArrayRef<uint8_t> &Buffer,<br>
+                              uint32_t Length) const override;<br>
+<br>
   uint32_t getLength() const override { return StreamLength; }<br>
<br>
 private:<br>
<br>
Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Raw/PDBFile.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Raw/PDBFile.h?rev=268343&r1=268342&r2=268343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Raw/PDBFile.h?rev=268343&r1=268342&r2=268343&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/DebugInfo/PDB/Raw/PDBFile.h (original)<br>
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Raw/PDBFile.h Mon May  2 19:28:21 2016<br>
@@ -23,6 +23,7 @@ namespace pdb {<br>
 struct PDBFileContext;<br>
 class DbiStream;<br>
 class InfoStream;<br>
+class TpiStream;<br>
<br>
 class PDBFile {<br>
 public:<br>
@@ -59,11 +60,13 @@ public:<br>
<br>
   InfoStream &getPDBInfoStream();<br>
   DbiStream &getPDBDbiStream();<br>
+  TpiStream &getPDBTpiStream();<br>
<br>
 private:<br>
   std::unique_ptr<PDBFileContext> Context;<br>
   std::unique_ptr<InfoStream> Info;<br>
   std::unique_ptr<DbiStream> Dbi;<br>
+  std::unique_ptr<TpiStream> Tpi;<br>
 };<br>
 }<br>
 }<br>
<br>
Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Raw/RawConstants.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Raw/RawConstants.h?rev=268343&r1=268342&r2=268343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Raw/RawConstants.h?rev=268343&r1=268342&r2=268343&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/DebugInfo/PDB/Raw/RawConstants.h (original)<br>
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Raw/RawConstants.h Mon May  2 19:28:21 2016<br>
@@ -35,6 +35,14 @@ enum PdbRaw_DbiVer : uint32_t {<br>
   PdbDbiV110 = 20091201<br>
 };<br>
<br>
+enum PdbRaw_TpiVer : uint32_t {<br>
+  PdbTpiV40 = 19950410,<br>
+  PdbTpiV41 = 19951122,<br>
+  PdbTpiV50 = 19961031,<br>
+  PdbTpiV70 = 19990903,<br>
+  PdbTpiV80 = 20040203,<br>
+};<br>
+<br>
 enum SpecialStream : uint32_t {<br>
   StreamPDB = 1,<br>
   StreamTPI = 2,<br>
<br>
Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Raw/StreamInterface.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Raw/StreamInterface.h?rev=268343&r1=268342&r2=268343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Raw/StreamInterface.h?rev=268343&r1=268342&r2=268343&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/DebugInfo/PDB/Raw/StreamInterface.h (original)<br>
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Raw/StreamInterface.h Mon May  2 19:28:21 2016<br>
@@ -23,6 +23,10 @@ public:<br>
<br>
   virtual std::error_code readBytes(uint32_t Offset,<br>
                                     MutableArrayRef<uint8_t> Buffer) const = 0;<br>
+  virtual std::error_code getArrayRef(uint32_t Offset,<br>
+                                      ArrayRef<uint8_t> &Buffer,<br>
+                                      uint32_t Length) const = 0;<br>
+<br>
   virtual uint32_t getLength() const = 0;<br>
 };<br>
 }<br>
<br>
Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Raw/StreamReader.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Raw/StreamReader.h?rev=268343&r1=268342&r2=268343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Raw/StreamReader.h?rev=268343&r1=268342&r2=268343&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/DebugInfo/PDB/Raw/StreamReader.h (original)<br>
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Raw/StreamReader.h Mon May  2 19:28:21 2016<br>
@@ -39,6 +39,8 @@ public:<br>
     return readBytes(Casted);<br>
   }<br>
<br>
+  std::error_code getArrayRef(ArrayRef<uint8_t> &Array, uint32_t Length);<br>
+<br>
   void setOffset(uint32_t Off) { Offset = Off; }<br>
   uint32_t getOffset() const { return Offset; }<br>
   uint32_t getLength() const { return Stream.getLength(); }<br>
<br>
Added: llvm/trunk/include/llvm/DebugInfo/PDB/Raw/TpiStream.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Raw/TpiStream.h?rev=268343&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Raw/TpiStream.h?rev=268343&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/DebugInfo/PDB/Raw/TpiStream.h (added)<br>
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Raw/TpiStream.h Mon May  2 19:28:21 2016<br>
@@ -0,0 +1,62 @@<br>
+//===- TpiStream.cpp - PDB Type Info (TPI) Stream 2 Access ------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBTPISTREAM_H<br>
+#define LLVM_DEBUGINFO_PDB_RAW_PDBTPISTREAM_H<br>
+<br>
+#include "llvm/DebugInfo/PDB/PDBTypes.h"<br>
+#include "llvm/DebugInfo/PDB/Raw/ByteStream.h"<br>
+#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"<br>
+#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"<br>
+<br>
+namespace llvm {<br>
+namespace pdb {<br>
+class PDBFile;<br>
+<br>
+typedef uint32_t (*HashFunctionType)(uint8_t *, uint32_t);<br>
+<br>
+class TpiStream {<br>
+  struct HeaderInfo;<br>
+<br>
+public:<br>
+  struct HashedTypeRecord {<br>
+    uint32_t Hash;<br>
+    codeview::TypeLeafKind Kind;<br>
+    ArrayRef<uint8_t> Record;<br>
+  };<br>
+<br>
+  TpiStream(PDBFile &File);<br>
+  ~TpiStream();<br>
+  std::error_code reload();<br>
+<br>
+  PdbRaw_TpiVer getTpiVersion() const;<br>
+<br>
+  uint32_t TypeIndexBegin() const;<br>
+  uint32_t TypeIndexEnd() const;<br>
+  uint32_t NumTypeRecords() const;<br>
+<br>
+  ArrayRef<HashedTypeRecord> records() const;<br>
+<br>
+private:<br>
+  PDBFile &Pdb;<br>
+  MappedBlockStream Stream;<br>
+  HashFunctionType HashFunction;<br>
+<br>
+  ByteStream RecordsBuffer;<br>
+  ByteStream TypeIndexOffsetBuffer;<br>
+  ByteStream HashValuesBuffer;<br>
+  ByteStream HashAdjBuffer;<br>
+<br>
+  std::vector<HashedTypeRecord> TypeRecords;<br>
+  std::unique_ptr<HeaderInfo> Header;<br>
+};<br>
+}<br>
+}<br>
+<br>
+#endif<br>
<br>
Modified: llvm/trunk/lib/DebugInfo/PDB/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/CMakeLists.txt?rev=268343&r1=268342&r2=268343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/CMakeLists.txt?rev=268343&r1=268342&r2=268343&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/DebugInfo/PDB/CMakeLists.txt (original)<br>
+++ llvm/trunk/lib/DebugInfo/PDB/CMakeLists.txt Mon May  2 19:28:21 2016<br>
@@ -36,7 +36,8 @@ add_pdb_impl_folder(Raw<br>
   Raw/NameHashTable.cpp<br>
   Raw/NameMap.cpp<br>
   Raw/RawSession.cpp<br>
-  Raw/StreamReader.cpp)<br>
+  Raw/StreamReader.cpp<br>
+  Raw/TpiStream.cpp)<br>
<br>
 list(APPEND LIBPDB_ADDITIONAL_HEADER_DIRS "${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/PDB")<br>
<br>
<br>
Modified: llvm/trunk/lib/DebugInfo/PDB/Raw/ByteStream.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Raw/ByteStream.cpp?rev=268343&r1=268342&r2=268343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Raw/ByteStream.cpp?rev=268343&r1=268342&r2=268343&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/DebugInfo/PDB/Raw/ByteStream.cpp (original)<br>
+++ llvm/trunk/lib/DebugInfo/PDB/Raw/ByteStream.cpp Mon May  2 19:28:21 2016<br>
@@ -58,6 +58,15 @@ std::error_code ByteStream::readBytes(ui<br>
   return std::error_code();<br>
 }<br>
<br>
+std::error_code ByteStream::getArrayRef(uint32_t Offset,<br>
+                                        ArrayRef<uint8_t> &Buffer,<br>
+                                        uint32_t Length) const {<br>
+  if (Data.size() < Length + Offset)<br>
+    return std::make_error_code(std::errc::bad_address);<br>
+  Buffer = Data.slice(Offset, Length);<br>
+  return std::error_code();<br>
+}<br>
+<br>
 uint32_t ByteStream::getLength() const { return Data.size(); }<br>
<br>
 StringRef ByteStream::str() const {<br>
<br>
Modified: llvm/trunk/lib/DebugInfo/PDB/Raw/MappedBlockStream.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Raw/MappedBlockStream.cpp?rev=268343&r1=268342&r2=268343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Raw/MappedBlockStream.cpp?rev=268343&r1=268342&r2=268343&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/DebugInfo/PDB/Raw/MappedBlockStream.cpp (original)<br>
+++ llvm/trunk/lib/DebugInfo/PDB/Raw/MappedBlockStream.cpp Mon May  2 19:28:21 2016<br>
@@ -51,3 +51,9 @@ MappedBlockStream::readBytes(uint32_t Of<br>
<br>
   return std::error_code();<br>
 }<br>
+<br>
+std::error_code MappedBlockStream::getArrayRef(uint32_t Offset,<br>
+                                               ArrayRef<uint8_t> &Buffer,<br>
+                                               uint32_t Length) const {<br>
+  return std::make_error_code(std::errc::operation_not_supported);<br>
+}<br>
<br>
Modified: llvm/trunk/lib/DebugInfo/PDB/Raw/PDBFile.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Raw/PDBFile.cpp?rev=268343&r1=268342&r2=268343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Raw/PDBFile.cpp?rev=268343&r1=268342&r2=268343&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/DebugInfo/PDB/Raw/PDBFile.cpp (original)<br>
+++ llvm/trunk/lib/DebugInfo/PDB/Raw/PDBFile.cpp Mon May  2 19:28:21 2016<br>
@@ -11,6 +11,7 @@<br>
 #include "llvm/ADT/ArrayRef.h"<br>
 #include "llvm/DebugInfo/PDB/Raw/DbiStream.h"<br>
 #include "llvm/DebugInfo/PDB/Raw/InfoStream.h"<br>
+#include "llvm/DebugInfo/PDB/Raw/TpiStream.h"<br>
 #include "llvm/Support/Endian.h"<br>
 #include "llvm/Support/MemoryBuffer.h"<br>
<br>
@@ -119,6 +120,8 @@ StringRef PDBFile::getBlockData(uint32_t<br>
 std::error_code PDBFile::parseFileHeaders() {<br>
   std::error_code EC;<br>
   MemoryBufferRef BufferRef = *Context->Buffer;<br>
+  // Make sure the file is sufficiently large to hold a super block.<br>
+  // Do this before attempting to read the super block.<br>
   if (BufferRef.getBufferSize() < sizeof(SuperBlock))<br>
     return std::make_error_code(std::errc::illegal_byte_sequence);<br>
<br>
@@ -135,10 +138,6 @@ std::error_code PDBFile::parseFileHeader<br>
   if (BufferRef.getBufferSize() % SB->BlockSize != 0)<br>
     return std::make_error_code(std::errc::illegal_byte_sequence);<br>
<br>
-  // Make sure the file is sufficiently large to hold a super block.<br>
-  if (BufferRef.getBufferSize() < sizeof(SuperBlock))<br>
-    return std::make_error_code(std::errc::illegal_byte_sequence);<br>
-<br>
   // Check the magic bytes.<br>
   if (memcmp(SB->MagicBytes, Magic, sizeof(Magic)) != 0)<br>
     return std::make_error_code(std::errc::illegal_byte_sequence);<br>
@@ -271,3 +270,11 @@ DbiStream &PDBFile::getPDBDbiStream() {<br>
   }<br>
   return *Dbi;<br>
 }<br>
+<br>
+TpiStream &PDBFile::getPDBTpiStream() {<br>
+  if (!Tpi) {<br>
+    Tpi.reset(new TpiStream(*this));<br>
+    Tpi->reload();<br>
+  }<br>
+  return *Tpi;<br>
+}<br>
<br>
Modified: llvm/trunk/lib/DebugInfo/PDB/Raw/StreamReader.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Raw/StreamReader.cpp?rev=268343&r1=268342&r2=268343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Raw/StreamReader.cpp?rev=268343&r1=268342&r2=268343&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/DebugInfo/PDB/Raw/StreamReader.cpp (original)<br>
+++ llvm/trunk/lib/DebugInfo/PDB/Raw/StreamReader.cpp Mon May  2 19:28:21 2016<br>
@@ -39,3 +39,11 @@ std::error_code StreamReader::readZeroSt<br>
   } while (C != '\0');<br>
   return std::error_code();<br>
 }<br>
+<br>
+std::error_code StreamReader::getArrayRef(ArrayRef<uint8_t> &Array,<br>
+                                          uint32_t Length) {<br>
+  if (auto EC = Stream.getArrayRef(Offset, Array, Length))<br>
+    return EC;<br>
+  Offset += Length;<br>
+  return std::error_code();<br>
+}<br>
<br>
Added: llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp?rev=268343&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp?rev=268343&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp (added)<br>
+++ llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp Mon May  2 19:28:21 2016<br>
@@ -0,0 +1,143 @@<br>
+//===- TpiStream.cpp - PDB Type Info (TPI) Stream 2 Access ----------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "llvm/DebugInfo/PDB/Raw/TpiStream.h"<br>
+<br>
+#include "llvm/DebugInfo/CodeView/CodeView.h"<br>
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"<br>
+#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"<br>
+#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"<br>
+#include "llvm/DebugInfo/PDB/Raw/StreamReader.h"<br>
+<br>
+#include "llvm/Support/Endian.h"<br>
+<br>
+using namespace llvm;<br>
+using namespace llvm::support;<br>
+using namespace llvm::pdb;<br>
+<br>
+namespace {<br>
+const uint32_t MinTypeIndex = codeview::TypeIndex::FirstNonSimpleIndex;<br>
+<br>
+const uint32_t MinHashBuckets = 0x1000;<br>
+const uint32_t MaxHashBuckets = 0x40000;<br>
+}<br>
+<br>
+static uint32_t HashBufferV8(uint8_t *buffer, uint32_t NumBuckets) {<br>
+  // Not yet implemented, this is probably some variation of CRC32 but we need<br>
+  // to be sure of the precise implementation otherwise we won't be able to work<br>
+  // with persisted hash values.<br>
+  return 0;<br>
+}<br>
+<br>
+struct TpiStream::HeaderInfo {<br>
+  struct EmbeddedBuf {<br>
+    little32_t Off;<br>
+    ulittle32_t Length;<br>
+  };<br>
+<br>
+  ulittle32_t Version;<br>
+  ulittle32_t HeaderSize;<br>
+  ulittle32_t TypeIndexBegin;<br>
+  ulittle32_t TypeIndexEnd;<br>
+  ulittle32_t TypeRecordBytes;<br>
+<br>
+  ulittle16_t HashStreamIndex;<br>
+  ulittle16_t HashAuxStreamIndex;<br>
+  ulittle32_t HashKeySize;<br>
+  ulittle32_t NumHashBuckets;<br>
+<br>
+  EmbeddedBuf HashValueBuffer;<br>
+  EmbeddedBuf IndexOffsetBuffer;<br>
+  EmbeddedBuf HashAdjBuffer;<br>
+};<br>
+<br>
+TpiStream::TpiStream(PDBFile &File)<br>
+    : Pdb(File), Stream(StreamTPI, File), HashFunction(nullptr) {}<br>
+<br>
+TpiStream::~TpiStream() {}<br>
+<br>
+std::error_code TpiStream::reload() {<br>
+  StreamReader Reader(Stream);<br>
+<br>
+  if (Reader.bytesRemaining() < sizeof(HeaderInfo))<br>
+    return std::make_error_code(std::errc::illegal_byte_sequence);<br>
+<br>
+  Header.reset(new HeaderInfo());<br>
+  Reader.readObject(Header.get());<br>
+<br>
+  if (Header->Version != PdbTpiV80)<br>
+    return std::make_error_code(std::errc::not_supported);<br>
+<br>
+  if (Header->HeaderSize != sizeof(HeaderInfo))<br>
+    return std::make_error_code(std::errc::illegal_byte_sequence);<br>
+<br>
+  if (Header->HashKeySize != sizeof(ulittle32_t))<br>
+    return std::make_error_code(std::errc::illegal_byte_sequence);<br>
+<br>
+  if (Header->NumHashBuckets < MinHashBuckets ||<br>
+      Header->NumHashBuckets > MaxHashBuckets)<br>
+    return std::make_error_code(std::errc::illegal_byte_sequence);<br>
+<br>
+  HashFunction = HashBufferV8;<br>
+<br>
+  // The actual type records themselves come from this stream<br>
+  RecordsBuffer.initialize(Reader, Header->TypeRecordBytes);<br>
+  TypeRecords.resize(TypeIndexEnd() - ::MinTypeIndex);<br>
+  StreamReader RecordsReader(RecordsBuffer);<br>
+  for (uint32_t I = TypeIndexBegin(); I < TypeIndexEnd(); ++I) {<br>
+    HashedTypeRecord &Record = TypeRecords[I - ::MinTypeIndex];<br>
+    codeview::TypeRecordPrefix Prefix;<br>
+    if (auto EC = RecordsReader.readObject(&Prefix))<br>
+      return EC;<br>
+<br>
+    Record.Kind =<br>
+        static_cast<codeview::TypeLeafKind>(static_cast<uint16_t>(Prefix.Leaf));<br>
+<br>
+    // Since we read this entire buffer into a ByteStream, we are guaranteed<br>
+    // that the entire buffer is contiguous (i.e. there's no longer a chance<br>
+    // that it splits across a page boundary.  So we can request a reference<br>
+    // directly into the stream buffer to avoid unnecessary memory copies.<br>
+    uint32_t RecordSize = Prefix.Len - sizeof(Prefix.Leaf);<br>
+    if (auto EC = RecordsReader.getArrayRef(Record.Record, RecordSize))<br>
+      return EC;<br>
+  }<br>
+<br>
+  // Hash indices, hash values, etc come from the hash stream.<br>
+  MappedBlockStream HS(Header->HashStreamIndex, Pdb);<br>
+  StreamReader HSR(HS);<br>
+  HSR.setOffset(Header->HashValueBuffer.Off);<br>
+  HashValuesBuffer.initialize(HSR, Header->HashValueBuffer.Length);<br>
+<br>
+  HSR.setOffset(Header->HashAdjBuffer.Off);<br>
+  HashAdjBuffer.initialize(HSR, Header->HashAdjBuffer.Length);<br>
+<br>
+  HSR.setOffset(Header->IndexOffsetBuffer.Off);<br>
+  TypeIndexOffsetBuffer.initialize(HSR, Header->IndexOffsetBuffer.Length);<br>
+<br>
+  return std::error_code();<br>
+}<br>
+<br>
+PdbRaw_TpiVer TpiStream::getTpiVersion() const {<br>
+  uint32_t Value = Header->Version;<br>
+  return static_cast<PdbRaw_TpiVer>(Value);<br>
+}<br>
+<br>
+uint32_t TpiStream::TypeIndexBegin() const { return Header->TypeIndexBegin; }<br>
+<br>
+uint32_t TpiStream::TypeIndexEnd() const { return Header->TypeIndexEnd; }<br>
+<br>
+uint32_t TpiStream::NumTypeRecords() const {<br>
+  return TypeIndexEnd() - TypeIndexBegin();<br>
+}<br>
+<br>
+ArrayRef<TpiStream::HashedTypeRecord> TpiStream::records() const {<br>
+  const HashedTypeRecord *Begin =<br>
+      &TypeRecords[TypeIndexBegin() - ::MinTypeIndex];<br>
+  return ArrayRef<HashedTypeRecord>(Begin, NumTypeRecords());<br>
+}<br>
<br>
Modified: llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test?rev=268343&r1=268342&r2=268343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test?rev=268343&r1=268342&r2=268343&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test (original)<br>
+++ llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test Mon May  2 19:28:21 2016<br>
@@ -62,6 +62,15 @@<br>
 ; EMPTY-NEXT:     Type Server Index: 0<br>
 ; EMPTY-NEXT:     Has EC Info: 0<br>
 ; EMPTY-NEXT:     0 Contributing Source Files:<br>
+; EMPTY-NEXT: TPI Version: 20040203<br>
+; EMPTY-NEXT: Record count: 75<br>
+; EMPTY-NEXT:   Kind: 0x4609  Bytes: [00 00 00 00]<br>
+; EMPTY-NEXT:   Kind: 0x4104  Bytes: [74 00 00 00 00 00 00 00 00 10 00 00]<br>
+; EMPTY-NEXT:   Kind: 0x4611  Bytes: [02 15 03 00 01 00 61 70 61 72 74 6D 65 6E 74 00<br>
+; EMPTY-NEXT:                         02 15 03 00 02 00 73 69 6E 67 6C 65 00 F3 F2 F1<br>
+; EMPTY-NEXT:                         02 15 03 00 03 00 66 72 65 65 00 F1 02 15 03 00<br>
+; EMPTY-NEXT:                         04 00 6E 65 75 74 72 61 6C 00 F2 F1 02 15 03 00<br>
+; EMPTY-NEXT:                         05 00 62 6F 74 68 00 F1]<br>
<br>
 BIG:      BlockSize: 4096<br>
 BIG-NEXT: Unknown0: 2<br>
<br>
Modified: llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp?rev=268343&r1=268342&r2=268343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp?rev=268343&r1=268342&r2=268343&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp (original)<br>
+++ llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp Mon May  2 19:28:21 2016<br>
@@ -43,6 +43,7 @@<br>
 #include "llvm/DebugInfo/PDB/Raw/PDBFile.h"<br>
 #include "llvm/DebugInfo/PDB/Raw/RawSession.h"<br>
 #include "llvm/DebugInfo/PDB/Raw/StreamReader.h"<br>
+#include "llvm/DebugInfo/PDB/Raw/TpiStream.h"<br>
 #include "llvm/Support/CommandLine.h"<br>
 #include "llvm/Support/ConvertUTF.h"<br>
 #include "llvm/Support/FileSystem.h"<br>
@@ -148,6 +149,29 @@ cl::opt<bool> NoEnumDefs("no-enum-defini<br>
                          cl::cat(FilterCategory));<br>
 }<br>
<br>
+static void dumpBytes(raw_ostream &S, ArrayRef<uint8_t> Bytes,<br>
+                      uint32_t BytesPerRow, uint32_t Indent) {<br>
+  S << "[";<br>
+  uint32_t I = 0;<br>
+<br>
+  uint32_t BytesRemaining = Bytes.size();<br>
+  while (BytesRemaining > 0) {<br>
+    uint32_t BytesThisLine = std::min(BytesRemaining, BytesPerRow);<br>
+    for (size_t L = 0; L < BytesThisLine; ++L, ++I) {<br>
+      S << format_hex_no_prefix(Bytes[I], 2, true);<br>
+      if (L + 1 < BytesThisLine)<br>
+        S << ' ';<br>
+    }<br>
+    BytesRemaining -= BytesThisLine;<br>
+    if (BytesRemaining > 0) {<br>
+      S << '\n';<br>
+      S.indent(Indent);<br>
+    }<br>
+  }<br>
+  S << ']';<br>
+  S.flush();<br>
+}<br></blockquote><div><br></div><div>Could this reuse ScopedPrinter via it's printBinaryBlock?</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+<br>
 static void dumpStructure(RawSession &RS) {<br>
   PDBFile &File = RS.getPDBFile();<br>
<br>
@@ -293,6 +317,16 @@ static void dumpStructure(RawSession &RS<br>
       outs().indent(8) << File << '\n';<br>
     }<br>
   }<br>
+<br>
+  TpiStream &Tpi = File.getPDBTpiStream();<br>
+  outs() << "TPI Version: " << Tpi.getTpiVersion() << '\n';<br>
+  outs() << "Record count: " << Tpi.NumTypeRecords() << '\n';<br>
+  for (auto &Record : Tpi.records()) {<br>
+    outs().indent(2) << "Kind: 0x" << Record.Kind;<br>
+    outs().indent(2) << "Bytes: ";<br>
+    dumpBytes(outs(), Record.Record, 16, 24);<br>
+    outs() << '\n';<br>
+  }<br>
 }<br>
<br>
 static void reportError(StringRef Path, PDB_ErrorCode Error) {<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div></div>