CodeViewRecordIO.cpp revision 360784
1//===- CodeViewRecordIO.cpp -------------------------------------*- 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/CodeView/CodeViewRecordIO.h"
10#include "llvm/DebugInfo/CodeView/CodeView.h"
11#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
12#include "llvm/Support/BinaryStreamReader.h"
13#include "llvm/Support/BinaryStreamWriter.h"
14
15using namespace llvm;
16using namespace llvm::codeview;
17
18Error CodeViewRecordIO::beginRecord(Optional<uint32_t> MaxLength) {
19  RecordLimit Limit;
20  Limit.MaxLength = MaxLength;
21  Limit.BeginOffset = getCurrentOffset();
22  Limits.push_back(Limit);
23  return Error::success();
24}
25
26Error CodeViewRecordIO::endRecord() {
27  assert(!Limits.empty() && "Not in a record!");
28  Limits.pop_back();
29  // We would like to assert that we actually read / wrote all the bytes that we
30  // expected to for this record, but unfortunately we can't do this.  Some
31  // producers such as MASM over-allocate for certain types of records and
32  // commit the extraneous data, so when reading we can't be sure every byte
33  // will have been read.  And when writing we over-allocate temporarily since
34  // we don't know how big the record is until we're finished writing it, so
35  // even though we don't commit the extraneous data, we still can't guarantee
36  // we're at the end of the allocated data.
37
38  if (isStreaming()) {
39    // For streaming mode, add padding to align with 4 byte boundaries for each
40    // record
41    uint32_t Align = getStreamedLen() % 4;
42    if (Align == 0)
43      return Error::success();
44
45    int PaddingBytes = 4 - Align;
46    while (PaddingBytes > 0) {
47      char Pad = static_cast<uint8_t>(LF_PAD0 + PaddingBytes);
48      StringRef BytesSR = StringRef(&Pad, sizeof(Pad));
49      Streamer->EmitBytes(BytesSR);
50      --PaddingBytes;
51    }
52    resetStreamedLen();
53  }
54  return Error::success();
55}
56
57uint32_t CodeViewRecordIO::maxFieldLength() const {
58  if (isStreaming())
59    return 0;
60
61  assert(!Limits.empty() && "Not in a record!");
62
63  // The max length of the next field is the minimum of all lengths that would
64  // be allowed by any of the sub-records we're in.  In practice, we can only
65  // ever be at most 1 sub-record deep (in a FieldList), but this works for
66  // the general case.
67  uint32_t Offset = getCurrentOffset();
68  Optional<uint32_t> Min = Limits.front().bytesRemaining(Offset);
69  for (auto X : makeArrayRef(Limits).drop_front()) {
70    Optional<uint32_t> ThisMin = X.bytesRemaining(Offset);
71    if (ThisMin.hasValue())
72      Min = (Min.hasValue()) ? std::min(*Min, *ThisMin) : *ThisMin;
73  }
74  assert(Min.hasValue() && "Every field must have a maximum length!");
75
76  return *Min;
77}
78
79Error CodeViewRecordIO::padToAlignment(uint32_t Align) {
80  if (isReading())
81    return Reader->padToAlignment(Align);
82  return Writer->padToAlignment(Align);
83}
84
85Error CodeViewRecordIO::skipPadding() {
86  assert(!isWriting() && "Cannot skip padding while writing!");
87
88  if (Reader->bytesRemaining() == 0)
89    return Error::success();
90
91  uint8_t Leaf = Reader->peek();
92  if (Leaf < LF_PAD0)
93    return Error::success();
94  // Leaf is greater than 0xf0. We should advance by the number of bytes in
95  // the low 4 bits.
96  unsigned BytesToAdvance = Leaf & 0x0F;
97  return Reader->skip(BytesToAdvance);
98}
99
100Error CodeViewRecordIO::mapByteVectorTail(ArrayRef<uint8_t> &Bytes,
101                                          const Twine &Comment) {
102  if (isStreaming()) {
103    emitComment(Comment);
104    Streamer->EmitBinaryData(toStringRef(Bytes));
105    incrStreamedLen(Bytes.size());
106  } else if (isWriting()) {
107    if (auto EC = Writer->writeBytes(Bytes))
108      return EC;
109  } else {
110    if (auto EC = Reader->readBytes(Bytes, Reader->bytesRemaining()))
111      return EC;
112  }
113  return Error::success();
114}
115
116Error CodeViewRecordIO::mapByteVectorTail(std::vector<uint8_t> &Bytes,
117                                          const Twine &Comment) {
118  ArrayRef<uint8_t> BytesRef(Bytes);
119  if (auto EC = mapByteVectorTail(BytesRef, Comment))
120    return EC;
121  if (!isWriting())
122    Bytes.assign(BytesRef.begin(), BytesRef.end());
123
124  return Error::success();
125}
126
127Error CodeViewRecordIO::mapInteger(TypeIndex &TypeInd, const Twine &Comment) {
128  if (isStreaming()) {
129    std::string TypeNameStr = Streamer->getTypeName(TypeInd);
130    if (!TypeNameStr.empty())
131      emitComment(Comment + ": " + TypeNameStr);
132    else
133      emitComment(Comment);
134    Streamer->EmitIntValue(TypeInd.getIndex(), sizeof(TypeInd.getIndex()));
135    incrStreamedLen(sizeof(TypeInd.getIndex()));
136  } else if (isWriting()) {
137    if (auto EC = Writer->writeInteger(TypeInd.getIndex()))
138      return EC;
139  } else {
140    uint32_t I;
141    if (auto EC = Reader->readInteger(I))
142      return EC;
143    TypeInd.setIndex(I);
144  }
145  return Error::success();
146}
147
148Error CodeViewRecordIO::mapEncodedInteger(int64_t &Value,
149                                          const Twine &Comment) {
150  if (isStreaming()) {
151    if (Value >= 0)
152      emitEncodedUnsignedInteger(static_cast<uint64_t>(Value), Comment);
153    else
154      emitEncodedSignedInteger(Value, Comment);
155  } else if (isWriting()) {
156    if (Value >= 0) {
157      if (auto EC = writeEncodedUnsignedInteger(static_cast<uint64_t>(Value)))
158        return EC;
159    } else {
160      if (auto EC = writeEncodedSignedInteger(Value))
161        return EC;
162    }
163  } else {
164    APSInt N;
165    if (auto EC = consume(*Reader, N))
166      return EC;
167    Value = N.getExtValue();
168  }
169
170  return Error::success();
171}
172
173Error CodeViewRecordIO::mapEncodedInteger(uint64_t &Value,
174                                          const Twine &Comment) {
175  if (isStreaming())
176    emitEncodedUnsignedInteger(Value, Comment);
177  else if (isWriting()) {
178    if (auto EC = writeEncodedUnsignedInteger(Value))
179      return EC;
180  } else {
181    APSInt N;
182    if (auto EC = consume(*Reader, N))
183      return EC;
184    Value = N.getZExtValue();
185  }
186  return Error::success();
187}
188
189Error CodeViewRecordIO::mapEncodedInteger(APSInt &Value, const Twine &Comment) {
190  if (isStreaming()) {
191    if (Value.isSigned())
192      emitEncodedSignedInteger(Value.getSExtValue(), Comment);
193    else
194      emitEncodedUnsignedInteger(Value.getZExtValue(), Comment);
195  } else if (isWriting()) {
196    if (Value.isSigned())
197      return writeEncodedSignedInteger(Value.getSExtValue());
198    return writeEncodedUnsignedInteger(Value.getZExtValue());
199  } else
200    return consume(*Reader, Value);
201  return Error::success();
202}
203
204Error CodeViewRecordIO::mapStringZ(StringRef &Value, const Twine &Comment) {
205  if (isStreaming()) {
206    auto NullTerminatedString = StringRef(Value.data(), Value.size() + 1);
207    emitComment(Comment);
208    Streamer->EmitBytes(NullTerminatedString);
209    incrStreamedLen(NullTerminatedString.size());
210  } else if (isWriting()) {
211    // Truncate if we attempt to write too much.
212    StringRef S = Value.take_front(maxFieldLength() - 1);
213    if (auto EC = Writer->writeCString(S))
214      return EC;
215  } else {
216    if (auto EC = Reader->readCString(Value))
217      return EC;
218  }
219  return Error::success();
220}
221
222Error CodeViewRecordIO::mapGuid(GUID &Guid, const Twine &Comment) {
223  constexpr uint32_t GuidSize = 16;
224
225  if (isStreaming()) {
226    StringRef GuidSR =
227        StringRef((reinterpret_cast<const char *>(&Guid)), GuidSize);
228    emitComment(Comment);
229    Streamer->EmitBytes(GuidSR);
230    incrStreamedLen(GuidSize);
231    return Error::success();
232  }
233
234  if (maxFieldLength() < GuidSize)
235    return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
236
237  if (isWriting()) {
238    if (auto EC = Writer->writeBytes(Guid.Guid))
239      return EC;
240  } else {
241    ArrayRef<uint8_t> GuidBytes;
242    if (auto EC = Reader->readBytes(GuidBytes, GuidSize))
243      return EC;
244    memcpy(Guid.Guid, GuidBytes.data(), GuidSize);
245  }
246  return Error::success();
247}
248
249Error CodeViewRecordIO::mapStringZVectorZ(std::vector<StringRef> &Value,
250                                          const Twine &Comment) {
251
252  if (!isReading()) {
253    emitComment(Comment);
254    for (auto V : Value) {
255      if (auto EC = mapStringZ(V))
256        return EC;
257    }
258    uint8_t FinalZero = 0;
259    if (auto EC = mapInteger(FinalZero))
260      return EC;
261  } else {
262    StringRef S;
263    if (auto EC = mapStringZ(S))
264      return EC;
265    while (!S.empty()) {
266      Value.push_back(S);
267      if (auto EC = mapStringZ(S))
268        return EC;
269    };
270  }
271  return Error::success();
272}
273
274void CodeViewRecordIO::emitEncodedSignedInteger(const int64_t &Value,
275                                                const Twine &Comment) {
276  assert(Value < 0 && "Encoded integer is not signed!");
277  if (Value >= std::numeric_limits<int8_t>::min()) {
278    Streamer->EmitIntValue(LF_CHAR, 2);
279    emitComment(Comment);
280    Streamer->EmitIntValue(Value, 1);
281    incrStreamedLen(3);
282  } else if (Value >= std::numeric_limits<int16_t>::min()) {
283    Streamer->EmitIntValue(LF_SHORT, 2);
284    emitComment(Comment);
285    Streamer->EmitIntValue(Value, 2);
286    incrStreamedLen(4);
287  } else if (Value >= std::numeric_limits<int32_t>::min()) {
288    Streamer->EmitIntValue(LF_LONG, 2);
289    emitComment(Comment);
290    Streamer->EmitIntValue(Value, 4);
291    incrStreamedLen(6);
292  } else {
293    Streamer->EmitIntValue(LF_QUADWORD, 2);
294    emitComment(Comment);
295    Streamer->EmitIntValue(Value, 4);
296    incrStreamedLen(6);
297  }
298}
299
300void CodeViewRecordIO::emitEncodedUnsignedInteger(const uint64_t &Value,
301                                                  const Twine &Comment) {
302  if (Value < LF_NUMERIC) {
303    emitComment(Comment);
304    Streamer->EmitIntValue(Value, 2);
305    incrStreamedLen(2);
306  } else if (Value <= std::numeric_limits<uint16_t>::max()) {
307    Streamer->EmitIntValue(LF_USHORT, 2);
308    emitComment(Comment);
309    Streamer->EmitIntValue(Value, 2);
310    incrStreamedLen(4);
311  } else if (Value <= std::numeric_limits<uint32_t>::max()) {
312    Streamer->EmitIntValue(LF_ULONG, 2);
313    emitComment(Comment);
314    Streamer->EmitIntValue(Value, 4);
315    incrStreamedLen(6);
316  } else {
317    Streamer->EmitIntValue(LF_UQUADWORD, 2);
318    emitComment(Comment);
319    Streamer->EmitIntValue(Value, 8);
320    incrStreamedLen(6);
321  }
322}
323
324Error CodeViewRecordIO::writeEncodedSignedInteger(const int64_t &Value) {
325  assert(Value < 0 && "Encoded integer is not signed!");
326  if (Value >= std::numeric_limits<int8_t>::min()) {
327    if (auto EC = Writer->writeInteger<uint16_t>(LF_CHAR))
328      return EC;
329    if (auto EC = Writer->writeInteger<int8_t>(Value))
330      return EC;
331  } else if (Value >= std::numeric_limits<int16_t>::min()) {
332    if (auto EC = Writer->writeInteger<uint16_t>(LF_SHORT))
333      return EC;
334    if (auto EC = Writer->writeInteger<int16_t>(Value))
335      return EC;
336  } else if (Value >= std::numeric_limits<int32_t>::min()) {
337    if (auto EC = Writer->writeInteger<uint16_t>(LF_LONG))
338      return EC;
339    if (auto EC = Writer->writeInteger<int32_t>(Value))
340      return EC;
341  } else {
342    if (auto EC = Writer->writeInteger<uint16_t>(LF_QUADWORD))
343      return EC;
344    if (auto EC = Writer->writeInteger(Value))
345      return EC;
346  }
347  return Error::success();
348}
349
350Error CodeViewRecordIO::writeEncodedUnsignedInteger(const uint64_t &Value) {
351  if (Value < LF_NUMERIC) {
352    if (auto EC = Writer->writeInteger<uint16_t>(Value))
353      return EC;
354  } else if (Value <= std::numeric_limits<uint16_t>::max()) {
355    if (auto EC = Writer->writeInteger<uint16_t>(LF_USHORT))
356      return EC;
357    if (auto EC = Writer->writeInteger<uint16_t>(Value))
358      return EC;
359  } else if (Value <= std::numeric_limits<uint32_t>::max()) {
360    if (auto EC = Writer->writeInteger<uint16_t>(LF_ULONG))
361      return EC;
362    if (auto EC = Writer->writeInteger<uint32_t>(Value))
363      return EC;
364  } else {
365    if (auto EC = Writer->writeInteger<uint16_t>(LF_UQUADWORD))
366      return EC;
367    if (auto EC = Writer->writeInteger(Value))
368      return EC;
369  }
370
371  return Error::success();
372}
373