aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp
blob: 703ae5d718329ebeef5180a3ed9f53e0d9d34cc0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
//===- TpiStream.cpp - PDB Type Info (TPI) Stream 2 Access ----------------===//
//
//                     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/TpiStream.h"

#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
#include "llvm/DebugInfo/PDB/Raw/StreamReader.h"

#include "llvm/Support/Endian.h"

using namespace llvm;
using namespace llvm::support;
using namespace llvm::pdb;

namespace {
const uint32_t MinTypeIndex = codeview::TypeIndex::FirstNonSimpleIndex;

const uint32_t MinHashBuckets = 0x1000;
const uint32_t MaxHashBuckets = 0x40000;
}

static uint32_t HashBufferV8(uint8_t *buffer, uint32_t NumBuckets) {
  // Not yet implemented, this is probably some variation of CRC32 but we need
  // to be sure of the precise implementation otherwise we won't be able to work
  // with persisted hash values.
  return 0;
}

struct TpiStream::HeaderInfo {
  struct EmbeddedBuf {
    little32_t Off;
    ulittle32_t Length;
  };

  ulittle32_t Version;
  ulittle32_t HeaderSize;
  ulittle32_t TypeIndexBegin;
  ulittle32_t TypeIndexEnd;
  ulittle32_t TypeRecordBytes;

  ulittle16_t HashStreamIndex;
  ulittle16_t HashAuxStreamIndex;
  ulittle32_t HashKeySize;
  ulittle32_t NumHashBuckets;

  EmbeddedBuf HashValueBuffer;
  EmbeddedBuf IndexOffsetBuffer;
  EmbeddedBuf HashAdjBuffer;
};

TpiStream::TpiStream(PDBFile &File)
    : Pdb(File), Stream(StreamTPI, File), HashFunction(nullptr) {}

TpiStream::~TpiStream() {}

std::error_code TpiStream::reload() {
  StreamReader Reader(Stream);

  if (Reader.bytesRemaining() < sizeof(HeaderInfo))
    return std::make_error_code(std::errc::illegal_byte_sequence);

  Header.reset(new HeaderInfo());
  Reader.readObject(Header.get());

  if (Header->Version != PdbTpiV80)
    return std::make_error_code(std::errc::not_supported);

  if (Header->HeaderSize != sizeof(HeaderInfo))
    return std::make_error_code(std::errc::illegal_byte_sequence);

  if (Header->HashKeySize != sizeof(ulittle32_t))
    return std::make_error_code(std::errc::illegal_byte_sequence);

  if (Header->NumHashBuckets < MinHashBuckets ||
      Header->NumHashBuckets > MaxHashBuckets)
    return std::make_error_code(std::errc::illegal_byte_sequence);

  HashFunction = HashBufferV8;

  // The actual type records themselves come from this stream
  RecordsBuffer.initialize(Reader, Header->TypeRecordBytes);

  // Hash indices, hash values, etc come from the hash stream.
  MappedBlockStream HS(Header->HashStreamIndex, Pdb);
  StreamReader HSR(HS);
  HSR.setOffset(Header->HashValueBuffer.Off);
  HashValuesBuffer.initialize(HSR, Header->HashValueBuffer.Length);

  HSR.setOffset(Header->HashAdjBuffer.Off);
  HashAdjBuffer.initialize(HSR, Header->HashAdjBuffer.Length);

  HSR.setOffset(Header->IndexOffsetBuffer.Off);
  TypeIndexOffsetBuffer.initialize(HSR, Header->IndexOffsetBuffer.Length);

  return std::error_code();
}

PdbRaw_TpiVer TpiStream::getTpiVersion() const {
  uint32_t Value = Header->Version;
  return static_cast<PdbRaw_TpiVer>(Value);
}

uint32_t TpiStream::TypeIndexBegin() const { return Header->TypeIndexBegin; }

uint32_t TpiStream::TypeIndexEnd() const { return Header->TypeIndexEnd; }

uint32_t TpiStream::NumTypeRecords() const {
  return TypeIndexEnd() - TypeIndexBegin();
}

iterator_range<codeview::TypeIterator> TpiStream::types() const {
  return codeview::makeTypeRange(RecordsBuffer.str());
}