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.
25 StringRef llvm::codeview::getBytesAsCharacters(ArrayRef<uint8_t> LeafData) {
26   return StringRef(reinterpret_cast<const char *>(LeafData.data()),
27                    LeafData.size());
28 }
29 
30 StringRef llvm::codeview::getBytesAsCString(ArrayRef<uint8_t> LeafData) {
31   return getBytesAsCharacters(LeafData).split('\0').first;
32 }
33 
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     Num = APSInt(APInt(/*numBits=*/8,
49                        *reinterpret_cast<const int8_t *>(Data.data()),
50                        /*isSigned=*/true),
51                  /*isUnsigned=*/false);
52     Data = Data.drop_front(1);
53     return std::error_code();
54   case LF_SHORT:
55     Num = APSInt(APInt(/*numBits=*/16,
56                        *reinterpret_cast<const little16_t *>(Data.data()),
57                        /*isSigned=*/true),
58                  /*isUnsigned=*/false);
59     Data = Data.drop_front(2);
60     return std::error_code();
61   case LF_USHORT:
62     Num = APSInt(APInt(/*numBits=*/16,
63                        *reinterpret_cast<const ulittle16_t *>(Data.data()),
64                        /*isSigned=*/false),
65                  /*isUnsigned=*/true);
66     Data = Data.drop_front(2);
67     return std::error_code();
68   case LF_LONG:
69     Num = APSInt(APInt(/*numBits=*/32,
70                        *reinterpret_cast<const little32_t *>(Data.data()),
71                        /*isSigned=*/true),
72                  /*isUnsigned=*/false);
73     Data = Data.drop_front(4);
74     return std::error_code();
75   case LF_ULONG:
76     Num = APSInt(APInt(/*numBits=*/32,
77                        *reinterpret_cast<const ulittle32_t *>(Data.data()),
78                        /*isSigned=*/FalseVal),
79                  /*isUnsigned=*/true);
80     Data = Data.drop_front(4);
81     return std::error_code();
82   case LF_QUADWORD:
83     Num = APSInt(APInt(/*numBits=*/64,
84                        *reinterpret_cast<const little64_t *>(Data.data()),
85                        /*isSigned=*/true),
86                  /*isUnsigned=*/false);
87     Data = Data.drop_front(8);
88     return std::error_code();
89   case LF_UQUADWORD:
90     Num = APSInt(APInt(/*numBits=*/64,
91                        *reinterpret_cast<const ulittle64_t *>(Data.data()),
92                        /*isSigned=*/false),
93                  /*isUnsigned=*/true);
94     Data = Data.drop_front(8);
95     return std::error_code();
96   }
97   return std::make_error_code(std::errc::illegal_byte_sequence);
98 }
99 
100 std::error_code llvm::codeview::consume(StringRef &Data, APSInt &Num) {
101   ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end());
102   auto EC = consume(Bytes, Num);
103   Data = StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size());
104   return EC;
105 }
106 
107 /// Decode a numeric leaf value that is known to be a uint64_t.
108 std::error_code llvm::codeview::consume_numeric(ArrayRef<uint8_t> &Data,
109                                                 uint64_t &Num) {
110   APSInt N;
111   if (auto EC = consume(Data, N))
112     return EC;
113   if (N.isSigned() || !N.isIntN(64))
114     return std::make_error_code(std::errc::illegal_byte_sequence);
115   Num = N.getLimitedValue();
116   return std::error_code();
117 }
118 
119 std::error_code llvm::codeview::consume(ArrayRef<uint8_t> &Data,
120                                         uint32_t &Item) {
121   const support::ulittle32_t *IntPtr;
122   if (auto EC = consumeObject(Data, IntPtr))
123     return EC;
124   Item = *IntPtr;
125   return std::error_code();
126 }
127 
128 std::error_code llvm::codeview::consume(StringRef &Data, uint32_t &Item) {
129   ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end());
130   auto EC = consume(Bytes, Item);
131   Data = StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size());
132   return EC;
133 }
134 
135 std::error_code llvm::codeview::consume(ArrayRef<uint8_t> &Data,
136                                         int32_t &Item) {
137   const support::little32_t *IntPtr;
138   if (auto EC = consumeObject(Data, IntPtr))
139     return EC;
140   Item = *IntPtr;
141   return std::error_code();
142 }
143 
144 std::error_code llvm::codeview::consume(ArrayRef<uint8_t> &Data,
145                                         StringRef &Item) {
146   if (Data.empty())
147     return std::make_error_code(std::errc::illegal_byte_sequence);
148 
149   StringRef Rest;
150   std::tie(Item, Rest) = getBytesAsCharacters(Data).split('\0');
151   // We expect this to be null terminated.  If it was not, it is an error.
152   if (Data.size() == Item.size())
153     return std::make_error_code(std::errc::illegal_byte_sequence);
154 
155   Data = ArrayRef<uint8_t>(Rest.bytes_begin(), Rest.bytes_end());
156   return std::error_code();
157 }
158