1 //===- CodeViewRecordIO.cpp -------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
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/BinaryStreamReader.h"
14 #include "llvm/DebugInfo/MSF/BinaryStreamWriter.h"
15 
16 using namespace llvm;
17 using namespace llvm::codeview;
18 
19 Error CodeViewRecordIO::beginRecord(Optional<uint32_t> MaxLength) {
20   RecordLimit Limit;
21   Limit.MaxLength = MaxLength;
22   Limit.BeginOffset = getCurrentOffset();
23   Limits.push_back(Limit);
24   return Error::success();
25 }
26 
27 Error CodeViewRecordIO::endRecord() {
28   assert(!Limits.empty() && "Not in a record!");
29   Limits.pop_back();
30   return Error::success();
31 }
32 
33 uint32_t CodeViewRecordIO::maxFieldLength() const {
34   assert(!Limits.empty() && "Not in a record!");
35 
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
39   // the general case.
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;
46   }
47   assert(Min.hasValue() && "Every field must have a maximum length!");
48 
49   return *Min;
50 }
51 
52 Error CodeViewRecordIO::skipPadding() {
53   assert(!isWriting() && "Cannot skip padding while writing!");
54 
55   if (Reader->bytesRemaining() == 0)
56     return Error::success();
57 
58   uint8_t Leaf = Reader->peek();
59   if (Leaf < LF_PAD0)
60     return Error::success();
61   // Leaf is greater than 0xf0. We should advance by the number of bytes in
62   // the low 4 bits.
63   unsigned BytesToAdvance = Leaf & 0x0F;
64   return Reader->skip(BytesToAdvance);
65 }
66 
67 Error CodeViewRecordIO::mapByteVectorTail(ArrayRef<uint8_t> &Bytes) {
68   if (isWriting()) {
69     if (auto EC = Writer->writeBytes(Bytes))
70       return EC;
71   } else {
72     if (auto EC = Reader->readBytes(Bytes, Reader->bytesRemaining()))
73       return EC;
74   }
75   return Error::success();
76 }
77 
78 Error CodeViewRecordIO::mapByteVectorTail(std::vector<uint8_t> &Bytes) {
79   ArrayRef<uint8_t> BytesRef(Bytes);
80   if (auto EC = mapByteVectorTail(BytesRef))
81     return EC;
82   if (!isWriting())
83     Bytes.assign(BytesRef.begin(), BytesRef.end());
84 
85   return Error::success();
86 }
87 
88 Error CodeViewRecordIO::mapInteger(TypeIndex &TypeInd) {
89   if (isWriting()) {
90     if (auto EC =
91             Writer->writeInteger(TypeInd.getIndex(), llvm::support::little))
92       return EC;
93     return Error::success();
94   }
95 
96   uint32_t I;
97   if (auto EC = Reader->readInteger(I, llvm::support::little))
98     return EC;
99   TypeInd.setIndex(I);
100   return Error::success();
101 }
102 
103 Error CodeViewRecordIO::mapEncodedInteger(int64_t &Value) {
104   if (isWriting()) {
105     if (Value >= 0) {
106       if (auto EC = writeEncodedUnsignedInteger(static_cast<uint64_t>(Value)))
107         return EC;
108     } else {
109       if (auto EC = writeEncodedSignedInteger(Value))
110         return EC;
111     }
112   } else {
113     APSInt N;
114     if (auto EC = consume(*Reader, N))
115       return EC;
116     Value = N.getExtValue();
117   }
118 
119   return Error::success();
120 }
121 
122 Error CodeViewRecordIO::mapEncodedInteger(uint64_t &Value) {
123   if (isWriting()) {
124     if (auto EC = writeEncodedUnsignedInteger(Value))
125       return EC;
126   } else {
127     APSInt N;
128     if (auto EC = consume(*Reader, N))
129       return EC;
130     Value = N.getZExtValue();
131   }
132   return Error::success();
133 }
134 
135 Error CodeViewRecordIO::mapEncodedInteger(APSInt &Value) {
136   if (isWriting()) {
137     if (Value.isSigned())
138       return writeEncodedSignedInteger(Value.getSExtValue());
139     return writeEncodedUnsignedInteger(Value.getZExtValue());
140   }
141 
142   return consume(*Reader, Value);
143 }
144 
145 Error CodeViewRecordIO::mapStringZ(StringRef &Value) {
146   if (isWriting()) {
147     // Truncate if we attempt to write too much.
148     StringRef S = Value.take_front(maxFieldLength() - 1);
149     if (auto EC = Writer->writeCString(S))
150       return EC;
151   } else {
152     if (auto EC = Reader->readCString(Value))
153       return EC;
154   }
155   return Error::success();
156 }
157 
158 Error CodeViewRecordIO::mapGuid(StringRef &Guid) {
159   constexpr uint32_t GuidSize = 16;
160   if (maxFieldLength() < GuidSize)
161     return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
162 
163   if (isWriting()) {
164     assert(Guid.size() == 16 && "Invalid Guid Size!");
165     if (auto EC = Writer->writeFixedString(Guid))
166       return EC;
167   } else {
168     if (auto EC = Reader->readFixedString(Guid, 16))
169       return EC;
170   }
171   return Error::success();
172 }
173 
174 Error CodeViewRecordIO::mapStringZVectorZ(std::vector<StringRef> &Value) {
175   if (isWriting()) {
176     for (auto V : Value) {
177       if (auto EC = mapStringZ(V))
178         return EC;
179     }
180     if (auto EC = Writer->writeInteger<uint8_t>(0, llvm::support::little))
181       return EC;
182   } else {
183     StringRef S;
184     if (auto EC = mapStringZ(S))
185       return EC;
186     while (!S.empty()) {
187       Value.push_back(S);
188       if (auto EC = mapStringZ(S))
189         return EC;
190     };
191   }
192   return Error::success();
193 }
194 
195 Error CodeViewRecordIO::writeEncodedSignedInteger(const int64_t &Value) {
196   assert(Value < 0 && "Encoded integer is not signed!");
197   if (Value >= std::numeric_limits<int8_t>::min()) {
198     if (auto EC =
199             Writer->writeInteger<uint16_t>(LF_CHAR, llvm::support::little))
200       return EC;
201     if (auto EC = Writer->writeInteger<int8_t>(Value, llvm::support::little))
202       return EC;
203   } else if (Value >= std::numeric_limits<int16_t>::min()) {
204     if (auto EC =
205             Writer->writeInteger<uint16_t>(LF_SHORT, llvm::support::little))
206       return EC;
207     if (auto EC = Writer->writeInteger<int16_t>(Value, llvm::support::little))
208       return EC;
209   } else if (Value >= std::numeric_limits<int32_t>::min()) {
210     if (auto EC =
211             Writer->writeInteger<uint16_t>(LF_LONG, llvm::support::little))
212       return EC;
213     if (auto EC = Writer->writeInteger<int32_t>(Value, llvm::support::little))
214       return EC;
215   } else {
216     if (auto EC =
217             Writer->writeInteger<uint16_t>(LF_QUADWORD, llvm::support::little))
218       return EC;
219     if (auto EC = Writer->writeInteger(Value, llvm::support::little))
220       return EC;
221   }
222   return Error::success();
223 }
224 
225 Error CodeViewRecordIO::writeEncodedUnsignedInteger(const uint64_t &Value) {
226   if (Value < LF_NUMERIC) {
227     if (auto EC = Writer->writeInteger<uint16_t>(Value, llvm::support::little))
228       return EC;
229   } else if (Value <= std::numeric_limits<uint16_t>::max()) {
230     if (auto EC =
231             Writer->writeInteger<uint16_t>(LF_USHORT, llvm::support::little))
232       return EC;
233     if (auto EC = Writer->writeInteger<uint16_t>(Value, llvm::support::little))
234       return EC;
235   } else if (Value <= std::numeric_limits<uint32_t>::max()) {
236     if (auto EC =
237             Writer->writeInteger<uint16_t>(LF_ULONG, llvm::support::little))
238       return EC;
239     if (auto EC = Writer->writeInteger<uint32_t>(Value, llvm::support::little))
240       return EC;
241   } else {
242     if (auto EC =
243             Writer->writeInteger<uint16_t>(LF_UQUADWORD, llvm::support::little))
244       return EC;
245     if (auto EC = Writer->writeInteger(Value, llvm::support::little))
246       return EC;
247   }
248 
249   return Error::success();
250 }
251