17251ede7SZachary Turner //===- CodeViewRecordIO.cpp -------------------------------------*- C++ -*-===// 27251ede7SZachary Turner // 37251ede7SZachary Turner // The LLVM Compiler Infrastructure 47251ede7SZachary Turner // 57251ede7SZachary Turner // This file is distributed under the University of Illinois Open Source 67251ede7SZachary Turner // License. See LICENSE.TXT for details. 77251ede7SZachary Turner // 87251ede7SZachary Turner //===----------------------------------------------------------------------===// 97251ede7SZachary Turner 107251ede7SZachary Turner #include "llvm/DebugInfo/CodeView/CodeViewRecordIO.h" 117251ede7SZachary Turner #include "llvm/DebugInfo/CodeView/CodeView.h" 127251ede7SZachary Turner #include "llvm/DebugInfo/CodeView/RecordSerialization.h" 13d9dc2829SZachary Turner #include "llvm/Support/BinaryStreamReader.h" 14d9dc2829SZachary Turner #include "llvm/Support/BinaryStreamWriter.h" 157251ede7SZachary Turner 167251ede7SZachary Turner using namespace llvm; 177251ede7SZachary Turner using namespace llvm::codeview; 187251ede7SZachary Turner 194efa0a42SZachary Turner Error CodeViewRecordIO::beginRecord(Optional<uint32_t> MaxLength) { 204efa0a42SZachary Turner RecordLimit Limit; 214efa0a42SZachary Turner Limit.MaxLength = MaxLength; 224efa0a42SZachary Turner Limit.BeginOffset = getCurrentOffset(); 234efa0a42SZachary Turner Limits.push_back(Limit); 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. 387251ede7SZachary Turner return Error::success(); 397251ede7SZachary Turner } 407251ede7SZachary Turner 414efa0a42SZachary Turner uint32_t CodeViewRecordIO::maxFieldLength() const { 424efa0a42SZachary Turner assert(!Limits.empty() && "Not in a record!"); 434efa0a42SZachary Turner 444efa0a42SZachary Turner // The max length of the next field is the minimum of all lengths that would 454efa0a42SZachary Turner // be allowed by any of the sub-records we're in. In practice, we can only 464efa0a42SZachary Turner // ever be at most 1 sub-record deep (in a FieldList), but this works for 474efa0a42SZachary Turner // the general case. 484efa0a42SZachary Turner uint32_t Offset = getCurrentOffset(); 494efa0a42SZachary Turner Optional<uint32_t> Min = Limits.front().bytesRemaining(Offset); 504efa0a42SZachary Turner for (auto X : makeArrayRef(Limits).drop_front()) { 514efa0a42SZachary Turner Optional<uint32_t> ThisMin = X.bytesRemaining(Offset); 524efa0a42SZachary Turner if (ThisMin.hasValue()) 534efa0a42SZachary Turner Min = (Min.hasValue()) ? std::min(*Min, *ThisMin) : *ThisMin; 544efa0a42SZachary Turner } 554efa0a42SZachary Turner assert(Min.hasValue() && "Every field must have a maximum length!"); 564efa0a42SZachary Turner 574efa0a42SZachary Turner return *Min; 584efa0a42SZachary Turner } 594efa0a42SZachary Turner 60ebd3ae83SZachary Turner Error CodeViewRecordIO::padToAlignment(uint32_t Align) { 61ebd3ae83SZachary Turner if (isReading()) 62ebd3ae83SZachary Turner return Reader->padToAlignment(Align); 63ebd3ae83SZachary Turner return Writer->padToAlignment(Align); 64ebd3ae83SZachary Turner } 65ebd3ae83SZachary Turner 667251ede7SZachary Turner Error CodeViewRecordIO::skipPadding() { 677251ede7SZachary Turner assert(!isWriting() && "Cannot skip padding while writing!"); 687251ede7SZachary Turner 697251ede7SZachary Turner if (Reader->bytesRemaining() == 0) 707251ede7SZachary Turner return Error::success(); 717251ede7SZachary Turner 727251ede7SZachary Turner uint8_t Leaf = Reader->peek(); 737251ede7SZachary Turner if (Leaf < LF_PAD0) 747251ede7SZachary Turner return Error::success(); 757251ede7SZachary Turner // Leaf is greater than 0xf0. We should advance by the number of bytes in 767251ede7SZachary Turner // the low 4 bits. 777251ede7SZachary Turner unsigned BytesToAdvance = Leaf & 0x0F; 787251ede7SZachary Turner return Reader->skip(BytesToAdvance); 797251ede7SZachary Turner } 807251ede7SZachary Turner 817251ede7SZachary Turner Error CodeViewRecordIO::mapByteVectorTail(ArrayRef<uint8_t> &Bytes) { 827251ede7SZachary Turner if (isWriting()) { 837251ede7SZachary Turner if (auto EC = Writer->writeBytes(Bytes)) 847251ede7SZachary Turner return EC; 857251ede7SZachary Turner } else { 867251ede7SZachary Turner if (auto EC = Reader->readBytes(Bytes, Reader->bytesRemaining())) 877251ede7SZachary Turner return EC; 887251ede7SZachary Turner } 897251ede7SZachary Turner return Error::success(); 907251ede7SZachary Turner } 917251ede7SZachary Turner 9246225b19SZachary Turner Error CodeViewRecordIO::mapByteVectorTail(std::vector<uint8_t> &Bytes) { 9346225b19SZachary Turner ArrayRef<uint8_t> BytesRef(Bytes); 9446225b19SZachary Turner if (auto EC = mapByteVectorTail(BytesRef)) 9546225b19SZachary Turner return EC; 9646225b19SZachary Turner if (!isWriting()) 9746225b19SZachary Turner Bytes.assign(BytesRef.begin(), BytesRef.end()); 9846225b19SZachary Turner 9946225b19SZachary Turner return Error::success(); 10046225b19SZachary Turner } 10146225b19SZachary Turner 1027251ede7SZachary Turner Error CodeViewRecordIO::mapInteger(TypeIndex &TypeInd) { 1037251ede7SZachary Turner if (isWriting()) { 104695ed56bSZachary Turner if (auto EC = Writer->writeInteger(TypeInd.getIndex())) 1057251ede7SZachary Turner return EC; 1067251ede7SZachary Turner return Error::success(); 1077251ede7SZachary Turner } 1087251ede7SZachary Turner 1097251ede7SZachary Turner uint32_t I; 110695ed56bSZachary Turner if (auto EC = Reader->readInteger(I)) 1117251ede7SZachary Turner return EC; 1127251ede7SZachary Turner TypeInd.setIndex(I); 1137251ede7SZachary Turner return Error::success(); 1147251ede7SZachary Turner } 1157251ede7SZachary Turner 1167251ede7SZachary Turner Error CodeViewRecordIO::mapEncodedInteger(int64_t &Value) { 1177251ede7SZachary Turner if (isWriting()) { 1187251ede7SZachary Turner if (Value >= 0) { 1197251ede7SZachary Turner if (auto EC = writeEncodedUnsignedInteger(static_cast<uint64_t>(Value))) 1207251ede7SZachary Turner return EC; 1217251ede7SZachary Turner } else { 1227251ede7SZachary Turner if (auto EC = writeEncodedSignedInteger(Value)) 1237251ede7SZachary Turner return EC; 1247251ede7SZachary Turner } 1257251ede7SZachary Turner } else { 1267251ede7SZachary Turner APSInt N; 1277251ede7SZachary Turner if (auto EC = consume(*Reader, N)) 1287251ede7SZachary Turner return EC; 1297251ede7SZachary Turner Value = N.getExtValue(); 1307251ede7SZachary Turner } 1317251ede7SZachary Turner 1327251ede7SZachary Turner return Error::success(); 1337251ede7SZachary Turner } 1347251ede7SZachary Turner 1357251ede7SZachary Turner Error CodeViewRecordIO::mapEncodedInteger(uint64_t &Value) { 1367251ede7SZachary Turner if (isWriting()) { 1377251ede7SZachary Turner if (auto EC = writeEncodedUnsignedInteger(Value)) 1387251ede7SZachary Turner return EC; 1397251ede7SZachary Turner } else { 1407251ede7SZachary Turner APSInt N; 1417251ede7SZachary Turner if (auto EC = consume(*Reader, N)) 1427251ede7SZachary Turner return EC; 1437251ede7SZachary Turner Value = N.getZExtValue(); 1447251ede7SZachary Turner } 1457251ede7SZachary Turner return Error::success(); 1467251ede7SZachary Turner } 1477251ede7SZachary Turner 1487251ede7SZachary Turner Error CodeViewRecordIO::mapEncodedInteger(APSInt &Value) { 1497251ede7SZachary Turner if (isWriting()) { 1507251ede7SZachary Turner if (Value.isSigned()) 1517251ede7SZachary Turner return writeEncodedSignedInteger(Value.getSExtValue()); 1527251ede7SZachary Turner return writeEncodedUnsignedInteger(Value.getZExtValue()); 1537251ede7SZachary Turner } 1547251ede7SZachary Turner 1557251ede7SZachary Turner return consume(*Reader, Value); 1567251ede7SZachary Turner } 1577251ede7SZachary Turner 1587251ede7SZachary Turner Error CodeViewRecordIO::mapStringZ(StringRef &Value) { 1597251ede7SZachary Turner if (isWriting()) { 1604efa0a42SZachary Turner // Truncate if we attempt to write too much. 1614efa0a42SZachary Turner StringRef S = Value.take_front(maxFieldLength() - 1); 162120faca4SZachary Turner if (auto EC = Writer->writeCString(S)) 1637251ede7SZachary Turner return EC; 1647251ede7SZachary Turner } else { 165120faca4SZachary Turner if (auto EC = Reader->readCString(Value)) 1667251ede7SZachary Turner return EC; 1677251ede7SZachary Turner } 1687251ede7SZachary Turner return Error::success(); 1697251ede7SZachary Turner } 1707251ede7SZachary Turner 171*67653ee0SReid Kleckner Error CodeViewRecordIO::mapGuid(GUID &Guid) { 1724efa0a42SZachary Turner constexpr uint32_t GuidSize = 16; 1734efa0a42SZachary Turner if (maxFieldLength() < GuidSize) 1744efa0a42SZachary Turner return make_error<CodeViewError>(cv_error_code::insufficient_buffer); 1754efa0a42SZachary Turner 1767251ede7SZachary Turner if (isWriting()) { 177*67653ee0SReid Kleckner if (auto EC = Writer->writeBytes(Guid.Guid)) 1787251ede7SZachary Turner return EC; 1797251ede7SZachary Turner } else { 180*67653ee0SReid Kleckner ArrayRef<uint8_t> GuidBytes; 181*67653ee0SReid Kleckner if (auto EC = Reader->readBytes(GuidBytes, GuidSize)) 1827251ede7SZachary Turner return EC; 183*67653ee0SReid Kleckner memcpy(Guid.Guid, GuidBytes.data(), GuidSize); 1847251ede7SZachary Turner } 1857251ede7SZachary Turner return Error::success(); 1867251ede7SZachary Turner } 1877251ede7SZachary Turner 18846225b19SZachary Turner Error CodeViewRecordIO::mapStringZVectorZ(std::vector<StringRef> &Value) { 18946225b19SZachary Turner if (isWriting()) { 19046225b19SZachary Turner for (auto V : Value) { 19146225b19SZachary Turner if (auto EC = mapStringZ(V)) 19246225b19SZachary Turner return EC; 19346225b19SZachary Turner } 194695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint8_t>(0)) 19546225b19SZachary Turner return EC; 19646225b19SZachary Turner } else { 19746225b19SZachary Turner StringRef S; 19846225b19SZachary Turner if (auto EC = mapStringZ(S)) 19946225b19SZachary Turner return EC; 20046225b19SZachary Turner while (!S.empty()) { 20146225b19SZachary Turner Value.push_back(S); 20246225b19SZachary Turner if (auto EC = mapStringZ(S)) 20346225b19SZachary Turner return EC; 20446225b19SZachary Turner }; 20546225b19SZachary Turner } 20646225b19SZachary Turner return Error::success(); 20746225b19SZachary Turner } 20846225b19SZachary Turner 2097251ede7SZachary Turner Error CodeViewRecordIO::writeEncodedSignedInteger(const int64_t &Value) { 2107251ede7SZachary Turner assert(Value < 0 && "Encoded integer is not signed!"); 2117251ede7SZachary Turner if (Value >= std::numeric_limits<int8_t>::min()) { 212695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_CHAR)) 2137251ede7SZachary Turner return EC; 214695ed56bSZachary Turner if (auto EC = Writer->writeInteger<int8_t>(Value)) 2157251ede7SZachary Turner return EC; 2167251ede7SZachary Turner } else if (Value >= std::numeric_limits<int16_t>::min()) { 217695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_SHORT)) 2187251ede7SZachary Turner return EC; 219695ed56bSZachary Turner if (auto EC = Writer->writeInteger<int16_t>(Value)) 2207251ede7SZachary Turner return EC; 2217251ede7SZachary Turner } else if (Value >= std::numeric_limits<int32_t>::min()) { 222695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_LONG)) 2237251ede7SZachary Turner return EC; 224695ed56bSZachary Turner if (auto EC = Writer->writeInteger<int32_t>(Value)) 2257251ede7SZachary Turner return EC; 2267251ede7SZachary Turner } else { 227695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_QUADWORD)) 2287251ede7SZachary Turner return EC; 229695ed56bSZachary Turner if (auto EC = Writer->writeInteger(Value)) 2307251ede7SZachary Turner return EC; 2317251ede7SZachary Turner } 2327251ede7SZachary Turner return Error::success(); 2337251ede7SZachary Turner } 2347251ede7SZachary Turner 2357251ede7SZachary Turner Error CodeViewRecordIO::writeEncodedUnsignedInteger(const uint64_t &Value) { 2367251ede7SZachary Turner if (Value < LF_NUMERIC) { 237695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(Value)) 2387251ede7SZachary Turner return EC; 2397251ede7SZachary Turner } else if (Value <= std::numeric_limits<uint16_t>::max()) { 240695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_USHORT)) 2417251ede7SZachary Turner return EC; 242695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(Value)) 2437251ede7SZachary Turner return EC; 2447251ede7SZachary Turner } else if (Value <= std::numeric_limits<uint32_t>::max()) { 245695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_ULONG)) 2467251ede7SZachary Turner return EC; 247695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint32_t>(Value)) 2487251ede7SZachary Turner return EC; 2497251ede7SZachary Turner } else { 250695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_UQUADWORD)) 2517251ede7SZachary Turner return EC; 252695ed56bSZachary Turner if (auto EC = Writer->writeInteger(Value)) 2537251ede7SZachary Turner return EC; 2547251ede7SZachary Turner } 2557251ede7SZachary Turner 2567251ede7SZachary Turner return Error::success(); 2577251ede7SZachary Turner } 258