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" 17*660230ebSZachary Turner #include "llvm/DebugInfo/CodeView/CodeViewError.h" 1838cc8b3fSZachary Turner #include "llvm/DebugInfo/CodeView/TypeRecord.h" 1938cc8b3fSZachary Turner 2038cc8b3fSZachary Turner using namespace llvm; 2138cc8b3fSZachary Turner using namespace llvm::codeview; 2238cc8b3fSZachary Turner using namespace llvm::support; 2338cc8b3fSZachary Turner 2438cc8b3fSZachary Turner /// Reinterpret a byte array as an array of characters. Does not interpret as 2538cc8b3fSZachary Turner /// a C string, as StringRef has several helpers (split) that make that easy. 2638cc8b3fSZachary Turner StringRef llvm::codeview::getBytesAsCharacters(ArrayRef<uint8_t> LeafData) { 2738cc8b3fSZachary Turner return StringRef(reinterpret_cast<const char *>(LeafData.data()), 2838cc8b3fSZachary Turner LeafData.size()); 2938cc8b3fSZachary Turner } 3038cc8b3fSZachary Turner 3138cc8b3fSZachary Turner StringRef llvm::codeview::getBytesAsCString(ArrayRef<uint8_t> LeafData) { 3238cc8b3fSZachary Turner return getBytesAsCharacters(LeafData).split('\0').first; 3338cc8b3fSZachary Turner } 3438cc8b3fSZachary Turner 35*660230ebSZachary Turner Error llvm::codeview::consume(ArrayRef<uint8_t> &Data, APSInt &Num) { 3638cc8b3fSZachary Turner // Used to avoid overload ambiguity on APInt construtor. 3738cc8b3fSZachary Turner bool FalseVal = false; 3838cc8b3fSZachary Turner if (Data.size() < 2) 39*660230ebSZachary Turner return make_error<CodeViewError>( 40*660230ebSZachary Turner cv_error_code::insufficient_buffer, 41*660230ebSZachary Turner "Buffer does not contain enough data for an APSInt"); 4238cc8b3fSZachary Turner uint16_t Short = *reinterpret_cast<const ulittle16_t *>(Data.data()); 4338cc8b3fSZachary Turner Data = Data.drop_front(2); 4438cc8b3fSZachary Turner if (Short < LF_NUMERIC) { 4538cc8b3fSZachary Turner Num = APSInt(APInt(/*numBits=*/16, Short, /*isSigned=*/false), 4638cc8b3fSZachary Turner /*isUnsigned=*/true); 47*660230ebSZachary Turner return Error::success(); 4838cc8b3fSZachary Turner } 4938cc8b3fSZachary Turner switch (Short) { 5038cc8b3fSZachary Turner case LF_CHAR: 516c13db40SDavid Majnemer if (Data.size() < 1) 52*660230ebSZachary Turner return make_error<CodeViewError>( 53*660230ebSZachary Turner cv_error_code::insufficient_buffer, 54*660230ebSZachary Turner "Buffer does not contain enough data for an LF_CHAR"); 5538cc8b3fSZachary Turner Num = APSInt(APInt(/*numBits=*/8, 5638cc8b3fSZachary Turner *reinterpret_cast<const int8_t *>(Data.data()), 5738cc8b3fSZachary Turner /*isSigned=*/true), 5838cc8b3fSZachary Turner /*isUnsigned=*/false); 5938cc8b3fSZachary Turner Data = Data.drop_front(1); 60*660230ebSZachary Turner return Error::success(); 6138cc8b3fSZachary Turner case LF_SHORT: 626c13db40SDavid Majnemer if (Data.size() < 2) 63*660230ebSZachary Turner return make_error<CodeViewError>( 64*660230ebSZachary Turner cv_error_code::insufficient_buffer, 65*660230ebSZachary Turner "Buffer does not contain enough data for an LF_SHORT"); 6638cc8b3fSZachary Turner Num = APSInt(APInt(/*numBits=*/16, 6738cc8b3fSZachary Turner *reinterpret_cast<const little16_t *>(Data.data()), 6838cc8b3fSZachary Turner /*isSigned=*/true), 6938cc8b3fSZachary Turner /*isUnsigned=*/false); 7038cc8b3fSZachary Turner Data = Data.drop_front(2); 71*660230ebSZachary Turner return Error::success(); 7238cc8b3fSZachary Turner case LF_USHORT: 736c13db40SDavid Majnemer if (Data.size() < 2) 74*660230ebSZachary Turner return make_error<CodeViewError>( 75*660230ebSZachary Turner cv_error_code::insufficient_buffer, 76*660230ebSZachary Turner "Buffer does not contain enough data for an LF_USHORT"); 7738cc8b3fSZachary Turner Num = APSInt(APInt(/*numBits=*/16, 7838cc8b3fSZachary Turner *reinterpret_cast<const ulittle16_t *>(Data.data()), 7938cc8b3fSZachary Turner /*isSigned=*/false), 8038cc8b3fSZachary Turner /*isUnsigned=*/true); 8138cc8b3fSZachary Turner Data = Data.drop_front(2); 82*660230ebSZachary Turner return Error::success(); 8338cc8b3fSZachary Turner case LF_LONG: 846c13db40SDavid Majnemer if (Data.size() < 4) 85*660230ebSZachary Turner return make_error<CodeViewError>( 86*660230ebSZachary Turner cv_error_code::insufficient_buffer, 87*660230ebSZachary Turner "Buffer does not contain enough data for an LF_LONG"); 8838cc8b3fSZachary Turner Num = APSInt(APInt(/*numBits=*/32, 8938cc8b3fSZachary Turner *reinterpret_cast<const little32_t *>(Data.data()), 9038cc8b3fSZachary Turner /*isSigned=*/true), 9138cc8b3fSZachary Turner /*isUnsigned=*/false); 9238cc8b3fSZachary Turner Data = Data.drop_front(4); 93*660230ebSZachary Turner return Error::success(); 9438cc8b3fSZachary Turner case LF_ULONG: 956c13db40SDavid Majnemer if (Data.size() < 4) 96*660230ebSZachary Turner return make_error<CodeViewError>( 97*660230ebSZachary Turner cv_error_code::insufficient_buffer, 98*660230ebSZachary Turner "Buffer does not contain enough data for an LF_ULONG"); 9938cc8b3fSZachary Turner Num = APSInt(APInt(/*numBits=*/32, 10038cc8b3fSZachary Turner *reinterpret_cast<const ulittle32_t *>(Data.data()), 10138cc8b3fSZachary Turner /*isSigned=*/FalseVal), 10238cc8b3fSZachary Turner /*isUnsigned=*/true); 10338cc8b3fSZachary Turner Data = Data.drop_front(4); 104*660230ebSZachary Turner return Error::success(); 10538cc8b3fSZachary Turner case LF_QUADWORD: 1066c13db40SDavid Majnemer if (Data.size() < 8) 107*660230ebSZachary Turner return make_error<CodeViewError>( 108*660230ebSZachary Turner cv_error_code::insufficient_buffer, 109*660230ebSZachary Turner "Buffer does not contain enough data for an LF_QUADWORD"); 11038cc8b3fSZachary Turner Num = APSInt(APInt(/*numBits=*/64, 11138cc8b3fSZachary Turner *reinterpret_cast<const little64_t *>(Data.data()), 11238cc8b3fSZachary Turner /*isSigned=*/true), 11338cc8b3fSZachary Turner /*isUnsigned=*/false); 11438cc8b3fSZachary Turner Data = Data.drop_front(8); 115*660230ebSZachary Turner return Error::success(); 11638cc8b3fSZachary Turner case LF_UQUADWORD: 1176c13db40SDavid Majnemer if (Data.size() < 8) 118*660230ebSZachary Turner return make_error<CodeViewError>( 119*660230ebSZachary Turner cv_error_code::insufficient_buffer, 120*660230ebSZachary Turner "Buffer does not contain enough data for an LF_UQUADWORD"); 12138cc8b3fSZachary Turner Num = APSInt(APInt(/*numBits=*/64, 12238cc8b3fSZachary Turner *reinterpret_cast<const ulittle64_t *>(Data.data()), 12338cc8b3fSZachary Turner /*isSigned=*/false), 12438cc8b3fSZachary Turner /*isUnsigned=*/true); 12538cc8b3fSZachary Turner Data = Data.drop_front(8); 126*660230ebSZachary Turner return Error::success(); 12738cc8b3fSZachary Turner } 128*660230ebSZachary Turner return make_error<CodeViewError>(cv_error_code::corrupt_record, 129*660230ebSZachary Turner "Buffer contains invalid APSInt type"); 13038cc8b3fSZachary Turner } 13138cc8b3fSZachary Turner 132*660230ebSZachary Turner Error llvm::codeview::consume(StringRef &Data, APSInt &Num) { 13338cc8b3fSZachary Turner ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end()); 13438cc8b3fSZachary Turner auto EC = consume(Bytes, Num); 13538cc8b3fSZachary Turner Data = StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size()); 13638cc8b3fSZachary Turner return EC; 13738cc8b3fSZachary Turner } 13838cc8b3fSZachary Turner 13938cc8b3fSZachary Turner /// Decode a numeric leaf value that is known to be a uint64_t. 140*660230ebSZachary Turner Error llvm::codeview::consume_numeric(ArrayRef<uint8_t> &Data, uint64_t &Num) { 14138cc8b3fSZachary Turner APSInt N; 14238cc8b3fSZachary Turner if (auto EC = consume(Data, N)) 14338cc8b3fSZachary Turner return EC; 14438cc8b3fSZachary Turner if (N.isSigned() || !N.isIntN(64)) 145*660230ebSZachary Turner return make_error<CodeViewError>(cv_error_code::corrupt_record, 146*660230ebSZachary Turner "Data is not a numeric value!"); 14738cc8b3fSZachary Turner Num = N.getLimitedValue(); 148*660230ebSZachary Turner return Error::success(); 14938cc8b3fSZachary Turner } 15038cc8b3fSZachary Turner 151*660230ebSZachary Turner Error llvm::codeview::consume(ArrayRef<uint8_t> &Data, uint32_t &Item) { 15238cc8b3fSZachary Turner const support::ulittle32_t *IntPtr; 15338cc8b3fSZachary Turner if (auto EC = consumeObject(Data, IntPtr)) 15438cc8b3fSZachary Turner return EC; 15538cc8b3fSZachary Turner Item = *IntPtr; 156*660230ebSZachary Turner return Error::success(); 15738cc8b3fSZachary Turner } 15838cc8b3fSZachary Turner 159*660230ebSZachary Turner Error llvm::codeview::consume(StringRef &Data, uint32_t &Item) { 16038cc8b3fSZachary Turner ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end()); 16138cc8b3fSZachary Turner auto EC = consume(Bytes, Item); 16238cc8b3fSZachary Turner Data = StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size()); 16338cc8b3fSZachary Turner return EC; 16438cc8b3fSZachary Turner } 16538cc8b3fSZachary Turner 166*660230ebSZachary Turner Error llvm::codeview::consume(ArrayRef<uint8_t> &Data, int32_t &Item) { 16738cc8b3fSZachary Turner const support::little32_t *IntPtr; 16838cc8b3fSZachary Turner if (auto EC = consumeObject(Data, IntPtr)) 16938cc8b3fSZachary Turner return EC; 17038cc8b3fSZachary Turner Item = *IntPtr; 171*660230ebSZachary Turner return Error::success(); 17238cc8b3fSZachary Turner } 17338cc8b3fSZachary Turner 174*660230ebSZachary Turner Error llvm::codeview::consume(ArrayRef<uint8_t> &Data, StringRef &Item) { 17538cc8b3fSZachary Turner if (Data.empty()) 176*660230ebSZachary Turner return make_error<CodeViewError>(cv_error_code::corrupt_record, 177*660230ebSZachary Turner "Null terminated string buffer is empty!"); 17838cc8b3fSZachary Turner 17938cc8b3fSZachary Turner StringRef Rest; 18038cc8b3fSZachary Turner std::tie(Item, Rest) = getBytesAsCharacters(Data).split('\0'); 18138cc8b3fSZachary Turner // We expect this to be null terminated. If it was not, it is an error. 18238cc8b3fSZachary Turner if (Data.size() == Item.size()) 183*660230ebSZachary Turner return make_error<CodeViewError>(cv_error_code::corrupt_record, 184*660230ebSZachary Turner "Expected null terminator!"); 18538cc8b3fSZachary Turner 18638cc8b3fSZachary Turner Data = ArrayRef<uint8_t>(Rest.bytes_begin(), Rest.bytes_end()); 187*660230ebSZachary Turner return Error::success(); 18838cc8b3fSZachary Turner } 189