1 //===-- RecordSerialization.cpp -------------------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Utilities for serializing and deserializing CodeView records.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/DebugInfo/CodeView/RecordSerialization.h"
15 #include "llvm/ADT/APInt.h"
16 #include "llvm/ADT/APSInt.h"
17 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
18
19 using namespace llvm;
20 using namespace llvm::codeview;
21 using namespace llvm::support;
22
23 /// Reinterpret a byte array as an array of characters. Does not interpret as
24 /// a C string, as StringRef has several helpers (split) that make that easy.
getBytesAsCharacters(ArrayRef<uint8_t> LeafData)25 StringRef llvm::codeview::getBytesAsCharacters(ArrayRef<uint8_t> LeafData) {
26 return StringRef(reinterpret_cast<const char *>(LeafData.data()),
27 LeafData.size());
28 }
29
getBytesAsCString(ArrayRef<uint8_t> LeafData)30 StringRef llvm::codeview::getBytesAsCString(ArrayRef<uint8_t> LeafData) {
31 return getBytesAsCharacters(LeafData).split('\0').first;
32 }
33
consume(ArrayRef<uint8_t> & Data,APSInt & Num)34 std::error_code llvm::codeview::consume(ArrayRef<uint8_t> &Data, APSInt &Num) {
35 // Used to avoid overload ambiguity on APInt construtor.
36 bool FalseVal = false;
37 if (Data.size() < 2)
38 return std::make_error_code(std::errc::illegal_byte_sequence);
39 uint16_t Short = *reinterpret_cast<const ulittle16_t *>(Data.data());
40 Data = Data.drop_front(2);
41 if (Short < LF_NUMERIC) {
42 Num = APSInt(APInt(/*numBits=*/16, Short, /*isSigned=*/false),
43 /*isUnsigned=*/true);
44 return std::error_code();
45 }
46 switch (Short) {
47 case LF_CHAR:
48 if (Data.size() < 1)
49 return std::make_error_code(std::errc::illegal_byte_sequence);
50 Num = APSInt(APInt(/*numBits=*/8,
51 *reinterpret_cast<const int8_t *>(Data.data()),
52 /*isSigned=*/true),
53 /*isUnsigned=*/false);
54 Data = Data.drop_front(1);
55 return std::error_code();
56 case LF_SHORT:
57 if (Data.size() < 2)
58 return std::make_error_code(std::errc::illegal_byte_sequence);
59 Num = APSInt(APInt(/*numBits=*/16,
60 *reinterpret_cast<const little16_t *>(Data.data()),
61 /*isSigned=*/true),
62 /*isUnsigned=*/false);
63 Data = Data.drop_front(2);
64 return std::error_code();
65 case LF_USHORT:
66 if (Data.size() < 2)
67 return std::make_error_code(std::errc::illegal_byte_sequence);
68 Num = APSInt(APInt(/*numBits=*/16,
69 *reinterpret_cast<const ulittle16_t *>(Data.data()),
70 /*isSigned=*/false),
71 /*isUnsigned=*/true);
72 Data = Data.drop_front(2);
73 return std::error_code();
74 case LF_LONG:
75 if (Data.size() < 4)
76 return std::make_error_code(std::errc::illegal_byte_sequence);
77 Num = APSInt(APInt(/*numBits=*/32,
78 *reinterpret_cast<const little32_t *>(Data.data()),
79 /*isSigned=*/true),
80 /*isUnsigned=*/false);
81 Data = Data.drop_front(4);
82 return std::error_code();
83 case LF_ULONG:
84 if (Data.size() < 4)
85 return std::make_error_code(std::errc::illegal_byte_sequence);
86 Num = APSInt(APInt(/*numBits=*/32,
87 *reinterpret_cast<const ulittle32_t *>(Data.data()),
88 /*isSigned=*/FalseVal),
89 /*isUnsigned=*/true);
90 Data = Data.drop_front(4);
91 return std::error_code();
92 case LF_QUADWORD:
93 if (Data.size() < 8)
94 return std::make_error_code(std::errc::illegal_byte_sequence);
95 Num = APSInt(APInt(/*numBits=*/64,
96 *reinterpret_cast<const little64_t *>(Data.data()),
97 /*isSigned=*/true),
98 /*isUnsigned=*/false);
99 Data = Data.drop_front(8);
100 return std::error_code();
101 case LF_UQUADWORD:
102 if (Data.size() < 8)
103 return std::make_error_code(std::errc::illegal_byte_sequence);
104 Num = APSInt(APInt(/*numBits=*/64,
105 *reinterpret_cast<const ulittle64_t *>(Data.data()),
106 /*isSigned=*/false),
107 /*isUnsigned=*/true);
108 Data = Data.drop_front(8);
109 return std::error_code();
110 }
111 return std::make_error_code(std::errc::illegal_byte_sequence);
112 }
113
consume(StringRef & Data,APSInt & Num)114 std::error_code llvm::codeview::consume(StringRef &Data, APSInt &Num) {
115 ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end());
116 auto EC = consume(Bytes, Num);
117 Data = StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size());
118 return EC;
119 }
120
121 /// Decode a numeric leaf value that is known to be a uint64_t.
consume_numeric(ArrayRef<uint8_t> & Data,uint64_t & Num)122 std::error_code llvm::codeview::consume_numeric(ArrayRef<uint8_t> &Data,
123 uint64_t &Num) {
124 APSInt N;
125 if (auto EC = consume(Data, N))
126 return EC;
127 if (N.isSigned() || !N.isIntN(64))
128 return std::make_error_code(std::errc::illegal_byte_sequence);
129 Num = N.getLimitedValue();
130 return std::error_code();
131 }
132
consume(ArrayRef<uint8_t> & Data,uint32_t & Item)133 std::error_code llvm::codeview::consume(ArrayRef<uint8_t> &Data,
134 uint32_t &Item) {
135 const support::ulittle32_t *IntPtr;
136 if (auto EC = consumeObject(Data, IntPtr))
137 return EC;
138 Item = *IntPtr;
139 return std::error_code();
140 }
141
consume(StringRef & Data,uint32_t & Item)142 std::error_code llvm::codeview::consume(StringRef &Data, uint32_t &Item) {
143 ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end());
144 auto EC = consume(Bytes, Item);
145 Data = StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size());
146 return EC;
147 }
148
consume(ArrayRef<uint8_t> & Data,int32_t & Item)149 std::error_code llvm::codeview::consume(ArrayRef<uint8_t> &Data,
150 int32_t &Item) {
151 const support::little32_t *IntPtr;
152 if (auto EC = consumeObject(Data, IntPtr))
153 return EC;
154 Item = *IntPtr;
155 return std::error_code();
156 }
157
consume(ArrayRef<uint8_t> & Data,StringRef & Item)158 std::error_code llvm::codeview::consume(ArrayRef<uint8_t> &Data,
159 StringRef &Item) {
160 if (Data.empty())
161 return std::make_error_code(std::errc::illegal_byte_sequence);
162
163 StringRef Rest;
164 std::tie(Item, Rest) = getBytesAsCharacters(Data).split('\0');
165 // We expect this to be null terminated. If it was not, it is an error.
166 if (Data.size() == Item.size())
167 return std::make_error_code(std::errc::illegal_byte_sequence);
168
169 Data = ArrayRef<uint8_t>(Rest.bytes_begin(), Rest.bytes_end());
170 return std::error_code();
171 }
172