1 //===-- RecordSerialization.cpp -------------------------------------------===// 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 // Utilities for serializing and deserializing CodeView records. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/DebugInfo/CodeView/RecordSerialization.h" 15 #include "llvm/ADT/APInt.h" 16 #include "llvm/ADT/APSInt.h" 17 #include "llvm/DebugInfo/CodeView/CodeViewError.h" 18 #include "llvm/DebugInfo/CodeView/TypeRecord.h" 19 20 using namespace llvm; 21 using namespace llvm::codeview; 22 using namespace llvm::support; 23 24 /// Reinterpret a byte array as an array of characters. Does not interpret as 25 /// a C string, as StringRef has several helpers (split) that make that easy. 26 StringRef llvm::codeview::getBytesAsCharacters(ArrayRef<uint8_t> LeafData) { 27 return StringRef(reinterpret_cast<const char *>(LeafData.data()), 28 LeafData.size()); 29 } 30 31 StringRef llvm::codeview::getBytesAsCString(ArrayRef<uint8_t> LeafData) { 32 return getBytesAsCharacters(LeafData).split('\0').first; 33 } 34 35 Error llvm::codeview::consume(ArrayRef<uint8_t> &Data, APSInt &Num) { 36 // Used to avoid overload ambiguity on APInt construtor. 37 bool FalseVal = false; 38 if (Data.size() < 2) 39 return make_error<CodeViewError>( 40 cv_error_code::insufficient_buffer, 41 "Buffer does not contain enough data for an APSInt"); 42 uint16_t Short = *reinterpret_cast<const ulittle16_t *>(Data.data()); 43 Data = Data.drop_front(2); 44 if (Short < LF_NUMERIC) { 45 Num = APSInt(APInt(/*numBits=*/16, Short, /*isSigned=*/false), 46 /*isUnsigned=*/true); 47 return Error::success(); 48 } 49 switch (Short) { 50 case LF_CHAR: 51 if (Data.size() < 1) 52 return make_error<CodeViewError>( 53 cv_error_code::insufficient_buffer, 54 "Buffer does not contain enough data for an LF_CHAR"); 55 Num = APSInt(APInt(/*numBits=*/8, 56 *reinterpret_cast<const int8_t *>(Data.data()), 57 /*isSigned=*/true), 58 /*isUnsigned=*/false); 59 Data = Data.drop_front(1); 60 return Error::success(); 61 case LF_SHORT: 62 if (Data.size() < 2) 63 return make_error<CodeViewError>( 64 cv_error_code::insufficient_buffer, 65 "Buffer does not contain enough data for an LF_SHORT"); 66 Num = APSInt(APInt(/*numBits=*/16, 67 *reinterpret_cast<const little16_t *>(Data.data()), 68 /*isSigned=*/true), 69 /*isUnsigned=*/false); 70 Data = Data.drop_front(2); 71 return Error::success(); 72 case LF_USHORT: 73 if (Data.size() < 2) 74 return make_error<CodeViewError>( 75 cv_error_code::insufficient_buffer, 76 "Buffer does not contain enough data for an LF_USHORT"); 77 Num = APSInt(APInt(/*numBits=*/16, 78 *reinterpret_cast<const ulittle16_t *>(Data.data()), 79 /*isSigned=*/false), 80 /*isUnsigned=*/true); 81 Data = Data.drop_front(2); 82 return Error::success(); 83 case LF_LONG: 84 if (Data.size() < 4) 85 return make_error<CodeViewError>( 86 cv_error_code::insufficient_buffer, 87 "Buffer does not contain enough data for an LF_LONG"); 88 Num = APSInt(APInt(/*numBits=*/32, 89 *reinterpret_cast<const little32_t *>(Data.data()), 90 /*isSigned=*/true), 91 /*isUnsigned=*/false); 92 Data = Data.drop_front(4); 93 return Error::success(); 94 case LF_ULONG: 95 if (Data.size() < 4) 96 return make_error<CodeViewError>( 97 cv_error_code::insufficient_buffer, 98 "Buffer does not contain enough data for an LF_ULONG"); 99 Num = APSInt(APInt(/*numBits=*/32, 100 *reinterpret_cast<const ulittle32_t *>(Data.data()), 101 /*isSigned=*/FalseVal), 102 /*isUnsigned=*/true); 103 Data = Data.drop_front(4); 104 return Error::success(); 105 case LF_QUADWORD: 106 if (Data.size() < 8) 107 return make_error<CodeViewError>( 108 cv_error_code::insufficient_buffer, 109 "Buffer does not contain enough data for an LF_QUADWORD"); 110 Num = APSInt(APInt(/*numBits=*/64, 111 *reinterpret_cast<const little64_t *>(Data.data()), 112 /*isSigned=*/true), 113 /*isUnsigned=*/false); 114 Data = Data.drop_front(8); 115 return Error::success(); 116 case LF_UQUADWORD: 117 if (Data.size() < 8) 118 return make_error<CodeViewError>( 119 cv_error_code::insufficient_buffer, 120 "Buffer does not contain enough data for an LF_UQUADWORD"); 121 Num = APSInt(APInt(/*numBits=*/64, 122 *reinterpret_cast<const ulittle64_t *>(Data.data()), 123 /*isSigned=*/false), 124 /*isUnsigned=*/true); 125 Data = Data.drop_front(8); 126 return Error::success(); 127 } 128 return make_error<CodeViewError>(cv_error_code::corrupt_record, 129 "Buffer contains invalid APSInt type"); 130 } 131 132 Error llvm::codeview::consume(StringRef &Data, APSInt &Num) { 133 ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end()); 134 auto EC = consume(Bytes, Num); 135 Data = StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size()); 136 return EC; 137 } 138 139 /// Decode a numeric leaf value that is known to be a uint64_t. 140 Error llvm::codeview::consume_numeric(ArrayRef<uint8_t> &Data, uint64_t &Num) { 141 APSInt N; 142 if (auto EC = consume(Data, N)) 143 return EC; 144 if (N.isSigned() || !N.isIntN(64)) 145 return make_error<CodeViewError>(cv_error_code::corrupt_record, 146 "Data is not a numeric value!"); 147 Num = N.getLimitedValue(); 148 return Error::success(); 149 } 150 151 Error llvm::codeview::consume(ArrayRef<uint8_t> &Data, uint32_t &Item) { 152 const support::ulittle32_t *IntPtr; 153 if (auto EC = consumeObject(Data, IntPtr)) 154 return EC; 155 Item = *IntPtr; 156 return Error::success(); 157 } 158 159 Error llvm::codeview::consume(StringRef &Data, uint32_t &Item) { 160 ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end()); 161 auto EC = consume(Bytes, Item); 162 Data = StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size()); 163 return EC; 164 } 165 166 Error llvm::codeview::consume(ArrayRef<uint8_t> &Data, int32_t &Item) { 167 const support::little32_t *IntPtr; 168 if (auto EC = consumeObject(Data, IntPtr)) 169 return EC; 170 Item = *IntPtr; 171 return Error::success(); 172 } 173 174 Error llvm::codeview::consume(ArrayRef<uint8_t> &Data, StringRef &Item) { 175 if (Data.empty()) 176 return make_error<CodeViewError>(cv_error_code::corrupt_record, 177 "Null terminated string buffer is empty!"); 178 179 StringRef Rest; 180 std::tie(Item, Rest) = getBytesAsCharacters(Data).split('\0'); 181 // We expect this to be null terminated. If it was not, it is an error. 182 if (Data.size() == Item.size()) 183 return make_error<CodeViewError>(cv_error_code::corrupt_record, 184 "Expected null terminator!"); 185 186 Data = ArrayRef<uint8_t>(Rest.bytes_begin(), Rest.bytes_end()); 187 return Error::success(); 188 } 189