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