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: + llvm::Optional 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 @@ -236,13 +236,7 @@ // CONSIDER after local and llgs debugging are merged, register set support can // be moved into a base x86-64 class with IsRegisterSetAvailable made virtual. 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) - ++sets; - } - - return sets; + return k_num_register_sets; } const RegisterSet * @@ -370,8 +364,8 @@ } } -int NativeRegisterContextNetBSD_x86_64::GetSetForNativeRegNum( - int reg_num) const { +llvm::Optional 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 +375,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 llvm::None; // MPXR if (reg_num >= k_first_mpxc_i386 && reg_num <= k_last_mpxc_i386) - return -1; // MPXC + return llvm::None; // MPXC if (reg_num >= k_first_dbr_i386 && reg_num <= k_last_dbr_i386) return DBRegSet; // DBR break; @@ -395,9 +389,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 llvm::None; // MPXR if (reg_num >= k_first_mpxc_x86_64 && reg_num <= k_last_mpxc_x86_64) - return -1; // MPXC + return llvm::None; // MPXC if (reg_num >= k_first_dbr_x86_64 && reg_num <= k_last_dbr_x86_64) return DBRegSet; // DBR break; @@ -437,33 +431,12 @@ } Status -NativeRegisterContextNetBSD_x86_64::ReadRegister(const RegisterInfo *reg_info, - RegisterValue ®_value) { - Status error; - - if (!reg_info) { - error.SetErrorString("reg_info NULL"); - return error; - } +NativeRegisterContextNetBSD_x86_64::GetRegisterFromCache( + const RegisterInfo *reg_info, RegisterValue ®_value, uint32_t set) { + assert(reg_info); + 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 +448,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 +694,14 @@ 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) { + assert(reg_info); 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; - } - - 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 +715,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 +964,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 "llvm/ADT/Optional.h" + +#include +#include + +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 llvm::Optional 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,102 @@ +//===-- 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; + } + + llvm::Optional set = GetRegisterSetForRegNum(reg); + if (!set) { + error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set", + reg_info->name); + return error; + } + + error = ReadRegisterSet(set.getValue()); + if (error.Fail()) + return error; + + return GetRegisterFromCache(reg_info, reg_value, set.getValue()); +} + +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; + } + + llvm::Optional set = GetRegisterSetForRegNum(reg); + if (!set) { + error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set", + reg_info->name); + return error; + } + + error = ReadRegisterSet(set.getValue()); + if (error.Fail()) + return error; + + error = SetRegisterInCache(reg_info, reg_value, set.getValue()); + if (error.Fail()) + return error; + + return WriteRegisterSet(set.getValue()); +} + +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(); +}