138cc8b3fSZachary Turner //===-- RecordSerialization.cpp -------------------------------------------===// 238cc8b3fSZachary Turner // 338cc8b3fSZachary Turner // The LLVM Compiler Infrastructure 438cc8b3fSZachary Turner // 538cc8b3fSZachary Turner // This file is distributed under the University of Illinois Open Source 638cc8b3fSZachary Turner // License. See LICENSE.TXT for details. 738cc8b3fSZachary Turner // 838cc8b3fSZachary Turner //===----------------------------------------------------------------------===// 938cc8b3fSZachary Turner // 1038cc8b3fSZachary Turner // Utilities for serializing and deserializing CodeView records. 1138cc8b3fSZachary Turner // 1238cc8b3fSZachary Turner //===----------------------------------------------------------------------===// 1338cc8b3fSZachary Turner 1438cc8b3fSZachary Turner #include "llvm/DebugInfo/CodeView/RecordSerialization.h" 1538cc8b3fSZachary Turner #include "llvm/ADT/APInt.h" 1638cc8b3fSZachary Turner #include "llvm/ADT/APSInt.h" 1738cc8b3fSZachary Turner #include "llvm/DebugInfo/CodeView/TypeRecord.h" 1838cc8b3fSZachary Turner 1938cc8b3fSZachary Turner using namespace llvm; 2038cc8b3fSZachary Turner using namespace llvm::codeview; 2138cc8b3fSZachary Turner using namespace llvm::support; 2238cc8b3fSZachary Turner 2338cc8b3fSZachary Turner /// Reinterpret a byte array as an array of characters. Does not interpret as 2438cc8b3fSZachary Turner /// a C string, as StringRef has several helpers (split) that make that easy. 2538cc8b3fSZachary Turner StringRef llvm::codeview::getBytesAsCharacters(ArrayRef<uint8_t> LeafData) { 2638cc8b3fSZachary Turner return StringRef(reinterpret_cast<const char *>(LeafData.data()), 2738cc8b3fSZachary Turner LeafData.size()); 2838cc8b3fSZachary Turner } 2938cc8b3fSZachary Turner 3038cc8b3fSZachary Turner StringRef llvm::codeview::getBytesAsCString(ArrayRef<uint8_t> LeafData) { 3138cc8b3fSZachary Turner return getBytesAsCharacters(LeafData).split('\0').first; 3238cc8b3fSZachary Turner } 3338cc8b3fSZachary Turner 3438cc8b3fSZachary Turner std::error_code llvm::codeview::consume(ArrayRef<uint8_t> &Data, APSInt &Num) { 3538cc8b3fSZachary Turner // Used to avoid overload ambiguity on APInt construtor. 3638cc8b3fSZachary Turner bool FalseVal = false; 3738cc8b3fSZachary Turner if (Data.size() < 2) 3838cc8b3fSZachary Turner return std::make_error_code(std::errc::illegal_byte_sequence); 3938cc8b3fSZachary Turner uint16_t Short = *reinterpret_cast<const ulittle16_t *>(Data.data()); 4038cc8b3fSZachary Turner Data = Data.drop_front(2); 4138cc8b3fSZachary Turner if (Short < LF_NUMERIC) { 4238cc8b3fSZachary Turner Num = APSInt(APInt(/*numBits=*/16, Short, /*isSigned=*/false), 4338cc8b3fSZachary Turner /*isUnsigned=*/true); 4438cc8b3fSZachary Turner return std::error_code(); 4538cc8b3fSZachary Turner } 4638cc8b3fSZachary Turner switch (Short) { 4738cc8b3fSZachary Turner case LF_CHAR: 48*6c13db40SDavid Majnemer if (Data.size() < 1) 49*6c13db40SDavid Majnemer return std::make_error_code(std::errc::illegal_byte_sequence); 5038cc8b3fSZachary Turner Num = APSInt(APInt(/*numBits=*/8, 5138cc8b3fSZachary Turner *reinterpret_cast<const int8_t *>(Data.data()), 5238cc8b3fSZachary Turner /*isSigned=*/true), 5338cc8b3fSZachary Turner /*isUnsigned=*/false); 5438cc8b3fSZachary Turner Data = Data.drop_front(1); 5538cc8b3fSZachary Turner return std::error_code(); 5638cc8b3fSZachary Turner case LF_SHORT: 57*6c13db40SDavid Majnemer if (Data.size() < 2) 58*6c13db40SDavid Majnemer return std::make_error_code(std::errc::illegal_byte_sequence); 5938cc8b3fSZachary Turner Num = APSInt(APInt(/*numBits=*/16, 6038cc8b3fSZachary Turner *reinterpret_cast<const little16_t *>(Data.data()), 6138cc8b3fSZachary Turner /*isSigned=*/true), 6238cc8b3fSZachary Turner /*isUnsigned=*/false); 6338cc8b3fSZachary Turner Data = Data.drop_front(2); 6438cc8b3fSZachary Turner return std::error_code(); 6538cc8b3fSZachary Turner case LF_USHORT: 66*6c13db40SDavid Majnemer if (Data.size() < 2) 67*6c13db40SDavid Majnemer return std::make_error_code(std::errc::illegal_byte_sequence); 6838cc8b3fSZachary Turner Num = APSInt(APInt(/*numBits=*/16, 6938cc8b3fSZachary Turner *reinterpret_cast<const ulittle16_t *>(Data.data()), 7038cc8b3fSZachary Turner /*isSigned=*/false), 7138cc8b3fSZachary Turner /*isUnsigned=*/true); 7238cc8b3fSZachary Turner Data = Data.drop_front(2); 7338cc8b3fSZachary Turner return std::error_code(); 7438cc8b3fSZachary Turner case LF_LONG: 75*6c13db40SDavid Majnemer if (Data.size() < 4) 76*6c13db40SDavid Majnemer return std::make_error_code(std::errc::illegal_byte_sequence); 7738cc8b3fSZachary Turner Num = APSInt(APInt(/*numBits=*/32, 7838cc8b3fSZachary Turner *reinterpret_cast<const little32_t *>(Data.data()), 7938cc8b3fSZachary Turner /*isSigned=*/true), 8038cc8b3fSZachary Turner /*isUnsigned=*/false); 8138cc8b3fSZachary Turner Data = Data.drop_front(4); 8238cc8b3fSZachary Turner return std::error_code(); 8338cc8b3fSZachary Turner case LF_ULONG: 84*6c13db40SDavid Majnemer if (Data.size() < 4) 85*6c13db40SDavid Majnemer return std::make_error_code(std::errc::illegal_byte_sequence); 8638cc8b3fSZachary Turner Num = APSInt(APInt(/*numBits=*/32, 8738cc8b3fSZachary Turner *reinterpret_cast<const ulittle32_t *>(Data.data()), 8838cc8b3fSZachary Turner /*isSigned=*/FalseVal), 8938cc8b3fSZachary Turner /*isUnsigned=*/true); 9038cc8b3fSZachary Turner Data = Data.drop_front(4); 9138cc8b3fSZachary Turner return std::error_code(); 9238cc8b3fSZachary Turner case LF_QUADWORD: 93*6c13db40SDavid Majnemer if (Data.size() < 8) 94*6c13db40SDavid Majnemer return std::make_error_code(std::errc::illegal_byte_sequence); 9538cc8b3fSZachary Turner Num = APSInt(APInt(/*numBits=*/64, 9638cc8b3fSZachary Turner *reinterpret_cast<const little64_t *>(Data.data()), 9738cc8b3fSZachary Turner /*isSigned=*/true), 9838cc8b3fSZachary Turner /*isUnsigned=*/false); 9938cc8b3fSZachary Turner Data = Data.drop_front(8); 10038cc8b3fSZachary Turner return std::error_code(); 10138cc8b3fSZachary Turner case LF_UQUADWORD: 102*6c13db40SDavid Majnemer if (Data.size() < 8) 103*6c13db40SDavid Majnemer return std::make_error_code(std::errc::illegal_byte_sequence); 10438cc8b3fSZachary Turner Num = APSInt(APInt(/*numBits=*/64, 10538cc8b3fSZachary Turner *reinterpret_cast<const ulittle64_t *>(Data.data()), 10638cc8b3fSZachary Turner /*isSigned=*/false), 10738cc8b3fSZachary Turner /*isUnsigned=*/true); 10838cc8b3fSZachary Turner Data = Data.drop_front(8); 10938cc8b3fSZachary Turner return std::error_code(); 11038cc8b3fSZachary Turner } 11138cc8b3fSZachary Turner return std::make_error_code(std::errc::illegal_byte_sequence); 11238cc8b3fSZachary Turner } 11338cc8b3fSZachary Turner 11438cc8b3fSZachary Turner std::error_code llvm::codeview::consume(StringRef &Data, APSInt &Num) { 11538cc8b3fSZachary Turner ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end()); 11638cc8b3fSZachary Turner auto EC = consume(Bytes, Num); 11738cc8b3fSZachary Turner Data = StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size()); 11838cc8b3fSZachary Turner return EC; 11938cc8b3fSZachary Turner } 12038cc8b3fSZachary Turner 12138cc8b3fSZachary Turner /// Decode a numeric leaf value that is known to be a uint64_t. 12238cc8b3fSZachary Turner std::error_code llvm::codeview::consume_numeric(ArrayRef<uint8_t> &Data, 12338cc8b3fSZachary Turner uint64_t &Num) { 12438cc8b3fSZachary Turner APSInt N; 12538cc8b3fSZachary Turner if (auto EC = consume(Data, N)) 12638cc8b3fSZachary Turner return EC; 12738cc8b3fSZachary Turner if (N.isSigned() || !N.isIntN(64)) 12838cc8b3fSZachary Turner return std::make_error_code(std::errc::illegal_byte_sequence); 12938cc8b3fSZachary Turner Num = N.getLimitedValue(); 13038cc8b3fSZachary Turner return std::error_code(); 13138cc8b3fSZachary Turner } 13238cc8b3fSZachary Turner 13338cc8b3fSZachary Turner std::error_code llvm::codeview::consume(ArrayRef<uint8_t> &Data, 13438cc8b3fSZachary Turner uint32_t &Item) { 13538cc8b3fSZachary Turner const support::ulittle32_t *IntPtr; 13638cc8b3fSZachary Turner if (auto EC = consumeObject(Data, IntPtr)) 13738cc8b3fSZachary Turner return EC; 13838cc8b3fSZachary Turner Item = *IntPtr; 13938cc8b3fSZachary Turner return std::error_code(); 14038cc8b3fSZachary Turner } 14138cc8b3fSZachary Turner 14238cc8b3fSZachary Turner std::error_code llvm::codeview::consume(StringRef &Data, uint32_t &Item) { 14338cc8b3fSZachary Turner ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end()); 14438cc8b3fSZachary Turner auto EC = consume(Bytes, Item); 14538cc8b3fSZachary Turner Data = StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size()); 14638cc8b3fSZachary Turner return EC; 14738cc8b3fSZachary Turner } 14838cc8b3fSZachary Turner 14938cc8b3fSZachary Turner std::error_code llvm::codeview::consume(ArrayRef<uint8_t> &Data, 15038cc8b3fSZachary Turner int32_t &Item) { 15138cc8b3fSZachary Turner const support::little32_t *IntPtr; 15238cc8b3fSZachary Turner if (auto EC = consumeObject(Data, IntPtr)) 15338cc8b3fSZachary Turner return EC; 15438cc8b3fSZachary Turner Item = *IntPtr; 15538cc8b3fSZachary Turner return std::error_code(); 15638cc8b3fSZachary Turner } 15738cc8b3fSZachary Turner 15838cc8b3fSZachary Turner std::error_code llvm::codeview::consume(ArrayRef<uint8_t> &Data, 15938cc8b3fSZachary Turner StringRef &Item) { 16038cc8b3fSZachary Turner if (Data.empty()) 16138cc8b3fSZachary Turner return std::make_error_code(std::errc::illegal_byte_sequence); 16238cc8b3fSZachary Turner 16338cc8b3fSZachary Turner StringRef Rest; 16438cc8b3fSZachary Turner std::tie(Item, Rest) = getBytesAsCharacters(Data).split('\0'); 16538cc8b3fSZachary Turner // We expect this to be null terminated. If it was not, it is an error. 16638cc8b3fSZachary Turner if (Data.size() == Item.size()) 16738cc8b3fSZachary Turner return std::make_error_code(std::errc::illegal_byte_sequence); 16838cc8b3fSZachary Turner 16938cc8b3fSZachary Turner Data = ArrayRef<uint8_t>(Rest.bytes_begin(), Rest.bytes_end()); 17038cc8b3fSZachary Turner return std::error_code(); 17138cc8b3fSZachary Turner } 172