1 //===-- RecordSerialization.cpp -------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Utilities for serializing and deserializing CodeView records.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/DebugInfo/CodeView/RecordSerialization.h"
15 #include "llvm/ADT/APInt.h"
16 #include "llvm/ADT/APSInt.h"
17 #include "llvm/DebugInfo/CodeView/CodeViewError.h"
18 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
19 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
20 #include "llvm/Support/BinaryByteStream.h"
23 using namespace llvm::codeview
;
24 using namespace llvm::support
;
26 /// Reinterpret a byte array as an array of characters. Does not interpret as
27 /// a C string, as StringRef has several helpers (split) that make that easy.
28 StringRef
llvm::codeview::getBytesAsCharacters(ArrayRef
<uint8_t> LeafData
) {
29 return StringRef(reinterpret_cast<const char *>(LeafData
.data()),
33 StringRef
llvm::codeview::getBytesAsCString(ArrayRef
<uint8_t> LeafData
) {
34 return getBytesAsCharacters(LeafData
).split('\0').first
;
37 Error
llvm::codeview::consume(BinaryStreamReader
&Reader
, APSInt
&Num
) {
38 // Used to avoid overload ambiguity on APInt construtor.
39 bool FalseVal
= false;
41 if (auto EC
= Reader
.readInteger(Short
))
44 if (Short
< LF_NUMERIC
) {
45 Num
= APSInt(APInt(/*numBits=*/16, Short
, /*isSigned=*/false),
47 return Error::success();
53 if (auto EC
= Reader
.readInteger(N
))
55 Num
= APSInt(APInt(8, N
, true), false);
56 return Error::success();
60 if (auto EC
= Reader
.readInteger(N
))
62 Num
= APSInt(APInt(16, N
, true), false);
63 return Error::success();
67 if (auto EC
= Reader
.readInteger(N
))
69 Num
= APSInt(APInt(16, N
, false), true);
70 return Error::success();
74 if (auto EC
= Reader
.readInteger(N
))
76 Num
= APSInt(APInt(32, N
, true), false);
77 return Error::success();
81 if (auto EC
= Reader
.readInteger(N
))
83 Num
= APSInt(APInt(32, N
, FalseVal
), true);
84 return Error::success();
88 if (auto EC
= Reader
.readInteger(N
))
90 Num
= APSInt(APInt(64, N
, true), false);
91 return Error::success();
95 if (auto EC
= Reader
.readInteger(N
))
97 Num
= APSInt(APInt(64, N
, false), true);
98 return Error::success();
101 return make_error
<CodeViewError
>(cv_error_code::corrupt_record
,
102 "Buffer contains invalid APSInt type");
105 Error
llvm::codeview::consume(StringRef
&Data
, APSInt
&Num
) {
106 ArrayRef
<uint8_t> Bytes(Data
.bytes_begin(), Data
.bytes_end());
107 BinaryByteStream
S(Bytes
, llvm::support::little
);
108 BinaryStreamReader
SR(S
);
109 auto EC
= consume(SR
, Num
);
110 Data
= Data
.take_back(SR
.bytesRemaining());
114 /// Decode a numeric leaf value that is known to be a uint64_t.
115 Error
llvm::codeview::consume_numeric(BinaryStreamReader
&Reader
,
118 if (auto EC
= consume(Reader
, N
))
120 if (N
.isSigned() || !N
.isIntN(64))
121 return make_error
<CodeViewError
>(cv_error_code::corrupt_record
,
122 "Data is not a numeric value!");
123 Num
= N
.getLimitedValue();
124 return Error::success();
127 Error
llvm::codeview::consume(BinaryStreamReader
&Reader
, uint32_t &Item
) {
128 return Reader
.readInteger(Item
);
131 Error
llvm::codeview::consume(StringRef
&Data
, uint32_t &Item
) {
132 ArrayRef
<uint8_t> Bytes(Data
.bytes_begin(), Data
.bytes_end());
133 BinaryByteStream
S(Bytes
, llvm::support::little
);
134 BinaryStreamReader
SR(S
);
135 auto EC
= consume(SR
, Item
);
136 Data
= Data
.take_back(SR
.bytesRemaining());
140 Error
llvm::codeview::consume(BinaryStreamReader
&Reader
, int32_t &Item
) {
141 return Reader
.readInteger(Item
);
144 Error
llvm::codeview::consume(BinaryStreamReader
&Reader
, StringRef
&Item
) {
146 return make_error
<CodeViewError
>(cv_error_code::corrupt_record
,
147 "Null terminated string buffer is empty!");
149 return Reader
.readCString(Item
);
152 Expected
<CVSymbol
> llvm::codeview::readSymbolFromStream(BinaryStreamRef Stream
,
154 return readCVRecordFromStream
<SymbolKind
>(Stream
, Offset
);