LLVM 20.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
13#include "llvm/ADT/StringRef.h"
17#include "llvm/Support/Error.h"
18#include <cassert>
19#include <cstdint>
20#include <type_traits>
21
22namespace llvm {
23
24template <typename T> class ArrayRef;
25class APSInt;
26
27namespace codeview {
28class TypeIndex;
29struct GUID;
30
32public:
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
53public:
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
64 Error beginRecord(std::optional<uint32_t> MaxLength);
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
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
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
218private:
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 std::optional<uint32_t> MaxLength;
247
248 std::optional<uint32_t> bytesRemaining(uint32_t CurrentOffset) const {
249 if (!MaxLength)
250 return std::nullopt;
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
uint64_t Size
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
#define I(x, y, z)
Definition: MD5.cpp:58
OptimizedStructLayoutField Field
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
An arbitrary precision integer that knows its signedness.
Definition: APSInt.h:23
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
Provides read only access to a subclass of BinaryStream.
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...
uint8_t peek() const
Examine the next byte of the underlying stream without advancing the stream's offset.
Error readInteger(T &Dest)
Read an integer of the specified endianness into Dest and update the stream's offset.
Provides write only access to a subclass of WritableBinaryStream.
Error writeInteger(T Value)
Write the integer Value to the underlying stream in the specified endianness.
Error writeObject(const T &Obj)
Writes the object Obj to the underlying stream, as if by using memcpy.
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:337
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
LLVM Value Representation.
Definition: Value.h:74
Error mapVectorTail(T &Items, const ElementMapper &Mapper, const Twine &Comment="")
CodeViewRecordIO(BinaryStreamWriter &Writer)
Error padToAlignment(uint32_t Align)
Error mapVectorN(T &Items, const ElementMapper &Mapper, const Twine &Comment="")
Error mapInteger(T &Value, const Twine &Comment="")
Error mapInteger(TypeIndex &TypeInd, const Twine &Comment="")
CodeViewRecordIO(BinaryStreamReader &Reader)
Error mapGuid(GUID &Guid, const Twine &Comment="")
Error mapStringZVectorZ(std::vector< StringRef > &Value, const Twine &Comment="")
Error mapStringZ(StringRef &Value, const Twine &Comment="")
Error mapEnum(T &Value, const Twine &Comment="")
Error mapEncodedInteger(int64_t &Value, const Twine &Comment="")
Error beginRecord(std::optional< uint32_t > MaxLength)
Error mapByteVectorTail(ArrayRef< uint8_t > &Bytes, const Twine &Comment="")
CodeViewRecordIO(CodeViewRecordStreamer &Streamer)
void emitRawComment(const Twine &T)
virtual void emitBytes(StringRef Data)=0
virtual void AddComment(const Twine &T)=0
virtual void emitIntValue(uint64_t Value, unsigned Size)=0
virtual void emitBinaryData(StringRef Data)=0
virtual std::string getTypeName(TypeIndex TI)=0
virtual void AddRawComment(const Twine &T)=0
A 32-bit type reference.
Definition: TypeIndex.h:96
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
ArrayRef(const T &OneElt) -> ArrayRef< T >
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
This represents the 'GUID' type from windows.h.
Definition: GUID.h:21