1 //===- CodeViewRecordIO.cpp -------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/DebugInfo/CodeView/CodeViewRecordIO.h"
11 #include "llvm/DebugInfo/CodeView/CodeView.h"
12 #include "llvm/DebugInfo/CodeView/RecordSerialization.h"
13 #include "llvm/DebugInfo/MSF/StreamReader.h"
14 #include "llvm/DebugInfo/MSF/StreamWriter.h"
17 using namespace llvm::codeview;
19 Error CodeViewRecordIO::beginRecord(Optional<uint32_t> MaxLength) {
21 Limit.MaxLength = MaxLength;
22 Limit.BeginOffset = getCurrentOffset();
23 Limits.push_back(Limit);
24 return Error::success();
27 Error CodeViewRecordIO::endRecord() {
28 assert(!Limits.empty() && "Not in a record!");
30 return Error::success();
33 uint32_t CodeViewRecordIO::maxFieldLength() const {
34 assert(!Limits.empty() && "Not in a record!");
36 // The max length of the next field is the minimum of all lengths that would
37 // be allowed by any of the sub-records we're in. In practice, we can only
38 // ever be at most 1 sub-record deep (in a FieldList), but this works for
40 uint32_t Offset = getCurrentOffset();
41 Optional<uint32_t> Min = Limits.front().bytesRemaining(Offset);
42 for (auto X : makeArrayRef(Limits).drop_front()) {
43 Optional<uint32_t> ThisMin = X.bytesRemaining(Offset);
44 if (ThisMin.hasValue())
45 Min = (Min.hasValue()) ? std::min(*Min, *ThisMin) : *ThisMin;
47 assert(Min.hasValue() && "Every field must have a maximum length!");
52 Error CodeViewRecordIO::skipPadding() {
53 assert(!isWriting() && "Cannot skip padding while writing!");
55 if (Reader->bytesRemaining() == 0)
56 return Error::success();
58 uint8_t Leaf = Reader->peek();
60 return Error::success();
61 // Leaf is greater than 0xf0. We should advance by the number of bytes in
63 unsigned BytesToAdvance = Leaf & 0x0F;
64 return Reader->skip(BytesToAdvance);
67 Error CodeViewRecordIO::mapByteVectorTail(ArrayRef<uint8_t> &Bytes) {
69 if (auto EC = Writer->writeBytes(Bytes))
72 if (auto EC = Reader->readBytes(Bytes, Reader->bytesRemaining()))
75 return Error::success();
78 Error CodeViewRecordIO::mapByteVectorTail(std::vector<uint8_t> &Bytes) {
79 ArrayRef<uint8_t> BytesRef(Bytes);
80 if (auto EC = mapByteVectorTail(BytesRef))
83 Bytes.assign(BytesRef.begin(), BytesRef.end());
85 return Error::success();
88 Error CodeViewRecordIO::mapInteger(TypeIndex &TypeInd) {
90 if (auto EC = Writer->writeInteger(TypeInd.getIndex()))
92 return Error::success();
96 if (auto EC = Reader->readInteger(I))
99 return Error::success();
102 Error CodeViewRecordIO::mapEncodedInteger(int64_t &Value) {
105 if (auto EC = writeEncodedUnsignedInteger(static_cast<uint64_t>(Value)))
108 if (auto EC = writeEncodedSignedInteger(Value))
113 if (auto EC = consume(*Reader, N))
115 Value = N.getExtValue();
118 return Error::success();
121 Error CodeViewRecordIO::mapEncodedInteger(uint64_t &Value) {
123 if (auto EC = writeEncodedUnsignedInteger(Value))
127 if (auto EC = consume(*Reader, N))
129 Value = N.getZExtValue();
131 return Error::success();
134 Error CodeViewRecordIO::mapEncodedInteger(APSInt &Value) {
136 if (Value.isSigned())
137 return writeEncodedSignedInteger(Value.getSExtValue());
138 return writeEncodedUnsignedInteger(Value.getZExtValue());
141 return consume(*Reader, Value);
144 Error CodeViewRecordIO::mapStringZ(StringRef &Value) {
146 // Truncate if we attempt to write too much.
147 StringRef S = Value.take_front(maxFieldLength() - 1);
148 if (auto EC = Writer->writeZeroString(S))
151 if (auto EC = Reader->readZeroString(Value))
154 return Error::success();
157 Error CodeViewRecordIO::mapGuid(StringRef &Guid) {
158 constexpr uint32_t GuidSize = 16;
159 if (maxFieldLength() < GuidSize)
160 return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
163 assert(Guid.size() == 16 && "Invalid Guid Size!");
164 if (auto EC = Writer->writeFixedString(Guid))
167 if (auto EC = Reader->readFixedString(Guid, 16))
170 return Error::success();
173 Error CodeViewRecordIO::mapStringZVectorZ(std::vector<StringRef> &Value) {
175 for (auto V : Value) {
176 if (auto EC = mapStringZ(V))
179 if (auto EC = Writer->writeInteger(uint8_t(0)))
183 if (auto EC = mapStringZ(S))
187 if (auto EC = mapStringZ(S))
191 return Error::success();
194 Error CodeViewRecordIO::writeEncodedSignedInteger(const int64_t &Value) {
195 assert(Value < 0 && "Encoded integer is not signed!");
196 if (Value >= std::numeric_limits<int8_t>::min()) {
197 if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_CHAR)))
199 if (auto EC = Writer->writeInteger(static_cast<int8_t>(Value)))
201 } else if (Value >= std::numeric_limits<int16_t>::min()) {
202 if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_SHORT)))
204 if (auto EC = Writer->writeInteger(static_cast<int16_t>(Value)))
206 } else if (Value >= std::numeric_limits<int32_t>::min()) {
207 if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_LONG)))
209 if (auto EC = Writer->writeInteger(static_cast<int32_t>(Value)))
212 if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_QUADWORD)))
214 if (auto EC = Writer->writeInteger(Value))
217 return Error::success();
220 Error CodeViewRecordIO::writeEncodedUnsignedInteger(const uint64_t &Value) {
221 if (Value < LF_NUMERIC) {
222 if (auto EC = Writer->writeInteger(static_cast<uint16_t>(Value)))
224 } else if (Value <= std::numeric_limits<uint16_t>::max()) {
225 if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_USHORT)))
227 if (auto EC = Writer->writeInteger(static_cast<uint16_t>(Value)))
229 } else if (Value <= std::numeric_limits<uint32_t>::max()) {
230 if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_ULONG)))
232 if (auto EC = Writer->writeInteger(static_cast<uint32_t>(Value)))
235 if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_UQUADWORD)))
237 if (auto EC = Writer->writeInteger(Value))
241 return Error::success();