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" 13*d9dc2829SZachary Turner #include "llvm/Support/BinaryStreamReader.h" 14*d9dc2829SZachary 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(); 307251ede7SZachary Turner return Error::success(); 317251ede7SZachary Turner } 327251ede7SZachary Turner 334efa0a42SZachary Turner uint32_t CodeViewRecordIO::maxFieldLength() const { 344efa0a42SZachary Turner assert(!Limits.empty() && "Not in a record!"); 354efa0a42SZachary Turner 364efa0a42SZachary Turner // The max length of the next field is the minimum of all lengths that would 374efa0a42SZachary Turner // be allowed by any of the sub-records we're in. In practice, we can only 384efa0a42SZachary Turner // ever be at most 1 sub-record deep (in a FieldList), but this works for 394efa0a42SZachary Turner // the general case. 404efa0a42SZachary Turner uint32_t Offset = getCurrentOffset(); 414efa0a42SZachary Turner Optional<uint32_t> Min = Limits.front().bytesRemaining(Offset); 424efa0a42SZachary Turner for (auto X : makeArrayRef(Limits).drop_front()) { 434efa0a42SZachary Turner Optional<uint32_t> ThisMin = X.bytesRemaining(Offset); 444efa0a42SZachary Turner if (ThisMin.hasValue()) 454efa0a42SZachary Turner Min = (Min.hasValue()) ? std::min(*Min, *ThisMin) : *ThisMin; 464efa0a42SZachary Turner } 474efa0a42SZachary Turner assert(Min.hasValue() && "Every field must have a maximum length!"); 484efa0a42SZachary Turner 494efa0a42SZachary Turner return *Min; 504efa0a42SZachary Turner } 514efa0a42SZachary Turner 527251ede7SZachary Turner Error CodeViewRecordIO::skipPadding() { 537251ede7SZachary Turner assert(!isWriting() && "Cannot skip padding while writing!"); 547251ede7SZachary Turner 557251ede7SZachary Turner if (Reader->bytesRemaining() == 0) 567251ede7SZachary Turner return Error::success(); 577251ede7SZachary Turner 587251ede7SZachary Turner uint8_t Leaf = Reader->peek(); 597251ede7SZachary Turner if (Leaf < LF_PAD0) 607251ede7SZachary Turner return Error::success(); 617251ede7SZachary Turner // Leaf is greater than 0xf0. We should advance by the number of bytes in 627251ede7SZachary Turner // the low 4 bits. 637251ede7SZachary Turner unsigned BytesToAdvance = Leaf & 0x0F; 647251ede7SZachary Turner return Reader->skip(BytesToAdvance); 657251ede7SZachary Turner } 667251ede7SZachary Turner 677251ede7SZachary Turner Error CodeViewRecordIO::mapByteVectorTail(ArrayRef<uint8_t> &Bytes) { 687251ede7SZachary Turner if (isWriting()) { 697251ede7SZachary Turner if (auto EC = Writer->writeBytes(Bytes)) 707251ede7SZachary Turner return EC; 717251ede7SZachary Turner } else { 727251ede7SZachary Turner if (auto EC = Reader->readBytes(Bytes, Reader->bytesRemaining())) 737251ede7SZachary Turner return EC; 747251ede7SZachary Turner } 757251ede7SZachary Turner return Error::success(); 767251ede7SZachary Turner } 777251ede7SZachary Turner 7846225b19SZachary Turner Error CodeViewRecordIO::mapByteVectorTail(std::vector<uint8_t> &Bytes) { 7946225b19SZachary Turner ArrayRef<uint8_t> BytesRef(Bytes); 8046225b19SZachary Turner if (auto EC = mapByteVectorTail(BytesRef)) 8146225b19SZachary Turner return EC; 8246225b19SZachary Turner if (!isWriting()) 8346225b19SZachary Turner Bytes.assign(BytesRef.begin(), BytesRef.end()); 8446225b19SZachary Turner 8546225b19SZachary Turner return Error::success(); 8646225b19SZachary Turner } 8746225b19SZachary Turner 887251ede7SZachary Turner Error CodeViewRecordIO::mapInteger(TypeIndex &TypeInd) { 897251ede7SZachary Turner if (isWriting()) { 90695ed56bSZachary Turner if (auto EC = Writer->writeInteger(TypeInd.getIndex())) 917251ede7SZachary Turner return EC; 927251ede7SZachary Turner return Error::success(); 937251ede7SZachary Turner } 947251ede7SZachary Turner 957251ede7SZachary Turner uint32_t I; 96695ed56bSZachary Turner if (auto EC = Reader->readInteger(I)) 977251ede7SZachary Turner return EC; 987251ede7SZachary Turner TypeInd.setIndex(I); 997251ede7SZachary Turner return Error::success(); 1007251ede7SZachary Turner } 1017251ede7SZachary Turner 1027251ede7SZachary Turner Error CodeViewRecordIO::mapEncodedInteger(int64_t &Value) { 1037251ede7SZachary Turner if (isWriting()) { 1047251ede7SZachary Turner if (Value >= 0) { 1057251ede7SZachary Turner if (auto EC = writeEncodedUnsignedInteger(static_cast<uint64_t>(Value))) 1067251ede7SZachary Turner return EC; 1077251ede7SZachary Turner } else { 1087251ede7SZachary Turner if (auto EC = writeEncodedSignedInteger(Value)) 1097251ede7SZachary Turner return EC; 1107251ede7SZachary Turner } 1117251ede7SZachary Turner } else { 1127251ede7SZachary Turner APSInt N; 1137251ede7SZachary Turner if (auto EC = consume(*Reader, N)) 1147251ede7SZachary Turner return EC; 1157251ede7SZachary Turner Value = N.getExtValue(); 1167251ede7SZachary Turner } 1177251ede7SZachary Turner 1187251ede7SZachary Turner return Error::success(); 1197251ede7SZachary Turner } 1207251ede7SZachary Turner 1217251ede7SZachary Turner Error CodeViewRecordIO::mapEncodedInteger(uint64_t &Value) { 1227251ede7SZachary Turner if (isWriting()) { 1237251ede7SZachary Turner if (auto EC = writeEncodedUnsignedInteger(Value)) 1247251ede7SZachary Turner return EC; 1257251ede7SZachary Turner } else { 1267251ede7SZachary Turner APSInt N; 1277251ede7SZachary Turner if (auto EC = consume(*Reader, N)) 1287251ede7SZachary Turner return EC; 1297251ede7SZachary Turner Value = N.getZExtValue(); 1307251ede7SZachary Turner } 1317251ede7SZachary Turner return Error::success(); 1327251ede7SZachary Turner } 1337251ede7SZachary Turner 1347251ede7SZachary Turner Error CodeViewRecordIO::mapEncodedInteger(APSInt &Value) { 1357251ede7SZachary Turner if (isWriting()) { 1367251ede7SZachary Turner if (Value.isSigned()) 1377251ede7SZachary Turner return writeEncodedSignedInteger(Value.getSExtValue()); 1387251ede7SZachary Turner return writeEncodedUnsignedInteger(Value.getZExtValue()); 1397251ede7SZachary Turner } 1407251ede7SZachary Turner 1417251ede7SZachary Turner return consume(*Reader, Value); 1427251ede7SZachary Turner } 1437251ede7SZachary Turner 1447251ede7SZachary Turner Error CodeViewRecordIO::mapStringZ(StringRef &Value) { 1457251ede7SZachary Turner if (isWriting()) { 1464efa0a42SZachary Turner // Truncate if we attempt to write too much. 1474efa0a42SZachary Turner StringRef S = Value.take_front(maxFieldLength() - 1); 148120faca4SZachary Turner if (auto EC = Writer->writeCString(S)) 1497251ede7SZachary Turner return EC; 1507251ede7SZachary Turner } else { 151120faca4SZachary Turner if (auto EC = Reader->readCString(Value)) 1527251ede7SZachary Turner return EC; 1537251ede7SZachary Turner } 1547251ede7SZachary Turner return Error::success(); 1557251ede7SZachary Turner } 1567251ede7SZachary Turner 1577251ede7SZachary Turner Error CodeViewRecordIO::mapGuid(StringRef &Guid) { 1584efa0a42SZachary Turner constexpr uint32_t GuidSize = 16; 1594efa0a42SZachary Turner if (maxFieldLength() < GuidSize) 1604efa0a42SZachary Turner return make_error<CodeViewError>(cv_error_code::insufficient_buffer); 1614efa0a42SZachary Turner 1627251ede7SZachary Turner if (isWriting()) { 1637251ede7SZachary Turner assert(Guid.size() == 16 && "Invalid Guid Size!"); 1647251ede7SZachary Turner if (auto EC = Writer->writeFixedString(Guid)) 1657251ede7SZachary Turner return EC; 1667251ede7SZachary Turner } else { 1677251ede7SZachary Turner if (auto EC = Reader->readFixedString(Guid, 16)) 1687251ede7SZachary Turner return EC; 1697251ede7SZachary Turner } 1707251ede7SZachary Turner return Error::success(); 1717251ede7SZachary Turner } 1727251ede7SZachary Turner 17346225b19SZachary Turner Error CodeViewRecordIO::mapStringZVectorZ(std::vector<StringRef> &Value) { 17446225b19SZachary Turner if (isWriting()) { 17546225b19SZachary Turner for (auto V : Value) { 17646225b19SZachary Turner if (auto EC = mapStringZ(V)) 17746225b19SZachary Turner return EC; 17846225b19SZachary Turner } 179695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint8_t>(0)) 18046225b19SZachary Turner return EC; 18146225b19SZachary Turner } else { 18246225b19SZachary Turner StringRef S; 18346225b19SZachary Turner if (auto EC = mapStringZ(S)) 18446225b19SZachary Turner return EC; 18546225b19SZachary Turner while (!S.empty()) { 18646225b19SZachary Turner Value.push_back(S); 18746225b19SZachary Turner if (auto EC = mapStringZ(S)) 18846225b19SZachary Turner return EC; 18946225b19SZachary Turner }; 19046225b19SZachary Turner } 19146225b19SZachary Turner return Error::success(); 19246225b19SZachary Turner } 19346225b19SZachary Turner 1947251ede7SZachary Turner Error CodeViewRecordIO::writeEncodedSignedInteger(const int64_t &Value) { 1957251ede7SZachary Turner assert(Value < 0 && "Encoded integer is not signed!"); 1967251ede7SZachary Turner if (Value >= std::numeric_limits<int8_t>::min()) { 197695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_CHAR)) 1987251ede7SZachary Turner return EC; 199695ed56bSZachary Turner if (auto EC = Writer->writeInteger<int8_t>(Value)) 2007251ede7SZachary Turner return EC; 2017251ede7SZachary Turner } else if (Value >= std::numeric_limits<int16_t>::min()) { 202695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_SHORT)) 2037251ede7SZachary Turner return EC; 204695ed56bSZachary Turner if (auto EC = Writer->writeInteger<int16_t>(Value)) 2057251ede7SZachary Turner return EC; 2067251ede7SZachary Turner } else if (Value >= std::numeric_limits<int32_t>::min()) { 207695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_LONG)) 2087251ede7SZachary Turner return EC; 209695ed56bSZachary Turner if (auto EC = Writer->writeInteger<int32_t>(Value)) 2107251ede7SZachary Turner return EC; 2117251ede7SZachary Turner } else { 212695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_QUADWORD)) 2137251ede7SZachary Turner return EC; 214695ed56bSZachary Turner if (auto EC = Writer->writeInteger(Value)) 2157251ede7SZachary Turner return EC; 2167251ede7SZachary Turner } 2177251ede7SZachary Turner return Error::success(); 2187251ede7SZachary Turner } 2197251ede7SZachary Turner 2207251ede7SZachary Turner Error CodeViewRecordIO::writeEncodedUnsignedInteger(const uint64_t &Value) { 2217251ede7SZachary Turner if (Value < LF_NUMERIC) { 222695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(Value)) 2237251ede7SZachary Turner return EC; 2247251ede7SZachary Turner } else if (Value <= std::numeric_limits<uint16_t>::max()) { 225695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_USHORT)) 2267251ede7SZachary Turner return EC; 227695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(Value)) 2287251ede7SZachary Turner return EC; 2297251ede7SZachary Turner } else if (Value <= std::numeric_limits<uint32_t>::max()) { 230695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_ULONG)) 2317251ede7SZachary Turner return EC; 232695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint32_t>(Value)) 2337251ede7SZachary Turner return EC; 2347251ede7SZachary Turner } else { 235695ed56bSZachary Turner if (auto EC = Writer->writeInteger<uint16_t>(LF_UQUADWORD)) 2367251ede7SZachary Turner return EC; 237695ed56bSZachary Turner if (auto EC = Writer->writeInteger(Value)) 2387251ede7SZachary Turner return EC; 2397251ede7SZachary Turner } 2407251ede7SZachary Turner 2417251ede7SZachary Turner return Error::success(); 2427251ede7SZachary Turner } 243