Path: blob/main/contrib/llvm-project/lldb/source/Target/RegisterContext.cpp
96333 views
//===-- RegisterContext.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/Target/RegisterContext.h"9#include "lldb/Core/Module.h"10#include "lldb/Core/Value.h"11#include "lldb/Expression/DWARFExpression.h"12#include "lldb/Target/ExecutionContext.h"13#include "lldb/Target/Process.h"14#include "lldb/Target/StackFrame.h"15#include "lldb/Target/Target.h"16#include "lldb/Target/Thread.h"17#include "lldb/Utility/DataExtractor.h"18#include "lldb/Utility/Endian.h"19#include "lldb/Utility/RegisterValue.h"20#include "lldb/Utility/Scalar.h"2122using namespace lldb;23using namespace lldb_private;2425RegisterContext::RegisterContext(Thread &thread, uint32_t concrete_frame_idx)26: m_thread(thread), m_concrete_frame_idx(concrete_frame_idx),27m_stop_id(thread.GetProcess()->GetStopID()) {}2829RegisterContext::~RegisterContext() = default;3031void RegisterContext::InvalidateIfNeeded(bool force) {32ProcessSP process_sp(m_thread.GetProcess());33bool invalidate = force;34uint32_t process_stop_id = UINT32_MAX;3536if (process_sp)37process_stop_id = process_sp->GetStopID();38else39invalidate = true;4041if (!invalidate)42invalidate = process_stop_id != GetStopID();4344if (invalidate) {45InvalidateAllRegisters();46SetStopID(process_stop_id);47}48}4950const RegisterInfo *51RegisterContext::GetRegisterInfoByName(llvm::StringRef reg_name,52uint32_t start_idx) {53if (reg_name.empty())54return nullptr;5556// Generic register names take precedence over specific register names.57// For example, on x86 we want "sp" to refer to the complete RSP/ESP register58// rather than the 16-bit SP pseudo-register.59uint32_t generic_reg = Args::StringToGenericRegister(reg_name);60if (generic_reg != LLDB_INVALID_REGNUM) {61const RegisterInfo *reg_info =62GetRegisterInfo(eRegisterKindGeneric, generic_reg);63if (reg_info)64return reg_info;65}6667const uint32_t num_registers = GetRegisterCount();68for (uint32_t reg = start_idx; reg < num_registers; ++reg) {69const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);7071if (reg_name.equals_insensitive(reg_info->name) ||72reg_name.equals_insensitive(reg_info->alt_name))73return reg_info;74}7576return nullptr;77}7879const RegisterInfo *RegisterContext::GetRegisterInfo(lldb::RegisterKind kind,80uint32_t num) {81const uint32_t reg_num = ConvertRegisterKindToRegisterNumber(kind, num);82if (reg_num == LLDB_INVALID_REGNUM)83return nullptr;84return GetRegisterInfoAtIndex(reg_num);85}8687const char *RegisterContext::GetRegisterName(uint32_t reg) {88const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);89if (reg_info)90return reg_info->name;91return nullptr;92}9394uint64_t RegisterContext::GetPC(uint64_t fail_value) {95uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,96LLDB_REGNUM_GENERIC_PC);97uint64_t pc = ReadRegisterAsUnsigned(reg, fail_value);9899if (pc != fail_value) {100TargetSP target_sp = m_thread.CalculateTarget();101if (target_sp) {102Target *target = target_sp.get();103if (target)104pc = target->GetOpcodeLoadAddress(pc, AddressClass::eCode);105}106}107108return pc;109}110111uint64_t RegisterContext::GetThreadPointer(uint64_t fail_value) {112uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,113LLDB_REGNUM_GENERIC_TP);114return ReadRegisterAsUnsigned(reg, fail_value);115}116117bool RegisterContext::SetPC(uint64_t pc) {118uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,119LLDB_REGNUM_GENERIC_PC);120bool success = WriteRegisterFromUnsigned(reg, pc);121if (success) {122StackFrameSP frame_sp(123m_thread.GetFrameWithConcreteFrameIndex(m_concrete_frame_idx));124if (frame_sp)125frame_sp->ChangePC(pc);126else127m_thread.ClearStackFrames();128}129return success;130}131132bool RegisterContext::GetPCForSymbolication(Address &address) {133addr_t pc = GetPC(LLDB_INVALID_ADDRESS);134if (pc == LLDB_INVALID_ADDRESS)135return false;136TargetSP target_sp = m_thread.CalculateTarget();137if (!target_sp.get())138return false;139140if (!BehavesLikeZerothFrame() && pc != 0)141pc--;142address.SetLoadAddress(pc, target_sp.get());143return true;144}145146bool RegisterContext::SetPC(Address addr) {147TargetSP target_sp = m_thread.CalculateTarget();148Target *target = target_sp.get();149150lldb::addr_t callAddr = addr.GetCallableLoadAddress(target);151if (callAddr == LLDB_INVALID_ADDRESS)152return false;153154return SetPC(callAddr);155}156157uint64_t RegisterContext::GetSP(uint64_t fail_value) {158uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,159LLDB_REGNUM_GENERIC_SP);160return ReadRegisterAsUnsigned(reg, fail_value);161}162163bool RegisterContext::SetSP(uint64_t sp) {164uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,165LLDB_REGNUM_GENERIC_SP);166return WriteRegisterFromUnsigned(reg, sp);167}168169uint64_t RegisterContext::GetFP(uint64_t fail_value) {170uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,171LLDB_REGNUM_GENERIC_FP);172return ReadRegisterAsUnsigned(reg, fail_value);173}174175bool RegisterContext::SetFP(uint64_t fp) {176uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,177LLDB_REGNUM_GENERIC_FP);178return WriteRegisterFromUnsigned(reg, fp);179}180181uint64_t RegisterContext::GetReturnAddress(uint64_t fail_value) {182uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,183LLDB_REGNUM_GENERIC_RA);184return ReadRegisterAsUnsigned(reg, fail_value);185}186187uint64_t RegisterContext::GetFlags(uint64_t fail_value) {188uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,189LLDB_REGNUM_GENERIC_FLAGS);190return ReadRegisterAsUnsigned(reg, fail_value);191}192193uint64_t RegisterContext::ReadRegisterAsUnsigned(uint32_t reg,194uint64_t fail_value) {195if (reg != LLDB_INVALID_REGNUM)196return ReadRegisterAsUnsigned(GetRegisterInfoAtIndex(reg), fail_value);197return fail_value;198}199200uint64_t RegisterContext::ReadRegisterAsUnsigned(const RegisterInfo *reg_info,201uint64_t fail_value) {202if (reg_info) {203RegisterValue value;204if (ReadRegister(reg_info, value))205return value.GetAsUInt64();206}207return fail_value;208}209210bool RegisterContext::WriteRegisterFromUnsigned(uint32_t reg, uint64_t uval) {211if (reg == LLDB_INVALID_REGNUM)212return false;213return WriteRegisterFromUnsigned(GetRegisterInfoAtIndex(reg), uval);214}215216bool RegisterContext::WriteRegisterFromUnsigned(const RegisterInfo *reg_info,217uint64_t uval) {218if (reg_info) {219RegisterValue value;220if (value.SetUInt(uval, reg_info->byte_size))221return WriteRegister(reg_info, value);222}223return false;224}225226bool RegisterContext::CopyFromRegisterContext(lldb::RegisterContextSP context) {227uint32_t num_register_sets = context->GetRegisterSetCount();228// We don't know that two threads have the same register context, so require229// the threads to be the same.230if (context->GetThreadID() != GetThreadID())231return false;232233if (num_register_sets != GetRegisterSetCount())234return false;235236RegisterContextSP frame_zero_context = m_thread.GetRegisterContext();237238for (uint32_t set_idx = 0; set_idx < num_register_sets; ++set_idx) {239const RegisterSet *const reg_set = GetRegisterSet(set_idx);240241const uint32_t num_registers = reg_set->num_registers;242for (uint32_t reg_idx = 0; reg_idx < num_registers; ++reg_idx) {243const uint32_t reg = reg_set->registers[reg_idx];244const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);245if (!reg_info || reg_info->value_regs)246continue;247RegisterValue reg_value;248249// If we can reconstruct the register from the frame we are copying from,250// then do so, otherwise use the value from frame 0.251if (context->ReadRegister(reg_info, reg_value)) {252WriteRegister(reg_info, reg_value);253} else if (frame_zero_context->ReadRegister(reg_info, reg_value)) {254WriteRegister(reg_info, reg_value);255}256}257}258return true;259}260261lldb::tid_t RegisterContext::GetThreadID() const { return m_thread.GetID(); }262263uint32_t RegisterContext::NumSupportedHardwareBreakpoints() { return 0; }264265uint32_t RegisterContext::SetHardwareBreakpoint(lldb::addr_t addr,266size_t size) {267return LLDB_INVALID_INDEX32;268}269270// Used when parsing DWARF and EH frame information and any other object file271// sections that contain register numbers in them.272uint32_t273RegisterContext::ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,274uint32_t num) {275const uint32_t num_regs = GetRegisterCount();276277assert(kind < kNumRegisterKinds);278for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) {279const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_idx);280281if (reg_info->kinds[kind] == num)282return reg_idx;283}284285return LLDB_INVALID_REGNUM;286}287288bool RegisterContext::ClearHardwareBreakpoint(uint32_t hw_idx) { return false; }289290uint32_t RegisterContext::NumSupportedHardwareWatchpoints() { return 0; }291292uint32_t RegisterContext::SetHardwareWatchpoint(lldb::addr_t addr, size_t size,293bool read, bool write) {294return LLDB_INVALID_INDEX32;295}296297bool RegisterContext::ClearHardwareWatchpoint(uint32_t hw_index) {298return false;299}300301bool RegisterContext::HardwareSingleStep(bool enable) { return false; }302303Status RegisterContext::ReadRegisterValueFromMemory(304const RegisterInfo *reg_info, lldb::addr_t src_addr, uint32_t src_len,305RegisterValue ®_value) {306Status error;307if (reg_info == nullptr) {308error.SetErrorString("invalid register info argument.");309return error;310}311312// Moving from addr into a register313//314// Case 1: src_len == dst_len315//316// |AABBCCDD| Address contents317// |AABBCCDD| Register contents318//319// Case 2: src_len > dst_len320//321// Status! (The register should always be big enough to hold the data)322//323// Case 3: src_len < dst_len324//325// |AABB| Address contents326// |AABB0000| Register contents [on little-endian hardware]327// |0000AABB| Register contents [on big-endian hardware]328const uint32_t dst_len = reg_info->byte_size;329330if (src_len > dst_len) {331error.SetErrorStringWithFormat(332"%u bytes is too big to store in register %s (%u bytes)", src_len,333reg_info->name, dst_len);334return error;335}336337ProcessSP process_sp(m_thread.GetProcess());338if (process_sp) {339RegisterValue::BytesContainer src(src_len);340341// Read the memory342const uint32_t bytes_read =343process_sp->ReadMemory(src_addr, src.data(), src_len, error);344345// Make sure the memory read succeeded...346if (bytes_read != src_len) {347if (error.Success()) {348// This might happen if we read _some_ bytes but not all349error.SetErrorStringWithFormat("read %u of %u bytes", bytes_read,350src_len);351}352return error;353}354355// We now have a memory buffer that contains the part or all of the356// register value. Set the register value using this memory data.357// TODO: we might need to add a parameter to this function in case the byte358// order of the memory data doesn't match the process. For now we are359// assuming they are the same.360reg_value.SetFromMemoryData(*reg_info, src.data(), src_len,361process_sp->GetByteOrder(), error);362} else363error.SetErrorString("invalid process");364365return error;366}367368Status RegisterContext::WriteRegisterValueToMemory(369const RegisterInfo *reg_info, lldb::addr_t dst_addr, uint32_t dst_len,370const RegisterValue ®_value) {371Status error;372ProcessSP process_sp(m_thread.GetProcess());373374if (!process_sp) {375error.SetErrorString("invalid process");376return error;377}378379if (reg_info == nullptr) {380error.SetErrorString("Invalid register info argument.");381return error;382}383384// TODO: we might need to add a parameter to this function in case the byte385// order of the memory data doesn't match the process. For now we are386// assuming they are the same.387RegisterValue::BytesContainer dst(dst_len);388const uint32_t bytes_copied = reg_value.GetAsMemoryData(389*reg_info, dst.data(), dst_len, process_sp->GetByteOrder(), error);390391if (error.Success()) {392if (bytes_copied == 0) {393error.SetErrorString("byte copy failed.");394} else {395const uint32_t bytes_written =396process_sp->WriteMemory(dst_addr, dst.data(), bytes_copied, error);397if (bytes_written != bytes_copied) {398if (error.Success()) {399// This might happen if we read _some_ bytes but not all400error.SetErrorStringWithFormat("only wrote %u of %u bytes",401bytes_written, bytes_copied);402}403}404}405}406407return error;408}409410lldb::ByteOrder RegisterContext::GetByteOrder() {411// Get the target process whose privileged thread was used for the register412// read.413lldb::ByteOrder byte_order = lldb::eByteOrderInvalid;414lldb_private::Process *process = CalculateProcess().get();415416if (process)417byte_order = process->GetByteOrder();418return byte_order;419}420421bool RegisterContext::ReadAllRegisterValues(422lldb_private::RegisterCheckpoint ®_checkpoint) {423return ReadAllRegisterValues(reg_checkpoint.GetData());424}425426bool RegisterContext::WriteAllRegisterValues(427const lldb_private::RegisterCheckpoint ®_checkpoint) {428return WriteAllRegisterValues(reg_checkpoint.GetData());429}430431TargetSP RegisterContext::CalculateTarget() {432return m_thread.CalculateTarget();433}434435ProcessSP RegisterContext::CalculateProcess() {436return m_thread.CalculateProcess();437}438439ThreadSP RegisterContext::CalculateThread() {440return m_thread.shared_from_this();441}442443StackFrameSP RegisterContext::CalculateStackFrame() {444// Register contexts might belong to many frames if we have inlined functions445// inside a frame since all inlined functions share the same registers, so we446// can't definitively say which frame we come from...447return StackFrameSP();448}449450void RegisterContext::CalculateExecutionContext(ExecutionContext &exe_ctx) {451m_thread.CalculateExecutionContext(exe_ctx);452}453454bool RegisterContext::ConvertBetweenRegisterKinds(lldb::RegisterKind source_rk,455uint32_t source_regnum,456lldb::RegisterKind target_rk,457uint32_t &target_regnum) {458const uint32_t num_registers = GetRegisterCount();459for (uint32_t reg = 0; reg < num_registers; ++reg) {460const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);461462if (reg_info->kinds[source_rk] == source_regnum) {463target_regnum = reg_info->kinds[target_rk];464return (target_regnum != LLDB_INVALID_REGNUM);465}466}467return false;468}469470471