1 //===-- Value.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_CORE_VALUE_H
10 #define LLDB_CORE_VALUE_H
11 
12 #include "lldb/Symbol/CompilerType.h"
13 #include "lldb/Utility/DataBufferHeap.h"
14 #include "lldb/Utility/Scalar.h"
15 #include "lldb/Utility/Status.h"
16 #include "lldb/lldb-enumerations.h"
17 #include "lldb/lldb-private-enumerations.h"
18 #include "lldb/lldb-private-types.h"
19 
20 #include "llvm/ADT/APInt.h"
21 
22 #include <vector>
23 
24 #include <stdint.h>
25 #include <string.h>
26 
27 namespace lldb_private {
28 class DataExtractor;
29 class ExecutionContext;
30 class Module;
31 class Stream;
32 class Type;
33 class Variable;
34 }
35 
36 namespace lldb_private {
37 
38 class Value {
39 public:
40   // Values Less than zero are an error, greater than or equal to zero returns
41   // what the Scalar result is.
42   enum ValueType {
43     // m_value contains...
44     // ============================
45     eValueTypeScalar,      // raw scalar value
46     eValueTypeVector,      // byte array of m_vector.length with endianness of
47                            // m_vector.byte_order
48     eValueTypeFileAddress, // file address value
49     eValueTypeLoadAddress, // load address value
50     eValueTypeHostAddress  // host address value (for memory in the process that
51                            // is using liblldb)
52   };
53 
54   enum ContextType // Type that describes Value::m_context
55   {
56     // m_context contains...
57     // ====================
58     eContextTypeInvalid,      // undefined
59     eContextTypeRegisterInfo, // RegisterInfo * (can be a scalar or a vector
60                               // register)
61     eContextTypeLLDBType,     // lldb_private::Type *
62     eContextTypeVariable      // lldb_private::Variable *
63   };
64 
65   const static size_t kMaxByteSize = 32u;
66 
67   struct Vector {
68     // The byte array must be big enough to hold vector registers for any
69     // supported target.
70     uint8_t bytes[kMaxByteSize];
71     size_t length;
72     lldb::ByteOrder byte_order;
73 
74     Vector() : length(0), byte_order(lldb::eByteOrderInvalid) {}
75 
76     Vector(const Vector &vector) { *this = vector; }
77     const Vector &operator=(const Vector &vector) {
78       SetBytes(vector.bytes, vector.length, vector.byte_order);
79       return *this;
80     }
81 
82     void Clear() { length = 0; }
83 
84     bool SetBytes(const void *bytes, size_t length,
85                   lldb::ByteOrder byte_order) {
86       this->length = length;
87       this->byte_order = byte_order;
88       if (length)
89         ::memcpy(this->bytes, bytes,
90                  length < kMaxByteSize ? length : kMaxByteSize);
91       return IsValid();
92     }
93 
94     bool IsValid() const {
95       return (length > 0 && length < kMaxByteSize &&
96               byte_order != lldb::eByteOrderInvalid);
97     }
98     // Casts a vector, if valid, to an unsigned int of matching or largest
99     // supported size. Truncates to the beginning of the vector if required.
100     // Returns a default constructed Scalar if the Vector data is internally
101     // inconsistent.
102     llvm::APInt rhs = llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128,
103                                   ((type128 *)bytes)->x);
104     Scalar GetAsScalar() const {
105       Scalar scalar;
106       if (IsValid()) {
107         if (length == 1)
108           scalar = *(const uint8_t *)bytes;
109         else if (length == 2)
110           scalar = *(const uint16_t *)bytes;
111         else if (length == 4)
112           scalar = *(const uint32_t *)bytes;
113         else if (length == 8)
114           scalar = *(const uint64_t *)bytes;
115         else if (length >= 16)
116           scalar = rhs;
117       }
118       return scalar;
119     }
120   };
121 
122   Value();
123   Value(const Scalar &scalar);
124   Value(const Vector &vector);
125   Value(const void *bytes, int len);
126   Value(const Value &rhs);
127 
128   void SetBytes(const void *bytes, int len);
129 
130   void AppendBytes(const void *bytes, int len);
131 
132   Value &operator=(const Value &rhs);
133 
134   const CompilerType &GetCompilerType();
135 
136   void SetCompilerType(const CompilerType &compiler_type);
137 
138   ValueType GetValueType() const;
139 
140   AddressType GetValueAddressType() const;
141 
142   ContextType GetContextType() const { return m_context_type; }
143 
144   void SetValueType(ValueType value_type) { m_value_type = value_type; }
145 
146   void ClearContext() {
147     m_context = nullptr;
148     m_context_type = eContextTypeInvalid;
149   }
150 
151   void SetContext(ContextType context_type, void *p) {
152     m_context_type = context_type;
153     m_context = p;
154     if (m_context_type == eContextTypeRegisterInfo) {
155       RegisterInfo *reg_info = GetRegisterInfo();
156       if (reg_info->encoding == lldb::eEncodingVector &&
157           m_vector.byte_order != lldb::eByteOrderInvalid)
158         SetValueType(eValueTypeScalar);
159     }
160   }
161 
162   RegisterInfo *GetRegisterInfo() const;
163 
164   Type *GetType();
165 
166   Scalar &ResolveValue(ExecutionContext *exe_ctx);
167 
168   const Scalar &GetScalar() const { return m_value; }
169 
170   const Vector &GetVector() const { return m_vector; }
171 
172   Scalar &GetScalar() { return m_value; }
173 
174   Vector &GetVector() { return m_vector; }
175 
176   bool SetVectorBytes(const Vector &vector) {
177     m_vector = vector;
178     return m_vector.IsValid();
179   }
180 
181   bool SetVectorBytes(uint8_t *bytes, size_t length,
182                       lldb::ByteOrder byte_order) {
183     return m_vector.SetBytes(bytes, length, byte_order);
184   }
185 
186   bool SetScalarFromVector() {
187     if (m_vector.IsValid()) {
188       m_value = m_vector.GetAsScalar();
189       return true;
190     }
191     return false;
192   }
193 
194   size_t ResizeData(size_t len);
195 
196   size_t AppendDataToHostBuffer(const Value &rhs);
197 
198   DataBufferHeap &GetBuffer() { return m_data_buffer; }
199 
200   const DataBufferHeap &GetBuffer() const { return m_data_buffer; }
201 
202   bool ValueOf(ExecutionContext *exe_ctx);
203 
204   Variable *GetVariable();
205 
206   void Dump(Stream *strm);
207 
208   lldb::Format GetValueDefaultFormat();
209 
210   uint64_t GetValueByteSize(Status *error_ptr, ExecutionContext *exe_ctx);
211 
212   Status GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data,
213                         Module *module); // Can be nullptr
214 
215   static const char *GetValueTypeAsCString(ValueType context_type);
216 
217   static const char *GetContextTypeAsCString(ContextType context_type);
218 
219   /// Convert this value's file address to a load address, if possible.
220   void ConvertToLoadAddress(Module *module, Target *target);
221 
222   bool GetData(DataExtractor &data);
223 
224   void Clear();
225 
226 protected:
227   Scalar m_value;
228   Vector m_vector;
229   CompilerType m_compiler_type;
230   void *m_context;
231   ValueType m_value_type;
232   ContextType m_context_type;
233   DataBufferHeap m_data_buffer;
234 };
235 
236 class ValueList {
237 public:
238   ValueList() : m_values() {}
239 
240   ValueList(const ValueList &rhs);
241 
242   ~ValueList() = default;
243 
244   const ValueList &operator=(const ValueList &rhs);
245 
246   // void InsertValue (Value *value, size_t idx);
247   void PushValue(const Value &value);
248 
249   size_t GetSize();
250   Value *GetValueAtIndex(size_t idx);
251   void Clear();
252 
253 private:
254   typedef std::vector<Value> collection;
255 
256   collection m_values;
257 };
258 
259 } // namespace lldb_private
260 
261 #endif // LLDB_CORE_VALUE_H
262