Index: lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h =================================================================== --- lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h +++ lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h @@ -63,6 +63,8 @@ void Clear(); + bool IsReconfigurable(); + protected: // Classes that inherit from DynamicRegisterInfo can see and modify these typedef std::vector reg_collection; @@ -89,5 +91,6 @@ size_t m_reg_data_byte_size = 0u; // The number of bytes required to store // all registers bool m_finalized = false; + bool m_is_reconfigurable = false; }; #endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_DYNAMICREGISTERINFO_H Index: lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp =================================================================== --- lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp +++ lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp @@ -650,6 +650,8 @@ } } +bool DynamicRegisterInfo::IsReconfigurable() { return m_is_reconfigurable; } + size_t DynamicRegisterInfo::GetNumRegisters() const { return m_regs.size(); } size_t DynamicRegisterInfo::GetNumRegisterSets() const { return m_sets.size(); } Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h =================================================================== --- lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h +++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h @@ -27,6 +27,10 @@ class ThreadGDBRemote; class ProcessGDBRemote; +class GDBRemoteDynamicRegisterInfo; + +typedef std::shared_ptr + GDBRemoteDynamicRegisterInfoSP; class GDBRemoteDynamicRegisterInfo : public DynamicRegisterInfo { public: @@ -35,12 +39,14 @@ ~GDBRemoteDynamicRegisterInfo() override = default; void HardcodeARMRegisters(bool from_scratch); + + void CloneFrom(GDBRemoteDynamicRegisterInfoSP process_reginfo); }; class GDBRemoteRegisterContext : public RegisterContext { public: GDBRemoteRegisterContext(ThreadGDBRemote &thread, uint32_t concrete_frame_idx, - GDBRemoteDynamicRegisterInfo ®_info, + GDBRemoteDynamicRegisterInfoSP reg_info_sp, bool read_all_at_once, bool write_all_at_once); ~GDBRemoteRegisterContext() override; @@ -106,7 +112,7 @@ m_reg_valid[reg] = valid; } - GDBRemoteDynamicRegisterInfo &m_reg_info; + GDBRemoteDynamicRegisterInfoSP m_reg_info_sp; std::vector m_reg_valid; DataExtractor m_reg_data; bool m_read_all_at_once; Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp =================================================================== --- lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp +++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp @@ -31,19 +31,20 @@ // GDBRemoteRegisterContext constructor GDBRemoteRegisterContext::GDBRemoteRegisterContext( ThreadGDBRemote &thread, uint32_t concrete_frame_idx, - GDBRemoteDynamicRegisterInfo ®_info, bool read_all_at_once, + GDBRemoteDynamicRegisterInfoSP reg_info_sp, bool read_all_at_once, bool write_all_at_once) - : RegisterContext(thread, concrete_frame_idx), m_reg_info(reg_info), - m_reg_valid(), m_reg_data(), m_read_all_at_once(read_all_at_once), + : RegisterContext(thread, concrete_frame_idx), + m_reg_info_sp(std::move(reg_info_sp)), m_reg_valid(), m_reg_data(), + m_read_all_at_once(read_all_at_once), m_write_all_at_once(write_all_at_once) { // Resize our vector of bools to contain one bool for every register. We will // use these boolean values to know when a register value is valid in // m_reg_data. - m_reg_valid.resize(reg_info.GetNumRegisters()); + m_reg_valid.resize(m_reg_info_sp->GetNumRegisters()); // Make a heap based buffer that is big enough to store all registers DataBufferSP reg_data_sp( - new DataBufferHeap(reg_info.GetRegisterDataByteSize(), 0)); + new DataBufferHeap(m_reg_info_sp->GetRegisterDataByteSize(), 0)); m_reg_data.SetData(reg_data_sp); m_reg_data.SetByteOrder(thread.GetProcess()->GetByteOrder()); } @@ -62,12 +63,12 @@ } size_t GDBRemoteRegisterContext::GetRegisterCount() { - return m_reg_info.GetNumRegisters(); + return m_reg_info_sp->GetNumRegisters(); } const RegisterInfo * GDBRemoteRegisterContext::GetRegisterInfoAtIndex(size_t reg) { - RegisterInfo *reg_info = m_reg_info.GetRegisterInfoAtIndex(reg); + RegisterInfo *reg_info = m_reg_info_sp->GetRegisterInfoAtIndex(reg); if (reg_info && reg_info->dynamic_size_dwarf_expr_bytes) { const ArchSpec &arch = m_thread.GetProcess()->GetTarget().GetArchitecture(); @@ -78,11 +79,11 @@ } size_t GDBRemoteRegisterContext::GetRegisterSetCount() { - return m_reg_info.GetNumRegisterSets(); + return m_reg_info_sp->GetNumRegisterSets(); } const RegisterSet *GDBRemoteRegisterContext::GetRegisterSet(size_t reg_set) { - return m_reg_info.GetRegisterSet(reg_set); + return m_reg_info_sp->GetRegisterSet(reg_set); } bool GDBRemoteRegisterContext::ReadRegister(const RegisterInfo *reg_info, @@ -209,9 +210,10 @@ SetAllRegisterValid(true); return true; } else if (buffer_sp->GetByteSize() > 0) { - const int regcount = m_reg_info.GetNumRegisters(); + const int regcount = m_reg_info_sp->GetNumRegisters(); for (int i = 0; i < regcount; i++) { - struct RegisterInfo *reginfo = m_reg_info.GetRegisterInfoAtIndex(i); + struct RegisterInfo *reginfo = + m_reg_info_sp->GetRegisterInfoAtIndex(i); if (reginfo->byte_offset + reginfo->byte_size <= buffer_sp->GetByteSize()) { m_reg_valid[i] = true; @@ -506,7 +508,7 @@ // m_reg_data buffer } data_sp = std::make_shared( - m_reg_data.GetDataStart(), m_reg_info.GetRegisterDataByteSize()); + m_reg_data.GetDataStart(), m_reg_info_sp->GetRegisterDataByteSize()); return true; } else { @@ -708,7 +710,22 @@ uint32_t GDBRemoteRegisterContext::ConvertRegisterKindToRegisterNumber( lldb::RegisterKind kind, uint32_t num) { - return m_reg_info.ConvertRegisterKindToRegisterNumber(kind, num); + return m_reg_info_sp->ConvertRegisterKindToRegisterNumber(kind, num); +} + +void GDBRemoteDynamicRegisterInfo::CloneFrom( + GDBRemoteDynamicRegisterInfoSP proc_reginfo) { + m_regs = proc_reginfo->m_regs; + m_sets = proc_reginfo->m_sets; + m_set_reg_nums = proc_reginfo->m_set_reg_nums; + m_set_names = proc_reginfo->m_set_names; + m_value_regs_map = proc_reginfo->m_value_regs_map; + m_invalidate_regs_map = proc_reginfo->m_invalidate_regs_map; + m_dynamic_reg_size_map = proc_reginfo->m_dynamic_reg_size_map; + m_reg_data_byte_size = proc_reginfo->m_reg_data_byte_size; + + m_finalized = proc_reginfo->m_finalized; + m_is_reconfigurable = proc_reginfo->m_is_reconfigurable; } void GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters(bool from_scratch) { Index: lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h =================================================================== --- lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -254,7 +254,7 @@ // the last stop // packet variable std::recursive_mutex m_last_stop_packet_mutex; - GDBRemoteDynamicRegisterInfo m_register_info; + GDBRemoteDynamicRegisterInfoSP m_register_info_sp; Broadcaster m_async_broadcaster; lldb::ListenerSP m_async_listener_sp; HostThread m_async_thread; Index: lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp =================================================================== --- lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -249,7 +249,7 @@ ListenerSP listener_sp) : Process(target_sp, listener_sp), m_debugserver_pid(LLDB_INVALID_PROCESS_ID), m_last_stop_packet_mutex(), - m_register_info(), + m_register_info_sp(nullptr), m_async_broadcaster(nullptr, "lldb.process.gdb-remote.async-broadcaster"), m_async_listener_sp( Listener::MakeListener("lldb.process.gdb-remote.async-listener")), @@ -368,8 +368,8 @@ m_breakpoint_pc_offset = breakpoint_pc_int_value->GetValue(); } - if (m_register_info.SetRegisterInfo(*target_definition_sp, - GetTarget().GetArchitecture()) > 0) { + if (m_register_info_sp->SetRegisterInfo( + *target_definition_sp, GetTarget().GetArchitecture()) > 0) { return true; } } @@ -396,10 +396,11 @@ } void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) { - if (!force && m_register_info.GetNumRegisters() > 0) + if (!force && m_register_info_sp) return; - m_register_info.Clear(); + m_register_info_sp = std::make_shared(); + m_register_info_sp->Clear(); // Check if qHostInfo specified a specific packet timeout for this // connection. If so then lets update our setting so the user knows what the @@ -581,7 +582,7 @@ if (ABISP abi_sp = ABI::FindPlugin(shared_from_this(), arch_to_use)) abi_sp->AugmentRegisterInfo(reg_info); - m_register_info.AddRegister(reg_info, reg_name, alt_name, set_name); + m_register_info_sp->AddRegister(reg_info, reg_name, alt_name, set_name); } else { break; // ensure exit before reg_num is incremented } @@ -590,8 +591,8 @@ } } - if (m_register_info.GetNumRegisters() > 0) { - m_register_info.Finalize(GetTarget().GetArchitecture()); + if (m_register_info_sp->GetNumRegisters() > 0) { + m_register_info_sp->Finalize(GetTarget().GetArchitecture()); return; } @@ -600,21 +601,21 @@ // updated debugserver down on the devices. On the other hand, if the // accumulated reg_num is positive, see if we can add composite registers to // the existing primordial ones. - bool from_scratch = (m_register_info.GetNumRegisters() == 0); + bool from_scratch = (m_register_info_sp->GetNumRegisters() == 0); if (!target_arch.IsValid()) { if (arch_to_use.IsValid() && (arch_to_use.GetMachine() == llvm::Triple::arm || arch_to_use.GetMachine() == llvm::Triple::thumb) && arch_to_use.GetTriple().getVendor() == llvm::Triple::Apple) - m_register_info.HardcodeARMRegisters(from_scratch); + m_register_info_sp->HardcodeARMRegisters(from_scratch); } else if (target_arch.GetMachine() == llvm::Triple::arm || target_arch.GetMachine() == llvm::Triple::thumb) { - m_register_info.HardcodeARMRegisters(from_scratch); + m_register_info_sp->HardcodeARMRegisters(from_scratch); } // At this point, we can finalize our register info. - m_register_info.Finalize(GetTarget().GetArchitecture()); + m_register_info_sp->Finalize(GetTarget().GetArchitecture()); } Status ProcessGDBRemote::WillLaunch(lldb_private::Module *module) { @@ -4567,7 +4568,7 @@ // ABI is also potentially incorrect. ABISP abi_to_use_sp = ABI::FindPlugin(shared_from_this(), arch_to_use); for (auto &feature_node : feature_nodes) { - ParseRegisters(feature_node, target_info, this->m_register_info, + ParseRegisters(feature_node, target_info, *this->m_register_info_sp, abi_to_use_sp, reg_num_remote, reg_num_local); } @@ -4597,9 +4598,9 @@ uint32_t reg_num_local = 0; if (GetGDBServerRegisterInfoXMLAndProcess(arch_to_use, "target.xml", reg_num_remote, reg_num_local)) - this->m_register_info.Finalize(arch_to_use); + this->m_register_info_sp->Finalize(arch_to_use); - return m_register_info.GetNumRegisters() > 0; + return m_register_info_sp->GetNumRegisters() > 0; } llvm::Expected ProcessGDBRemote::GetLoadedModuleList() { Index: lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h =================================================================== --- lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h +++ lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h @@ -14,6 +14,8 @@ #include "lldb/Target/Thread.h" #include "lldb/Utility/StructuredData.h" +#include "GDBRemoteRegisterContext.h" + class StringExtractor; namespace lldb_private { @@ -101,6 +103,8 @@ m_queue_serial_number; // Queue info from stop reply/stop info for thread lldb_private::LazyBool m_associated_with_libdispatch_queue; + GDBRemoteDynamicRegisterInfoSP m_reg_info_sp; + bool PrivateSetRegisterValue(uint32_t reg, llvm::ArrayRef data); bool PrivateSetRegisterValue(uint32_t reg, uint64_t regval); Index: lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp =================================================================== --- lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp +++ lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp @@ -42,6 +42,22 @@ Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_THREAD)); LLDB_LOG(log, "this = {0}, pid = {1}, tid = {2}", this, process.GetID(), GetID()); + // At this point we can clone reg_info for architectures supporting + // run-time update to register sizes and offsets.. + ProcessSP process_sp(GetProcess()); + if (process_sp) { + ProcessGDBRemote *gdb_process = + static_cast(process_sp.get()); + + if (!m_reg_info_sp) { + if (!gdb_process->m_register_info_sp->IsReconfigurable()) + m_reg_info_sp = gdb_process->m_register_info_sp; + else { + m_reg_info_sp = std::make_shared(); + m_reg_info_sp->CloneFrom(gdb_process->m_register_info_sp); + } + } + } } ThreadGDBRemote::~ThreadGDBRemote() { @@ -307,8 +323,8 @@ !pSupported || gdb_process->m_use_g_packet_for_reading; bool write_all_registers_at_once = !pSupported; reg_ctx_sp = std::make_shared( - *this, concrete_frame_idx, gdb_process->m_register_info, - read_all_registers_at_once, write_all_registers_at_once); + *this, concrete_frame_idx, m_reg_info_sp, read_all_registers_at_once, + write_all_registers_at_once); } } else { reg_ctx_sp = GetUnwinder().CreateRegisterContextForFrame(frame);