138cc8b3fSZachary Turner //===-- RecordSerialization.cpp -------------------------------------------===//
238cc8b3fSZachary Turner //
338cc8b3fSZachary Turner //                     The LLVM Compiler Infrastructure
438cc8b3fSZachary Turner //
538cc8b3fSZachary Turner // This file is distributed under the University of Illinois Open Source
638cc8b3fSZachary Turner // License. See LICENSE.TXT for details.
738cc8b3fSZachary Turner //
838cc8b3fSZachary Turner //===----------------------------------------------------------------------===//
938cc8b3fSZachary Turner //
1038cc8b3fSZachary Turner // Utilities for serializing and deserializing CodeView records.
1138cc8b3fSZachary Turner //
1238cc8b3fSZachary Turner //===----------------------------------------------------------------------===//
1338cc8b3fSZachary Turner 
1438cc8b3fSZachary Turner #include "llvm/DebugInfo/CodeView/RecordSerialization.h"
1538cc8b3fSZachary Turner #include "llvm/ADT/APInt.h"
1638cc8b3fSZachary Turner #include "llvm/ADT/APSInt.h"
17*660230ebSZachary Turner #include "llvm/DebugInfo/CodeView/CodeViewError.h"
1838cc8b3fSZachary Turner #include "llvm/DebugInfo/CodeView/TypeRecord.h"
1938cc8b3fSZachary Turner 
2038cc8b3fSZachary Turner using namespace llvm;
2138cc8b3fSZachary Turner using namespace llvm::codeview;
2238cc8b3fSZachary Turner using namespace llvm::support;
2338cc8b3fSZachary Turner 
2438cc8b3fSZachary Turner /// Reinterpret a byte array as an array of characters. Does not interpret as
2538cc8b3fSZachary Turner /// a C string, as StringRef has several helpers (split) that make that easy.
2638cc8b3fSZachary Turner StringRef llvm::codeview::getBytesAsCharacters(ArrayRef<uint8_t> LeafData) {
2738cc8b3fSZachary Turner   return StringRef(reinterpret_cast<const char *>(LeafData.data()),
2838cc8b3fSZachary Turner                    LeafData.size());
2938cc8b3fSZachary Turner }
3038cc8b3fSZachary Turner 
3138cc8b3fSZachary Turner StringRef llvm::codeview::getBytesAsCString(ArrayRef<uint8_t> LeafData) {
3238cc8b3fSZachary Turner   return getBytesAsCharacters(LeafData).split('\0').first;
3338cc8b3fSZachary Turner }
3438cc8b3fSZachary Turner 
35*660230ebSZachary Turner Error llvm::codeview::consume(ArrayRef<uint8_t> &Data, APSInt &Num) {
3638cc8b3fSZachary Turner   // Used to avoid overload ambiguity on APInt construtor.
3738cc8b3fSZachary Turner   bool FalseVal = false;
3838cc8b3fSZachary Turner   if (Data.size() < 2)
39*660230ebSZachary Turner     return make_error<CodeViewError>(
40*660230ebSZachary Turner         cv_error_code::insufficient_buffer,
41*660230ebSZachary Turner         "Buffer does not contain enough data for an APSInt");
4238cc8b3fSZachary Turner   uint16_t Short = *reinterpret_cast<const ulittle16_t *>(Data.data());
4338cc8b3fSZachary Turner   Data = Data.drop_front(2);
4438cc8b3fSZachary Turner   if (Short < LF_NUMERIC) {
4538cc8b3fSZachary Turner     Num = APSInt(APInt(/*numBits=*/16, Short, /*isSigned=*/false),
4638cc8b3fSZachary Turner                  /*isUnsigned=*/true);
47*660230ebSZachary Turner     return Error::success();
4838cc8b3fSZachary Turner   }
4938cc8b3fSZachary Turner   switch (Short) {
5038cc8b3fSZachary Turner   case LF_CHAR:
516c13db40SDavid Majnemer     if (Data.size() < 1)
52*660230ebSZachary Turner       return make_error<CodeViewError>(
53*660230ebSZachary Turner           cv_error_code::insufficient_buffer,
54*660230ebSZachary Turner           "Buffer does not contain enough data for an LF_CHAR");
5538cc8b3fSZachary Turner     Num = APSInt(APInt(/*numBits=*/8,
5638cc8b3fSZachary Turner                        *reinterpret_cast<const int8_t *>(Data.data()),
5738cc8b3fSZachary Turner                        /*isSigned=*/true),
5838cc8b3fSZachary Turner                  /*isUnsigned=*/false);
5938cc8b3fSZachary Turner     Data = Data.drop_front(1);
60*660230ebSZachary Turner     return Error::success();
6138cc8b3fSZachary Turner   case LF_SHORT:
626c13db40SDavid Majnemer     if (Data.size() < 2)
63*660230ebSZachary Turner       return make_error<CodeViewError>(
64*660230ebSZachary Turner           cv_error_code::insufficient_buffer,
65*660230ebSZachary Turner           "Buffer does not contain enough data for an LF_SHORT");
6638cc8b3fSZachary Turner     Num = APSInt(APInt(/*numBits=*/16,
6738cc8b3fSZachary Turner                        *reinterpret_cast<const little16_t *>(Data.data()),
6838cc8b3fSZachary Turner                        /*isSigned=*/true),
6938cc8b3fSZachary Turner                  /*isUnsigned=*/false);
7038cc8b3fSZachary Turner     Data = Data.drop_front(2);
71*660230ebSZachary Turner     return Error::success();
7238cc8b3fSZachary Turner   case LF_USHORT:
736c13db40SDavid Majnemer     if (Data.size() < 2)
74*660230ebSZachary Turner       return make_error<CodeViewError>(
75*660230ebSZachary Turner           cv_error_code::insufficient_buffer,
76*660230ebSZachary Turner           "Buffer does not contain enough data for an LF_USHORT");
7738cc8b3fSZachary Turner     Num = APSInt(APInt(/*numBits=*/16,
7838cc8b3fSZachary Turner                        *reinterpret_cast<const ulittle16_t *>(Data.data()),
7938cc8b3fSZachary Turner                        /*isSigned=*/false),
8038cc8b3fSZachary Turner                  /*isUnsigned=*/true);
8138cc8b3fSZachary Turner     Data = Data.drop_front(2);
82*660230ebSZachary Turner     return Error::success();
8338cc8b3fSZachary Turner   case LF_LONG:
846c13db40SDavid Majnemer     if (Data.size() < 4)
85*660230ebSZachary Turner       return make_error<CodeViewError>(
86*660230ebSZachary Turner           cv_error_code::insufficient_buffer,
87*660230ebSZachary Turner           "Buffer does not contain enough data for an LF_LONG");
8838cc8b3fSZachary Turner     Num = APSInt(APInt(/*numBits=*/32,
8938cc8b3fSZachary Turner                        *reinterpret_cast<const little32_t *>(Data.data()),
9038cc8b3fSZachary Turner                        /*isSigned=*/true),
9138cc8b3fSZachary Turner                  /*isUnsigned=*/false);
9238cc8b3fSZachary Turner     Data = Data.drop_front(4);
93*660230ebSZachary Turner     return Error::success();
9438cc8b3fSZachary Turner   case LF_ULONG:
956c13db40SDavid Majnemer     if (Data.size() < 4)
96*660230ebSZachary Turner       return make_error<CodeViewError>(
97*660230ebSZachary Turner           cv_error_code::insufficient_buffer,
98*660230ebSZachary Turner           "Buffer does not contain enough data for an LF_ULONG");
9938cc8b3fSZachary Turner     Num = APSInt(APInt(/*numBits=*/32,
10038cc8b3fSZachary Turner                        *reinterpret_cast<const ulittle32_t *>(Data.data()),
10138cc8b3fSZachary Turner                        /*isSigned=*/FalseVal),
10238cc8b3fSZachary Turner                  /*isUnsigned=*/true);
10338cc8b3fSZachary Turner     Data = Data.drop_front(4);
104*660230ebSZachary Turner     return Error::success();
10538cc8b3fSZachary Turner   case LF_QUADWORD:
1066c13db40SDavid Majnemer     if (Data.size() < 8)
107*660230ebSZachary Turner       return make_error<CodeViewError>(
108*660230ebSZachary Turner           cv_error_code::insufficient_buffer,
109*660230ebSZachary Turner           "Buffer does not contain enough data for an LF_QUADWORD");
11038cc8b3fSZachary Turner     Num = APSInt(APInt(/*numBits=*/64,
11138cc8b3fSZachary Turner                        *reinterpret_cast<const little64_t *>(Data.data()),
11238cc8b3fSZachary Turner                        /*isSigned=*/true),
11338cc8b3fSZachary Turner                  /*isUnsigned=*/false);
11438cc8b3fSZachary Turner     Data = Data.drop_front(8);
115*660230ebSZachary Turner     return Error::success();
11638cc8b3fSZachary Turner   case LF_UQUADWORD:
1176c13db40SDavid Majnemer     if (Data.size() < 8)
118*660230ebSZachary Turner       return make_error<CodeViewError>(
119*660230ebSZachary Turner           cv_error_code::insufficient_buffer,
120*660230ebSZachary Turner           "Buffer does not contain enough data for an LF_UQUADWORD");
12138cc8b3fSZachary Turner     Num = APSInt(APInt(/*numBits=*/64,
12238cc8b3fSZachary Turner                        *reinterpret_cast<const ulittle64_t *>(Data.data()),
12338cc8b3fSZachary Turner                        /*isSigned=*/false),
12438cc8b3fSZachary Turner                  /*isUnsigned=*/true);
12538cc8b3fSZachary Turner     Data = Data.drop_front(8);
126*660230ebSZachary Turner     return Error::success();
12738cc8b3fSZachary Turner   }
128*660230ebSZachary Turner   return make_error<CodeViewError>(cv_error_code::corrupt_record,
129*660230ebSZachary Turner                                    "Buffer contains invalid APSInt type");
13038cc8b3fSZachary Turner }
13138cc8b3fSZachary Turner 
132*660230ebSZachary Turner Error llvm::codeview::consume(StringRef &Data, APSInt &Num) {
13338cc8b3fSZachary Turner   ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end());
13438cc8b3fSZachary Turner   auto EC = consume(Bytes, Num);
13538cc8b3fSZachary Turner   Data = StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size());
13638cc8b3fSZachary Turner   return EC;
13738cc8b3fSZachary Turner }
13838cc8b3fSZachary Turner 
13938cc8b3fSZachary Turner /// Decode a numeric leaf value that is known to be a uint64_t.
140*660230ebSZachary Turner Error llvm::codeview::consume_numeric(ArrayRef<uint8_t> &Data, uint64_t &Num) {
14138cc8b3fSZachary Turner   APSInt N;
14238cc8b3fSZachary Turner   if (auto EC = consume(Data, N))
14338cc8b3fSZachary Turner     return EC;
14438cc8b3fSZachary Turner   if (N.isSigned() || !N.isIntN(64))
145*660230ebSZachary Turner     return make_error<CodeViewError>(cv_error_code::corrupt_record,
146*660230ebSZachary Turner                                      "Data is not a numeric value!");
14738cc8b3fSZachary Turner   Num = N.getLimitedValue();
148*660230ebSZachary Turner   return Error::success();
14938cc8b3fSZachary Turner }
15038cc8b3fSZachary Turner 
151*660230ebSZachary Turner Error llvm::codeview::consume(ArrayRef<uint8_t> &Data, uint32_t &Item) {
15238cc8b3fSZachary Turner   const support::ulittle32_t *IntPtr;
15338cc8b3fSZachary Turner   if (auto EC = consumeObject(Data, IntPtr))
15438cc8b3fSZachary Turner     return EC;
15538cc8b3fSZachary Turner   Item = *IntPtr;
156*660230ebSZachary Turner   return Error::success();
15738cc8b3fSZachary Turner }
15838cc8b3fSZachary Turner 
159*660230ebSZachary Turner Error llvm::codeview::consume(StringRef &Data, uint32_t &Item) {
16038cc8b3fSZachary Turner   ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end());
16138cc8b3fSZachary Turner   auto EC = consume(Bytes, Item);
16238cc8b3fSZachary Turner   Data = StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size());
16338cc8b3fSZachary Turner   return EC;
16438cc8b3fSZachary Turner }
16538cc8b3fSZachary Turner 
166*660230ebSZachary Turner Error llvm::codeview::consume(ArrayRef<uint8_t> &Data, int32_t &Item) {
16738cc8b3fSZachary Turner   const support::little32_t *IntPtr;
16838cc8b3fSZachary Turner   if (auto EC = consumeObject(Data, IntPtr))
16938cc8b3fSZachary Turner     return EC;
17038cc8b3fSZachary Turner   Item = *IntPtr;
171*660230ebSZachary Turner   return Error::success();
17238cc8b3fSZachary Turner }
17338cc8b3fSZachary Turner 
174*660230ebSZachary Turner Error llvm::codeview::consume(ArrayRef<uint8_t> &Data, StringRef &Item) {
17538cc8b3fSZachary Turner   if (Data.empty())
176*660230ebSZachary Turner     return make_error<CodeViewError>(cv_error_code::corrupt_record,
177*660230ebSZachary Turner                                      "Null terminated string buffer is empty!");
17838cc8b3fSZachary Turner 
17938cc8b3fSZachary Turner   StringRef Rest;
18038cc8b3fSZachary Turner   std::tie(Item, Rest) = getBytesAsCharacters(Data).split('\0');
18138cc8b3fSZachary Turner   // We expect this to be null terminated.  If it was not, it is an error.
18238cc8b3fSZachary Turner   if (Data.size() == Item.size())
183*660230ebSZachary Turner     return make_error<CodeViewError>(cv_error_code::corrupt_record,
184*660230ebSZachary Turner                                      "Expected null terminator!");
18538cc8b3fSZachary Turner 
18638cc8b3fSZachary Turner   Data = ArrayRef<uint8_t>(Rest.bytes_begin(), Rest.bytes_end());
187*660230ebSZachary Turner   return Error::success();
18838cc8b3fSZachary Turner }
189