blob: 40eb567d1679d76591496fbd79eb6d2103e2dbe5 [file] [log] [blame]
Zachary Turner53a65ba2016-04-26 18:42:34 +00001//===- PDBDbiStream.cpp - PDB Dbi Stream (Stream 3) Access ----------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "llvm/DebugInfo/PDB/Raw/PDBDbiStream.h"
11#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
12#include "llvm/DebugInfo/PDB/Raw/PDBInfoStream.h"
13#include "llvm/DebugInfo/PDB/Raw/PDBRawConstants.h"
14
15using namespace llvm;
16using namespace llvm::support;
17
18namespace {
19// Some of the values are stored in bitfields. Since this needs to be portable
20// across compilers and architectures (big / little endian in particular) we
21// can't use the actual structures below, but must instead do the shifting
22// and masking ourselves. The struct definitions are provided for reference.
23
24// struct DbiFlags {
25// uint16_t IncrementalLinking : 1; // True if linked incrementally
26// uint16_t IsStripped : 1; // True if private symbols were stripped.
27// uint16_t HasCTypes : 1; // True if linked with /debug:ctypes.
28// uint16_t Reserved : 13;
29//};
30const uint16_t FlagIncrementalMask = 0x0001;
31const uint16_t FlagStrippedMask = 0x0002;
32const uint16_t FlagHasCTypesMask = 0x0004;
33
34// struct DbiBuildNo {
35// uint16_t MinorVersion : 8;
36// uint16_t MajorVersion : 7;
37// uint16_t NewVersionFormat : 1;
38//};
39const uint16_t BuildMinorMask = 0x00FF;
40const uint16_t BuildMinorShift = 0;
41
42const uint16_t BuildMajorMask = 0x7F00;
43const uint16_t BuildMajorShift = 8;
Zachary Turner53a65ba2016-04-26 18:42:34 +000044}
45
46struct PDBDbiStream::HeaderInfo {
Zachary Turnerff788aa2016-04-26 19:24:10 +000047 little32_t VersionSignature;
Zachary Turner53a65ba2016-04-26 18:42:34 +000048 ulittle32_t VersionHeader;
49 ulittle32_t Age; // Should match PDBInfoStream.
50 ulittle16_t GSSyms;
51 ulittle16_t BuildNumber; // See DbiBuildNo structure.
52 ulittle16_t PSSyms;
53 ulittle16_t PdbDllVersion; // version of mspdbNNN.dll
54 ulittle16_t SymRecords; // Number of symbols
55 ulittle16_t PdbDllRbld; // rbld number of mspdbNNN.dll
56 little32_t ModiSubstreamSize; // Size of module info stream
57 little32_t SecContrSubstreamSize; // Size of sec. contribution stream
58 little32_t SectionMapSize;
59 little32_t FileInfoSize;
60 little32_t TypeServerSize; // Size of type server map
61 ulittle32_t MFCTypeServerIndex; // Index of MFC Type Server
62 little32_t OptionalDbgHdrSize; // Size of DbgHeader info
63 little32_t ECSubstreamSize; // Size of EC stream (what is EC?)
64 ulittle16_t Flags; // See DbiFlags enum.
65 ulittle16_t MachineType; // See PDB_MachineType enum.
66
67 ulittle32_t Reserved; // Pad to 64 bytes
68};
69
70PDBDbiStream::PDBDbiStream(PDBFile &File) : Pdb(File), Stream(3, File) {
71 static_assert(sizeof(HeaderInfo) == 64, "Invalid HeaderInfo size!");
72}
73
74PDBDbiStream::~PDBDbiStream() {}
75
76std::error_code PDBDbiStream::reload() {
77 Stream.setOffset(0);
78 Header.reset(new HeaderInfo());
79
80 if (Stream.getLength() < sizeof(HeaderInfo))
81 return std::make_error_code(std::errc::illegal_byte_sequence);
82 Stream.readObject(Header.get());
83
84 if (Header->VersionSignature != -1)
85 return std::make_error_code(std::errc::illegal_byte_sequence);
86
87 // Prior to VC50 an old style header was used. We don't support this.
88 if (Header->VersionHeader < PdbDbiV50)
89 return std::make_error_code(std::errc::not_supported);
90
91 if (Header->Age != Pdb.getPDBInfoStream().getAge())
92 return std::make_error_code(std::errc::illegal_byte_sequence);
93
94 if (Stream.getLength() !=
95 sizeof(HeaderInfo) + Header->ModiSubstreamSize +
96 Header->SecContrSubstreamSize + Header->SectionMapSize +
97 Header->FileInfoSize + Header->TypeServerSize +
98 Header->OptionalDbgHdrSize + Header->ECSubstreamSize)
99 return std::make_error_code(std::errc::illegal_byte_sequence);
100
101 return std::error_code();
102}
103
104PdbRaw_DbiVer PDBDbiStream::getDbiVersion() const {
105 uint32_t Value = Header->VersionHeader;
106 return static_cast<PdbRaw_DbiVer>(Value);
107}
108
109uint32_t PDBDbiStream::getAge() const { return Header->Age; }
110
111bool PDBDbiStream::isIncrementallyLinked() const {
112 return (Header->Flags & FlagIncrementalMask) != 0;
113}
114
115bool PDBDbiStream::hasCTypes() const {
116 return (Header->Flags & FlagHasCTypesMask) != 0;
117}
118
119bool PDBDbiStream::isStripped() const {
120 return (Header->Flags & FlagStrippedMask) != 0;
121}
122
123uint16_t PDBDbiStream::getBuildMajorVersion() const {
124 return (Header->BuildNumber & BuildMajorMask) >> BuildMajorShift;
125}
126
127uint16_t PDBDbiStream::getBuildMinorVersion() const {
128 return (Header->BuildNumber & BuildMinorMask) >> BuildMinorShift;
129}
130
131uint32_t PDBDbiStream::getPdbDllVersion() const {
132 return Header->PdbDllVersion;
133}
134
135uint32_t PDBDbiStream::getNumberOfSymbols() const { return Header->SymRecords; }
136
137PDB_Machine PDBDbiStream::getMachineType() const {
138 uint16_t Machine = Header->MachineType;
139 return static_cast<PDB_Machine>(Machine);
140}