Index: lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h =================================================================== --- lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h +++ lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h @@ -20,6 +20,7 @@ #include "Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h" #include "Plugins/Process/Utility/RegisterContext_x86.h" +#include "Plugins/Process/Utility/NativeRegisterContextCache.h" #include "Plugins/Process/Utility/NativeRegisterContextWatchpoint_x86.h" #include "Plugins/Process/Utility/lldb-x86-register-enums.h" @@ -30,6 +31,7 @@ class NativeRegisterContextNetBSD_x86_64 : public NativeRegisterContextNetBSD, + public NativeRegisterContextCache, public NativeRegisterContextWatchpoint_x86 { public: NativeRegisterContextNetBSD_x86_64(const ArchSpec &target_arch, @@ -38,12 +40,6 @@ const RegisterSet *GetRegisterSet(uint32_t set_index) const override; - Status ReadRegister(const RegisterInfo *reg_info, - RegisterValue ®_value) override; - - Status WriteRegister(const RegisterInfo *reg_info, - const RegisterValue ®_value) override; - Status ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; @@ -51,6 +47,19 @@ Status CopyHardwareWatchpointsFrom(NativeRegisterContextNetBSD &source) override; +protected: + uint32_t GetRegisterSetForRegNum(uint32_t reg_index) const override; + + Status ReadRegisterSet(uint32_t set) override; + Status WriteRegisterSet(uint32_t set) override; + + Status GetRegisterFromCache(const RegisterInfo *reg_info, + RegisterValue ®_value, + uint32_t set) override; + Status SetRegisterInCache(const RegisterInfo *reg_info, + const RegisterValue ®_value, + uint32_t set) override; + private: // Private member types. enum { GPRegSet, XStateRegSet, DBRegSet }; @@ -60,11 +69,7 @@ struct xstate m_xstate; struct dbreg m_dbr; - int GetSetForNativeRegNum(int reg_num) const; int GetDR(int num) const; - - Status ReadRegisterSet(uint32_t set); - Status WriteRegisterSet(uint32_t set); }; } // namespace process_netbsd Index: lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp =================================================================== --- lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp +++ lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp @@ -238,7 +238,7 @@ uint32_t NativeRegisterContextNetBSD_x86_64::GetRegisterSetCount() const { uint32_t sets = 0; for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) { - if (GetSetForNativeRegNum(set_index) != -1) + if (GetRegisterSetForRegNum(set_index) != LLDB_INVALID_REGNUM) ++sets; } @@ -370,8 +370,8 @@ } } -int NativeRegisterContextNetBSD_x86_64::GetSetForNativeRegNum( - int reg_num) const { +uint32_t NativeRegisterContextNetBSD_x86_64::GetRegisterSetForRegNum( + uint32_t reg_num) const { switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { case llvm::Triple::x86: if (reg_num >= k_first_gpr_i386 && reg_num <= k_last_gpr_i386) @@ -381,9 +381,9 @@ if (reg_num >= k_first_avx_i386 && reg_num <= k_last_avx_i386) return XStateRegSet; // AVX if (reg_num >= k_first_mpxr_i386 && reg_num <= k_last_mpxr_i386) - return -1; // MPXR + return LLDB_INVALID_REGSET; // MPXR if (reg_num >= k_first_mpxc_i386 && reg_num <= k_last_mpxc_i386) - return -1; // MPXC + return LLDB_INVALID_REGSET; // MPXC if (reg_num >= k_first_dbr_i386 && reg_num <= k_last_dbr_i386) return DBRegSet; // DBR break; @@ -395,9 +395,9 @@ if (reg_num >= k_first_avx_x86_64 && reg_num <= k_last_avx_x86_64) return XStateRegSet; // AVX if (reg_num >= k_first_mpxr_x86_64 && reg_num <= k_last_mpxr_x86_64) - return -1; // MPXR + return LLDB_INVALID_REGSET; // MPXR if (reg_num >= k_first_mpxc_x86_64 && reg_num <= k_last_mpxc_x86_64) - return -1; // MPXC + return LLDB_INVALID_REGSET; // MPXC if (reg_num >= k_first_dbr_x86_64 && reg_num <= k_last_dbr_x86_64) return DBRegSet; // DBR break; @@ -437,33 +437,14 @@ } Status -NativeRegisterContextNetBSD_x86_64::ReadRegister(const RegisterInfo *reg_info, - RegisterValue ®_value) { - Status error; +NativeRegisterContextNetBSD_x86_64::GetRegisterFromCache( + const RegisterInfo *reg_info, RegisterValue ®_value, uint32_t set) { - if (!reg_info) { - error.SetErrorString("reg_info NULL"); - return error; - } + assert(reg_info); + assert(set != LLDB_INVALID_REGSET); + Status error; uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; - if (reg == LLDB_INVALID_REGNUM) { - // This is likely an internal register for lldb use only and should not be - // directly queried. - error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb " - "register, cannot read directly", - reg_info->name); - return error; - } - - int set = GetSetForNativeRegNum(reg); - if (set == -1) { - // This is likely an internal register for lldb use only and should not be - // directly queried. - error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set", - reg_info->name); - return error; - } switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { case llvm::Triple::x86_64: @@ -475,10 +456,6 @@ llvm_unreachable("Unhandled target architecture."); } - error = ReadRegisterSet(set); - if (error.Fail()) - return error; - switch (reg) { #if defined(__x86_64__) case lldb_rax_x86_64: @@ -725,34 +702,16 @@ return error; } -Status NativeRegisterContextNetBSD_x86_64::WriteRegister( - const RegisterInfo *reg_info, const RegisterValue ®_value) { +Status NativeRegisterContextNetBSD_x86_64::SetRegisterInCache( + const RegisterInfo *reg_info, + const RegisterValue ®_value, + uint32_t set) { - Status error; - - if (!reg_info) { - error.SetErrorString("reg_info NULL"); - return error; - } + assert(reg_info); + assert(set != LLDB_INVALID_REGSET); + Status error; uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; - if (reg == LLDB_INVALID_REGNUM) { - // This is likely an internal register for lldb use only and should not be - // directly queried. - error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb " - "register, cannot read directly", - reg_info->name); - return error; - } - - int set = GetSetForNativeRegNum(reg); - if (set == -1) { - // This is likely an internal register for lldb use only and should not be - // directly queried. - error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set", - reg_info->name); - return error; - } uint64_t new_xstate_bv = XCR0_X87; // the most common case @@ -766,10 +725,6 @@ llvm_unreachable("Unhandled target architecture."); } - error = ReadRegisterSet(set); - if (error.Fail()) - return error; - switch (reg) { #if defined(__x86_64__) case lldb_rax_x86_64: @@ -1019,7 +974,7 @@ if (set == XStateRegSet) m_xstate.xs_xstate_bv |= new_xstate_bv; - return WriteRegisterSet(set); + return Status(); } Status NativeRegisterContextNetBSD_x86_64::ReadAllRegisterValues( Index: lldb/source/Plugins/Process/Utility/CMakeLists.txt =================================================================== --- lldb/source/Plugins/Process/Utility/CMakeLists.txt +++ lldb/source/Plugins/Process/Utility/CMakeLists.txt @@ -9,6 +9,7 @@ LinuxProcMaps.cpp LinuxSignals.cpp MipsLinuxSignals.cpp + NativeRegisterContextCache.cpp NativeRegisterContextRegisterInfo.cpp NativeRegisterContextWatchpoint_x86.cpp NetBSDSignals.cpp Index: lldb/source/Plugins/Process/Utility/NativeRegisterContextCache.h =================================================================== --- /dev/null +++ lldb/source/Plugins/Process/Utility/NativeRegisterContextCache.h @@ -0,0 +1,52 @@ +//===-- NativeRegisterContextCache.h ----------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_NativeRegisterContextCache_h +#define lldb_NativeRegisterContextCache_h + +#include "Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h" + +#include +#include + +#define LLDB_INVALID_REGSET UINT32_MAX + +namespace lldb_private { + +enum class RegSetCacheStatus { + Empty, + Read, + Written, +}; + +class NativeRegisterContextCache + : public virtual NativeRegisterContextRegisterInfo { +public: + Status ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value) override; + Status WriteRegister(const RegisterInfo *reg_info, const RegisterValue ®_value) override; + Status FlushRegisterSets(); + +protected: + virtual uint32_t GetRegisterSetForRegNum(uint32_t reg_index) const = 0; + + virtual Status ReadRegisterSet(uint32_t set) = 0; + virtual Status WriteRegisterSet(uint32_t set) = 0; + + virtual Status GetRegisterFromCache(const RegisterInfo *reg_info, RegisterValue ®_value, uint32_t set) = 0; + virtual Status SetRegisterInCache(const RegisterInfo *reg_info, const RegisterValue ®_value, uint32_t set) = 0; + + virtual Status FlushRegisterSet(uint32_t set); + +private: + std::map m_regset_cache_status; +}; + +} // namespace lldb_private + +#endif // #ifndef lldb_NativeRegisterContextCache_h + Index: lldb/source/Plugins/Process/Utility/NativeRegisterContextCache.cpp =================================================================== --- /dev/null +++ lldb/source/Plugins/Process/Utility/NativeRegisterContextCache.cpp @@ -0,0 +1,106 @@ +//===-- NativeRegisterContextCache.cpp ------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "NativeRegisterContextCache.h" + +using namespace lldb_private; + +Status +NativeRegisterContextCache::ReadRegister(const RegisterInfo *reg_info, + RegisterValue ®_value) { + Status error; + + if (!reg_info) { + error.SetErrorString("reg_info NULL"); + return error; + } + + uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + if (reg == LLDB_INVALID_REGNUM) { + // This is likely an internal register for lldb use only and should not be + // directly queried. + error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb " + "register, cannot read directly", + reg_info->name); + return error; + } + + uint32_t set = GetRegisterSetForRegNum(reg); + if (set == LLDB_INVALID_REGSET) { + // This is likely an internal register for lldb use only and should not be + // directly queried. + error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set", + reg_info->name); + return error; + } + + error = ReadRegisterSet(set); + if (error.Fail()) + return error; + + return GetRegisterFromCache(reg_info, reg_value, set); +} + +Status NativeRegisterContextCache::WriteRegister( + const RegisterInfo *reg_info, const RegisterValue ®_value) { + + Status error; + + if (!reg_info) { + error.SetErrorString("reg_info NULL"); + return error; + } + + uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + if (reg == LLDB_INVALID_REGNUM) { + // This is likely an internal register for lldb use only and should not be + // directly queried. + error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb " + "register, cannot read directly", + reg_info->name); + return error; + } + + uint32_t set = GetRegisterSetForRegNum(reg); + if (set == LLDB_INVALID_REGSET) { + // This is likely an internal register for lldb use only and should not be + // directly queried. + error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set", + reg_info->name); + return error; + } + + error = ReadRegisterSet(set); + if (error.Fail()) + return error; + + error = SetRegisterInCache(reg_info, reg_value, set); + if (error.Fail()) + return error; + + return WriteRegisterSet(set); +} + +Status NativeRegisterContextCache::FlushRegisterSets() { + Status error; + + for (auto kv : m_regset_cache_status) { + if (kv.second == RegSetCacheStatus::Empty) + continue; + error = FlushRegisterSet(kv.first); + if (error.Fail()) + break; + } + + return error; +} + +Status NativeRegisterContextCache::FlushRegisterSet(uint32_t set) { + m_regset_cache_status[set] = RegSetCacheStatus::Empty; + return Status(); +}