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/GUID.h" 12#include "llvm/DebugInfo/CodeView/RecordSerialization.h" 13#include "llvm/DebugInfo/CodeView/TypeIndex.h" 14#include "llvm/Support/BinaryStreamReader.h" 15#include "llvm/Support/BinaryStreamWriter.h" 16 17using namespace llvm; 18using namespace llvm::codeview; 19 20Error CodeViewRecordIO::beginRecord(std::optional<uint32_t> MaxLength) { 21 RecordLimit Limit; 22 Limit.MaxLength = MaxLength; 23 Limit.BeginOffset = getCurrentOffset(); 24 Limits.push_back(Limit); 25 return Error::success(); 26} 27 28Error CodeViewRecordIO::endRecord() { 29 assert(!Limits.empty() && "Not in a record!"); 30 Limits.pop_back(); 31 // We would like to assert that we actually read / wrote all the bytes that we 32 // expected to for this record, but unfortunately we can't do this. Some 33 // producers such as MASM over-allocate for certain types of records and 34 // commit the extraneous data, so when reading we can't be sure every byte 35 // will have been read. And when writing we over-allocate temporarily since 36 // we don't know how big the record is until we're finished writing it, so 37 // even though we don't commit the extraneous data, we still can't guarantee 38 // we're at the end of the allocated data. 39 40 if (isStreaming()) { 41 // For streaming mode, add padding to align with 4 byte boundaries for each 42 // record 43 uint32_t Align = getStreamedLen() % 4; 44 if (Align == 0) 45 return Error::success(); 46 47 int PaddingBytes = 4 - Align; 48 while (PaddingBytes > 0) { 49 char Pad = static_cast<uint8_t>(LF_PAD0 + PaddingBytes); 50 StringRef BytesSR = StringRef(&Pad, sizeof(Pad)); 51 Streamer->emitBytes(BytesSR); 52 --PaddingBytes; 53 } 54 resetStreamedLen(); 55 } 56 return Error::success(); 57} 58 59uint32_t CodeViewRecordIO::maxFieldLength() const { 60 if (isStreaming()) 61 return 0; 62 63 assert(!Limits.empty() && "Not in a record!"); 64 65 // The max length of the next field is the minimum of all lengths that would 66 // be allowed by any of the sub-records we're in. In practice, we can only 67 // ever be at most 1 sub-record deep (in a FieldList), but this works for 68 // the general case. 69 uint32_t Offset = getCurrentOffset(); 70 std::optional<uint32_t> Min = Limits.front().bytesRemaining(Offset); 71 for (auto X : ArrayRef(Limits).drop_front()) { 72 std::optional<uint32_t> ThisMin = X.bytesRemaining(Offset); 73 if (ThisMin) 74 Min = Min ? std::min(*Min, *ThisMin) : *ThisMin; 75 } 76 assert(Min && "Every field must have a maximum length!"); 77 78 return *Min; 79} 80 81Error CodeViewRecordIO::padToAlignment(uint32_t Align) { 82 if (isReading()) 83 return Reader->padToAlignment(Align); 84 return Writer->padToAlignment(Align); 85} 86 87Error CodeViewRecordIO::skipPadding() { 88 assert(!isWriting() && "Cannot skip padding while writing!"); 89 90 if (Reader->bytesRemaining() == 0) 91 return Error::success(); 92 93 uint8_t Leaf = Reader->peek(); 94 if (Leaf < LF_PAD0) 95 return Error::success(); 96 // Leaf is greater than 0xf0. We should advance by the number of bytes in 97 // the low 4 bits. 98 unsigned BytesToAdvance = Leaf & 0x0F; 99 return Reader->skip(BytesToAdvance); 100} 101 102Error CodeViewRecordIO::mapByteVectorTail(ArrayRef<uint8_t> &Bytes, 103 const Twine &Comment) { 104 if (isStreaming()) { 105 emitComment(Comment); 106 Streamer->emitBinaryData(toStringRef(Bytes)); 107 incrStreamedLen(Bytes.size()); 108 } else if (isWriting()) { 109 if (auto EC = Writer->writeBytes(Bytes)) 110 return EC; 111 } else { 112 if (auto EC = Reader->readBytes(Bytes, Reader->bytesRemaining())) 113 return EC; 114 } 115 return Error::success(); 116} 117 118Error CodeViewRecordIO::mapByteVectorTail(std::vector<uint8_t> &Bytes, 119 const Twine &Comment) { 120 ArrayRef<uint8_t> BytesRef(Bytes); 121 if (auto EC = mapByteVectorTail(BytesRef, Comment)) 122 return EC; 123 if (!isWriting()) 124 Bytes.assign(BytesRef.begin(), BytesRef.end()); 125 126 return Error::success(); 127} 128 129Error CodeViewRecordIO::mapInteger(TypeIndex &TypeInd, const Twine &Comment) { 130 if (isStreaming()) { 131 std::string TypeNameStr = Streamer->getTypeName(TypeInd); 132 if (!TypeNameStr.empty()) 133 emitComment(Comment + ": " + TypeNameStr); 134 else 135 emitComment(Comment); 136 Streamer->emitIntValue(TypeInd.getIndex(), sizeof(TypeInd.getIndex())); 137 incrStreamedLen(sizeof(TypeInd.getIndex())); 138 } else if (isWriting()) { 139 if (auto EC = Writer->writeInteger(TypeInd.getIndex())) 140 return EC; 141 } else { 142 uint32_t I; 143 if (auto EC = Reader->readInteger(I)) 144 return EC; 145 TypeInd.setIndex(I); 146 } 147 return Error::success(); 148} 149 150Error CodeViewRecordIO::mapEncodedInteger(int64_t &Value, 151 const Twine &Comment) { 152 if (isStreaming()) { 153 if (Value >= 0) 154 emitEncodedUnsignedInteger(static_cast<uint64_t>(Value), Comment); 155 else 156 emitEncodedSignedInteger(Value, Comment); 157 } else if (isWriting()) { 158 if (Value >= 0) { 159 if (auto EC = writeEncodedUnsignedInteger(static_cast<uint64_t>(Value))) 160 return EC; 161 } else { 162 if (auto EC = writeEncodedSignedInteger(Value)) 163 return EC; 164 } 165 } else { 166 APSInt N; 167 if (auto EC = consume(*Reader, N)) 168 return EC; 169 Value = N.getExtValue(); 170 } 171 172 return Error::success(); 173} 174 175Error CodeViewRecordIO::mapEncodedInteger(uint64_t &Value, 176 const Twine &Comment) { 177 if (isStreaming()) 178 emitEncodedUnsignedInteger(Value, Comment); 179 else if (isWriting()) { 180 if (auto EC = writeEncodedUnsignedInteger(Value)) 181 return EC; 182 } else { 183 APSInt N; 184 if (auto EC = consume(*Reader, N)) 185 return EC; 186 Value = N.getZExtValue(); 187 } 188 return Error::success(); 189} 190 191Error CodeViewRecordIO::mapEncodedInteger(APSInt &Value, const Twine &Comment) { 192 if (isStreaming()) { 193 // FIXME: We also need to handle big values here, but it's 194 // not clear how we can excercise this code path yet. 195 if (Value.isSigned()) 196 emitEncodedSignedInteger(Value.getSExtValue(), Comment); 197 else 198 emitEncodedUnsignedInteger(Value.getZExtValue(), Comment); 199 } else if (isWriting()) { 200 if (Value.isSigned()) 201 return writeEncodedSignedInteger( 202 Value.isSingleWord() ? Value.getSExtValue() : INT64_MIN); 203 return writeEncodedUnsignedInteger(Value.getLimitedValue()); 204 } else 205 return consume(*Reader, Value); 206 return Error::success(); 207} 208 209Error CodeViewRecordIO::mapStringZ(StringRef &Value, const Twine &Comment) { 210 if (isStreaming()) { 211 auto NullTerminatedString = StringRef(Value.data(), Value.size() + 1); 212 emitComment(Comment); 213 Streamer->emitBytes(NullTerminatedString); 214 incrStreamedLen(NullTerminatedString.size()); 215 } else if (isWriting()) { 216 // Truncate if we attempt to write too much. 217 StringRef S = Value.take_front(maxFieldLength() - 1); 218 if (auto EC = Writer->writeCString(S)) 219 return EC; 220 } else { 221 if (auto EC = Reader->readCString(Value)) 222 return EC; 223 } 224 return Error::success(); 225} 226 227Error CodeViewRecordIO::mapGuid(GUID &Guid, const Twine &Comment) { 228 constexpr uint32_t GuidSize = 16; 229 230 if (isStreaming()) { 231 StringRef GuidSR = 232 StringRef((reinterpret_cast<const char *>(&Guid)), GuidSize); 233 emitComment(Comment); 234 Streamer->emitBytes(GuidSR); 235 incrStreamedLen(GuidSize); 236 return Error::success(); 237 } 238 239 if (maxFieldLength() < GuidSize) 240 return make_error<CodeViewError>(cv_error_code::insufficient_buffer); 241 242 if (isWriting()) { 243 if (auto EC = Writer->writeBytes(Guid.Guid)) 244 return EC; 245 } else { 246 ArrayRef<uint8_t> GuidBytes; 247 if (auto EC = Reader->readBytes(GuidBytes, GuidSize)) 248 return EC; 249 memcpy(Guid.Guid, GuidBytes.data(), GuidSize); 250 } 251 return Error::success(); 252} 253 254Error CodeViewRecordIO::mapStringZVectorZ(std::vector<StringRef> &Value, 255 const Twine &Comment) { 256 257 if (!isReading()) { 258 emitComment(Comment); 259 for (auto V : Value) { 260 if (auto EC = mapStringZ(V)) 261 return EC; 262 } 263 uint8_t FinalZero = 0; 264 if (auto EC = mapInteger(FinalZero)) 265 return EC; 266 } else { 267 StringRef S; 268 if (auto EC = mapStringZ(S)) 269 return EC; 270 while (!S.empty()) { 271 Value.push_back(S); 272 if (auto EC = mapStringZ(S)) 273 return EC; 274 }; 275 } 276 return Error::success(); 277} 278 279void CodeViewRecordIO::emitEncodedSignedInteger(const int64_t &Value, 280 const Twine &Comment) { 281 // FIXME: There are no test cases covering this function. 282 // This may be because we always consider enumerators to be unsigned. 283 // See FIXME at CodeViewDebug.cpp : CodeViewDebug::lowerTypeEnum. 284 if (Value < LF_NUMERIC && Value >= 0) { 285 emitComment(Comment); 286 Streamer->emitIntValue(Value, 2); 287 incrStreamedLen(2); 288 } else if (Value >= std::numeric_limits<int8_t>::min() && 289 Value <= std::numeric_limits<int8_t>::max()) { 290 Streamer->emitIntValue(LF_CHAR, 2); 291 emitComment(Comment); 292 Streamer->emitIntValue(Value, 1); 293 incrStreamedLen(3); 294 } else if (Value >= std::numeric_limits<int16_t>::min() && 295 Value <= std::numeric_limits<int16_t>::max()) { 296 Streamer->emitIntValue(LF_SHORT, 2); 297 emitComment(Comment); 298 Streamer->emitIntValue(Value, 2); 299 incrStreamedLen(4); 300 } else if (Value >= std::numeric_limits<int32_t>::min() && 301 Value <= std::numeric_limits<int32_t>::max()) { 302 Streamer->emitIntValue(LF_LONG, 2); 303 emitComment(Comment); 304 Streamer->emitIntValue(Value, 4); 305 incrStreamedLen(6); 306 } else { 307 Streamer->emitIntValue(LF_QUADWORD, 2); 308 emitComment(Comment); 309 Streamer->emitIntValue(Value, 4); // FIXME: Why not 8 (size of quadword)? 310 incrStreamedLen(6); // FIXME: Why not 10 (8 + 2)? 311 } 312} 313 314void CodeViewRecordIO::emitEncodedUnsignedInteger(const uint64_t &Value, 315 const Twine &Comment) { 316 if (Value < LF_NUMERIC) { 317 emitComment(Comment); 318 Streamer->emitIntValue(Value, 2); 319 incrStreamedLen(2); 320 } else if (Value <= std::numeric_limits<uint16_t>::max()) { 321 Streamer->emitIntValue(LF_USHORT, 2); 322 emitComment(Comment); 323 Streamer->emitIntValue(Value, 2); 324 incrStreamedLen(4); 325 } else if (Value <= std::numeric_limits<uint32_t>::max()) { 326 Streamer->emitIntValue(LF_ULONG, 2); 327 emitComment(Comment); 328 Streamer->emitIntValue(Value, 4); 329 incrStreamedLen(6); 330 } else { 331 // FIXME: There are no test cases covering this block. 332 Streamer->emitIntValue(LF_UQUADWORD, 2); 333 emitComment(Comment); 334 Streamer->emitIntValue(Value, 8); 335 incrStreamedLen(6); // FIXME: Why not 10 (8 + 2)? 336 } 337} 338 339Error CodeViewRecordIO::writeEncodedSignedInteger(const int64_t &Value) { 340 if (Value < LF_NUMERIC && Value >= 0) { 341 if (auto EC = Writer->writeInteger<int16_t>(Value)) 342 return EC; 343 } else if (Value >= std::numeric_limits<int8_t>::min() && 344 Value <= std::numeric_limits<int8_t>::max()) { 345 if (auto EC = Writer->writeInteger<uint16_t>(LF_CHAR)) 346 return EC; 347 if (auto EC = Writer->writeInteger<int8_t>(Value)) 348 return EC; 349 } else if (Value >= std::numeric_limits<int16_t>::min() && 350 Value <= std::numeric_limits<int16_t>::max()) { 351 if (auto EC = Writer->writeInteger<uint16_t>(LF_SHORT)) 352 return EC; 353 if (auto EC = Writer->writeInteger<int16_t>(Value)) 354 return EC; 355 } else if (Value >= std::numeric_limits<int32_t>::min() && 356 Value <= std::numeric_limits<int32_t>::max()) { 357 if (auto EC = Writer->writeInteger<uint16_t>(LF_LONG)) 358 return EC; 359 if (auto EC = Writer->writeInteger<int32_t>(Value)) 360 return EC; 361 } else { 362 if (auto EC = Writer->writeInteger<uint16_t>(LF_QUADWORD)) 363 return EC; 364 if (auto EC = Writer->writeInteger(Value)) 365 return EC; 366 } 367 return Error::success(); 368} 369 370Error CodeViewRecordIO::writeEncodedUnsignedInteger(const uint64_t &Value) { 371 if (Value < LF_NUMERIC) { 372 if (auto EC = Writer->writeInteger<uint16_t>(Value)) 373 return EC; 374 } else if (Value <= std::numeric_limits<uint16_t>::max()) { 375 if (auto EC = Writer->writeInteger<uint16_t>(LF_USHORT)) 376 return EC; 377 if (auto EC = Writer->writeInteger<uint16_t>(Value)) 378 return EC; 379 } else if (Value <= std::numeric_limits<uint32_t>::max()) { 380 if (auto EC = Writer->writeInteger<uint16_t>(LF_ULONG)) 381 return EC; 382 if (auto EC = Writer->writeInteger<uint32_t>(Value)) 383 return EC; 384 } else { 385 if (auto EC = Writer->writeInteger<uint16_t>(LF_UQUADWORD)) 386 return EC; 387 if (auto EC = Writer->writeInteger(Value)) 388 return EC; 389 } 390 391 return Error::success(); 392} 393