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" 17660230ebSZachary Turner #include "llvm/DebugInfo/CodeView/CodeViewError.h" 1838cc8b3fSZachary Turner #include "llvm/DebugInfo/CodeView/TypeRecord.h" 19*4d49eb9fSZachary Turner #include "llvm/DebugInfo/MSF/ByteStream.h" 2038cc8b3fSZachary Turner 2138cc8b3fSZachary Turner using namespace llvm; 2238cc8b3fSZachary Turner using namespace llvm::codeview; 2338cc8b3fSZachary Turner using namespace llvm::support; 2438cc8b3fSZachary Turner 2538cc8b3fSZachary Turner /// Reinterpret a byte array as an array of characters. Does not interpret as 2638cc8b3fSZachary Turner /// a C string, as StringRef has several helpers (split) that make that easy. 2738cc8b3fSZachary Turner StringRef llvm::codeview::getBytesAsCharacters(ArrayRef<uint8_t> LeafData) { 2838cc8b3fSZachary Turner return StringRef(reinterpret_cast<const char *>(LeafData.data()), 2938cc8b3fSZachary Turner LeafData.size()); 3038cc8b3fSZachary Turner } 3138cc8b3fSZachary Turner 3238cc8b3fSZachary Turner StringRef llvm::codeview::getBytesAsCString(ArrayRef<uint8_t> LeafData) { 3338cc8b3fSZachary Turner return getBytesAsCharacters(LeafData).split('\0').first; 3438cc8b3fSZachary Turner } 3538cc8b3fSZachary Turner 36*4d49eb9fSZachary Turner Error llvm::codeview::consume(msf::StreamReader &Reader, APSInt &Num) { 3738cc8b3fSZachary Turner // Used to avoid overload ambiguity on APInt construtor. 3838cc8b3fSZachary Turner bool FalseVal = false; 39*4d49eb9fSZachary Turner uint16_t Short; 40*4d49eb9fSZachary Turner if (auto EC = Reader.readInteger(Short)) 41*4d49eb9fSZachary Turner return EC; 42*4d49eb9fSZachary Turner 4338cc8b3fSZachary Turner if (Short < LF_NUMERIC) { 4438cc8b3fSZachary Turner Num = APSInt(APInt(/*numBits=*/16, Short, /*isSigned=*/false), 4538cc8b3fSZachary Turner /*isUnsigned=*/true); 46660230ebSZachary Turner return Error::success(); 4738cc8b3fSZachary Turner } 48*4d49eb9fSZachary Turner 4938cc8b3fSZachary Turner switch (Short) { 50*4d49eb9fSZachary Turner case LF_CHAR: { 51*4d49eb9fSZachary Turner int8_t N; 52*4d49eb9fSZachary Turner if (auto EC = Reader.readInteger(N)) 53*4d49eb9fSZachary Turner return EC; 54*4d49eb9fSZachary Turner Num = APSInt(APInt(8, N, true), false); 55660230ebSZachary Turner return Error::success(); 56*4d49eb9fSZachary Turner } 57*4d49eb9fSZachary Turner case LF_SHORT: { 58*4d49eb9fSZachary Turner int16_t N; 59*4d49eb9fSZachary Turner if (auto EC = Reader.readInteger(N)) 60*4d49eb9fSZachary Turner return EC; 61*4d49eb9fSZachary Turner Num = APSInt(APInt(16, N, true), false); 62660230ebSZachary Turner return Error::success(); 63*4d49eb9fSZachary Turner } 64*4d49eb9fSZachary Turner case LF_USHORT: { 65*4d49eb9fSZachary Turner uint16_t N; 66*4d49eb9fSZachary Turner if (auto EC = Reader.readInteger(N)) 67*4d49eb9fSZachary Turner return EC; 68*4d49eb9fSZachary Turner Num = APSInt(APInt(16, N, false), true); 69660230ebSZachary Turner return Error::success(); 70*4d49eb9fSZachary Turner } 71*4d49eb9fSZachary Turner case LF_LONG: { 72*4d49eb9fSZachary Turner int32_t N; 73*4d49eb9fSZachary Turner if (auto EC = Reader.readInteger(N)) 74*4d49eb9fSZachary Turner return EC; 75*4d49eb9fSZachary Turner Num = APSInt(APInt(32, N, true), false); 76660230ebSZachary Turner return Error::success(); 77*4d49eb9fSZachary Turner } 78*4d49eb9fSZachary Turner case LF_ULONG: { 79*4d49eb9fSZachary Turner uint32_t N; 80*4d49eb9fSZachary Turner if (auto EC = Reader.readInteger(N)) 81*4d49eb9fSZachary Turner return EC; 82*4d49eb9fSZachary Turner Num = APSInt(APInt(32, N, FalseVal), true); 83660230ebSZachary Turner return Error::success(); 84*4d49eb9fSZachary Turner } 85*4d49eb9fSZachary Turner case LF_QUADWORD: { 86*4d49eb9fSZachary Turner int64_t N; 87*4d49eb9fSZachary Turner if (auto EC = Reader.readInteger(N)) 88*4d49eb9fSZachary Turner return EC; 89*4d49eb9fSZachary Turner Num = APSInt(APInt(64, N, true), false); 90660230ebSZachary Turner return Error::success(); 91*4d49eb9fSZachary Turner } 92*4d49eb9fSZachary Turner case LF_UQUADWORD: { 93*4d49eb9fSZachary Turner uint64_t N; 94*4d49eb9fSZachary Turner if (auto EC = Reader.readInteger(N)) 95*4d49eb9fSZachary Turner return EC; 96*4d49eb9fSZachary Turner Num = APSInt(APInt(64, N, false), true); 97660230ebSZachary Turner return Error::success(); 9838cc8b3fSZachary Turner } 99*4d49eb9fSZachary Turner } 100660230ebSZachary Turner return make_error<CodeViewError>(cv_error_code::corrupt_record, 101660230ebSZachary Turner "Buffer contains invalid APSInt type"); 10238cc8b3fSZachary Turner } 10338cc8b3fSZachary Turner 104660230ebSZachary Turner Error llvm::codeview::consume(StringRef &Data, APSInt &Num) { 10538cc8b3fSZachary Turner ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end()); 106*4d49eb9fSZachary Turner msf::ByteStream S(Bytes); 107*4d49eb9fSZachary Turner msf::StreamReader SR(S); 108*4d49eb9fSZachary Turner auto EC = consume(SR, Num); 109*4d49eb9fSZachary Turner Data = Data.take_back(SR.bytesRemaining()); 11038cc8b3fSZachary Turner return EC; 11138cc8b3fSZachary Turner } 11238cc8b3fSZachary Turner 11338cc8b3fSZachary Turner /// Decode a numeric leaf value that is known to be a uint64_t. 114*4d49eb9fSZachary Turner Error llvm::codeview::consume_numeric(msf::StreamReader &Reader, 115*4d49eb9fSZachary Turner uint64_t &Num) { 11638cc8b3fSZachary Turner APSInt N; 117*4d49eb9fSZachary Turner if (auto EC = consume(Reader, N)) 11838cc8b3fSZachary Turner return EC; 11938cc8b3fSZachary Turner if (N.isSigned() || !N.isIntN(64)) 120660230ebSZachary Turner return make_error<CodeViewError>(cv_error_code::corrupt_record, 121660230ebSZachary Turner "Data is not a numeric value!"); 12238cc8b3fSZachary Turner Num = N.getLimitedValue(); 123660230ebSZachary Turner return Error::success(); 12438cc8b3fSZachary Turner } 12538cc8b3fSZachary Turner 126*4d49eb9fSZachary Turner Error llvm::codeview::consume(msf::StreamReader &Reader, uint32_t &Item) { 127*4d49eb9fSZachary Turner return Reader.readInteger(Item); 12838cc8b3fSZachary Turner } 12938cc8b3fSZachary Turner 130660230ebSZachary Turner Error llvm::codeview::consume(StringRef &Data, uint32_t &Item) { 13138cc8b3fSZachary Turner ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end()); 132*4d49eb9fSZachary Turner msf::ByteStream S(Bytes); 133*4d49eb9fSZachary Turner msf::StreamReader SR(S); 134*4d49eb9fSZachary Turner auto EC = consume(SR, Item); 135*4d49eb9fSZachary Turner Data = Data.take_back(SR.bytesRemaining()); 13638cc8b3fSZachary Turner return EC; 13738cc8b3fSZachary Turner } 13838cc8b3fSZachary Turner 139*4d49eb9fSZachary Turner Error llvm::codeview::consume(msf::StreamReader &Reader, int32_t &Item) { 140*4d49eb9fSZachary Turner return Reader.readInteger(Item); 14138cc8b3fSZachary Turner } 14238cc8b3fSZachary Turner 143*4d49eb9fSZachary Turner Error llvm::codeview::consume(msf::StreamReader &Reader, StringRef &Item) { 144*4d49eb9fSZachary Turner if (Reader.empty()) 145660230ebSZachary Turner return make_error<CodeViewError>(cv_error_code::corrupt_record, 146660230ebSZachary Turner "Null terminated string buffer is empty!"); 14738cc8b3fSZachary Turner 148*4d49eb9fSZachary Turner return Reader.readZeroString(Item); 14938cc8b3fSZachary Turner } 150