• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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