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