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