17251ede7SZachary Turner //===- CodeViewRecordIO.cpp -------------------------------------*- C++ -*-===// 27251ede7SZachary Turner // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 67251ede7SZachary Turner // 77251ede7SZachary Turner //===----------------------------------------------------------------------===// 87251ede7SZachary Turner 97251ede7SZachary Turner #include "llvm/DebugInfo/CodeView/CodeViewRecordIO.h" 107251ede7SZachary Turner #include "llvm/DebugInfo/CodeView/CodeView.h" 117251ede7SZachary Turner #include "llvm/DebugInfo/CodeView/RecordSerialization.h" 12d9dc2829SZachary Turner #include "llvm/Support/BinaryStreamReader.h" 13d9dc2829SZachary Turner #include "llvm/Support/BinaryStreamWriter.h" 147251ede7SZachary Turner 157251ede7SZachary Turner using namespace llvm; 167251ede7SZachary Turner using namespace llvm::codeview; 177251ede7SZachary Turner 184efa0a42SZachary Turner Error CodeViewRecordIO::beginRecord(Optional<uint32_t> MaxLength) { 194efa0a42SZachary Turner RecordLimit Limit; 204efa0a42SZachary Turner Limit.MaxLength = MaxLength; 214efa0a42SZachary Turner Limit.BeginOffset = getCurrentOffset(); 224efa0a42SZachary Turner Limits.push_back(Limit); 23*faed8516SNilanjana Basu resetStreamedLen(); 247251ede7SZachary Turner return Error::success(); 257251ede7SZachary Turner } 267251ede7SZachary Turner 277251ede7SZachary Turner Error CodeViewRecordIO::endRecord() { 284efa0a42SZachary Turner assert(!Limits.empty() && "Not in a record!"); 294efa0a42SZachary Turner Limits.pop_back(); 30ebd3ae83SZachary Turner // We would like to assert that we actually read / wrote all the bytes that we 31ebd3ae83SZachary Turner // expected to for this record, but unfortunately we can't do this. Some 32ebd3ae83SZachary Turner // producers such as MASM over-allocate for certain types of records and 33ebd3ae83SZachary Turner // commit the extraneous data, so when reading we can't be sure every byte 34ebd3ae83SZachary Turner // will have been read. And when writing we over-allocate temporarily since 35ebd3ae83SZachary Turner // we don't know how big the record is until we're finished writing it, so 36ebd3ae83SZachary Turner // even though we don't commit the extraneous data, we still can't guarantee 37ebd3ae83SZachary Turner // we're at the end of the allocated data. 38*faed8516SNilanjana Basu 39*faed8516SNilanjana Basu if (isStreaming()) { 40*faed8516SNilanjana Basu // For streaming mode, add padding to align with 4 byte boundaries for each 41*faed8516SNilanjana Basu // record 42*faed8516SNilanjana Basu uint32_t Align = getStreamedLen() % 4; 43*faed8516SNilanjana Basu if (Align == 0) 44*faed8516SNilanjana Basu return Error::success(); 45*faed8516SNilanjana Basu 46*faed8516SNilanjana Basu int PaddingBytes = 4 - Align; 47*faed8516SNilanjana Basu while (PaddingBytes > 0) { 48*faed8516SNilanjana Basu char Pad = static_cast<uint8_t>(LF_PAD0 + PaddingBytes); 49*faed8516SNilanjana Basu StringRef BytesSR = StringRef(&Pad, sizeof(Pad)); 50*faed8516SNilanjana Basu Streamer->EmitBytes(BytesSR); 51*faed8516SNilanjana Basu --PaddingBytes; 52*faed8516SNilanjana Basu } 53*faed8516SNilanjana Basu } 547251ede7SZachary Turner return Error::success(); 557251ede7SZachary Turner } 567251ede7SZachary Turner 574efa0a42SZachary Turner uint32_t CodeViewRecordIO::maxFieldLength() const { 58*faed8516SNilanjana Basu if (isStreaming()) 59*faed8516SNilanjana Basu return 0; 60*faed8516SNilanjana Basu 614efa0a42SZachary Turner assert(!Limits.empty() && "Not in a record!"); 624efa0a42SZachary Turner 634efa0a42SZachary Turner // The max length of the next field is the minimum of all lengths that would 644efa0a42SZachary Turner // be allowed by any of the sub-records we're in. In practice, we can only 654efa0a42SZachary Turner // ever be at most 1 sub-record deep (in a FieldList), but this works for 664efa0a42SZachary Turner // the general case. 674efa0a42SZachary Turner uint32_t Offset = getCurrentOffset(); 684efa0a42SZachary Turner Optional<uint32_t> Min = Limits.front().bytesRemaining(Offset); 694efa0a42SZachary Turner for (auto X : makeArrayRef(Limits).drop_front()) { 704efa0a42SZachary Turner Optional<uint32_t> ThisMin = X.bytesRemaining(Offset); 714efa0a42SZachary Turner if (ThisMin.hasValue()) 724efa0a42SZachary Turner Min = (Min.hasValue()) ? std::min(*Min, *ThisMin) : *ThisMin; 734efa0a42SZachary Turner } 744efa0a42SZachary Turner assert(Min.hasValue() && "Every field must have a maximum length!"); 754efa0a42SZachary Turner 764efa0a42SZachary Turner return *Min; 774efa0a42SZachary Turner } 784efa0a42SZachary Turner 79ebd3ae83SZachary Turner Error CodeViewRecordIO::padToAlignment(uint32_t Align) { 80ebd3ae83SZachary Turner if (isReading()) 81ebd3ae83SZachary Turner return Reader->padToAlignment(Align); 82ebd3ae83SZachary Turner return Writer->padToAlignment(Align); 83ebd3ae83SZachary Turner } 84ebd3ae83SZachary Turner 857251ede7SZachary Turner Error CodeViewRecordIO::skipPadding() { 867251ede7SZachary Turner assert(!isWriting() && "Cannot skip padding while writing!"); 877251ede7SZachary Turner 887251ede7SZachary Turner if (Reader->bytesRemaining() == 0) 897251ede7SZachary Turner return Error::success(); 907251ede7SZachary Turner 917251ede7SZachary Turner uint8_t Leaf = Reader->peek(); 927251ede7SZachary Turner if (Leaf < LF_PAD0) 937251ede7SZachary Turner return Error::success(); 947251ede7SZachary Turner // Leaf is greater than 0xf0. We should advance by the number of bytes in 957251ede7SZachary Turner // the low 4 bits. 967251ede7SZachary Turner unsigned BytesToAdvance = Leaf & 0x0F; 977251ede7SZachary Turner return Reader->skip(BytesToAdvance); 987251ede7SZachary Turner } 997251ede7SZachary Turner 1007251ede7SZachary Turner Error CodeViewRecordIO::mapByteVectorTail(ArrayRef<uint8_t> &Bytes) { 101*faed8516SNilanjana Basu if (isStreaming()) { 102*faed8516SNilanjana Basu Streamer->EmitBinaryData(toStringRef(Bytes)); 103*faed8516SNilanjana Basu incrStreamedLen(Bytes.size()); 104*faed8516SNilanjana Basu } else if (isWriting()) { 1057251ede7SZachary Turner if (auto EC = Writer->writeBytes(Bytes)) 1067251ede7SZachary Turner return EC; 1077251ede7SZachary Turner } else { 1087251ede7SZachary Turner if (auto EC = Reader->readBytes(Bytes, Reader->bytesRemaining())) 1097251ede7SZachary Turner return EC; 1107251ede7SZachary Turner } 1117251ede7SZachary Turner return Error::success(); 1127251ede7SZachary Turner } 1137251ede7SZachary Turner 11446225b19SZachary Turner Error CodeViewRecordIO::mapByteVectorTail(std::vector<uint8_t> &Bytes) { 11546225b19SZachary Turner ArrayRef<uint8_t> BytesRef(Bytes); 11646225b19SZachary Turner if (auto EC = mapByteVectorTail(BytesRef)) 11746225b19SZachary Turner return EC; 11846225b19SZachary Turner if (!isWriting()) 11946225b19SZachary Turner Bytes.assign(BytesRef.begin(), BytesRef.end()); 12046225b19SZachary Turner 12146225b19SZachary Turner return Error::success(); 12246225b19SZachary Turner } 12346225b19SZachary Turner 1247251ede7SZachary Turner Error CodeViewRecordIO::mapInteger(TypeIndex &TypeInd) { 125*faed8516SNilanjana Basu if (isStreaming()) { 126*faed8516SNilanjana Basu Streamer->EmitIntValue(TypeInd.getIndex(), sizeof(TypeInd.getIndex())); 127*faed8516SNilanjana Basu incrStreamedLen(sizeof(TypeInd.getIndex())); 128*faed8516SNilanjana Basu } else if (isWriting()) { 129695ed56bSZachary Turner if (auto EC = Writer->writeInteger(TypeInd.getIndex())) 1307251ede7SZachary Turner return EC; 131*faed8516SNilanjana Basu } else { 1327251ede7SZachary Turner uint32_t I; 133695ed56bSZachary Turner if (auto EC = Reader->readInteger(I)) 1347251ede7SZachary Turner return EC; 1357251ede7SZachary Turner TypeInd.setIndex(I); 136*faed8516SNilanjana Basu } 1377251ede7SZachary Turner return Error::success(); 1387251ede7SZachary Turner } 1397251ede7SZachary Turner 1407251ede7SZachary Turner Error CodeViewRecordIO::mapEncodedInteger(int64_t &Value) { 141*faed8516SNilanjana Basu if (isStreaming()) { 142*faed8516SNilanjana Basu if (Value >= 0) 143*faed8516SNilanjana Basu emitEncodedUnsignedInteger(static_cast<uint64_t>(Value)); 144*faed8516SNilanjana Basu else 145*faed8516SNilanjana Basu emitEncodedSignedInteger(Value); 146*faed8516SNilanjana Basu } else if (isWriting()) { 1477251ede7SZachary Turner if (Value >= 0) { 1487251ede7SZachary Turner if (auto EC = writeEncodedUnsignedInteger(static_cast<uint64_t>(Value))) 1497251ede7SZachary Turner return EC; 1507251ede7SZachary Turner } else { 1517251ede7SZachary Turner if (auto EC = writeEncodedSignedInteger(Value)) 1527251ede7SZachary Turner return EC; 1537251ede7SZachary Turner } 1547251ede7SZachary Turner } else { 1557251ede7SZachary Turner APSInt N; 1567251ede7SZachary Turner if (auto EC = consume(*Reader, N)) 1577251ede7SZachary Turner return EC; 1587251ede7SZachary Turner Value = N.getExtValue(); 1597251ede7SZachary Turner } 1607251ede7SZachary Turner 1617251ede7SZachary Turner return Error::success(); 1627251ede7SZachary Turner } 1637251ede7SZachary Turner 1647251ede7SZachary Turner Error CodeViewRecordIO::mapEncodedInteger(uint64_t &Value) { 165*faed8516SNilanjana Basu if (isStreaming()) 166*faed8516SNilanjana Basu emitEncodedUnsignedInteger(Value); 167*faed8516SNilanjana Basu else if (isWriting()) { 1687251ede7SZachary Turner if (auto EC = writeEncodedUnsignedInteger(Value)) 1697251ede7SZachary Turner return EC; 1707251ede7SZachary Turner } else { 1717251ede7SZachary Turner APSInt N; 1727251ede7SZachary Turner if (auto EC = consume(*Reader, N)) 1737251ede7SZachary Turner return EC; 1747251ede7SZachary Turner Value = N.getZExtValue(); 1757251ede7SZachary Turner } 1767251ede7SZachary Turner return Error::success(); 1777251ede7SZachary Turner } 1787251ede7SZachary Turner 1797251ede7SZachary Turner Error CodeViewRecordIO::mapEncodedInteger(APSInt &Value) { 180*faed8516SNilanjana Basu if (isStreaming()) { 181*faed8516SNilanjana Basu if (Value.isSigned()) 182*faed8516SNilanjana Basu emitEncodedSignedInteger(Value.getSExtValue()); 183*faed8516SNilanjana Basu else 184*faed8516SNilanjana Basu emitEncodedUnsignedInteger(Value.getZExtValue()); 185*faed8516SNilanjana Basu } else if (isWriting()) { 1867251ede7SZachary Turner if (Value.isSigned()) 1877251ede7SZachary Turner return writeEncodedSignedInteger(Value.getSExtValue()); 1887251ede7SZachary Turner return writeEncodedUnsignedInteger(Value.getZExtValue()); 189*faed8516SNilanjana Basu } else 1907251ede7SZachary Turner return consume(*Reader, Value); 191*faed8516SNilanjana Basu return Error::success(); 1927251ede7SZachary Turner } 1937251ede7SZachary Turner 1947251ede7SZachary Turner Error CodeViewRecordIO::mapStringZ(StringRef &Value) { 195*faed8516SNilanjana Basu if (isStreaming()) { 196*faed8516SNilanjana Basu auto NullTerminatedString = StringRef(Value.data(), Value.size() + 1); 197*faed8516SNilanjana Basu Streamer->EmitBytes(NullTerminatedString); 198*faed8516SNilanjana Basu incrStreamedLen(NullTerminatedString.size()); 199*faed8516SNilanjana Basu } else if (isWriting()) { 2004efa0a42SZachary Turner // Truncate if we attempt to write too much. 2014efa0a42SZachary Turner StringRef S = Value.take_front(maxFieldLength() - 1); 202120faca4SZachary Turner if (auto EC = Writer->writeCString(S)) 2037251ede7SZachary Turner return EC; 2047251ede7SZachary Turner } else { 205120faca4SZachary Turner if (auto EC = Reader->readCString(Value)) 2067251ede7SZachary Turner return EC; 2077251ede7SZachary Turner } 2087251ede7SZachary Turner return Error::success(); 2097251ede7SZachary Turner } 2107251ede7SZachary Turner 21167653ee0SReid Kleckner Error CodeViewRecordIO::mapGuid(GUID &Guid) { 2124efa0a42SZachary Turner constexpr uint32_t GuidSize = 16; 213*faed8516SNilanjana Basu 214*faed8516SNilanjana Basu if (isStreaming()) { 215*faed8516SNilanjana Basu StringRef GuidSR = 216*faed8516SNilanjana Basu StringRef((reinterpret_cast<const char *>(&Guid)), GuidSize); 217*faed8516SNilanjana Basu Streamer->EmitBytes(GuidSR); 218*faed8516SNilanjana Basu incrStreamedLen(GuidSize); 219*faed8516SNilanjana Basu return Error::success(); 220*faed8516SNilanjana Basu } 221*faed8516SNilanjana Basu 2224efa0a42SZachary Turner if (maxFieldLength() < GuidSize) 2234efa0a42SZachary Turner return make_error<CodeViewError>(cv_error_code::insufficient_buffer); 2244efa0a42SZachary Turner 2257251ede7SZachary Turner if (isWriting()) { 22667653ee0SReid Kleckner if (auto EC = Writer->writeBytes(Guid.Guid)) 2277251ede7SZachary Turner return EC; 2287251ede7SZachary Turner } else { 22967653ee0SReid Kleckner ArrayRef<uint8_t> GuidBytes; 23067653ee0SReid Kleckner if (auto EC = Reader->readBytes(GuidBytes, GuidSize)) 2317251ede7SZachary Turner return EC; 23267653ee0SReid Kleckner memcpy(Guid.Guid, GuidBytes.data(), GuidSize); 2337251ede7SZachary Turner } 2347251ede7SZachary Turner return Error::success(); 2357251ede7SZachary Turner } 2367251ede7SZachary Turner 23746225b19SZachary Turner Error CodeViewRecordIO::mapStringZVectorZ(std::vector<StringRef> &Value) { 238*faed8516SNilanjana Basu 239*faed8516SNilanjana Basu if (!isReading()) { 24046225b19SZachary Turner for (auto V : Value) { 24146225b19SZachary Turner if (auto EC = mapStringZ(V)) 24246225b19SZachary Turner return EC; 24346225b19SZachary Turner } 244*faed8516SNilanjana Basu uint8_t FinalZero = 0; 245*faed8516SNilanjana Basu if (auto EC = mapInteger(FinalZero)) 24646225b19SZachary Turner return EC; 24746225b19SZachary Turner } else { 24846225b19SZachary Turner StringRef S; 24946225b19SZachary Turner if (auto EC = mapStringZ(S)) 25046225b19SZachary Turner return EC; 25146225b19SZachary Turner while (!S.empty()) { 25246225b19SZachary Turner Value.push_back(S); 25346225b19SZachary Turner if (auto EC = mapStringZ(S)) 25446225b19SZachary Turner return EC; 25546225b19SZachary Turner }; 25646225b19SZachary Turner } 25746225b19SZachary Turner return Error::success(); 25846225b19SZachary Turner } 25946225b19SZachary Turner 260*faed8516SNilanjana Basu void CodeViewRecordIO::emitEncodedSignedInteger(const int64_t &Value) { 261*faed8516SNilanjana Basu assert(Value < 0 && "Encoded integer is not signed!"); 262*faed8516SNilanjana Basu if (Value >= std::numeric_limits<int8_t>::min()) { 263*faed8516SNilanjana Basu Streamer->EmitIntValue(LF_CHAR, 2); 264*faed8516SNilanjana Basu Streamer->EmitIntValue(Value, 1); 265*faed8516SNilanjana Basu incrStreamedLen(3); 266*faed8516SNilanjana Basu } else if (Value >= std::numeric_limits<int16_t>::min()) { 267*faed8516SNilanjana Basu Streamer->EmitIntValue(LF_SHORT, 2); 268*faed8516SNilanjana Basu Streamer->EmitIntValue(Value, 2); 269*faed8516SNilanjana Basu incrStreamedLen(4); 270*faed8516SNilanjana Basu } else if (Value >= std::numeric_limits<int32_t>::min()) { 271*faed8516SNilanjana Basu Streamer->EmitIntValue(LF_LONG, 2); 272*faed8516SNilanjana Basu Streamer->EmitIntValue(Value, 4); 273*faed8516SNilanjana Basu incrStreamedLen(6); 274*faed8516SNilanjana Basu } else { 275*faed8516SNilanjana Basu Streamer->EmitIntValue(LF_QUADWORD, 2); 276*faed8516SNilanjana Basu Streamer->EmitIntValue(Value, 4); 277*faed8516SNilanjana Basu incrStreamedLen(6); 278*faed8516SNilanjana Basu } 279*faed8516SNilanjana Basu } 280*faed8516SNilanjana Basu 281*faed8516SNilanjana Basu void CodeViewRecordIO::emitEncodedUnsignedInteger(const uint64_t &Value) { 282*faed8516SNilanjana Basu if (Value < LF_NUMERIC) { 283*faed8516SNilanjana Basu Streamer->EmitIntValue(Value, 2); 284*faed8516SNilanjana Basu incrStreamedLen(2); 285*faed8516SNilanjana Basu } else if (Value <= std::numeric_limits<uint16_t>::max()) { 286*faed8516SNilanjana Basu Streamer->EmitIntValue(LF_USHORT, 2); 287*faed8516SNilanjana Basu Streamer->EmitIntValue(Value, 2); 288*faed8516SNilanjana Basu incrStreamedLen(4); 289*faed8516SNilanjana Basu } else if (Value <= std::numeric_limits<uint32_t>::max()) { 290*faed8516SNilanjana Basu Streamer->EmitIntValue(LF_ULONG, 2); 291*faed8516SNilanjana Basu Streamer->EmitIntValue(Value, 4); 292*faed8516SNilanjana Basu incrStreamedLen(6); 293*faed8516SNilanjana Basu } else { 294*faed8516SNilanjana Basu Streamer->EmitIntValue(LF_UQUADWORD, 2); 295*faed8516SNilanjana Basu Streamer->EmitIntValue(Value, 8); 296*faed8516SNilanjana Basu incrStreamedLen(6); 297*faed8516SNilanjana Basu } 298*faed8516SNilanjana Basu } 299*faed8516SNilanjana Basu 3007251ede7SZachary Turner Error CodeViewRecordIO::writeEncodedSignedInteger(const int64_t &Value) { 3017251ede7SZachary Turner assert(Value < 0 && "Encoded integer is not signed!"); 3027251ede7SZachary Turner if (Value >= std::numeric_limits<int8_t>::min()) { 303695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_CHAR)) 3047251ede7SZachary Turner return EC; 305695ed56bSZachary Turner if (auto EC = Writer->writeInteger<int8_t>(Value)) 3067251ede7SZachary Turner return EC; 3077251ede7SZachary Turner } else if (Value >= std::numeric_limits<int16_t>::min()) { 308695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_SHORT)) 3097251ede7SZachary Turner return EC; 310695ed56bSZachary Turner if (auto EC = Writer->writeInteger<int16_t>(Value)) 3117251ede7SZachary Turner return EC; 3127251ede7SZachary Turner } else if (Value >= std::numeric_limits<int32_t>::min()) { 313695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_LONG)) 3147251ede7SZachary Turner return EC; 315695ed56bSZachary Turner if (auto EC = Writer->writeInteger<int32_t>(Value)) 3167251ede7SZachary Turner return EC; 3177251ede7SZachary Turner } else { 318695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_QUADWORD)) 3197251ede7SZachary Turner return EC; 320695ed56bSZachary Turner if (auto EC = Writer->writeInteger(Value)) 3217251ede7SZachary Turner return EC; 3227251ede7SZachary Turner } 3237251ede7SZachary Turner return Error::success(); 3247251ede7SZachary Turner } 3257251ede7SZachary Turner 3267251ede7SZachary Turner Error CodeViewRecordIO::writeEncodedUnsignedInteger(const uint64_t &Value) { 3277251ede7SZachary Turner if (Value < LF_NUMERIC) { 328695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(Value)) 3297251ede7SZachary Turner return EC; 3307251ede7SZachary Turner } else if (Value <= std::numeric_limits<uint16_t>::max()) { 331695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_USHORT)) 3327251ede7SZachary Turner return EC; 333695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(Value)) 3347251ede7SZachary Turner return EC; 3357251ede7SZachary Turner } else if (Value <= std::numeric_limits<uint32_t>::max()) { 336695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_ULONG)) 3377251ede7SZachary Turner return EC; 338695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint32_t>(Value)) 3397251ede7SZachary Turner return EC; 3407251ede7SZachary Turner } else { 341695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_UQUADWORD)) 3427251ede7SZachary Turner return EC; 343695ed56bSZachary Turner if (auto EC = Writer->writeInteger(Value)) 3447251ede7SZachary Turner return EC; 3457251ede7SZachary Turner } 3467251ede7SZachary Turner 3477251ede7SZachary Turner return Error::success(); 3487251ede7SZachary Turner } 349