1//===- InfoStream.cpp - PDB Info Stream (Stream 1) Access -------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
10#include "llvm/ADT/BitVector.h"
11#include "llvm/ADT/SmallVector.h"
12#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
13#include "llvm/DebugInfo/PDB/Native/RawError.h"
14#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
15#include "llvm/Support/BinaryStreamReader.h"
16
17using namespace llvm;
18using namespace llvm::codeview;
19using namespace llvm::msf;
20using namespace llvm::pdb;
21
22InfoStream::InfoStream(std::unique_ptr<BinaryStream> Stream)
23    : Stream(std::move(Stream)), Header(nullptr) {}
24
25Error InfoStream::reload() {
26  BinaryStreamReader Reader(*Stream);
27
28  if (auto EC = Reader.readObject(Header))
29    return joinErrors(
30        std::move(EC),
31        make_error<RawError>(raw_error_code::corrupt_file,
32                             "PDB Stream does not contain a header."));
33
34  switch (Header->Version) {
35  case PdbImplVC70:
36  case PdbImplVC80:
37  case PdbImplVC110:
38  case PdbImplVC140:
39    break;
40  default:
41    return make_error<RawError>(raw_error_code::corrupt_file,
42                                "Unsupported PDB stream version.");
43  }
44
45  uint32_t Offset = Reader.getOffset();
46  if (auto EC = NamedStreams.load(Reader))
47    return EC;
48  uint32_t NewOffset = Reader.getOffset();
49  NamedStreamMapByteSize = NewOffset - Offset;
50
51  Reader.setOffset(Offset);
52  if (auto EC = Reader.readSubstream(SubNamedStreams, NamedStreamMapByteSize))
53    return EC;
54
55  bool Stop = false;
56  while (!Stop && !Reader.empty()) {
57    PdbRaw_FeatureSig Sig;
58    if (auto EC = Reader.readEnum(Sig))
59      return EC;
60    // Since this value comes from a file, it's possible we have some strange
61    // value which doesn't correspond to any value.  We don't want to warn on
62    // -Wcovered-switch-default in this case, so switch on the integral value
63    // instead of the enumeration value.
64    switch (uint32_t(Sig)) {
65    case uint32_t(PdbRaw_FeatureSig::VC110):
66      // No other flags for VC110 PDB.
67      Stop = true;
68      LLVM_FALLTHROUGH;
69    case uint32_t(PdbRaw_FeatureSig::VC140):
70      Features |= PdbFeatureContainsIdStream;
71      break;
72    case uint32_t(PdbRaw_FeatureSig::NoTypeMerge):
73      Features |= PdbFeatureNoTypeMerging;
74      break;
75    case uint32_t(PdbRaw_FeatureSig::MinimalDebugInfo):
76      Features |= PdbFeatureMinimalDebugInfo;
77      break;
78    default:
79      continue;
80    }
81    FeatureSignatures.push_back(Sig);
82  }
83  return Error::success();
84}
85
86uint32_t InfoStream::getStreamSize() const { return Stream->getLength(); }
87
88Expected<uint32_t> InfoStream::getNamedStreamIndex(llvm::StringRef Name) const {
89  uint32_t Result;
90  if (!NamedStreams.get(Name, Result))
91    return make_error<RawError>(raw_error_code::no_stream);
92  return Result;
93}
94
95StringMap<uint32_t> InfoStream::named_streams() const {
96  return NamedStreams.entries();
97}
98
99bool InfoStream::containsIdStream() const {
100  return !!(Features & PdbFeatureContainsIdStream);
101}
102
103PdbRaw_ImplVer InfoStream::getVersion() const {
104  return static_cast<PdbRaw_ImplVer>(uint32_t(Header->Version));
105}
106
107uint32_t InfoStream::getSignature() const {
108  return uint32_t(Header->Signature);
109}
110
111uint32_t InfoStream::getAge() const { return uint32_t(Header->Age); }
112
113GUID InfoStream::getGuid() const { return Header->Guid; }
114
115uint32_t InfoStream::getNamedStreamMapByteSize() const {
116  return NamedStreamMapByteSize;
117}
118
119PdbRaw_Features InfoStream::getFeatures() const { return Features; }
120
121ArrayRef<PdbRaw_FeatureSig> InfoStream::getFeatureSignatures() const {
122  return FeatureSignatures;
123}
124
125const NamedStreamMap &InfoStream::getNamedStreams() const {
126  return NamedStreams;
127}
128
129BinarySubstreamRef InfoStream::getNamedStreamsBuffer() const {
130  return SubNamedStreams;
131}
132