mgorny created this revision. mgorny added reviewers: labath, krytarowski, emaste. Herald added a subscriber: arichardson. mgorny requested review of this revision.
// This is work-in-progress, submitted to get proposed API reviewed. No actual caching is done yet. // I am planning to use this for NetBSD and FreeBSD. It will also result in some of the code being deduplicated. Introduce a new API for caching register set reads and writes in the generic NativeRegisterContextRegisterInfo class. Use it in the NetBSD plugin for initial testing. The implementation provides a generic caching version of ReadRegister() and WriteRegister() that call virtual methods implemented in actual NativeRegisterContext* classes. This should not affect existing implementations since they override ReadRegister() and WriteRegister() already. The hook API consists of five methods that need to be implemented in NativeRegisterContext* classes: - GetRegisterSetForRegNum() to map register number to a register set number (the latter being opaque to NativeRegisterContextRegisterInfo). - ReadRegisterSet() and WriteRegisterSet() to respectively read regset into cache and write it back. The actual cache storage is provided by final classes (m_gpr, m_fpr...). - GetRegisterFromCache() and SetRegisterInCache() to respectively get and update individual register values inside the cache. The implementation of both methods can assume that ReadRegisterSet() has been called to fill the cache, and must not call either ReadRegisterSet() or WriteRegisterSet(). Optionally, the classes can also override: - FlushRegisterSet() method to control how register sets are flushed, in particular handling overlapping regsets. The NativeRegisterContextRegisterInfo class maintains state map of cache for individual regsets, and issues appropriate ReadRegisterSet() and WriteRegisterSet() calls to maintain it. It includes a FlushRegisterSets() method that needs to be called whenever the thread is about to resume execution. https://reviews.llvm.org/D89335 Files: lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h lldb/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.cpp lldb/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h
Index: lldb/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h =================================================================== --- lldb/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h +++ lldb/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h @@ -9,11 +9,21 @@ #ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_NATIVEREGISTERCONTEXTREGISTERINFO_H #define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_NATIVEREGISTERCONTEXTREGISTERINFO_H +#include <cstdint> +#include <map> #include <memory> #include "RegisterInfoInterface.h" #include "lldb/Host/common/NativeRegisterContext.h" +enum class RegSetCacheStatus { + Empty, + Read, + Written, +}; + +#define LLDB_INVALID_REGSET UINT32_MAX + namespace lldb_private { class NativeRegisterContextRegisterInfo : public NativeRegisterContext { public: @@ -33,8 +43,50 @@ const RegisterInfoInterface &GetRegisterInfoInterface() const; + Status ReadRegister(const RegisterInfo *reg_info, + RegisterValue ®_value) override; + + Status WriteRegister(const RegisterInfo *reg_info, + const RegisterValue ®_value) override; + + Status FlushRegisterSets(); + protected: std::unique_ptr<RegisterInfoInterface> m_register_info_interface_up; + + // APIs used to implement cached register access, they need to be defined + // only if ReadRegister() and WriteRegister() are not overriden + + virtual uint32_t GetRegisterSetForRegNum(uint32_t reg_index) const { + return LLDB_INVALID_REGSET; + } + + virtual Status ReadRegisterSet(uint32_t set) { + return Status("not implemented"); + } + + virtual Status WriteRegisterSet(uint32_t set) { + return Status("not implemented"); + } + + virtual Status GetRegisterFromCache(const RegisterInfo *reg_info, + RegisterValue ®_value, uint32_t set) { + return Status("not implemented"); + } + + virtual Status SetRegisterInCache(const RegisterInfo *reg_info, + const RegisterValue ®_value, + uint32_t set) { + return Status("not implemented"); + } + + virtual Status FlushRegisterSet(uint32_t set); + + // --------------------------------------------------------------------------- + +private: + std::map<int, RegSetCacheStatus> m_regset_cache_status; }; -} + +} // namespace lldb_private #endif Index: lldb/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.cpp =================================================================== --- lldb/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.cpp +++ lldb/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.cpp @@ -40,3 +40,98 @@ NativeRegisterContextRegisterInfo::GetRegisterInfoInterface() const { return *m_register_info_interface_up; } + +Status +NativeRegisterContextRegisterInfo::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 NativeRegisterContextRegisterInfo::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 NativeRegisterContextRegisterInfo::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 NativeRegisterContextRegisterInfo::FlushRegisterSet(uint32_t set) { + m_regset_cache_status[set] = RegSetCacheStatus::Empty; + return Status(); +} 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 @@ -39,12 +39,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; @@ -76,6 +70,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, FPRegSet, XStateRegSet, DBRegSet }; @@ -92,11 +99,7 @@ struct xstate m_xstate; #endif - 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 @@ -263,7 +263,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; } @@ -395,8 +395,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) @@ -406,9 +406,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; @@ -420,9 +420,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; @@ -484,33 +484,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: @@ -522,10 +503,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: @@ -771,34 +748,16 @@ return error; } -Status NativeRegisterContextNetBSD_x86_64::WriteRegister( - const RegisterInfo *reg_info, const RegisterValue ®_value) { - - Status error; +Status NativeRegisterContextNetBSD_x86_64::SetRegisterInCache( + const RegisterInfo *reg_info, + const 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: @@ -810,10 +769,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: @@ -1057,7 +1012,7 @@ llvm_unreachable("Reading unknown/unsupported register"); } - return WriteRegisterSet(set); + return Status(); } Status NativeRegisterContextNetBSD_x86_64::ReadAllRegisterValues(
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits