LLVM  10.0.0svn
CodeViewRecordIO.h
Go to the documentation of this file.
1 //===- CodeViewRecordIO.h ---------------------------------------*- 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 #ifndef LLVM_DEBUGINFO_CODEVIEW_CODEVIEWRECORDIO_H
10 #define LLVM_DEBUGINFO_CODEVIEW_CODEVIEWRECORDIO_H
11 
12 #include "llvm/ADT/APSInt.h"
13 #include "llvm/ADT/None.h"
14 #include "llvm/ADT/Optional.h"
15 #include "llvm/ADT/SmallVector.h"
16 #include "llvm/ADT/StringRef.h"
21 #include "llvm/Support/Error.h"
22 #include <cassert>
23 #include <cstdint>
24 #include <type_traits>
25 
26 namespace llvm {
27 
28 namespace codeview {
29 
31 public:
32  virtual void EmitBytes(StringRef Data) = 0;
33  virtual void EmitIntValue(uint64_t Value, unsigned Size) = 0;
34  virtual void EmitBinaryData(StringRef Data) = 0;
35  virtual void AddComment(const Twine &T) = 0;
36  virtual void AddRawComment(const Twine &T) = 0;
37  virtual bool isVerboseAsm() = 0;
38  virtual std::string getTypeName(TypeIndex TI) = 0;
39  virtual ~CodeViewRecordStreamer() = default;
40 };
41 
43  uint32_t getCurrentOffset() const {
44  if (isWriting())
45  return Writer->getOffset();
46  else if (isReading())
47  return Reader->getOffset();
48  else
49  return 0;
50  }
51 
52 public:
53  // deserializes records to structures
54  explicit CodeViewRecordIO(BinaryStreamReader &Reader) : Reader(&Reader) {}
55 
56  // serializes records to buffer
57  explicit CodeViewRecordIO(BinaryStreamWriter &Writer) : Writer(&Writer) {}
58 
59  // writes records to assembly file using MC library interface
61  : Streamer(&Streamer) {}
62 
63  Error beginRecord(Optional<uint32_t> MaxLength);
64  Error endRecord();
65 
66  Error mapInteger(TypeIndex &TypeInd, const Twine &Comment = "");
67 
68  bool isStreaming() const {
69  return (Streamer != nullptr) && (Reader == nullptr) && (Writer == nullptr);
70  }
71  bool isReading() const {
72  return (Reader != nullptr) && (Streamer == nullptr) && (Writer == nullptr);
73  }
74  bool isWriting() const {
75  return (Writer != nullptr) && (Streamer == nullptr) && (Reader == nullptr);
76  }
77 
78  uint32_t maxFieldLength() const;
79 
80  template <typename T> Error mapObject(T &Value) {
81  if (isStreaming()) {
82  StringRef BytesSR =
83  StringRef((reinterpret_cast<const char *>(&Value)), sizeof(Value));
84  Streamer->EmitBytes(BytesSR);
85  incrStreamedLen(sizeof(T));
86  return Error::success();
87  }
88 
89  if (isWriting())
90  return Writer->writeObject(Value);
91 
92  const T *ValuePtr;
93  if (auto EC = Reader->readObject(ValuePtr))
94  return EC;
95  Value = *ValuePtr;
96  return Error::success();
97  }
98 
99  template <typename T> Error mapInteger(T &Value, const Twine &Comment = "") {
100  if (isStreaming()) {
101  emitComment(Comment);
102  Streamer->EmitIntValue((int)Value, sizeof(T));
103  incrStreamedLen(sizeof(T));
104  return Error::success();
105  }
106 
107  if (isWriting())
108  return Writer->writeInteger(Value);
109 
110  return Reader->readInteger(Value);
111  }
112 
113  template <typename T> Error mapEnum(T &Value, const Twine &Comment = "") {
114  if (!isStreaming() && sizeof(Value) > maxFieldLength())
115  return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
116 
117  using U = typename std::underlying_type<T>::type;
118  U X;
119 
120  if (isWriting() || isStreaming())
121  X = static_cast<U>(Value);
122 
123  if (auto EC = mapInteger(X, Comment))
124  return EC;
125 
126  if (isReading())
127  Value = static_cast<T>(X);
128 
129  return Error::success();
130  }
131 
132  Error mapEncodedInteger(int64_t &Value, const Twine &Comment = "");
133  Error mapEncodedInteger(uint64_t &Value, const Twine &Comment = "");
134  Error mapEncodedInteger(APSInt &Value, const Twine &Comment = "");
135  Error mapStringZ(StringRef &Value, const Twine &Comment = "");
136  Error mapGuid(GUID &Guid, const Twine &Comment = "");
137 
138  Error mapStringZVectorZ(std::vector<StringRef> &Value,
139  const Twine &Comment = "");
140 
141  template <typename SizeType, typename T, typename ElementMapper>
142  Error mapVectorN(T &Items, const ElementMapper &Mapper,
143  const Twine &Comment = "") {
144  SizeType Size;
145  if (isStreaming()) {
146  Size = static_cast<SizeType>(Items.size());
147  emitComment(Comment);
148  Streamer->EmitIntValue(Size, sizeof(Size));
149  incrStreamedLen(sizeof(Size)); // add 1 for the delimiter
150 
151  for (auto &X : Items) {
152  if (auto EC = Mapper(*this, X))
153  return EC;
154  }
155  } else if (isWriting()) {
156  Size = static_cast<SizeType>(Items.size());
157  if (auto EC = Writer->writeInteger(Size))
158  return EC;
159 
160  for (auto &X : Items) {
161  if (auto EC = Mapper(*this, X))
162  return EC;
163  }
164  } else {
165  if (auto EC = Reader->readInteger(Size))
166  return EC;
167  for (SizeType I = 0; I < Size; ++I) {
168  typename T::value_type Item;
169  if (auto EC = Mapper(*this, Item))
170  return EC;
171  Items.push_back(Item);
172  }
173  }
174 
175  return Error::success();
176  }
177 
178  template <typename T, typename ElementMapper>
179  Error mapVectorTail(T &Items, const ElementMapper &Mapper,
180  const Twine &Comment = "") {
181  emitComment(Comment);
182  if (isStreaming() || isWriting()) {
183  for (auto &Item : Items) {
184  if (auto EC = Mapper(*this, Item))
185  return EC;
186  }
187  } else {
188  typename T::value_type Field;
189  // Stop when we run out of bytes or we hit record padding bytes.
190  while (!Reader->empty() && Reader->peek() < 0xf0 /* LF_PAD0 */) {
191  if (auto EC = Mapper(*this, Field))
192  return EC;
193  Items.push_back(Field);
194  }
195  }
196  return Error::success();
197  }
198 
199  Error mapByteVectorTail(ArrayRef<uint8_t> &Bytes, const Twine &Comment = "");
200  Error mapByteVectorTail(std::vector<uint8_t> &Bytes,
201  const Twine &Comment = "");
202 
203  Error padToAlignment(uint32_t Align);
204  Error skipPadding();
205 
206  uint64_t getStreamedLen() {
207  if (isStreaming())
208  return StreamedLen;
209  return 0;
210  }
211 
212  void emitRawComment(const Twine &T) {
213  if (isStreaming() && Streamer->isVerboseAsm())
214  Streamer->AddRawComment(T);
215  }
216 
217 private:
218  void emitEncodedSignedInteger(const int64_t &Value,
219  const Twine &Comment = "");
220  void emitEncodedUnsignedInteger(const uint64_t &Value,
221  const Twine &Comment = "");
222  Error writeEncodedSignedInteger(const int64_t &Value);
223  Error writeEncodedUnsignedInteger(const uint64_t &Value);
224 
225  void incrStreamedLen(const uint64_t &Len) {
226  if (isStreaming())
227  StreamedLen += Len;
228  }
229 
230  void resetStreamedLen() {
231  if (isStreaming())
232  StreamedLen = 4; // The record prefix is 4 bytes long
233  }
234 
235  void emitComment(const Twine &Comment) {
236  if (isStreaming() && Streamer->isVerboseAsm()) {
237  Twine TComment(Comment);
238  if (!TComment.isTriviallyEmpty())
239  Streamer->AddComment(TComment);
240  }
241  }
242 
243  struct RecordLimit {
244  uint32_t BeginOffset;
245  Optional<uint32_t> MaxLength;
246 
247  Optional<uint32_t> bytesRemaining(uint32_t CurrentOffset) const {
248  if (!MaxLength.hasValue())
249  return None;
250  assert(CurrentOffset >= BeginOffset);
251 
252  uint32_t BytesUsed = CurrentOffset - BeginOffset;
253  if (BytesUsed >= *MaxLength)
254  return 0;
255  return *MaxLength - BytesUsed;
256  }
257  };
258 
260 
261  BinaryStreamReader *Reader = nullptr;
262  BinaryStreamWriter *Writer = nullptr;
263  CodeViewRecordStreamer *Streamer = nullptr;
264  uint64_t StreamedLen = 0;
265 };
266 
267 } // end namespace codeview
268 } // end namespace llvm
269 
270 #endif // LLVM_DEBUGINFO_CODEVIEW_CODEVIEWRECORDIO_H
Error mapVectorN(T &Items, const ElementMapper &Mapper, const Twine &Comment="")
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
virtual std::string getTypeName(TypeIndex TI)=0
This class represents lattice values for constants.
Definition: AllocatorList.h:23
bool isTriviallyEmpty() const
Check if this twine is trivially empty; a false return value does not necessarily mean the twine is e...
Definition: Twine.h:400
CodeViewRecordIO(BinaryStreamWriter &Writer)
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:80
This represents the &#39;GUID&#39; type from windows.h.
Definition: GUID.h:21
Error mapVectorTail(T &Items, const ElementMapper &Mapper, const Twine &Comment="")
A 32-bit type reference.
Definition: TypeIndex.h:95
Error mapEnum(T &Value, const Twine &Comment="")
Error mapInteger(T &Value, const Twine &Comment="")
Provides write only access to a subclass of WritableBinaryStream.
CodeViewRecordIO(BinaryStreamReader &Reader)
virtual void EmitBytes(StringRef Data)=0
void emitRawComment(const Twine &T)
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:40
virtual void EmitIntValue(uint64_t Value, unsigned Size)=0
static ErrorSuccess success()
Create a success value.
Definition: Error.h:326
virtual void AddRawComment(const Twine &T)=0
virtual void AddComment(const Twine &T)=0
bool hasValue() const
Definition: Optional.h:259
CodeViewRecordIO(CodeViewRecordStreamer &Streamer)
#define I(x, y, z)
Definition: MD5.cpp:58
uint32_t Size
Definition: Profile.cpp:46
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
Definition: Value.h:74
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
Provides read only access to a subclass of BinaryStream.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
virtual void EmitBinaryData(StringRef Data)=0