17251ede7SZachary Turner //===- CodeViewRecordIO.cpp -------------------------------------*- C++ -*-===// 27251ede7SZachary Turner // 3*2946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*2946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 5*2946cd70SChandler 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); 237251ede7SZachary Turner return Error::success(); 247251ede7SZachary Turner } 257251ede7SZachary Turner 267251ede7SZachary Turner Error CodeViewRecordIO::endRecord() { 274efa0a42SZachary Turner assert(!Limits.empty() && "Not in a record!"); 284efa0a42SZachary Turner Limits.pop_back(); 29ebd3ae83SZachary Turner // We would like to assert that we actually read / wrote all the bytes that we 30ebd3ae83SZachary Turner // expected to for this record, but unfortunately we can't do this. Some 31ebd3ae83SZachary Turner // producers such as MASM over-allocate for certain types of records and 32ebd3ae83SZachary Turner // commit the extraneous data, so when reading we can't be sure every byte 33ebd3ae83SZachary Turner // will have been read. And when writing we over-allocate temporarily since 34ebd3ae83SZachary Turner // we don't know how big the record is until we're finished writing it, so 35ebd3ae83SZachary Turner // even though we don't commit the extraneous data, we still can't guarantee 36ebd3ae83SZachary Turner // we're at the end of the allocated data. 377251ede7SZachary Turner return Error::success(); 387251ede7SZachary Turner } 397251ede7SZachary Turner 404efa0a42SZachary Turner uint32_t CodeViewRecordIO::maxFieldLength() const { 414efa0a42SZachary Turner assert(!Limits.empty() && "Not in a record!"); 424efa0a42SZachary Turner 434efa0a42SZachary Turner // The max length of the next field is the minimum of all lengths that would 444efa0a42SZachary Turner // be allowed by any of the sub-records we're in. In practice, we can only 454efa0a42SZachary Turner // ever be at most 1 sub-record deep (in a FieldList), but this works for 464efa0a42SZachary Turner // the general case. 474efa0a42SZachary Turner uint32_t Offset = getCurrentOffset(); 484efa0a42SZachary Turner Optional<uint32_t> Min = Limits.front().bytesRemaining(Offset); 494efa0a42SZachary Turner for (auto X : makeArrayRef(Limits).drop_front()) { 504efa0a42SZachary Turner Optional<uint32_t> ThisMin = X.bytesRemaining(Offset); 514efa0a42SZachary Turner if (ThisMin.hasValue()) 524efa0a42SZachary Turner Min = (Min.hasValue()) ? std::min(*Min, *ThisMin) : *ThisMin; 534efa0a42SZachary Turner } 544efa0a42SZachary Turner assert(Min.hasValue() && "Every field must have a maximum length!"); 554efa0a42SZachary Turner 564efa0a42SZachary Turner return *Min; 574efa0a42SZachary Turner } 584efa0a42SZachary Turner 59ebd3ae83SZachary Turner Error CodeViewRecordIO::padToAlignment(uint32_t Align) { 60ebd3ae83SZachary Turner if (isReading()) 61ebd3ae83SZachary Turner return Reader->padToAlignment(Align); 62ebd3ae83SZachary Turner return Writer->padToAlignment(Align); 63ebd3ae83SZachary Turner } 64ebd3ae83SZachary Turner 657251ede7SZachary Turner Error CodeViewRecordIO::skipPadding() { 667251ede7SZachary Turner assert(!isWriting() && "Cannot skip padding while writing!"); 677251ede7SZachary Turner 687251ede7SZachary Turner if (Reader->bytesRemaining() == 0) 697251ede7SZachary Turner return Error::success(); 707251ede7SZachary Turner 717251ede7SZachary Turner uint8_t Leaf = Reader->peek(); 727251ede7SZachary Turner if (Leaf < LF_PAD0) 737251ede7SZachary Turner return Error::success(); 747251ede7SZachary Turner // Leaf is greater than 0xf0. We should advance by the number of bytes in 757251ede7SZachary Turner // the low 4 bits. 767251ede7SZachary Turner unsigned BytesToAdvance = Leaf & 0x0F; 777251ede7SZachary Turner return Reader->skip(BytesToAdvance); 787251ede7SZachary Turner } 797251ede7SZachary Turner 807251ede7SZachary Turner Error CodeViewRecordIO::mapByteVectorTail(ArrayRef<uint8_t> &Bytes) { 817251ede7SZachary Turner if (isWriting()) { 827251ede7SZachary Turner if (auto EC = Writer->writeBytes(Bytes)) 837251ede7SZachary Turner return EC; 847251ede7SZachary Turner } else { 857251ede7SZachary Turner if (auto EC = Reader->readBytes(Bytes, Reader->bytesRemaining())) 867251ede7SZachary Turner return EC; 877251ede7SZachary Turner } 887251ede7SZachary Turner return Error::success(); 897251ede7SZachary Turner } 907251ede7SZachary Turner 9146225b19SZachary Turner Error CodeViewRecordIO::mapByteVectorTail(std::vector<uint8_t> &Bytes) { 9246225b19SZachary Turner ArrayRef<uint8_t> BytesRef(Bytes); 9346225b19SZachary Turner if (auto EC = mapByteVectorTail(BytesRef)) 9446225b19SZachary Turner return EC; 9546225b19SZachary Turner if (!isWriting()) 9646225b19SZachary Turner Bytes.assign(BytesRef.begin(), BytesRef.end()); 9746225b19SZachary Turner 9846225b19SZachary Turner return Error::success(); 9946225b19SZachary Turner } 10046225b19SZachary Turner 1017251ede7SZachary Turner Error CodeViewRecordIO::mapInteger(TypeIndex &TypeInd) { 1027251ede7SZachary Turner if (isWriting()) { 103695ed56bSZachary Turner if (auto EC = Writer->writeInteger(TypeInd.getIndex())) 1047251ede7SZachary Turner return EC; 1057251ede7SZachary Turner return Error::success(); 1067251ede7SZachary Turner } 1077251ede7SZachary Turner 1087251ede7SZachary Turner uint32_t I; 109695ed56bSZachary Turner if (auto EC = Reader->readInteger(I)) 1107251ede7SZachary Turner return EC; 1117251ede7SZachary Turner TypeInd.setIndex(I); 1127251ede7SZachary Turner return Error::success(); 1137251ede7SZachary Turner } 1147251ede7SZachary Turner 1157251ede7SZachary Turner Error CodeViewRecordIO::mapEncodedInteger(int64_t &Value) { 1167251ede7SZachary Turner if (isWriting()) { 1177251ede7SZachary Turner if (Value >= 0) { 1187251ede7SZachary Turner if (auto EC = writeEncodedUnsignedInteger(static_cast<uint64_t>(Value))) 1197251ede7SZachary Turner return EC; 1207251ede7SZachary Turner } else { 1217251ede7SZachary Turner if (auto EC = writeEncodedSignedInteger(Value)) 1227251ede7SZachary Turner return EC; 1237251ede7SZachary Turner } 1247251ede7SZachary Turner } else { 1257251ede7SZachary Turner APSInt N; 1267251ede7SZachary Turner if (auto EC = consume(*Reader, N)) 1277251ede7SZachary Turner return EC; 1287251ede7SZachary Turner Value = N.getExtValue(); 1297251ede7SZachary Turner } 1307251ede7SZachary Turner 1317251ede7SZachary Turner return Error::success(); 1327251ede7SZachary Turner } 1337251ede7SZachary Turner 1347251ede7SZachary Turner Error CodeViewRecordIO::mapEncodedInteger(uint64_t &Value) { 1357251ede7SZachary Turner if (isWriting()) { 1367251ede7SZachary Turner if (auto EC = writeEncodedUnsignedInteger(Value)) 1377251ede7SZachary Turner return EC; 1387251ede7SZachary Turner } else { 1397251ede7SZachary Turner APSInt N; 1407251ede7SZachary Turner if (auto EC = consume(*Reader, N)) 1417251ede7SZachary Turner return EC; 1427251ede7SZachary Turner Value = N.getZExtValue(); 1437251ede7SZachary Turner } 1447251ede7SZachary Turner return Error::success(); 1457251ede7SZachary Turner } 1467251ede7SZachary Turner 1477251ede7SZachary Turner Error CodeViewRecordIO::mapEncodedInteger(APSInt &Value) { 1487251ede7SZachary Turner if (isWriting()) { 1497251ede7SZachary Turner if (Value.isSigned()) 1507251ede7SZachary Turner return writeEncodedSignedInteger(Value.getSExtValue()); 1517251ede7SZachary Turner return writeEncodedUnsignedInteger(Value.getZExtValue()); 1527251ede7SZachary Turner } 1537251ede7SZachary Turner 1547251ede7SZachary Turner return consume(*Reader, Value); 1557251ede7SZachary Turner } 1567251ede7SZachary Turner 1577251ede7SZachary Turner Error CodeViewRecordIO::mapStringZ(StringRef &Value) { 1587251ede7SZachary Turner if (isWriting()) { 1594efa0a42SZachary Turner // Truncate if we attempt to write too much. 1604efa0a42SZachary Turner StringRef S = Value.take_front(maxFieldLength() - 1); 161120faca4SZachary Turner if (auto EC = Writer->writeCString(S)) 1627251ede7SZachary Turner return EC; 1637251ede7SZachary Turner } else { 164120faca4SZachary Turner if (auto EC = Reader->readCString(Value)) 1657251ede7SZachary Turner return EC; 1667251ede7SZachary Turner } 1677251ede7SZachary Turner return Error::success(); 1687251ede7SZachary Turner } 1697251ede7SZachary Turner 17067653ee0SReid Kleckner Error CodeViewRecordIO::mapGuid(GUID &Guid) { 1714efa0a42SZachary Turner constexpr uint32_t GuidSize = 16; 1724efa0a42SZachary Turner if (maxFieldLength() < GuidSize) 1734efa0a42SZachary Turner return make_error<CodeViewError>(cv_error_code::insufficient_buffer); 1744efa0a42SZachary Turner 1757251ede7SZachary Turner if (isWriting()) { 17667653ee0SReid Kleckner if (auto EC = Writer->writeBytes(Guid.Guid)) 1777251ede7SZachary Turner return EC; 1787251ede7SZachary Turner } else { 17967653ee0SReid Kleckner ArrayRef<uint8_t> GuidBytes; 18067653ee0SReid Kleckner if (auto EC = Reader->readBytes(GuidBytes, GuidSize)) 1817251ede7SZachary Turner return EC; 18267653ee0SReid Kleckner memcpy(Guid.Guid, GuidBytes.data(), GuidSize); 1837251ede7SZachary Turner } 1847251ede7SZachary Turner return Error::success(); 1857251ede7SZachary Turner } 1867251ede7SZachary Turner 18746225b19SZachary Turner Error CodeViewRecordIO::mapStringZVectorZ(std::vector<StringRef> &Value) { 18846225b19SZachary Turner if (isWriting()) { 18946225b19SZachary Turner for (auto V : Value) { 19046225b19SZachary Turner if (auto EC = mapStringZ(V)) 19146225b19SZachary Turner return EC; 19246225b19SZachary Turner } 193695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint8_t>(0)) 19446225b19SZachary Turner return EC; 19546225b19SZachary Turner } else { 19646225b19SZachary Turner StringRef S; 19746225b19SZachary Turner if (auto EC = mapStringZ(S)) 19846225b19SZachary Turner return EC; 19946225b19SZachary Turner while (!S.empty()) { 20046225b19SZachary Turner Value.push_back(S); 20146225b19SZachary Turner if (auto EC = mapStringZ(S)) 20246225b19SZachary Turner return EC; 20346225b19SZachary Turner }; 20446225b19SZachary Turner } 20546225b19SZachary Turner return Error::success(); 20646225b19SZachary Turner } 20746225b19SZachary Turner 2087251ede7SZachary Turner Error CodeViewRecordIO::writeEncodedSignedInteger(const int64_t &Value) { 2097251ede7SZachary Turner assert(Value < 0 && "Encoded integer is not signed!"); 2107251ede7SZachary Turner if (Value >= std::numeric_limits<int8_t>::min()) { 211695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_CHAR)) 2127251ede7SZachary Turner return EC; 213695ed56bSZachary Turner if (auto EC = Writer->writeInteger<int8_t>(Value)) 2147251ede7SZachary Turner return EC; 2157251ede7SZachary Turner } else if (Value >= std::numeric_limits<int16_t>::min()) { 216695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_SHORT)) 2177251ede7SZachary Turner return EC; 218695ed56bSZachary Turner if (auto EC = Writer->writeInteger<int16_t>(Value)) 2197251ede7SZachary Turner return EC; 2207251ede7SZachary Turner } else if (Value >= std::numeric_limits<int32_t>::min()) { 221695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_LONG)) 2227251ede7SZachary Turner return EC; 223695ed56bSZachary Turner if (auto EC = Writer->writeInteger<int32_t>(Value)) 2247251ede7SZachary Turner return EC; 2257251ede7SZachary Turner } else { 226695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_QUADWORD)) 2277251ede7SZachary Turner return EC; 228695ed56bSZachary Turner if (auto EC = Writer->writeInteger(Value)) 2297251ede7SZachary Turner return EC; 2307251ede7SZachary Turner } 2317251ede7SZachary Turner return Error::success(); 2327251ede7SZachary Turner } 2337251ede7SZachary Turner 2347251ede7SZachary Turner Error CodeViewRecordIO::writeEncodedUnsignedInteger(const uint64_t &Value) { 2357251ede7SZachary Turner if (Value < LF_NUMERIC) { 236695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(Value)) 2377251ede7SZachary Turner return EC; 2387251ede7SZachary Turner } else if (Value <= std::numeric_limits<uint16_t>::max()) { 239695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_USHORT)) 2407251ede7SZachary Turner return EC; 241695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(Value)) 2427251ede7SZachary Turner return EC; 2437251ede7SZachary Turner } else if (Value <= std::numeric_limits<uint32_t>::max()) { 244695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_ULONG)) 2457251ede7SZachary Turner return EC; 246695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint32_t>(Value)) 2477251ede7SZachary Turner return EC; 2487251ede7SZachary Turner } else { 249695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_UQUADWORD)) 2507251ede7SZachary Turner return EC; 251695ed56bSZachary Turner if (auto EC = Writer->writeInteger(Value)) 2527251ede7SZachary Turner return EC; 2537251ede7SZachary Turner } 2547251ede7SZachary Turner 2557251ede7SZachary Turner return Error::success(); 2567251ede7SZachary Turner } 257