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/StreamReader.h"
14 #include "llvm/DebugInfo/MSF/StreamWriter.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::mapInteger(TypeIndex &TypeInd) {
79   if (isWriting()) {
80     if (auto EC = Writer->writeInteger(TypeInd.getIndex()))
81       return EC;
82     return Error::success();
83   }
84 
85   uint32_t I;
86   if (auto EC = Reader->readInteger(I))
87     return EC;
88   TypeInd.setIndex(I);
89   return Error::success();
90 }
91 
92 Error CodeViewRecordIO::mapEncodedInteger(int64_t &Value) {
93   if (isWriting()) {
94     if (Value >= 0) {
95       if (auto EC = writeEncodedUnsignedInteger(static_cast<uint64_t>(Value)))
96         return EC;
97     } else {
98       if (auto EC = writeEncodedSignedInteger(Value))
99         return EC;
100     }
101   } else {
102     APSInt N;
103     if (auto EC = consume(*Reader, N))
104       return EC;
105     Value = N.getExtValue();
106   }
107 
108   return Error::success();
109 }
110 
111 Error CodeViewRecordIO::mapEncodedInteger(uint64_t &Value) {
112   if (isWriting()) {
113     if (auto EC = writeEncodedUnsignedInteger(Value))
114       return EC;
115   } else {
116     APSInt N;
117     if (auto EC = consume(*Reader, N))
118       return EC;
119     Value = N.getZExtValue();
120   }
121   return Error::success();
122 }
123 
124 Error CodeViewRecordIO::mapEncodedInteger(APSInt &Value) {
125   if (isWriting()) {
126     if (Value.isSigned())
127       return writeEncodedSignedInteger(Value.getSExtValue());
128     return writeEncodedUnsignedInteger(Value.getZExtValue());
129   }
130 
131   return consume(*Reader, Value);
132 }
133 
134 Error CodeViewRecordIO::mapStringZ(StringRef &Value) {
135   if (isWriting()) {
136     // Truncate if we attempt to write too much.
137     StringRef S = Value.take_front(maxFieldLength() - 1);
138     if (auto EC = Writer->writeZeroString(S))
139       return EC;
140   } else {
141     if (auto EC = Reader->readZeroString(Value))
142       return EC;
143   }
144   return Error::success();
145 }
146 
147 Error CodeViewRecordIO::mapGuid(StringRef &Guid) {
148   constexpr uint32_t GuidSize = 16;
149   if (maxFieldLength() < GuidSize)
150     return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
151 
152   if (isWriting()) {
153     assert(Guid.size() == 16 && "Invalid Guid Size!");
154     if (auto EC = Writer->writeFixedString(Guid))
155       return EC;
156   } else {
157     if (auto EC = Reader->readFixedString(Guid, 16))
158       return EC;
159   }
160   return Error::success();
161 }
162 
163 Error CodeViewRecordIO::writeEncodedSignedInteger(const int64_t &Value) {
164   assert(Value < 0 && "Encoded integer is not signed!");
165   if (Value >= std::numeric_limits<int8_t>::min()) {
166     if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_CHAR)))
167       return EC;
168     if (auto EC = Writer->writeInteger(static_cast<int8_t>(Value)))
169       return EC;
170   } else if (Value >= std::numeric_limits<int16_t>::min()) {
171     if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_SHORT)))
172       return EC;
173     if (auto EC = Writer->writeInteger(static_cast<int16_t>(Value)))
174       return EC;
175   } else if (Value >= std::numeric_limits<int32_t>::min()) {
176     if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_LONG)))
177       return EC;
178     if (auto EC = Writer->writeInteger(static_cast<int32_t>(Value)))
179       return EC;
180   } else {
181     if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_QUADWORD)))
182       return EC;
183     if (auto EC = Writer->writeInteger(Value))
184       return EC;
185   }
186   return Error::success();
187 }
188 
189 Error CodeViewRecordIO::writeEncodedUnsignedInteger(const uint64_t &Value) {
190   if (Value < LF_NUMERIC) {
191     if (auto EC = Writer->writeInteger(static_cast<uint16_t>(Value)))
192       return EC;
193   } else if (Value <= std::numeric_limits<uint16_t>::max()) {
194     if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_USHORT)))
195       return EC;
196     if (auto EC = Writer->writeInteger(static_cast<uint16_t>(Value)))
197       return EC;
198   } else if (Value <= std::numeric_limits<uint32_t>::max()) {
199     if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_ULONG)))
200       return EC;
201     if (auto EC = Writer->writeInteger(static_cast<uint32_t>(Value)))
202       return EC;
203   } else {
204     if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_UQUADWORD)))
205       return EC;
206     if (auto EC = Writer->writeInteger(Value))
207       return EC;
208   }
209 
210   return Error::success();
211 }
212