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. 25 StringRef llvm::codeview::getBytesAsCharacters(ArrayRef<uint8_t> LeafData) { 26 return StringRef(reinterpret_cast<const char *>(LeafData.data()), 27 LeafData.size()); 28 } 29 30 StringRef llvm::codeview::getBytesAsCString(ArrayRef<uint8_t> LeafData) { 31 return getBytesAsCharacters(LeafData).split('\0').first; 32 } 33 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 Num = APSInt(APInt(/*numBits=*/8, 49 *reinterpret_cast<const int8_t *>(Data.data()), 50 /*isSigned=*/true), 51 /*isUnsigned=*/false); 52 Data = Data.drop_front(1); 53 return std::error_code(); 54 case LF_SHORT: 55 Num = APSInt(APInt(/*numBits=*/16, 56 *reinterpret_cast<const little16_t *>(Data.data()), 57 /*isSigned=*/true), 58 /*isUnsigned=*/false); 59 Data = Data.drop_front(2); 60 return std::error_code(); 61 case LF_USHORT: 62 Num = APSInt(APInt(/*numBits=*/16, 63 *reinterpret_cast<const ulittle16_t *>(Data.data()), 64 /*isSigned=*/false), 65 /*isUnsigned=*/true); 66 Data = Data.drop_front(2); 67 return std::error_code(); 68 case LF_LONG: 69 Num = APSInt(APInt(/*numBits=*/32, 70 *reinterpret_cast<const little32_t *>(Data.data()), 71 /*isSigned=*/true), 72 /*isUnsigned=*/false); 73 Data = Data.drop_front(4); 74 return std::error_code(); 75 case LF_ULONG: 76 Num = APSInt(APInt(/*numBits=*/32, 77 *reinterpret_cast<const ulittle32_t *>(Data.data()), 78 /*isSigned=*/FalseVal), 79 /*isUnsigned=*/true); 80 Data = Data.drop_front(4); 81 return std::error_code(); 82 case LF_QUADWORD: 83 Num = APSInt(APInt(/*numBits=*/64, 84 *reinterpret_cast<const little64_t *>(Data.data()), 85 /*isSigned=*/true), 86 /*isUnsigned=*/false); 87 Data = Data.drop_front(8); 88 return std::error_code(); 89 case LF_UQUADWORD: 90 Num = APSInt(APInt(/*numBits=*/64, 91 *reinterpret_cast<const ulittle64_t *>(Data.data()), 92 /*isSigned=*/false), 93 /*isUnsigned=*/true); 94 Data = Data.drop_front(8); 95 return std::error_code(); 96 } 97 return std::make_error_code(std::errc::illegal_byte_sequence); 98 } 99 100 std::error_code llvm::codeview::consume(StringRef &Data, APSInt &Num) { 101 ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end()); 102 auto EC = consume(Bytes, Num); 103 Data = StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size()); 104 return EC; 105 } 106 107 /// Decode a numeric leaf value that is known to be a uint64_t. 108 std::error_code llvm::codeview::consume_numeric(ArrayRef<uint8_t> &Data, 109 uint64_t &Num) { 110 APSInt N; 111 if (auto EC = consume(Data, N)) 112 return EC; 113 if (N.isSigned() || !N.isIntN(64)) 114 return std::make_error_code(std::errc::illegal_byte_sequence); 115 Num = N.getLimitedValue(); 116 return std::error_code(); 117 } 118 119 std::error_code llvm::codeview::consume(ArrayRef<uint8_t> &Data, 120 uint32_t &Item) { 121 const support::ulittle32_t *IntPtr; 122 if (auto EC = consumeObject(Data, IntPtr)) 123 return EC; 124 Item = *IntPtr; 125 return std::error_code(); 126 } 127 128 std::error_code llvm::codeview::consume(StringRef &Data, uint32_t &Item) { 129 ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end()); 130 auto EC = consume(Bytes, Item); 131 Data = StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size()); 132 return EC; 133 } 134 135 std::error_code llvm::codeview::consume(ArrayRef<uint8_t> &Data, 136 int32_t &Item) { 137 const support::little32_t *IntPtr; 138 if (auto EC = consumeObject(Data, IntPtr)) 139 return EC; 140 Item = *IntPtr; 141 return std::error_code(); 142 } 143 144 std::error_code llvm::codeview::consume(ArrayRef<uint8_t> &Data, 145 StringRef &Item) { 146 if (Data.empty()) 147 return std::make_error_code(std::errc::illegal_byte_sequence); 148 149 StringRef Rest; 150 std::tie(Item, Rest) = getBytesAsCharacters(Data).split('\0'); 151 // We expect this to be null terminated. If it was not, it is an error. 152 if (Data.size() == Item.size()) 153 return std::make_error_code(std::errc::illegal_byte_sequence); 154 155 Data = ArrayRef<uint8_t>(Rest.bytes_begin(), Rest.bytes_end()); 156 return std::error_code(); 157 } 158