1 //===-- RecordSerialization.cpp -------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // Utilities for serializing and deserializing CodeView records.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/DebugInfo/CodeView/RecordSerialization.h"
14 #include "llvm/ADT/APInt.h"
15 #include "llvm/ADT/APSInt.h"
16 #include "llvm/DebugInfo/CodeView/CodeViewError.h"
17 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
18 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
19 #include "llvm/Support/BinaryByteStream.h"
22 using namespace llvm::codeview;
23 using namespace llvm::support;
25 /// Reinterpret a byte array as an array of characters. Does not interpret as
26 /// a C string, as StringRef has several helpers (split) that make that easy.
27 StringRef llvm::codeview::getBytesAsCharacters(ArrayRef<uint8_t> LeafData) {
28 return StringRef(reinterpret_cast<const char *>(LeafData.data()),
32 StringRef llvm::codeview::getBytesAsCString(ArrayRef<uint8_t> LeafData) {
33 return getBytesAsCharacters(LeafData).split('\0').first;
36 Error llvm::codeview::consume(BinaryStreamReader &Reader, APSInt &Num) {
37 // Used to avoid overload ambiguity on APInt construtor.
38 bool FalseVal = false;
40 if (auto EC = Reader.readInteger(Short))
43 if (Short < LF_NUMERIC) {
44 Num = APSInt(APInt(/*numBits=*/16, Short, /*isSigned=*/false),
46 return Error::success();
52 if (auto EC = Reader.readInteger(N))
54 Num = APSInt(APInt(8, N, true), false);
55 return Error::success();
59 if (auto EC = Reader.readInteger(N))
61 Num = APSInt(APInt(16, N, true), false);
62 return Error::success();
66 if (auto EC = Reader.readInteger(N))
68 Num = APSInt(APInt(16, N, false), true);
69 return Error::success();
73 if (auto EC = Reader.readInteger(N))
75 Num = APSInt(APInt(32, N, true), false);
76 return Error::success();
80 if (auto EC = Reader.readInteger(N))
82 Num = APSInt(APInt(32, N, FalseVal), true);
83 return Error::success();
87 if (auto EC = Reader.readInteger(N))
89 Num = APSInt(APInt(64, N, true), false);
90 return Error::success();
94 if (auto EC = Reader.readInteger(N))
96 Num = APSInt(APInt(64, N, false), true);
97 return Error::success();
100 return make_error<CodeViewError>(cv_error_code::corrupt_record,
101 "Buffer contains invalid APSInt type");
104 Error llvm::codeview::consume(StringRef &Data, APSInt &Num) {
105 ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end());
106 BinaryByteStream S(Bytes, llvm::support::little);
107 BinaryStreamReader SR(S);
108 auto EC = consume(SR, Num);
109 Data = Data.take_back(SR.bytesRemaining());
113 /// Decode a numeric leaf value that is known to be a uint64_t.
114 Error llvm::codeview::consume_numeric(BinaryStreamReader &Reader,
117 if (auto EC = consume(Reader, N))
119 if (N.isSigned() || !N.isIntN(64))
120 return make_error<CodeViewError>(cv_error_code::corrupt_record,
121 "Data is not a numeric value!");
122 Num = N.getLimitedValue();
123 return Error::success();
126 Error llvm::codeview::consume(BinaryStreamReader &Reader, uint32_t &Item) {
127 return Reader.readInteger(Item);
130 Error llvm::codeview::consume(StringRef &Data, uint32_t &Item) {
131 ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end());
132 BinaryByteStream S(Bytes, llvm::support::little);
133 BinaryStreamReader SR(S);
134 auto EC = consume(SR, Item);
135 Data = Data.take_back(SR.bytesRemaining());
139 Error llvm::codeview::consume(BinaryStreamReader &Reader, int32_t &Item) {
140 return Reader.readInteger(Item);
143 Error llvm::codeview::consume(BinaryStreamReader &Reader, StringRef &Item) {
145 return make_error<CodeViewError>(cv_error_code::corrupt_record,
146 "Null terminated string buffer is empty!");
148 return Reader.readCString(Item);
151 Expected<CVSymbol> llvm::codeview::readSymbolFromStream(BinaryStreamRef Stream,
153 return readCVRecordFromStream<SymbolKind>(Stream, Offset);