]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/DebugInfo/CodeView/RecordSerialization.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / DebugInfo / CodeView / RecordSerialization.cpp
1 //===-- RecordSerialization.cpp -------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Utilities for serializing and deserializing CodeView records.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "llvm/DebugInfo/CodeView/RecordSerialization.h"
14 #include "llvm/ADT/APInt.h"
15 #include "llvm/ADT/APSInt.h"
16 #include "llvm/DebugInfo/CodeView/CodeViewError.h"
17 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
18 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
19 #include "llvm/Support/BinaryByteStream.h"
20
21 using namespace llvm;
22 using namespace llvm::codeview;
23 using namespace llvm::support;
24
25 /// Reinterpret a byte array as an array of characters. Does not interpret as
26 /// a C string, as StringRef has several helpers (split) that make that easy.
27 StringRef llvm::codeview::getBytesAsCharacters(ArrayRef<uint8_t> LeafData) {
28   return StringRef(reinterpret_cast<const char *>(LeafData.data()),
29                    LeafData.size());
30 }
31
32 StringRef llvm::codeview::getBytesAsCString(ArrayRef<uint8_t> LeafData) {
33   return getBytesAsCharacters(LeafData).split('\0').first;
34 }
35
36 Error llvm::codeview::consume(BinaryStreamReader &Reader, APSInt &Num) {
37   // Used to avoid overload ambiguity on APInt construtor.
38   bool FalseVal = false;
39   uint16_t Short;
40   if (auto EC = Reader.readInteger(Short))
41     return EC;
42
43   if (Short < LF_NUMERIC) {
44     Num = APSInt(APInt(/*numBits=*/16, Short, /*isSigned=*/false),
45                  /*isUnsigned=*/true);
46     return Error::success();
47   }
48
49   switch (Short) {
50   case LF_CHAR: {
51     int8_t N;
52     if (auto EC = Reader.readInteger(N))
53       return EC;
54     Num = APSInt(APInt(8, N, true), false);
55     return Error::success();
56   }
57   case LF_SHORT: {
58     int16_t N;
59     if (auto EC = Reader.readInteger(N))
60       return EC;
61     Num = APSInt(APInt(16, N, true), false);
62     return Error::success();
63   }
64   case LF_USHORT: {
65     uint16_t N;
66     if (auto EC = Reader.readInteger(N))
67       return EC;
68     Num = APSInt(APInt(16, N, false), true);
69     return Error::success();
70   }
71   case LF_LONG: {
72     int32_t N;
73     if (auto EC = Reader.readInteger(N))
74       return EC;
75     Num = APSInt(APInt(32, N, true), false);
76     return Error::success();
77   }
78   case LF_ULONG: {
79     uint32_t N;
80     if (auto EC = Reader.readInteger(N))
81       return EC;
82     Num = APSInt(APInt(32, N, FalseVal), true);
83     return Error::success();
84   }
85   case LF_QUADWORD: {
86     int64_t N;
87     if (auto EC = Reader.readInteger(N))
88       return EC;
89     Num = APSInt(APInt(64, N, true), false);
90     return Error::success();
91   }
92   case LF_UQUADWORD: {
93     uint64_t N;
94     if (auto EC = Reader.readInteger(N))
95       return EC;
96     Num = APSInt(APInt(64, N, false), true);
97     return Error::success();
98   }
99   }
100   return make_error<CodeViewError>(cv_error_code::corrupt_record,
101                                    "Buffer contains invalid APSInt type");
102 }
103
104 Error llvm::codeview::consume(StringRef &Data, APSInt &Num) {
105   ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end());
106   BinaryByteStream S(Bytes, llvm::support::little);
107   BinaryStreamReader SR(S);
108   auto EC = consume(SR, Num);
109   Data = Data.take_back(SR.bytesRemaining());
110   return EC;
111 }
112
113 /// Decode a numeric leaf value that is known to be a uint64_t.
114 Error llvm::codeview::consume_numeric(BinaryStreamReader &Reader,
115                                       uint64_t &Num) {
116   APSInt N;
117   if (auto EC = consume(Reader, N))
118     return EC;
119   if (N.isSigned() || !N.isIntN(64))
120     return make_error<CodeViewError>(cv_error_code::corrupt_record,
121                                      "Data is not a numeric value!");
122   Num = N.getLimitedValue();
123   return Error::success();
124 }
125
126 Error llvm::codeview::consume(BinaryStreamReader &Reader, uint32_t &Item) {
127   return Reader.readInteger(Item);
128 }
129
130 Error llvm::codeview::consume(StringRef &Data, uint32_t &Item) {
131   ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end());
132   BinaryByteStream S(Bytes, llvm::support::little);
133   BinaryStreamReader SR(S);
134   auto EC = consume(SR, Item);
135   Data = Data.take_back(SR.bytesRemaining());
136   return EC;
137 }
138
139 Error llvm::codeview::consume(BinaryStreamReader &Reader, int32_t &Item) {
140   return Reader.readInteger(Item);
141 }
142
143 Error llvm::codeview::consume(BinaryStreamReader &Reader, StringRef &Item) {
144   if (Reader.empty())
145     return make_error<CodeViewError>(cv_error_code::corrupt_record,
146                                      "Null terminated string buffer is empty!");
147
148   return Reader.readCString(Item);
149 }
150
151 Expected<CVSymbol> llvm::codeview::readSymbolFromStream(BinaryStreamRef Stream,
152                                                         uint32_t Offset) {
153   return readCVRecordFromStream<SymbolKind>(Stream, Offset);
154 }