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