1 //===-- RegisterValue.h -----------------------------------------*- C++ -*-===//
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 #ifndef LLDB_UTILITY_REGISTERVALUE_H
10 #define LLDB_UTILITY_REGISTERVALUE_H
11 
12 #include "lldb/Utility/Endian.h"
13 #include "lldb/Utility/Scalar.h"
14 #include "lldb/Utility/Status.h"
15 #include "lldb/lldb-enumerations.h"
16 #include "lldb/lldb-types.h"
17 #include "llvm/ADT/APInt.h"
18 #include "llvm/ADT/SmallVector.h"
19 #include "llvm/ADT/StringRef.h"
20 #include <cstdint>
21 #include <cstring>
22 #include <utility>
23 
24 namespace lldb_private {
25 class DataExtractor;
26 class Stream;
27 struct RegisterInfo;
28 
29 class RegisterValue {
30 public:
31   enum {
32     // What we can reasonably put on the stack, big enough to support up to 256
33     // byte AArch64 SVE.
34     kTypicalRegisterByteSize = 256u,
35     // Anything else we'll heap allocate storage for it.
36     kMaxRegisterByteSize = kTypicalRegisterByteSize,
37   };
38 
39   typedef llvm::SmallVector<uint8_t, kTypicalRegisterByteSize> BytesContainer;
40 
41   enum Type {
42     eTypeInvalid,
43     eTypeUInt8,
44     eTypeUInt16,
45     eTypeUInt32,
46     eTypeUInt64,
47     eTypeUInt128,
48     eTypeFloat,
49     eTypeDouble,
50     eTypeLongDouble,
51     eTypeBytes
52   };
53 
54   RegisterValue() : m_scalar(static_cast<unsigned long>(0)) {}
55 
56   explicit RegisterValue(uint8_t inst) : m_type(eTypeUInt8) { m_scalar = inst; }
57 
58   explicit RegisterValue(uint16_t inst) : m_type(eTypeUInt16) {
59     m_scalar = inst;
60   }
61 
62   explicit RegisterValue(uint32_t inst) : m_type(eTypeUInt32) {
63     m_scalar = inst;
64   }
65 
66   explicit RegisterValue(uint64_t inst) : m_type(eTypeUInt64) {
67     m_scalar = inst;
68   }
69 
70   explicit RegisterValue(llvm::APInt inst) : m_type(eTypeUInt128) {
71     m_scalar = llvm::APInt(std::move(inst));
72   }
73 
74   explicit RegisterValue(float value) : m_type(eTypeFloat) { m_scalar = value; }
75 
76   explicit RegisterValue(double value) : m_type(eTypeDouble) {
77     m_scalar = value;
78   }
79 
80   explicit RegisterValue(long double value) : m_type(eTypeLongDouble) {
81     m_scalar = value;
82   }
83 
84   explicit RegisterValue(llvm::ArrayRef<uint8_t> bytes,
85                          lldb::ByteOrder byte_order) {
86     SetBytes(bytes.data(), bytes.size(), byte_order);
87   }
88 
89   RegisterValue::Type GetType() const { return m_type; }
90 
91   bool CopyValue(const RegisterValue &rhs);
92 
93   void SetType(RegisterValue::Type type) { m_type = type; }
94 
95   RegisterValue::Type SetType(const RegisterInfo &reg_info);
96 
97   bool GetData(DataExtractor &data) const;
98 
99   // Copy the register value from this object into a buffer in "dst" and obey
100   // the "dst_byte_order" when copying the data. Also watch out in case
101   // "dst_len" is longer or shorter than the register value described by
102   // "reg_info" and only copy the least significant bytes of the register
103   // value, or pad the destination with zeroes if the register byte size is
104   // shorter that "dst_len" (all while correctly abiding the "dst_byte_order").
105   // Returns the number of bytes copied into "dst".
106   uint32_t GetAsMemoryData(const RegisterInfo &reg_info, void *dst,
107                            uint32_t dst_len, lldb::ByteOrder dst_byte_order,
108                            Status &error) const;
109 
110   uint32_t SetFromMemoryData(const RegisterInfo &reg_info, const void *src,
111                              uint32_t src_len, lldb::ByteOrder src_byte_order,
112                              Status &error);
113 
114   bool GetScalarValue(Scalar &scalar) const;
115 
116   uint8_t GetAsUInt8(uint8_t fail_value = UINT8_MAX,
117                      bool *success_ptr = nullptr) const {
118     if (m_type == eTypeUInt8) {
119       if (success_ptr)
120         *success_ptr = true;
121       return m_scalar.UChar(fail_value);
122     }
123     if (success_ptr)
124       *success_ptr = true;
125     return fail_value;
126   }
127 
128   uint16_t GetAsUInt16(uint16_t fail_value = UINT16_MAX,
129                        bool *success_ptr = nullptr) const;
130 
131   uint32_t GetAsUInt32(uint32_t fail_value = UINT32_MAX,
132                        bool *success_ptr = nullptr) const;
133 
134   uint64_t GetAsUInt64(uint64_t fail_value = UINT64_MAX,
135                        bool *success_ptr = nullptr) const;
136 
137   llvm::APInt GetAsUInt128(const llvm::APInt &fail_value,
138                            bool *success_ptr = nullptr) const;
139 
140   float GetAsFloat(float fail_value = 0.0f, bool *success_ptr = nullptr) const;
141 
142   double GetAsDouble(double fail_value = 0.0,
143                      bool *success_ptr = nullptr) const;
144 
145   long double GetAsLongDouble(long double fail_value = 0.0,
146                               bool *success_ptr = nullptr) const;
147 
148   void SetValueToInvalid() { m_type = eTypeInvalid; }
149 
150   bool ClearBit(uint32_t bit);
151 
152   bool SetBit(uint32_t bit);
153 
154   bool operator==(const RegisterValue &rhs) const;
155 
156   bool operator!=(const RegisterValue &rhs) const;
157 
158   void operator=(uint8_t uint) {
159     m_type = eTypeUInt8;
160     m_scalar = uint;
161   }
162 
163   void operator=(uint16_t uint) {
164     m_type = eTypeUInt16;
165     m_scalar = uint;
166   }
167 
168   void operator=(uint32_t uint) {
169     m_type = eTypeUInt32;
170     m_scalar = uint;
171   }
172 
173   void operator=(uint64_t uint) {
174     m_type = eTypeUInt64;
175     m_scalar = uint;
176   }
177 
178   void operator=(llvm::APInt uint) {
179     m_type = eTypeUInt128;
180     m_scalar = llvm::APInt(std::move(uint));
181   }
182 
183   void operator=(float f) {
184     m_type = eTypeFloat;
185     m_scalar = f;
186   }
187 
188   void operator=(double f) {
189     m_type = eTypeDouble;
190     m_scalar = f;
191   }
192 
193   void operator=(long double f) {
194     m_type = eTypeLongDouble;
195     m_scalar = f;
196   }
197 
198   void SetUInt8(uint8_t uint) {
199     m_type = eTypeUInt8;
200     m_scalar = uint;
201   }
202 
203   void SetUInt16(uint16_t uint) {
204     m_type = eTypeUInt16;
205     m_scalar = uint;
206   }
207 
208   void SetUInt32(uint32_t uint, Type t = eTypeUInt32) {
209     m_type = t;
210     m_scalar = uint;
211   }
212 
213   void SetUInt64(uint64_t uint, Type t = eTypeUInt64) {
214     m_type = t;
215     m_scalar = uint;
216   }
217 
218   void SetUInt128(llvm::APInt uint) {
219     m_type = eTypeUInt128;
220     m_scalar = std::move(uint);
221   }
222 
223   bool SetUInt(uint64_t uint, uint32_t byte_size);
224 
225   void SetFloat(float f) {
226     m_type = eTypeFloat;
227     m_scalar = f;
228   }
229 
230   void SetDouble(double f) {
231     m_type = eTypeDouble;
232     m_scalar = f;
233   }
234 
235   void SetLongDouble(long double f) {
236     m_type = eTypeLongDouble;
237     m_scalar = f;
238   }
239 
240   void SetBytes(const void *bytes, size_t length, lldb::ByteOrder byte_order);
241 
242   bool SignExtend(uint32_t sign_bitpos);
243 
244   Status SetValueFromString(const RegisterInfo *reg_info,
245                             llvm::StringRef value_str);
246   Status SetValueFromString(const RegisterInfo *reg_info,
247                             const char *value_str) = delete;
248 
249   Status SetValueFromData(const RegisterInfo &reg_info, DataExtractor &data,
250                           lldb::offset_t offset, bool partial_data_ok);
251 
252   const void *GetBytes() const;
253 
254   lldb::ByteOrder GetByteOrder() const {
255     if (m_type == eTypeBytes)
256       return buffer.byte_order;
257     return endian::InlHostByteOrder();
258   }
259 
260   uint32_t GetByteSize() const;
261 
262   void Clear();
263 
264 protected:
265   RegisterValue::Type m_type = eTypeInvalid;
266   Scalar m_scalar;
267 
268   struct RegisterValueBuffer {
269     // Start at max stack storage size. Move to the heap for anything larger.
270     RegisterValueBuffer() : bytes(kTypicalRegisterByteSize) {}
271 
272     mutable BytesContainer bytes;
273     lldb::ByteOrder byte_order = lldb::eByteOrderInvalid;
274   } buffer;
275 };
276 
277 } // namespace lldb_private
278 
279 #endif // LLDB_UTILITY_REGISTERVALUE_H
280