1d88c1a5aSDimitry Andric //===- CodeViewRecordIO.cpp -------------------------------------*- C++ -*-===//
2d88c1a5aSDimitry Andric //
3d88c1a5aSDimitry Andric // The LLVM Compiler Infrastructure
4d88c1a5aSDimitry Andric //
5d88c1a5aSDimitry Andric // This file is distributed under the University of Illinois Open Source
6d88c1a5aSDimitry Andric // License. See LICENSE.TXT for details.
7d88c1a5aSDimitry Andric //
8d88c1a5aSDimitry Andric //===----------------------------------------------------------------------===//
9d88c1a5aSDimitry Andric
10d88c1a5aSDimitry Andric #include "llvm/DebugInfo/CodeView/CodeViewRecordIO.h"
11d88c1a5aSDimitry Andric #include "llvm/DebugInfo/CodeView/CodeView.h"
12d88c1a5aSDimitry Andric #include "llvm/DebugInfo/CodeView/RecordSerialization.h"
137a7e6055SDimitry Andric #include "llvm/Support/BinaryStreamReader.h"
147a7e6055SDimitry Andric #include "llvm/Support/BinaryStreamWriter.h"
15d88c1a5aSDimitry Andric
16d88c1a5aSDimitry Andric using namespace llvm;
17d88c1a5aSDimitry Andric using namespace llvm::codeview;
18d88c1a5aSDimitry Andric
beginRecord(Optional<uint32_t> MaxLength)19d88c1a5aSDimitry Andric Error CodeViewRecordIO::beginRecord(Optional<uint32_t> MaxLength) {
20d88c1a5aSDimitry Andric RecordLimit Limit;
21d88c1a5aSDimitry Andric Limit.MaxLength = MaxLength;
22d88c1a5aSDimitry Andric Limit.BeginOffset = getCurrentOffset();
23d88c1a5aSDimitry Andric Limits.push_back(Limit);
24d88c1a5aSDimitry Andric return Error::success();
25d88c1a5aSDimitry Andric }
26d88c1a5aSDimitry Andric
endRecord()27d88c1a5aSDimitry Andric Error CodeViewRecordIO::endRecord() {
28d88c1a5aSDimitry Andric assert(!Limits.empty() && "Not in a record!");
29d88c1a5aSDimitry Andric Limits.pop_back();
306d97bb29SDimitry Andric // We would like to assert that we actually read / wrote all the bytes that we
316d97bb29SDimitry Andric // expected to for this record, but unfortunately we can't do this. Some
326d97bb29SDimitry Andric // producers such as MASM over-allocate for certain types of records and
336d97bb29SDimitry Andric // commit the extraneous data, so when reading we can't be sure every byte
346d97bb29SDimitry Andric // will have been read. And when writing we over-allocate temporarily since
356d97bb29SDimitry Andric // we don't know how big the record is until we're finished writing it, so
366d97bb29SDimitry Andric // even though we don't commit the extraneous data, we still can't guarantee
376d97bb29SDimitry Andric // we're at the end of the allocated data.
38d88c1a5aSDimitry Andric return Error::success();
39d88c1a5aSDimitry Andric }
40d88c1a5aSDimitry Andric
maxFieldLength() const41d88c1a5aSDimitry Andric uint32_t CodeViewRecordIO::maxFieldLength() const {
42d88c1a5aSDimitry Andric assert(!Limits.empty() && "Not in a record!");
43d88c1a5aSDimitry Andric
44d88c1a5aSDimitry Andric // The max length of the next field is the minimum of all lengths that would
45d88c1a5aSDimitry Andric // be allowed by any of the sub-records we're in. In practice, we can only
46d88c1a5aSDimitry Andric // ever be at most 1 sub-record deep (in a FieldList), but this works for
47d88c1a5aSDimitry Andric // the general case.
48d88c1a5aSDimitry Andric uint32_t Offset = getCurrentOffset();
49d88c1a5aSDimitry Andric Optional<uint32_t> Min = Limits.front().bytesRemaining(Offset);
50d88c1a5aSDimitry Andric for (auto X : makeArrayRef(Limits).drop_front()) {
51d88c1a5aSDimitry Andric Optional<uint32_t> ThisMin = X.bytesRemaining(Offset);
52d88c1a5aSDimitry Andric if (ThisMin.hasValue())
53d88c1a5aSDimitry Andric Min = (Min.hasValue()) ? std::min(*Min, *ThisMin) : *ThisMin;
54d88c1a5aSDimitry Andric }
55d88c1a5aSDimitry Andric assert(Min.hasValue() && "Every field must have a maximum length!");
56d88c1a5aSDimitry Andric
57d88c1a5aSDimitry Andric return *Min;
58d88c1a5aSDimitry Andric }
59d88c1a5aSDimitry Andric
padToAlignment(uint32_t Align)606d97bb29SDimitry Andric Error CodeViewRecordIO::padToAlignment(uint32_t Align) {
616d97bb29SDimitry Andric if (isReading())
626d97bb29SDimitry Andric return Reader->padToAlignment(Align);
636d97bb29SDimitry Andric return Writer->padToAlignment(Align);
646d97bb29SDimitry Andric }
656d97bb29SDimitry Andric
skipPadding()66d88c1a5aSDimitry Andric Error CodeViewRecordIO::skipPadding() {
67d88c1a5aSDimitry Andric assert(!isWriting() && "Cannot skip padding while writing!");
68d88c1a5aSDimitry Andric
69d88c1a5aSDimitry Andric if (Reader->bytesRemaining() == 0)
70d88c1a5aSDimitry Andric return Error::success();
71d88c1a5aSDimitry Andric
72d88c1a5aSDimitry Andric uint8_t Leaf = Reader->peek();
73d88c1a5aSDimitry Andric if (Leaf < LF_PAD0)
74d88c1a5aSDimitry Andric return Error::success();
75d88c1a5aSDimitry Andric // Leaf is greater than 0xf0. We should advance by the number of bytes in
76d88c1a5aSDimitry Andric // the low 4 bits.
77d88c1a5aSDimitry Andric unsigned BytesToAdvance = Leaf & 0x0F;
78d88c1a5aSDimitry Andric return Reader->skip(BytesToAdvance);
79d88c1a5aSDimitry Andric }
80d88c1a5aSDimitry Andric
mapByteVectorTail(ArrayRef<uint8_t> & Bytes)81d88c1a5aSDimitry Andric Error CodeViewRecordIO::mapByteVectorTail(ArrayRef<uint8_t> &Bytes) {
82d88c1a5aSDimitry Andric if (isWriting()) {
83d88c1a5aSDimitry Andric if (auto EC = Writer->writeBytes(Bytes))
84d88c1a5aSDimitry Andric return EC;
85d88c1a5aSDimitry Andric } else {
86d88c1a5aSDimitry Andric if (auto EC = Reader->readBytes(Bytes, Reader->bytesRemaining()))
87d88c1a5aSDimitry Andric return EC;
88d88c1a5aSDimitry Andric }
89d88c1a5aSDimitry Andric return Error::success();
90d88c1a5aSDimitry Andric }
91d88c1a5aSDimitry Andric
mapByteVectorTail(std::vector<uint8_t> & Bytes)92d88c1a5aSDimitry Andric Error CodeViewRecordIO::mapByteVectorTail(std::vector<uint8_t> &Bytes) {
93d88c1a5aSDimitry Andric ArrayRef<uint8_t> BytesRef(Bytes);
94d88c1a5aSDimitry Andric if (auto EC = mapByteVectorTail(BytesRef))
95d88c1a5aSDimitry Andric return EC;
96d88c1a5aSDimitry Andric if (!isWriting())
97d88c1a5aSDimitry Andric Bytes.assign(BytesRef.begin(), BytesRef.end());
98d88c1a5aSDimitry Andric
99d88c1a5aSDimitry Andric return Error::success();
100d88c1a5aSDimitry Andric }
101d88c1a5aSDimitry Andric
mapInteger(TypeIndex & TypeInd)102d88c1a5aSDimitry Andric Error CodeViewRecordIO::mapInteger(TypeIndex &TypeInd) {
103d88c1a5aSDimitry Andric if (isWriting()) {
104d88c1a5aSDimitry Andric if (auto EC = Writer->writeInteger(TypeInd.getIndex()))
105d88c1a5aSDimitry Andric return EC;
106d88c1a5aSDimitry Andric return Error::success();
107d88c1a5aSDimitry Andric }
108d88c1a5aSDimitry Andric
109d88c1a5aSDimitry Andric uint32_t I;
110d88c1a5aSDimitry Andric if (auto EC = Reader->readInteger(I))
111d88c1a5aSDimitry Andric return EC;
112d88c1a5aSDimitry Andric TypeInd.setIndex(I);
113d88c1a5aSDimitry Andric return Error::success();
114d88c1a5aSDimitry Andric }
115d88c1a5aSDimitry Andric
mapEncodedInteger(int64_t & Value)116d88c1a5aSDimitry Andric Error CodeViewRecordIO::mapEncodedInteger(int64_t &Value) {
117d88c1a5aSDimitry Andric if (isWriting()) {
118d88c1a5aSDimitry Andric if (Value >= 0) {
119d88c1a5aSDimitry Andric if (auto EC = writeEncodedUnsignedInteger(static_cast<uint64_t>(Value)))
120d88c1a5aSDimitry Andric return EC;
121d88c1a5aSDimitry Andric } else {
122d88c1a5aSDimitry Andric if (auto EC = writeEncodedSignedInteger(Value))
123d88c1a5aSDimitry Andric return EC;
124d88c1a5aSDimitry Andric }
125d88c1a5aSDimitry Andric } else {
126d88c1a5aSDimitry Andric APSInt N;
127d88c1a5aSDimitry Andric if (auto EC = consume(*Reader, N))
128d88c1a5aSDimitry Andric return EC;
129d88c1a5aSDimitry Andric Value = N.getExtValue();
130d88c1a5aSDimitry Andric }
131d88c1a5aSDimitry Andric
132d88c1a5aSDimitry Andric return Error::success();
133d88c1a5aSDimitry Andric }
134d88c1a5aSDimitry Andric
mapEncodedInteger(uint64_t & Value)135d88c1a5aSDimitry Andric Error CodeViewRecordIO::mapEncodedInteger(uint64_t &Value) {
136d88c1a5aSDimitry Andric if (isWriting()) {
137d88c1a5aSDimitry Andric if (auto EC = writeEncodedUnsignedInteger(Value))
138d88c1a5aSDimitry Andric return EC;
139d88c1a5aSDimitry Andric } else {
140d88c1a5aSDimitry Andric APSInt N;
141d88c1a5aSDimitry Andric if (auto EC = consume(*Reader, N))
142d88c1a5aSDimitry Andric return EC;
143d88c1a5aSDimitry Andric Value = N.getZExtValue();
144d88c1a5aSDimitry Andric }
145d88c1a5aSDimitry Andric return Error::success();
146d88c1a5aSDimitry Andric }
147d88c1a5aSDimitry Andric
mapEncodedInteger(APSInt & Value)148d88c1a5aSDimitry Andric Error CodeViewRecordIO::mapEncodedInteger(APSInt &Value) {
149d88c1a5aSDimitry Andric if (isWriting()) {
150d88c1a5aSDimitry Andric if (Value.isSigned())
151d88c1a5aSDimitry Andric return writeEncodedSignedInteger(Value.getSExtValue());
152d88c1a5aSDimitry Andric return writeEncodedUnsignedInteger(Value.getZExtValue());
153d88c1a5aSDimitry Andric }
154d88c1a5aSDimitry Andric
155d88c1a5aSDimitry Andric return consume(*Reader, Value);
156d88c1a5aSDimitry Andric }
157d88c1a5aSDimitry Andric
mapStringZ(StringRef & Value)158d88c1a5aSDimitry Andric Error CodeViewRecordIO::mapStringZ(StringRef &Value) {
159d88c1a5aSDimitry Andric if (isWriting()) {
160d88c1a5aSDimitry Andric // Truncate if we attempt to write too much.
161d88c1a5aSDimitry Andric StringRef S = Value.take_front(maxFieldLength() - 1);
1627a7e6055SDimitry Andric if (auto EC = Writer->writeCString(S))
163d88c1a5aSDimitry Andric return EC;
164d88c1a5aSDimitry Andric } else {
1657a7e6055SDimitry Andric if (auto EC = Reader->readCString(Value))
166d88c1a5aSDimitry Andric return EC;
167d88c1a5aSDimitry Andric }
168d88c1a5aSDimitry Andric return Error::success();
169d88c1a5aSDimitry Andric }
170d88c1a5aSDimitry Andric
mapGuid(GUID & Guid)171*b40b48b8SDimitry Andric Error CodeViewRecordIO::mapGuid(GUID &Guid) {
172d88c1a5aSDimitry Andric constexpr uint32_t GuidSize = 16;
173d88c1a5aSDimitry Andric if (maxFieldLength() < GuidSize)
174d88c1a5aSDimitry Andric return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
175d88c1a5aSDimitry Andric
176d88c1a5aSDimitry Andric if (isWriting()) {
177*b40b48b8SDimitry Andric if (auto EC = Writer->writeBytes(Guid.Guid))
178d88c1a5aSDimitry Andric return EC;
179d88c1a5aSDimitry Andric } else {
180*b40b48b8SDimitry Andric ArrayRef<uint8_t> GuidBytes;
181*b40b48b8SDimitry Andric if (auto EC = Reader->readBytes(GuidBytes, GuidSize))
182d88c1a5aSDimitry Andric return EC;
183*b40b48b8SDimitry Andric memcpy(Guid.Guid, GuidBytes.data(), GuidSize);
184d88c1a5aSDimitry Andric }
185d88c1a5aSDimitry Andric return Error::success();
186d88c1a5aSDimitry Andric }
187d88c1a5aSDimitry Andric
mapStringZVectorZ(std::vector<StringRef> & Value)188d88c1a5aSDimitry Andric Error CodeViewRecordIO::mapStringZVectorZ(std::vector<StringRef> &Value) {
189d88c1a5aSDimitry Andric if (isWriting()) {
190d88c1a5aSDimitry Andric for (auto V : Value) {
191d88c1a5aSDimitry Andric if (auto EC = mapStringZ(V))
192d88c1a5aSDimitry Andric return EC;
193d88c1a5aSDimitry Andric }
1947a7e6055SDimitry Andric if (auto EC = Writer->writeInteger<uint8_t>(0))
195d88c1a5aSDimitry Andric return EC;
196d88c1a5aSDimitry Andric } else {
197d88c1a5aSDimitry Andric StringRef S;
198d88c1a5aSDimitry Andric if (auto EC = mapStringZ(S))
199d88c1a5aSDimitry Andric return EC;
200d88c1a5aSDimitry Andric while (!S.empty()) {
201d88c1a5aSDimitry Andric Value.push_back(S);
202d88c1a5aSDimitry Andric if (auto EC = mapStringZ(S))
203d88c1a5aSDimitry Andric return EC;
204d88c1a5aSDimitry Andric };
205d88c1a5aSDimitry Andric }
206d88c1a5aSDimitry Andric return Error::success();
207d88c1a5aSDimitry Andric }
208d88c1a5aSDimitry Andric
writeEncodedSignedInteger(const int64_t & Value)209d88c1a5aSDimitry Andric Error CodeViewRecordIO::writeEncodedSignedInteger(const int64_t &Value) {
210d88c1a5aSDimitry Andric assert(Value < 0 && "Encoded integer is not signed!");
211d88c1a5aSDimitry Andric if (Value >= std::numeric_limits<int8_t>::min()) {
2127a7e6055SDimitry Andric if (auto EC = Writer->writeInteger<uint16_t>(LF_CHAR))
213d88c1a5aSDimitry Andric return EC;
2147a7e6055SDimitry Andric if (auto EC = Writer->writeInteger<int8_t>(Value))
215d88c1a5aSDimitry Andric return EC;
216d88c1a5aSDimitry Andric } else if (Value >= std::numeric_limits<int16_t>::min()) {
2177a7e6055SDimitry Andric if (auto EC = Writer->writeInteger<uint16_t>(LF_SHORT))
218d88c1a5aSDimitry Andric return EC;
2197a7e6055SDimitry Andric if (auto EC = Writer->writeInteger<int16_t>(Value))
220d88c1a5aSDimitry Andric return EC;
221d88c1a5aSDimitry Andric } else if (Value >= std::numeric_limits<int32_t>::min()) {
2227a7e6055SDimitry Andric if (auto EC = Writer->writeInteger<uint16_t>(LF_LONG))
223d88c1a5aSDimitry Andric return EC;
2247a7e6055SDimitry Andric if (auto EC = Writer->writeInteger<int32_t>(Value))
225d88c1a5aSDimitry Andric return EC;
226d88c1a5aSDimitry Andric } else {
2277a7e6055SDimitry Andric if (auto EC = Writer->writeInteger<uint16_t>(LF_QUADWORD))
228d88c1a5aSDimitry Andric return EC;
229d88c1a5aSDimitry Andric if (auto EC = Writer->writeInteger(Value))
230d88c1a5aSDimitry Andric return EC;
231d88c1a5aSDimitry Andric }
232d88c1a5aSDimitry Andric return Error::success();
233d88c1a5aSDimitry Andric }
234d88c1a5aSDimitry Andric
writeEncodedUnsignedInteger(const uint64_t & Value)235d88c1a5aSDimitry Andric Error CodeViewRecordIO::writeEncodedUnsignedInteger(const uint64_t &Value) {
236d88c1a5aSDimitry Andric if (Value < LF_NUMERIC) {
2377a7e6055SDimitry Andric if (auto EC = Writer->writeInteger<uint16_t>(Value))
238d88c1a5aSDimitry Andric return EC;
239d88c1a5aSDimitry Andric } else if (Value <= std::numeric_limits<uint16_t>::max()) {
2407a7e6055SDimitry Andric if (auto EC = Writer->writeInteger<uint16_t>(LF_USHORT))
241d88c1a5aSDimitry Andric return EC;
2427a7e6055SDimitry Andric if (auto EC = Writer->writeInteger<uint16_t>(Value))
243d88c1a5aSDimitry Andric return EC;
244d88c1a5aSDimitry Andric } else if (Value <= std::numeric_limits<uint32_t>::max()) {
2457a7e6055SDimitry Andric if (auto EC = Writer->writeInteger<uint16_t>(LF_ULONG))
246d88c1a5aSDimitry Andric return EC;
2477a7e6055SDimitry Andric if (auto EC = Writer->writeInteger<uint32_t>(Value))
248d88c1a5aSDimitry Andric return EC;
249d88c1a5aSDimitry Andric } else {
2507a7e6055SDimitry Andric if (auto EC = Writer->writeInteger<uint16_t>(LF_UQUADWORD))
251d88c1a5aSDimitry Andric return EC;
252d88c1a5aSDimitry Andric if (auto EC = Writer->writeInteger(Value))
253d88c1a5aSDimitry Andric return EC;
254d88c1a5aSDimitry Andric }
255d88c1a5aSDimitry Andric
256d88c1a5aSDimitry Andric return Error::success();
257d88c1a5aSDimitry Andric }
258