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" 18*14d90fd0SReid Kleckner #include "llvm/DebugInfo/CodeView/SymbolRecord.h" 1938cc8b3fSZachary Turner #include "llvm/DebugInfo/CodeView/TypeRecord.h" 20d9dc2829SZachary Turner #include "llvm/Support/BinaryByteStream.h" 2138cc8b3fSZachary Turner 2238cc8b3fSZachary Turner using namespace llvm; 2338cc8b3fSZachary Turner using namespace llvm::codeview; 2438cc8b3fSZachary Turner using namespace llvm::support; 2538cc8b3fSZachary Turner 2638cc8b3fSZachary Turner /// Reinterpret a byte array as an array of characters. Does not interpret as 2738cc8b3fSZachary Turner /// a C string, as StringRef has several helpers (split) that make that easy. 2838cc8b3fSZachary Turner StringRef llvm::codeview::getBytesAsCharacters(ArrayRef<uint8_t> LeafData) { 2938cc8b3fSZachary Turner return StringRef(reinterpret_cast<const char *>(LeafData.data()), 3038cc8b3fSZachary Turner LeafData.size()); 3138cc8b3fSZachary Turner } 3238cc8b3fSZachary Turner 3338cc8b3fSZachary Turner StringRef llvm::codeview::getBytesAsCString(ArrayRef<uint8_t> LeafData) { 3438cc8b3fSZachary Turner return getBytesAsCharacters(LeafData).split('\0').first; 3538cc8b3fSZachary Turner } 3638cc8b3fSZachary Turner 37120faca4SZachary Turner Error llvm::codeview::consume(BinaryStreamReader &Reader, APSInt &Num) { 3838cc8b3fSZachary Turner // Used to avoid overload ambiguity on APInt construtor. 3938cc8b3fSZachary Turner bool FalseVal = false; 404d49eb9fSZachary Turner uint16_t Short; 41695ed56bSZachary Turner if (auto EC = Reader.readInteger(Short)) 424d49eb9fSZachary Turner return EC; 434d49eb9fSZachary Turner 4438cc8b3fSZachary Turner if (Short < LF_NUMERIC) { 4538cc8b3fSZachary Turner Num = APSInt(APInt(/*numBits=*/16, Short, /*isSigned=*/false), 4638cc8b3fSZachary Turner /*isUnsigned=*/true); 47660230ebSZachary Turner return Error::success(); 4838cc8b3fSZachary Turner } 494d49eb9fSZachary Turner 5038cc8b3fSZachary Turner switch (Short) { 514d49eb9fSZachary Turner case LF_CHAR: { 524d49eb9fSZachary Turner int8_t N; 53695ed56bSZachary Turner if (auto EC = Reader.readInteger(N)) 544d49eb9fSZachary Turner return EC; 554d49eb9fSZachary Turner Num = APSInt(APInt(8, N, true), false); 56660230ebSZachary Turner return Error::success(); 574d49eb9fSZachary Turner } 584d49eb9fSZachary Turner case LF_SHORT: { 594d49eb9fSZachary Turner int16_t N; 60695ed56bSZachary Turner if (auto EC = Reader.readInteger(N)) 614d49eb9fSZachary Turner return EC; 624d49eb9fSZachary Turner Num = APSInt(APInt(16, N, true), false); 63660230ebSZachary Turner return Error::success(); 644d49eb9fSZachary Turner } 654d49eb9fSZachary Turner case LF_USHORT: { 664d49eb9fSZachary Turner uint16_t N; 67695ed56bSZachary Turner if (auto EC = Reader.readInteger(N)) 684d49eb9fSZachary Turner return EC; 694d49eb9fSZachary Turner Num = APSInt(APInt(16, N, false), true); 70660230ebSZachary Turner return Error::success(); 714d49eb9fSZachary Turner } 724d49eb9fSZachary Turner case LF_LONG: { 734d49eb9fSZachary Turner int32_t N; 74695ed56bSZachary Turner if (auto EC = Reader.readInteger(N)) 754d49eb9fSZachary Turner return EC; 764d49eb9fSZachary Turner Num = APSInt(APInt(32, N, true), false); 77660230ebSZachary Turner return Error::success(); 784d49eb9fSZachary Turner } 794d49eb9fSZachary Turner case LF_ULONG: { 804d49eb9fSZachary Turner uint32_t N; 81695ed56bSZachary Turner if (auto EC = Reader.readInteger(N)) 824d49eb9fSZachary Turner return EC; 834d49eb9fSZachary Turner Num = APSInt(APInt(32, N, FalseVal), true); 84660230ebSZachary Turner return Error::success(); 854d49eb9fSZachary Turner } 864d49eb9fSZachary Turner case LF_QUADWORD: { 874d49eb9fSZachary Turner int64_t N; 88695ed56bSZachary Turner if (auto EC = Reader.readInteger(N)) 894d49eb9fSZachary Turner return EC; 904d49eb9fSZachary Turner Num = APSInt(APInt(64, N, true), false); 91660230ebSZachary Turner return Error::success(); 924d49eb9fSZachary Turner } 934d49eb9fSZachary Turner case LF_UQUADWORD: { 944d49eb9fSZachary Turner uint64_t N; 95695ed56bSZachary Turner if (auto EC = Reader.readInteger(N)) 964d49eb9fSZachary Turner return EC; 974d49eb9fSZachary Turner Num = APSInt(APInt(64, N, false), true); 98660230ebSZachary Turner return Error::success(); 9938cc8b3fSZachary Turner } 1004d49eb9fSZachary Turner } 101660230ebSZachary Turner return make_error<CodeViewError>(cv_error_code::corrupt_record, 102660230ebSZachary Turner "Buffer contains invalid APSInt type"); 10338cc8b3fSZachary Turner } 10438cc8b3fSZachary Turner 105660230ebSZachary Turner Error llvm::codeview::consume(StringRef &Data, APSInt &Num) { 10638cc8b3fSZachary Turner ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end()); 107695ed56bSZachary Turner BinaryByteStream S(Bytes, llvm::support::little); 108120faca4SZachary Turner BinaryStreamReader SR(S); 1094d49eb9fSZachary Turner auto EC = consume(SR, Num); 1104d49eb9fSZachary Turner Data = Data.take_back(SR.bytesRemaining()); 11138cc8b3fSZachary Turner return EC; 11238cc8b3fSZachary Turner } 11338cc8b3fSZachary Turner 11438cc8b3fSZachary Turner /// Decode a numeric leaf value that is known to be a uint64_t. 115120faca4SZachary Turner Error llvm::codeview::consume_numeric(BinaryStreamReader &Reader, 1164d49eb9fSZachary Turner uint64_t &Num) { 11738cc8b3fSZachary Turner APSInt N; 1184d49eb9fSZachary Turner if (auto EC = consume(Reader, N)) 11938cc8b3fSZachary Turner return EC; 12038cc8b3fSZachary Turner if (N.isSigned() || !N.isIntN(64)) 121660230ebSZachary Turner return make_error<CodeViewError>(cv_error_code::corrupt_record, 122660230ebSZachary Turner "Data is not a numeric value!"); 12338cc8b3fSZachary Turner Num = N.getLimitedValue(); 124660230ebSZachary Turner return Error::success(); 12538cc8b3fSZachary Turner } 12638cc8b3fSZachary Turner 127120faca4SZachary Turner Error llvm::codeview::consume(BinaryStreamReader &Reader, uint32_t &Item) { 128695ed56bSZachary Turner return Reader.readInteger(Item); 12938cc8b3fSZachary Turner } 13038cc8b3fSZachary Turner 131660230ebSZachary Turner Error llvm::codeview::consume(StringRef &Data, uint32_t &Item) { 13238cc8b3fSZachary Turner ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end()); 133695ed56bSZachary Turner BinaryByteStream S(Bytes, llvm::support::little); 134120faca4SZachary Turner BinaryStreamReader SR(S); 1354d49eb9fSZachary Turner auto EC = consume(SR, Item); 1364d49eb9fSZachary Turner Data = Data.take_back(SR.bytesRemaining()); 13738cc8b3fSZachary Turner return EC; 13838cc8b3fSZachary Turner } 13938cc8b3fSZachary Turner 140120faca4SZachary Turner Error llvm::codeview::consume(BinaryStreamReader &Reader, int32_t &Item) { 141695ed56bSZachary Turner return Reader.readInteger(Item); 14238cc8b3fSZachary Turner } 14338cc8b3fSZachary Turner 144120faca4SZachary Turner Error llvm::codeview::consume(BinaryStreamReader &Reader, StringRef &Item) { 1454d49eb9fSZachary Turner if (Reader.empty()) 146660230ebSZachary Turner return make_error<CodeViewError>(cv_error_code::corrupt_record, 147660230ebSZachary Turner "Null terminated string buffer is empty!"); 14838cc8b3fSZachary Turner 149120faca4SZachary Turner return Reader.readCString(Item); 15038cc8b3fSZachary Turner } 151*14d90fd0SReid Kleckner 152*14d90fd0SReid Kleckner Expected<CVSymbol> llvm::codeview::readSymbolFromStream(BinaryStreamRef Stream, 153*14d90fd0SReid Kleckner uint32_t Offset) { 154*14d90fd0SReid Kleckner return readCVRecordFromStream<SymbolKind>(Stream, Offset); 155*14d90fd0SReid Kleckner } 156