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