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 15 using namespace llvm; 16 using namespace llvm::codeview; 17 18 Error CodeViewRecordIO::beginRecord(Optional<uint32_t> MaxLength) { 19 RecordLimit Limit; 20 Limit.MaxLength = MaxLength; 21 Limit.BeginOffset = getCurrentOffset(); 22 Limits.push_back(Limit); 23 resetStreamedLen(); 24 return Error::success(); 25 } 26 27 Error CodeViewRecordIO::endRecord() { 28 assert(!Limits.empty() && "Not in a record!"); 29 Limits.pop_back(); 30 // We would like to assert that we actually read / wrote all the bytes that we 31 // expected to for this record, but unfortunately we can't do this. Some 32 // producers such as MASM over-allocate for certain types of records and 33 // commit the extraneous data, so when reading we can't be sure every byte 34 // will have been read. And when writing we over-allocate temporarily since 35 // we don't know how big the record is until we're finished writing it, so 36 // even though we don't commit the extraneous data, we still can't guarantee 37 // we're at the end of the allocated data. 38 39 if (isStreaming()) { 40 // For streaming mode, add padding to align with 4 byte boundaries for each 41 // record 42 uint32_t Align = getStreamedLen() % 4; 43 if (Align == 0) 44 return Error::success(); 45 46 int PaddingBytes = 4 - Align; 47 while (PaddingBytes > 0) { 48 char Pad = static_cast<uint8_t>(LF_PAD0 + PaddingBytes); 49 StringRef BytesSR = StringRef(&Pad, sizeof(Pad)); 50 Streamer->EmitBytes(BytesSR); 51 --PaddingBytes; 52 } 53 } 54 return Error::success(); 55 } 56 57 uint32_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 79 Error CodeViewRecordIO::padToAlignment(uint32_t Align) { 80 if (isReading()) 81 return Reader->padToAlignment(Align); 82 return Writer->padToAlignment(Align); 83 } 84 85 Error 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 100 Error 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 116 Error 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 127 Error CodeViewRecordIO::mapInteger(TypeIndex &TypeInd, const Twine &Comment) { 128 if (isStreaming()) { 129 emitComment(Comment); 130 Streamer->EmitIntValue(TypeInd.getIndex(), sizeof(TypeInd.getIndex())); 131 incrStreamedLen(sizeof(TypeInd.getIndex())); 132 } else if (isWriting()) { 133 if (auto EC = Writer->writeInteger(TypeInd.getIndex())) 134 return EC; 135 } else { 136 uint32_t I; 137 if (auto EC = Reader->readInteger(I)) 138 return EC; 139 TypeInd.setIndex(I); 140 } 141 return Error::success(); 142 } 143 144 Error CodeViewRecordIO::mapEncodedInteger(int64_t &Value, 145 const Twine &Comment) { 146 if (isStreaming()) { 147 if (Value >= 0) 148 emitEncodedUnsignedInteger(static_cast<uint64_t>(Value), Comment); 149 else 150 emitEncodedSignedInteger(Value, Comment); 151 } else if (isWriting()) { 152 if (Value >= 0) { 153 if (auto EC = writeEncodedUnsignedInteger(static_cast<uint64_t>(Value))) 154 return EC; 155 } else { 156 if (auto EC = writeEncodedSignedInteger(Value)) 157 return EC; 158 } 159 } else { 160 APSInt N; 161 if (auto EC = consume(*Reader, N)) 162 return EC; 163 Value = N.getExtValue(); 164 } 165 166 return Error::success(); 167 } 168 169 Error CodeViewRecordIO::mapEncodedInteger(uint64_t &Value, 170 const Twine &Comment) { 171 if (isStreaming()) 172 emitEncodedUnsignedInteger(Value, Comment); 173 else if (isWriting()) { 174 if (auto EC = writeEncodedUnsignedInteger(Value)) 175 return EC; 176 } else { 177 APSInt N; 178 if (auto EC = consume(*Reader, N)) 179 return EC; 180 Value = N.getZExtValue(); 181 } 182 return Error::success(); 183 } 184 185 Error CodeViewRecordIO::mapEncodedInteger(APSInt &Value, const Twine &Comment) { 186 if (isStreaming()) { 187 if (Value.isSigned()) 188 emitEncodedSignedInteger(Value.getSExtValue(), Comment); 189 else 190 emitEncodedUnsignedInteger(Value.getZExtValue(), Comment); 191 } else if (isWriting()) { 192 if (Value.isSigned()) 193 return writeEncodedSignedInteger(Value.getSExtValue()); 194 return writeEncodedUnsignedInteger(Value.getZExtValue()); 195 } else 196 return consume(*Reader, Value); 197 return Error::success(); 198 } 199 200 Error CodeViewRecordIO::mapStringZ(StringRef &Value, const Twine &Comment) { 201 if (isStreaming()) { 202 auto NullTerminatedString = StringRef(Value.data(), Value.size() + 1); 203 emitComment(Comment); 204 Streamer->EmitBytes(NullTerminatedString); 205 incrStreamedLen(NullTerminatedString.size()); 206 } else if (isWriting()) { 207 // Truncate if we attempt to write too much. 208 StringRef S = Value.take_front(maxFieldLength() - 1); 209 if (auto EC = Writer->writeCString(S)) 210 return EC; 211 } else { 212 if (auto EC = Reader->readCString(Value)) 213 return EC; 214 } 215 return Error::success(); 216 } 217 218 Error CodeViewRecordIO::mapGuid(GUID &Guid, const Twine &Comment) { 219 constexpr uint32_t GuidSize = 16; 220 221 if (isStreaming()) { 222 StringRef GuidSR = 223 StringRef((reinterpret_cast<const char *>(&Guid)), GuidSize); 224 emitComment(Comment); 225 Streamer->EmitBytes(GuidSR); 226 incrStreamedLen(GuidSize); 227 return Error::success(); 228 } 229 230 if (maxFieldLength() < GuidSize) 231 return make_error<CodeViewError>(cv_error_code::insufficient_buffer); 232 233 if (isWriting()) { 234 if (auto EC = Writer->writeBytes(Guid.Guid)) 235 return EC; 236 } else { 237 ArrayRef<uint8_t> GuidBytes; 238 if (auto EC = Reader->readBytes(GuidBytes, GuidSize)) 239 return EC; 240 memcpy(Guid.Guid, GuidBytes.data(), GuidSize); 241 } 242 return Error::success(); 243 } 244 245 Error CodeViewRecordIO::mapStringZVectorZ(std::vector<StringRef> &Value, 246 const Twine &Comment) { 247 248 if (!isReading()) { 249 emitComment(Comment); 250 for (auto V : Value) { 251 if (auto EC = mapStringZ(V)) 252 return EC; 253 } 254 uint8_t FinalZero = 0; 255 if (auto EC = mapInteger(FinalZero)) 256 return EC; 257 } else { 258 StringRef S; 259 if (auto EC = mapStringZ(S)) 260 return EC; 261 while (!S.empty()) { 262 Value.push_back(S); 263 if (auto EC = mapStringZ(S)) 264 return EC; 265 }; 266 } 267 return Error::success(); 268 } 269 270 void CodeViewRecordIO::emitEncodedSignedInteger(const int64_t &Value, 271 const Twine &Comment) { 272 assert(Value < 0 && "Encoded integer is not signed!"); 273 if (Value >= std::numeric_limits<int8_t>::min()) { 274 Streamer->EmitIntValue(LF_CHAR, 2); 275 emitComment(Comment); 276 Streamer->EmitIntValue(Value, 1); 277 incrStreamedLen(3); 278 } else if (Value >= std::numeric_limits<int16_t>::min()) { 279 Streamer->EmitIntValue(LF_SHORT, 2); 280 emitComment(Comment); 281 Streamer->EmitIntValue(Value, 2); 282 incrStreamedLen(4); 283 } else if (Value >= std::numeric_limits<int32_t>::min()) { 284 Streamer->EmitIntValue(LF_LONG, 2); 285 emitComment(Comment); 286 Streamer->EmitIntValue(Value, 4); 287 incrStreamedLen(6); 288 } else { 289 Streamer->EmitIntValue(LF_QUADWORD, 2); 290 emitComment(Comment); 291 Streamer->EmitIntValue(Value, 4); 292 incrStreamedLen(6); 293 } 294 } 295 296 void CodeViewRecordIO::emitEncodedUnsignedInteger(const uint64_t &Value, 297 const Twine &Comment) { 298 if (Value < LF_NUMERIC) { 299 emitComment(Comment); 300 Streamer->EmitIntValue(Value, 2); 301 incrStreamedLen(2); 302 } else if (Value <= std::numeric_limits<uint16_t>::max()) { 303 Streamer->EmitIntValue(LF_USHORT, 2); 304 emitComment(Comment); 305 Streamer->EmitIntValue(Value, 2); 306 incrStreamedLen(4); 307 } else if (Value <= std::numeric_limits<uint32_t>::max()) { 308 Streamer->EmitIntValue(LF_ULONG, 2); 309 emitComment(Comment); 310 Streamer->EmitIntValue(Value, 4); 311 incrStreamedLen(6); 312 } else { 313 Streamer->EmitIntValue(LF_UQUADWORD, 2); 314 emitComment(Comment); 315 Streamer->EmitIntValue(Value, 8); 316 incrStreamedLen(6); 317 } 318 } 319 320 Error CodeViewRecordIO::writeEncodedSignedInteger(const int64_t &Value) { 321 assert(Value < 0 && "Encoded integer is not signed!"); 322 if (Value >= std::numeric_limits<int8_t>::min()) { 323 if (auto EC = Writer->writeInteger<uint16_t>(LF_CHAR)) 324 return EC; 325 if (auto EC = Writer->writeInteger<int8_t>(Value)) 326 return EC; 327 } else if (Value >= std::numeric_limits<int16_t>::min()) { 328 if (auto EC = Writer->writeInteger<uint16_t>(LF_SHORT)) 329 return EC; 330 if (auto EC = Writer->writeInteger<int16_t>(Value)) 331 return EC; 332 } else if (Value >= std::numeric_limits<int32_t>::min()) { 333 if (auto EC = Writer->writeInteger<uint16_t>(LF_LONG)) 334 return EC; 335 if (auto EC = Writer->writeInteger<int32_t>(Value)) 336 return EC; 337 } else { 338 if (auto EC = Writer->writeInteger<uint16_t>(LF_QUADWORD)) 339 return EC; 340 if (auto EC = Writer->writeInteger(Value)) 341 return EC; 342 } 343 return Error::success(); 344 } 345 346 Error CodeViewRecordIO::writeEncodedUnsignedInteger(const uint64_t &Value) { 347 if (Value < LF_NUMERIC) { 348 if (auto EC = Writer->writeInteger<uint16_t>(Value)) 349 return EC; 350 } else if (Value <= std::numeric_limits<uint16_t>::max()) { 351 if (auto EC = Writer->writeInteger<uint16_t>(LF_USHORT)) 352 return EC; 353 if (auto EC = Writer->writeInteger<uint16_t>(Value)) 354 return EC; 355 } else if (Value <= std::numeric_limits<uint32_t>::max()) { 356 if (auto EC = Writer->writeInteger<uint16_t>(LF_ULONG)) 357 return EC; 358 if (auto EC = Writer->writeInteger<uint32_t>(Value)) 359 return EC; 360 } else { 361 if (auto EC = Writer->writeInteger<uint16_t>(LF_UQUADWORD)) 362 return EC; 363 if (auto EC = Writer->writeInteger(Value)) 364 return EC; 365 } 366 367 return Error::success(); 368 } 369