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