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" 13d2684b79SZachary Turner #include "llvm/DebugInfo/MSF/BinaryStreamReader.h" 14d2684b79SZachary Turner #include "llvm/DebugInfo/MSF/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()) { 9005a75e40SNAKAMURA Takumi if (auto EC = 9105a75e40SNAKAMURA Takumi Writer->writeInteger(TypeInd.getIndex(), llvm::support::little)) 927251ede7SZachary Turner return EC; 937251ede7SZachary Turner return Error::success(); 947251ede7SZachary Turner } 957251ede7SZachary Turner 967251ede7SZachary Turner uint32_t I; 9705a75e40SNAKAMURA Takumi if (auto EC = Reader->readInteger(I, llvm::support::little)) 987251ede7SZachary Turner return EC; 997251ede7SZachary Turner TypeInd.setIndex(I); 1007251ede7SZachary Turner return Error::success(); 1017251ede7SZachary Turner } 1027251ede7SZachary Turner 1037251ede7SZachary Turner Error CodeViewRecordIO::mapEncodedInteger(int64_t &Value) { 1047251ede7SZachary Turner if (isWriting()) { 1057251ede7SZachary Turner if (Value >= 0) { 1067251ede7SZachary Turner if (auto EC = writeEncodedUnsignedInteger(static_cast<uint64_t>(Value))) 1077251ede7SZachary Turner return EC; 1087251ede7SZachary Turner } else { 1097251ede7SZachary Turner if (auto EC = writeEncodedSignedInteger(Value)) 1107251ede7SZachary Turner return EC; 1117251ede7SZachary Turner } 1127251ede7SZachary Turner } else { 1137251ede7SZachary Turner APSInt N; 1147251ede7SZachary Turner if (auto EC = consume(*Reader, N)) 1157251ede7SZachary Turner return EC; 1167251ede7SZachary Turner Value = N.getExtValue(); 1177251ede7SZachary Turner } 1187251ede7SZachary Turner 1197251ede7SZachary Turner return Error::success(); 1207251ede7SZachary Turner } 1217251ede7SZachary Turner 1227251ede7SZachary Turner Error CodeViewRecordIO::mapEncodedInteger(uint64_t &Value) { 1237251ede7SZachary Turner if (isWriting()) { 1247251ede7SZachary Turner if (auto EC = writeEncodedUnsignedInteger(Value)) 1257251ede7SZachary Turner return EC; 1267251ede7SZachary Turner } else { 1277251ede7SZachary Turner APSInt N; 1287251ede7SZachary Turner if (auto EC = consume(*Reader, N)) 1297251ede7SZachary Turner return EC; 1307251ede7SZachary Turner Value = N.getZExtValue(); 1317251ede7SZachary Turner } 1327251ede7SZachary Turner return Error::success(); 1337251ede7SZachary Turner } 1347251ede7SZachary Turner 1357251ede7SZachary Turner Error CodeViewRecordIO::mapEncodedInteger(APSInt &Value) { 1367251ede7SZachary Turner if (isWriting()) { 1377251ede7SZachary Turner if (Value.isSigned()) 1387251ede7SZachary Turner return writeEncodedSignedInteger(Value.getSExtValue()); 1397251ede7SZachary Turner return writeEncodedUnsignedInteger(Value.getZExtValue()); 1407251ede7SZachary Turner } 1417251ede7SZachary Turner 1427251ede7SZachary Turner return consume(*Reader, Value); 1437251ede7SZachary Turner } 1447251ede7SZachary Turner 1457251ede7SZachary Turner Error CodeViewRecordIO::mapStringZ(StringRef &Value) { 1467251ede7SZachary Turner if (isWriting()) { 1474efa0a42SZachary Turner // Truncate if we attempt to write too much. 1484efa0a42SZachary Turner StringRef S = Value.take_front(maxFieldLength() - 1); 149*120faca4SZachary Turner if (auto EC = Writer->writeCString(S)) 1507251ede7SZachary Turner return EC; 1517251ede7SZachary Turner } else { 152*120faca4SZachary Turner if (auto EC = Reader->readCString(Value)) 1537251ede7SZachary Turner return EC; 1547251ede7SZachary Turner } 1557251ede7SZachary Turner return Error::success(); 1567251ede7SZachary Turner } 1577251ede7SZachary Turner 1587251ede7SZachary Turner Error CodeViewRecordIO::mapGuid(StringRef &Guid) { 1594efa0a42SZachary Turner constexpr uint32_t GuidSize = 16; 1604efa0a42SZachary Turner if (maxFieldLength() < GuidSize) 1614efa0a42SZachary Turner return make_error<CodeViewError>(cv_error_code::insufficient_buffer); 1624efa0a42SZachary Turner 1637251ede7SZachary Turner if (isWriting()) { 1647251ede7SZachary Turner assert(Guid.size() == 16 && "Invalid Guid Size!"); 1657251ede7SZachary Turner if (auto EC = Writer->writeFixedString(Guid)) 1667251ede7SZachary Turner return EC; 1677251ede7SZachary Turner } else { 1687251ede7SZachary Turner if (auto EC = Reader->readFixedString(Guid, 16)) 1697251ede7SZachary Turner return EC; 1707251ede7SZachary Turner } 1717251ede7SZachary Turner return Error::success(); 1727251ede7SZachary Turner } 1737251ede7SZachary Turner 17446225b19SZachary Turner Error CodeViewRecordIO::mapStringZVectorZ(std::vector<StringRef> &Value) { 17546225b19SZachary Turner if (isWriting()) { 17646225b19SZachary Turner for (auto V : Value) { 17746225b19SZachary Turner if (auto EC = mapStringZ(V)) 17846225b19SZachary Turner return EC; 17946225b19SZachary Turner } 18005a75e40SNAKAMURA Takumi if (auto EC = Writer->writeInteger<uint8_t>(0, llvm::support::little)) 18146225b19SZachary Turner return EC; 18246225b19SZachary Turner } else { 18346225b19SZachary Turner StringRef S; 18446225b19SZachary Turner if (auto EC = mapStringZ(S)) 18546225b19SZachary Turner return EC; 18646225b19SZachary Turner while (!S.empty()) { 18746225b19SZachary Turner Value.push_back(S); 18846225b19SZachary Turner if (auto EC = mapStringZ(S)) 18946225b19SZachary Turner return EC; 19046225b19SZachary Turner }; 19146225b19SZachary Turner } 19246225b19SZachary Turner return Error::success(); 19346225b19SZachary Turner } 19446225b19SZachary Turner 1957251ede7SZachary Turner Error CodeViewRecordIO::writeEncodedSignedInteger(const int64_t &Value) { 1967251ede7SZachary Turner assert(Value < 0 && "Encoded integer is not signed!"); 1977251ede7SZachary Turner if (Value >= std::numeric_limits<int8_t>::min()) { 19805a75e40SNAKAMURA Takumi if (auto EC = 19905a75e40SNAKAMURA Takumi Writer->writeInteger<uint16_t>(LF_CHAR, llvm::support::little)) 2007251ede7SZachary Turner return EC; 20105a75e40SNAKAMURA Takumi if (auto EC = Writer->writeInteger<int8_t>(Value, llvm::support::little)) 2027251ede7SZachary Turner return EC; 2037251ede7SZachary Turner } else if (Value >= std::numeric_limits<int16_t>::min()) { 20405a75e40SNAKAMURA Takumi if (auto EC = 20505a75e40SNAKAMURA Takumi Writer->writeInteger<uint16_t>(LF_SHORT, llvm::support::little)) 2067251ede7SZachary Turner return EC; 20705a75e40SNAKAMURA Takumi if (auto EC = Writer->writeInteger<int16_t>(Value, llvm::support::little)) 2087251ede7SZachary Turner return EC; 2097251ede7SZachary Turner } else if (Value >= std::numeric_limits<int32_t>::min()) { 21005a75e40SNAKAMURA Takumi if (auto EC = 21105a75e40SNAKAMURA Takumi Writer->writeInteger<uint16_t>(LF_LONG, llvm::support::little)) 2127251ede7SZachary Turner return EC; 21305a75e40SNAKAMURA Takumi if (auto EC = Writer->writeInteger<int32_t>(Value, llvm::support::little)) 2147251ede7SZachary Turner return EC; 2157251ede7SZachary Turner } else { 21605a75e40SNAKAMURA Takumi if (auto EC = 21705a75e40SNAKAMURA Takumi Writer->writeInteger<uint16_t>(LF_QUADWORD, llvm::support::little)) 2187251ede7SZachary Turner return EC; 21905a75e40SNAKAMURA Takumi if (auto EC = Writer->writeInteger(Value, llvm::support::little)) 2207251ede7SZachary Turner return EC; 2217251ede7SZachary Turner } 2227251ede7SZachary Turner return Error::success(); 2237251ede7SZachary Turner } 2247251ede7SZachary Turner 2257251ede7SZachary Turner Error CodeViewRecordIO::writeEncodedUnsignedInteger(const uint64_t &Value) { 2267251ede7SZachary Turner if (Value < LF_NUMERIC) { 22705a75e40SNAKAMURA Takumi if (auto EC = Writer->writeInteger<uint16_t>(Value, llvm::support::little)) 2287251ede7SZachary Turner return EC; 2297251ede7SZachary Turner } else if (Value <= std::numeric_limits<uint16_t>::max()) { 23005a75e40SNAKAMURA Takumi if (auto EC = 23105a75e40SNAKAMURA Takumi Writer->writeInteger<uint16_t>(LF_USHORT, llvm::support::little)) 2327251ede7SZachary Turner return EC; 23305a75e40SNAKAMURA Takumi if (auto EC = Writer->writeInteger<uint16_t>(Value, llvm::support::little)) 2347251ede7SZachary Turner return EC; 2357251ede7SZachary Turner } else if (Value <= std::numeric_limits<uint32_t>::max()) { 23605a75e40SNAKAMURA Takumi if (auto EC = 23705a75e40SNAKAMURA Takumi Writer->writeInteger<uint16_t>(LF_ULONG, llvm::support::little)) 2387251ede7SZachary Turner return EC; 23905a75e40SNAKAMURA Takumi if (auto EC = Writer->writeInteger<uint32_t>(Value, llvm::support::little)) 2407251ede7SZachary Turner return EC; 2417251ede7SZachary Turner } else { 24205a75e40SNAKAMURA Takumi if (auto EC = 24305a75e40SNAKAMURA Takumi Writer->writeInteger<uint16_t>(LF_UQUADWORD, llvm::support::little)) 2447251ede7SZachary Turner return EC; 24505a75e40SNAKAMURA Takumi if (auto EC = Writer->writeInteger(Value, llvm::support::little)) 2467251ede7SZachary Turner return EC; 2477251ede7SZachary Turner } 2487251ede7SZachary Turner 2497251ede7SZachary Turner return Error::success(); 2507251ede7SZachary Turner } 251