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