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/CodeViewError.h"
18 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
19 
20 using namespace llvm;
21 using namespace llvm::codeview;
22 using namespace llvm::support;
23 
24 /// Reinterpret a byte array as an array of characters. Does not interpret as
25 /// a C string, as StringRef has several helpers (split) that make that easy.
26 StringRef llvm::codeview::getBytesAsCharacters(ArrayRef<uint8_t> LeafData) {
27   return StringRef(reinterpret_cast<const char *>(LeafData.data()),
28                    LeafData.size());
29 }
30 
31 StringRef llvm::codeview::getBytesAsCString(ArrayRef<uint8_t> LeafData) {
32   return getBytesAsCharacters(LeafData).split('\0').first;
33 }
34 
35 Error llvm::codeview::consume(ArrayRef<uint8_t> &Data, APSInt &Num) {
36   // Used to avoid overload ambiguity on APInt construtor.
37   bool FalseVal = false;
38   if (Data.size() < 2)
39     return make_error<CodeViewError>(
40         cv_error_code::insufficient_buffer,
41         "Buffer does not contain enough data for an APSInt");
42   uint16_t Short = *reinterpret_cast<const ulittle16_t *>(Data.data());
43   Data = Data.drop_front(2);
44   if (Short < LF_NUMERIC) {
45     Num = APSInt(APInt(/*numBits=*/16, Short, /*isSigned=*/false),
46                  /*isUnsigned=*/true);
47     return Error::success();
48   }
49   switch (Short) {
50   case LF_CHAR:
51     if (Data.size() < 1)
52       return make_error<CodeViewError>(
53           cv_error_code::insufficient_buffer,
54           "Buffer does not contain enough data for an LF_CHAR");
55     Num = APSInt(APInt(/*numBits=*/8,
56                        *reinterpret_cast<const int8_t *>(Data.data()),
57                        /*isSigned=*/true),
58                  /*isUnsigned=*/false);
59     Data = Data.drop_front(1);
60     return Error::success();
61   case LF_SHORT:
62     if (Data.size() < 2)
63       return make_error<CodeViewError>(
64           cv_error_code::insufficient_buffer,
65           "Buffer does not contain enough data for an LF_SHORT");
66     Num = APSInt(APInt(/*numBits=*/16,
67                        *reinterpret_cast<const little16_t *>(Data.data()),
68                        /*isSigned=*/true),
69                  /*isUnsigned=*/false);
70     Data = Data.drop_front(2);
71     return Error::success();
72   case LF_USHORT:
73     if (Data.size() < 2)
74       return make_error<CodeViewError>(
75           cv_error_code::insufficient_buffer,
76           "Buffer does not contain enough data for an LF_USHORT");
77     Num = APSInt(APInt(/*numBits=*/16,
78                        *reinterpret_cast<const ulittle16_t *>(Data.data()),
79                        /*isSigned=*/false),
80                  /*isUnsigned=*/true);
81     Data = Data.drop_front(2);
82     return Error::success();
83   case LF_LONG:
84     if (Data.size() < 4)
85       return make_error<CodeViewError>(
86           cv_error_code::insufficient_buffer,
87           "Buffer does not contain enough data for an LF_LONG");
88     Num = APSInt(APInt(/*numBits=*/32,
89                        *reinterpret_cast<const little32_t *>(Data.data()),
90                        /*isSigned=*/true),
91                  /*isUnsigned=*/false);
92     Data = Data.drop_front(4);
93     return Error::success();
94   case LF_ULONG:
95     if (Data.size() < 4)
96       return make_error<CodeViewError>(
97           cv_error_code::insufficient_buffer,
98           "Buffer does not contain enough data for an LF_ULONG");
99     Num = APSInt(APInt(/*numBits=*/32,
100                        *reinterpret_cast<const ulittle32_t *>(Data.data()),
101                        /*isSigned=*/FalseVal),
102                  /*isUnsigned=*/true);
103     Data = Data.drop_front(4);
104     return Error::success();
105   case LF_QUADWORD:
106     if (Data.size() < 8)
107       return make_error<CodeViewError>(
108           cv_error_code::insufficient_buffer,
109           "Buffer does not contain enough data for an LF_QUADWORD");
110     Num = APSInt(APInt(/*numBits=*/64,
111                        *reinterpret_cast<const little64_t *>(Data.data()),
112                        /*isSigned=*/true),
113                  /*isUnsigned=*/false);
114     Data = Data.drop_front(8);
115     return Error::success();
116   case LF_UQUADWORD:
117     if (Data.size() < 8)
118       return make_error<CodeViewError>(
119           cv_error_code::insufficient_buffer,
120           "Buffer does not contain enough data for an LF_UQUADWORD");
121     Num = APSInt(APInt(/*numBits=*/64,
122                        *reinterpret_cast<const ulittle64_t *>(Data.data()),
123                        /*isSigned=*/false),
124                  /*isUnsigned=*/true);
125     Data = Data.drop_front(8);
126     return Error::success();
127   }
128   return make_error<CodeViewError>(cv_error_code::corrupt_record,
129                                    "Buffer contains invalid APSInt type");
130 }
131 
132 Error llvm::codeview::consume(StringRef &Data, APSInt &Num) {
133   ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end());
134   auto EC = consume(Bytes, Num);
135   Data = StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size());
136   return EC;
137 }
138 
139 /// Decode a numeric leaf value that is known to be a uint64_t.
140 Error llvm::codeview::consume_numeric(ArrayRef<uint8_t> &Data, uint64_t &Num) {
141   APSInt N;
142   if (auto EC = consume(Data, N))
143     return EC;
144   if (N.isSigned() || !N.isIntN(64))
145     return make_error<CodeViewError>(cv_error_code::corrupt_record,
146                                      "Data is not a numeric value!");
147   Num = N.getLimitedValue();
148   return Error::success();
149 }
150 
151 Error llvm::codeview::consume(ArrayRef<uint8_t> &Data, uint32_t &Item) {
152   const support::ulittle32_t *IntPtr;
153   if (auto EC = consumeObject(Data, IntPtr))
154     return EC;
155   Item = *IntPtr;
156   return Error::success();
157 }
158 
159 Error llvm::codeview::consume(StringRef &Data, uint32_t &Item) {
160   ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end());
161   auto EC = consume(Bytes, Item);
162   Data = StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size());
163   return EC;
164 }
165 
166 Error llvm::codeview::consume(ArrayRef<uint8_t> &Data, int32_t &Item) {
167   const support::little32_t *IntPtr;
168   if (auto EC = consumeObject(Data, IntPtr))
169     return EC;
170   Item = *IntPtr;
171   return Error::success();
172 }
173 
174 Error llvm::codeview::consume(ArrayRef<uint8_t> &Data, StringRef &Item) {
175   if (Data.empty())
176     return make_error<CodeViewError>(cv_error_code::corrupt_record,
177                                      "Null terminated string buffer is empty!");
178 
179   StringRef Rest;
180   std::tie(Item, Rest) = getBytesAsCharacters(Data).split('\0');
181   // We expect this to be null terminated.  If it was not, it is an error.
182   if (Data.size() == Item.size())
183     return make_error<CodeViewError>(cv_error_code::corrupt_record,
184                                      "Expected null terminator!");
185 
186   Data = ArrayRef<uint8_t>(Rest.bytes_begin(), Rest.bytes_end());
187   return Error::success();
188 }
189