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 ®_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 ®_info, void *dst, 107 uint32_t dst_len, lldb::ByteOrder dst_byte_order, 108 Status &error) const; 109 110 uint32_t SetFromMemoryData(const RegisterInfo ®_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 ®_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