Path: blob/main/contrib/llvm-project/lldb/source/Utility/RegisterValue.cpp
96333 views
//===-- RegisterValue.cpp -------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "lldb/Utility/RegisterValue.h"910#include "lldb/Utility/DataExtractor.h"11#include "lldb/Utility/Scalar.h"12#include "lldb/Utility/Status.h"13#include "lldb/Utility/Stream.h"14#include "lldb/Utility/StreamString.h"15#include "lldb/lldb-defines.h"16#include "lldb/lldb-private-types.h"1718#include "llvm/ADT/ArrayRef.h"19#include "llvm/ADT/StringRef.h"2021#include <cstdint>22#include <string>23#include <tuple>24#include <vector>2526#include <cassert>27#include <cinttypes>28#include <cstdio>2930using namespace lldb;31using namespace lldb_private;3233bool RegisterValue::GetData(DataExtractor &data) const {34return data.SetData(GetBytes(), GetByteSize(), GetByteOrder()) > 0;35}3637uint32_t RegisterValue::GetAsMemoryData(const RegisterInfo ®_info, void *dst,38uint32_t dst_len,39lldb::ByteOrder dst_byte_order,40Status &error) const {41// ReadRegister should have already been called on this object prior to42// calling this.43if (GetType() == eTypeInvalid) {44// No value has been read into this object...45error.SetErrorStringWithFormat(46"invalid register value type for register %s", reg_info.name);47return 0;48}4950const uint32_t src_len = reg_info.byte_size;5152// Extract the register data into a data extractor53DataExtractor reg_data;54if (!GetData(reg_data)) {55error.SetErrorString("invalid register value to copy into");56return 0;57}5859// Prepare a memory buffer that contains some or all of the register value60const uint32_t bytes_copied =61reg_data.CopyByteOrderedData(0, // src offset62src_len, // src length63dst, // dst buffer64dst_len, // dst length65dst_byte_order); // dst byte order66if (bytes_copied == 0)67error.SetErrorStringWithFormat(68"failed to copy data for register write of %s", reg_info.name);6970return bytes_copied;71}7273uint32_t RegisterValue::SetFromMemoryData(const RegisterInfo ®_info,74const void *src, uint32_t src_len,75lldb::ByteOrder src_byte_order,76Status &error) {77// Moving from addr into a register78//79// Case 1: src_len == dst_len80//81// |AABBCCDD| Address contents82// |AABBCCDD| Register contents83//84// Case 2: src_len > dst_len85//86// Status! (The register should always be big enough to hold the data)87//88// Case 3: src_len < dst_len89//90// |AABB| Address contents91// |AABB0000| Register contents [on little-endian hardware]92// |0000AABB| Register contents [on big-endian hardware]93const uint32_t dst_len = reg_info.byte_size;9495if (src_len > dst_len) {96error.SetErrorStringWithFormat(97"%u bytes is too big to store in register %s (%u bytes)", src_len,98reg_info.name, dst_len);99return 0;100}101102// Use a data extractor to correctly copy and pad the bytes read into the103// register value104DataExtractor src_data(src, src_len, src_byte_order, 4);105106error = SetValueFromData(reg_info, src_data, 0, true);107if (error.Fail())108return 0;109110// If SetValueFromData succeeded, we must have copied all of src_len111return src_len;112}113114bool RegisterValue::GetScalarValue(Scalar &scalar) const {115switch (m_type) {116case eTypeInvalid:117break;118case eTypeBytes: {119DataExtractor data(buffer.bytes.data(), buffer.bytes.size(),120buffer.byte_order, 1);121if (scalar.SetValueFromData(data, lldb::eEncodingUint, buffer.bytes.size())122.Success())123return true;124} break;125case eTypeUInt8:126case eTypeUInt16:127case eTypeUInt32:128case eTypeUInt64:129case eTypeUInt128:130case eTypeFloat:131case eTypeDouble:132case eTypeLongDouble:133scalar = m_scalar;134return true;135}136return false;137}138139void RegisterValue::Clear() { m_type = eTypeInvalid; }140141RegisterValue::Type RegisterValue::SetType(const RegisterInfo ®_info) {142// To change the type, we simply copy the data in again, using the new format143RegisterValue copy;144DataExtractor copy_data;145if (copy.CopyValue(*this) && copy.GetData(copy_data)) {146Status error = SetValueFromData(reg_info, copy_data, 0, true);147assert(error.Success() && "Expected SetValueFromData to succeed.");148UNUSED_IF_ASSERT_DISABLED(error);149}150151return m_type;152}153154Status RegisterValue::SetValueFromData(const RegisterInfo ®_info,155DataExtractor &src,156lldb::offset_t src_offset,157bool partial_data_ok) {158Status error;159160if (src.GetByteSize() == 0) {161error.SetErrorString("empty data.");162return error;163}164165if (reg_info.byte_size == 0) {166error.SetErrorString("invalid register info.");167return error;168}169170uint32_t src_len = src.GetByteSize() - src_offset;171172if (!partial_data_ok && (src_len < reg_info.byte_size)) {173error.SetErrorString("not enough data.");174return error;175}176177// Cap the data length if there is more than enough bytes for this register178// value179if (src_len > reg_info.byte_size)180src_len = reg_info.byte_size;181182type128 int128;183184m_type = eTypeInvalid;185switch (reg_info.encoding) {186case eEncodingInvalid:187break;188case eEncodingUint:189case eEncodingSint:190if (reg_info.byte_size == 1)191SetUInt8(src.GetMaxU32(&src_offset, src_len));192else if (reg_info.byte_size <= 2)193SetUInt16(src.GetMaxU32(&src_offset, src_len));194else if (reg_info.byte_size <= 4)195SetUInt32(src.GetMaxU32(&src_offset, src_len));196else if (reg_info.byte_size <= 8)197SetUInt64(src.GetMaxU64(&src_offset, src_len));198else if (reg_info.byte_size <= 16) {199uint64_t data1 = src.GetU64(&src_offset);200uint64_t data2 = src.GetU64(&src_offset);201if (src.GetByteOrder() == eByteOrderBig) {202int128.x[0] = data1;203int128.x[1] = data2;204} else {205int128.x[0] = data2;206int128.x[1] = data1;207}208SetUInt128(llvm::APInt(128, 2, int128.x));209}210break;211case eEncodingIEEE754:212if (reg_info.byte_size == sizeof(float))213SetFloat(src.GetFloat(&src_offset));214else if (reg_info.byte_size == sizeof(double))215SetDouble(src.GetDouble(&src_offset));216else if (reg_info.byte_size == sizeof(long double))217SetLongDouble(src.GetLongDouble(&src_offset));218break;219case eEncodingVector: {220m_type = eTypeBytes;221assert(reg_info.byte_size <= kMaxRegisterByteSize);222buffer.bytes.resize(reg_info.byte_size);223buffer.byte_order = src.GetByteOrder();224if (src.CopyByteOrderedData(225src_offset, // offset within "src" to start extracting data226src_len, // src length227buffer.bytes.data(), // dst buffer228buffer.bytes.size(), // dst length229buffer.byte_order) == 0) // dst byte order230{231error.SetErrorStringWithFormat(232"failed to copy data for register write of %s", reg_info.name);233return error;234}235}236}237238if (m_type == eTypeInvalid)239error.SetErrorStringWithFormat(240"invalid register value type for register %s", reg_info.name);241return error;242}243244// Helper function for RegisterValue::SetValueFromString()245static bool ParseVectorEncoding(const RegisterInfo *reg_info,246llvm::StringRef vector_str,247const uint32_t byte_size,248RegisterValue *reg_value) {249// Example: vector_str = "{0x2c 0x4b 0x2a 0x3e 0xd0 0x4f 0x2a 0x3e 0xac 0x4a250// 0x2a 0x3e 0x84 0x4f 0x2a 0x3e}".251vector_str = vector_str.trim();252vector_str.consume_front("{");253vector_str.consume_back("}");254vector_str = vector_str.trim();255256char Sep = ' ';257258// The first split should give us:259// ('0x2c', '0x4b 0x2a 0x3e 0xd0 0x4f 0x2a 0x3e 0xac 0x4a 0x2a 0x3e 0x84 0x4f260// 0x2a 0x3e').261llvm::StringRef car;262llvm::StringRef cdr = vector_str;263std::tie(car, cdr) = vector_str.split(Sep);264std::vector<uint8_t> bytes;265unsigned byte = 0;266267// Using radix auto-sensing by passing 0 as the radix. Keep on processing the268// vector elements as long as the parsing succeeds and the vector size is <269// byte_size.270while (!car.getAsInteger(0, byte) && bytes.size() < byte_size) {271bytes.push_back(byte);272std::tie(car, cdr) = cdr.split(Sep);273}274275// Check for vector of exact byte_size elements.276if (bytes.size() != byte_size)277return false;278279reg_value->SetBytes(&(bytes.front()), byte_size, eByteOrderLittle);280return true;281}282283static bool UInt64ValueIsValidForByteSize(uint64_t uval64,284size_t total_byte_size) {285if (total_byte_size > 8)286return false;287288if (total_byte_size == 8)289return true;290291const uint64_t max =292(static_cast<uint64_t>(1) << static_cast<uint64_t>(total_byte_size * 8)) -2931;294return uval64 <= max;295}296297static bool SInt64ValueIsValidForByteSize(int64_t sval64,298size_t total_byte_size) {299if (total_byte_size > 8)300return false;301302if (total_byte_size == 8)303return true;304305const int64_t max = (static_cast<int64_t>(1)306<< static_cast<uint64_t>(total_byte_size * 8 - 1)) -3071;308const int64_t min = ~(max);309return min <= sval64 && sval64 <= max;310}311312Status RegisterValue::SetValueFromString(const RegisterInfo *reg_info,313llvm::StringRef value_str) {314Status error;315if (reg_info == nullptr) {316error.SetErrorString("Invalid register info argument.");317return error;318}319320m_type = eTypeInvalid;321if (value_str.empty()) {322error.SetErrorString("Invalid c-string value string.");323return error;324}325const uint32_t byte_size = reg_info->byte_size;326327uint64_t uval64;328int64_t ival64;329float flt_val;330double dbl_val;331long double ldbl_val;332switch (reg_info->encoding) {333case eEncodingInvalid:334error.SetErrorString("Invalid encoding.");335break;336337case eEncodingUint:338if (byte_size > sizeof(uint64_t)) {339error.SetErrorStringWithFormat(340"unsupported unsigned integer byte size: %u", byte_size);341break;342}343if (value_str.getAsInteger(0, uval64)) {344error.SetErrorStringWithFormatv(345"'{0}' is not a valid unsigned integer string value", value_str);346break;347}348349if (!UInt64ValueIsValidForByteSize(uval64, byte_size)) {350error.SetErrorStringWithFormat(351"value 0x%" PRIx64352" is too large to fit in a %u byte unsigned integer value",353uval64, byte_size);354break;355}356357if (!SetUInt(uval64, reg_info->byte_size)) {358error.SetErrorStringWithFormat(359"unsupported unsigned integer byte size: %u", byte_size);360break;361}362break;363364case eEncodingSint:365if (byte_size > sizeof(long long)) {366error.SetErrorStringWithFormat("unsupported signed integer byte size: %u",367byte_size);368break;369}370371if (value_str.getAsInteger(0, ival64)) {372error.SetErrorStringWithFormatv(373"'{0}' is not a valid signed integer string value", value_str);374break;375}376377if (!SInt64ValueIsValidForByteSize(ival64, byte_size)) {378error.SetErrorStringWithFormat(379"value 0x%" PRIx64380" is too large to fit in a %u byte signed integer value",381ival64, byte_size);382break;383}384385if (!SetUInt(ival64, reg_info->byte_size)) {386error.SetErrorStringWithFormat("unsupported signed integer byte size: %u",387byte_size);388break;389}390break;391392case eEncodingIEEE754: {393std::string value_string = std::string(value_str);394if (byte_size == sizeof(float)) {395if (::sscanf(value_string.c_str(), "%f", &flt_val) != 1) {396error.SetErrorStringWithFormat("'%s' is not a valid float string value",397value_string.c_str());398break;399}400m_scalar = flt_val;401m_type = eTypeFloat;402} else if (byte_size == sizeof(double)) {403if (::sscanf(value_string.c_str(), "%lf", &dbl_val) != 1) {404error.SetErrorStringWithFormat("'%s' is not a valid float string value",405value_string.c_str());406break;407}408m_scalar = dbl_val;409m_type = eTypeDouble;410} else if (byte_size == sizeof(long double)) {411if (::sscanf(value_string.c_str(), "%Lf", &ldbl_val) != 1) {412error.SetErrorStringWithFormat("'%s' is not a valid float string value",413value_string.c_str());414break;415}416m_scalar = ldbl_val;417m_type = eTypeLongDouble;418} else {419error.SetErrorStringWithFormat("unsupported float byte size: %u",420byte_size);421return error;422}423break;424}425case eEncodingVector:426if (!ParseVectorEncoding(reg_info, value_str, byte_size, this))427error.SetErrorString("unrecognized vector encoding string value.");428break;429}430431return error;432}433434bool RegisterValue::SignExtend(uint32_t sign_bitpos) {435switch (m_type) {436case eTypeInvalid:437break;438439case eTypeUInt8:440case eTypeUInt16:441case eTypeUInt32:442case eTypeUInt64:443case eTypeUInt128:444return m_scalar.SignExtend(sign_bitpos);445case eTypeFloat:446case eTypeDouble:447case eTypeLongDouble:448case eTypeBytes:449break;450}451return false;452}453454bool RegisterValue::CopyValue(const RegisterValue &rhs) {455if (this == &rhs)456return rhs.m_type != eTypeInvalid;457458m_type = rhs.m_type;459switch (m_type) {460case eTypeInvalid:461return false;462case eTypeUInt8:463case eTypeUInt16:464case eTypeUInt32:465case eTypeUInt64:466case eTypeUInt128:467case eTypeFloat:468case eTypeDouble:469case eTypeLongDouble:470m_scalar = rhs.m_scalar;471break;472case eTypeBytes:473buffer.bytes = rhs.buffer.bytes;474buffer.byte_order = rhs.buffer.byte_order;475break;476}477return true;478}479480uint16_t RegisterValue::GetAsUInt16(uint16_t fail_value,481bool *success_ptr) const {482if (success_ptr)483*success_ptr = true;484485switch (m_type) {486default:487break;488case eTypeUInt8:489case eTypeUInt16:490return m_scalar.UShort(fail_value);491case eTypeBytes: {492switch (buffer.bytes.size()) {493default:494break;495case 1:496case 2:497return *reinterpret_cast<const uint16_t *>(buffer.bytes.data());498}499} break;500}501if (success_ptr)502*success_ptr = false;503return fail_value;504}505506uint32_t RegisterValue::GetAsUInt32(uint32_t fail_value,507bool *success_ptr) const {508if (success_ptr)509*success_ptr = true;510switch (m_type) {511default:512break;513case eTypeUInt8:514case eTypeUInt16:515case eTypeUInt32:516case eTypeFloat:517case eTypeDouble:518case eTypeLongDouble:519return m_scalar.UInt(fail_value);520case eTypeBytes: {521switch (buffer.bytes.size()) {522default:523break;524case 1:525case 2:526case 4:527return *reinterpret_cast<const uint32_t *>(buffer.bytes.data());528}529} break;530}531if (success_ptr)532*success_ptr = false;533return fail_value;534}535536uint64_t RegisterValue::GetAsUInt64(uint64_t fail_value,537bool *success_ptr) const {538if (success_ptr)539*success_ptr = true;540switch (m_type) {541default:542break;543case eTypeUInt8:544case eTypeUInt16:545case eTypeUInt32:546case eTypeUInt64:547case eTypeFloat:548case eTypeDouble:549case eTypeLongDouble:550return m_scalar.ULongLong(fail_value);551case eTypeBytes: {552switch (buffer.bytes.size()) {553default:554break;555case 1:556return *(const uint8_t *)buffer.bytes.data();557case 2:558return *reinterpret_cast<const uint16_t *>(buffer.bytes.data());559case 4:560return *reinterpret_cast<const uint32_t *>(buffer.bytes.data());561case 8:562return *reinterpret_cast<const uint64_t *>(buffer.bytes.data());563}564} break;565}566if (success_ptr)567*success_ptr = false;568return fail_value;569}570571llvm::APInt RegisterValue::GetAsUInt128(const llvm::APInt &fail_value,572bool *success_ptr) const {573if (success_ptr)574*success_ptr = true;575switch (m_type) {576default:577break;578case eTypeUInt8:579case eTypeUInt16:580case eTypeUInt32:581case eTypeUInt64:582case eTypeUInt128:583case eTypeFloat:584case eTypeDouble:585case eTypeLongDouble:586return m_scalar.UInt128(fail_value);587case eTypeBytes: {588switch (buffer.bytes.size()) {589default:590break;591case 1:592case 2:593case 4:594case 8:595case 16:596return llvm::APInt(597BITWIDTH_INT128, NUM_OF_WORDS_INT128,598(reinterpret_cast<const type128 *>(buffer.bytes.data()))->x);599}600} break;601}602if (success_ptr)603*success_ptr = false;604return fail_value;605}606607float RegisterValue::GetAsFloat(float fail_value, bool *success_ptr) const {608if (success_ptr)609*success_ptr = true;610switch (m_type) {611default:612break;613case eTypeUInt32:614case eTypeUInt64:615case eTypeUInt128:616case eTypeFloat:617case eTypeDouble:618case eTypeLongDouble:619return m_scalar.Float(fail_value);620}621if (success_ptr)622*success_ptr = false;623return fail_value;624}625626double RegisterValue::GetAsDouble(double fail_value, bool *success_ptr) const {627if (success_ptr)628*success_ptr = true;629switch (m_type) {630default:631break;632633case eTypeUInt32:634case eTypeUInt64:635case eTypeUInt128:636case eTypeFloat:637case eTypeDouble:638case eTypeLongDouble:639return m_scalar.Double(fail_value);640}641if (success_ptr)642*success_ptr = false;643return fail_value;644}645646long double RegisterValue::GetAsLongDouble(long double fail_value,647bool *success_ptr) const {648if (success_ptr)649*success_ptr = true;650switch (m_type) {651default:652break;653654case eTypeUInt32:655case eTypeUInt64:656case eTypeUInt128:657case eTypeFloat:658case eTypeDouble:659case eTypeLongDouble:660return m_scalar.LongDouble();661}662if (success_ptr)663*success_ptr = false;664return fail_value;665}666667const void *RegisterValue::GetBytes() const {668switch (m_type) {669case eTypeInvalid:670break;671case eTypeUInt8:672case eTypeUInt16:673case eTypeUInt32:674case eTypeUInt64:675case eTypeUInt128:676case eTypeFloat:677case eTypeDouble:678case eTypeLongDouble:679m_scalar.GetBytes(buffer.bytes);680return buffer.bytes.data();681case eTypeBytes:682return buffer.bytes.data();683}684return nullptr;685}686687uint32_t RegisterValue::GetByteSize() const {688switch (m_type) {689case eTypeInvalid:690break;691case eTypeUInt8:692return 1;693case eTypeUInt16:694return 2;695case eTypeUInt32:696case eTypeUInt64:697case eTypeUInt128:698case eTypeFloat:699case eTypeDouble:700case eTypeLongDouble:701return m_scalar.GetByteSize();702case eTypeBytes:703return buffer.bytes.size();704}705return 0;706}707708bool RegisterValue::SetUInt(uint64_t uint, uint32_t byte_size) {709if (byte_size == 0) {710SetUInt64(uint);711} else if (byte_size == 1) {712SetUInt8(uint);713} else if (byte_size <= 2) {714SetUInt16(uint);715} else if (byte_size <= 4) {716SetUInt32(uint);717} else if (byte_size <= 8) {718SetUInt64(uint);719} else if (byte_size <= 16) {720SetUInt128(llvm::APInt(128, uint));721} else722return false;723return true;724}725726void RegisterValue::SetBytes(const void *bytes, size_t length,727lldb::ByteOrder byte_order) {728if (bytes && length > 0) {729m_type = eTypeBytes;730buffer.bytes.resize(length);731memcpy(buffer.bytes.data(), bytes, length);732buffer.byte_order = byte_order;733} else {734m_type = eTypeInvalid;735buffer.bytes.resize(0);736}737}738739bool RegisterValue::operator==(const RegisterValue &rhs) const {740if (m_type == rhs.m_type) {741switch (m_type) {742case eTypeInvalid:743return true;744case eTypeUInt8:745case eTypeUInt16:746case eTypeUInt32:747case eTypeUInt64:748case eTypeUInt128:749case eTypeFloat:750case eTypeDouble:751case eTypeLongDouble:752return m_scalar == rhs.m_scalar;753case eTypeBytes:754return buffer.bytes == rhs.buffer.bytes;755}756}757return false;758}759760bool RegisterValue::operator!=(const RegisterValue &rhs) const {761return !(*this == rhs);762}763764bool RegisterValue::ClearBit(uint32_t bit) {765switch (m_type) {766case eTypeInvalid:767break;768769case eTypeUInt8:770case eTypeUInt16:771case eTypeUInt32:772case eTypeUInt64:773case eTypeUInt128:774if (bit < (GetByteSize() * 8)) {775return m_scalar.ClearBit(bit);776}777break;778779case eTypeFloat:780case eTypeDouble:781case eTypeLongDouble:782break;783784case eTypeBytes:785if (buffer.byte_order == eByteOrderBig ||786buffer.byte_order == eByteOrderLittle) {787uint32_t byte_idx;788if (buffer.byte_order == eByteOrderBig)789byte_idx = buffer.bytes.size() - (bit / 8) - 1;790else791byte_idx = bit / 8;792793const uint32_t byte_bit = bit % 8;794if (byte_idx < buffer.bytes.size()) {795buffer.bytes[byte_idx] &= ~(1u << byte_bit);796return true;797}798}799break;800}801return false;802}803804bool RegisterValue::SetBit(uint32_t bit) {805switch (m_type) {806case eTypeInvalid:807break;808809case eTypeUInt8:810case eTypeUInt16:811case eTypeUInt32:812case eTypeUInt64:813case eTypeUInt128:814if (bit < (GetByteSize() * 8)) {815return m_scalar.SetBit(bit);816}817break;818819case eTypeFloat:820case eTypeDouble:821case eTypeLongDouble:822break;823824case eTypeBytes:825if (buffer.byte_order == eByteOrderBig ||826buffer.byte_order == eByteOrderLittle) {827uint32_t byte_idx;828if (buffer.byte_order == eByteOrderBig)829byte_idx = buffer.bytes.size() - (bit / 8) - 1;830else831byte_idx = bit / 8;832833const uint32_t byte_bit = bit % 8;834if (byte_idx < buffer.bytes.size()) {835buffer.bytes[byte_idx] |= (1u << byte_bit);836return true;837}838}839break;840}841return false;842}843844845