• 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