1 //===- CodeViewRecordIO.cpp -------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "llvm/DebugInfo/CodeView/CodeViewRecordIO.h" 11 #include "llvm/DebugInfo/CodeView/CodeView.h" 12 #include "llvm/DebugInfo/CodeView/RecordSerialization.h" 13 #include "llvm/DebugInfo/MSF/StreamReader.h" 14 #include "llvm/DebugInfo/MSF/StreamWriter.h" 15 16 using namespace llvm; 17 using namespace llvm::codeview; 18 19 Error CodeViewRecordIO::beginRecord(uint16_t Kind) { 20 assert(!CurrentRecord.hasValue() && "There is already a record active!"); 21 CurrentRecord.emplace(); 22 23 CurrentRecord->Kind = Kind; 24 return Error::success(); 25 } 26 27 Error CodeViewRecordIO::endRecord() { 28 assert(CurrentRecord.hasValue() && "Not in a record!"); 29 CurrentRecord.reset(); 30 return Error::success(); 31 } 32 33 Error CodeViewRecordIO::skipPadding() { 34 assert(!isWriting() && "Cannot skip padding while writing!"); 35 36 if (Reader->bytesRemaining() == 0) 37 return Error::success(); 38 39 uint8_t Leaf = Reader->peek(); 40 if (Leaf < LF_PAD0) 41 return Error::success(); 42 // Leaf is greater than 0xf0. We should advance by the number of bytes in 43 // the low 4 bits. 44 unsigned BytesToAdvance = Leaf & 0x0F; 45 return Reader->skip(BytesToAdvance); 46 } 47 48 Error CodeViewRecordIO::mapByteVectorTail(ArrayRef<uint8_t> &Bytes) { 49 if (isWriting()) { 50 if (auto EC = Writer->writeBytes(Bytes)) 51 return EC; 52 } else { 53 if (auto EC = Reader->readBytes(Bytes, Reader->bytesRemaining())) 54 return EC; 55 } 56 return Error::success(); 57 } 58 59 Error CodeViewRecordIO::mapInteger(TypeIndex &TypeInd) { 60 if (isWriting()) { 61 if (auto EC = Writer->writeInteger(TypeInd.getIndex())) 62 return EC; 63 return Error::success(); 64 } 65 66 uint32_t I; 67 if (auto EC = Reader->readInteger(I)) 68 return EC; 69 TypeInd.setIndex(I); 70 return Error::success(); 71 } 72 73 Error CodeViewRecordIO::mapEncodedInteger(int64_t &Value) { 74 if (isWriting()) { 75 if (Value >= 0) { 76 if (auto EC = writeEncodedUnsignedInteger(static_cast<uint64_t>(Value))) 77 return EC; 78 } else { 79 if (auto EC = writeEncodedSignedInteger(Value)) 80 return EC; 81 } 82 } else { 83 APSInt N; 84 if (auto EC = consume(*Reader, N)) 85 return EC; 86 Value = N.getExtValue(); 87 } 88 89 return Error::success(); 90 } 91 92 Error CodeViewRecordIO::mapEncodedInteger(uint64_t &Value) { 93 if (isWriting()) { 94 if (auto EC = writeEncodedUnsignedInteger(Value)) 95 return EC; 96 } else { 97 APSInt N; 98 if (auto EC = consume(*Reader, N)) 99 return EC; 100 Value = N.getZExtValue(); 101 } 102 return Error::success(); 103 } 104 105 Error CodeViewRecordIO::mapEncodedInteger(APSInt &Value) { 106 if (isWriting()) { 107 if (Value.isSigned()) 108 return writeEncodedSignedInteger(Value.getSExtValue()); 109 return writeEncodedUnsignedInteger(Value.getZExtValue()); 110 } 111 112 return consume(*Reader, Value); 113 } 114 115 Error CodeViewRecordIO::mapStringZ(StringRef &Value) { 116 if (isWriting()) { 117 if (auto EC = Writer->writeZeroString(Value)) 118 return EC; 119 } else { 120 if (auto EC = Reader->readZeroString(Value)) 121 return EC; 122 } 123 return Error::success(); 124 } 125 126 Error CodeViewRecordIO::mapGuid(StringRef &Guid) { 127 if (isWriting()) { 128 assert(Guid.size() == 16 && "Invalid Guid Size!"); 129 if (auto EC = Writer->writeFixedString(Guid)) 130 return EC; 131 } else { 132 if (auto EC = Reader->readFixedString(Guid, 16)) 133 return EC; 134 } 135 return Error::success(); 136 } 137 138 Error CodeViewRecordIO::writeEncodedSignedInteger(const int64_t &Value) { 139 assert(Value < 0 && "Encoded integer is not signed!"); 140 if (Value >= std::numeric_limits<int8_t>::min()) { 141 if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_CHAR))) 142 return EC; 143 if (auto EC = Writer->writeInteger(static_cast<int8_t>(Value))) 144 return EC; 145 } else if (Value >= std::numeric_limits<int16_t>::min()) { 146 if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_SHORT))) 147 return EC; 148 if (auto EC = Writer->writeInteger(static_cast<int16_t>(Value))) 149 return EC; 150 } else if (Value >= std::numeric_limits<int32_t>::min()) { 151 if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_LONG))) 152 return EC; 153 if (auto EC = Writer->writeInteger(static_cast<int32_t>(Value))) 154 return EC; 155 } else { 156 if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_QUADWORD))) 157 return EC; 158 if (auto EC = Writer->writeInteger(Value)) 159 return EC; 160 } 161 return Error::success(); 162 } 163 164 Error CodeViewRecordIO::writeEncodedUnsignedInteger(const uint64_t &Value) { 165 if (Value < LF_NUMERIC) { 166 if (auto EC = Writer->writeInteger(static_cast<uint16_t>(Value))) 167 return EC; 168 } else if (Value <= std::numeric_limits<uint16_t>::max()) { 169 if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_USHORT))) 170 return EC; 171 if (auto EC = Writer->writeInteger(static_cast<uint16_t>(Value))) 172 return EC; 173 } else if (Value <= std::numeric_limits<uint32_t>::max()) { 174 if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_ULONG))) 175 return EC; 176 if (auto EC = Writer->writeInteger(static_cast<uint32_t>(Value))) 177 return EC; 178 } else { 179 if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_UQUADWORD))) 180 return EC; 181 if (auto EC = Writer->writeInteger(Value)) 182 return EC; 183 } 184 185 return Error::success(); 186 } 187