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
);