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