diff options
Diffstat (limited to 'lldb/tools/debugserver/source/MacOSX')
10 files changed, 222 insertions, 3 deletions
diff --git a/lldb/tools/debugserver/source/MacOSX/MachThread.cpp b/lldb/tools/debugserver/source/MacOSX/MachThread.cpp index c11d2c2ca82..f3a9d51c808 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachThread.cpp +++ b/lldb/tools/debugserver/source/MacOSX/MachThread.cpp @@ -617,6 +617,18 @@ MachThread::SetRegisterContext (const void *buf, nub_size_t buf_len) } uint32_t +MachThread::SaveRegisterState () +{ + return m_arch_ap->SaveRegisterState(); + +} +bool +MachThread::RestoreRegisterState (uint32_t save_id) +{ + return m_arch_ap->RestoreRegisterState(save_id); +} + +uint32_t MachThread::EnableHardwareBreakpoint (const DNBBreakpoint *bp) { if (bp != NULL && bp->IsBreakpoint()) diff --git a/lldb/tools/debugserver/source/MacOSX/MachThread.h b/lldb/tools/debugserver/source/MacOSX/MachThread.h index 7e16d49b78c..c3121112980 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachThread.h +++ b/lldb/tools/debugserver/source/MacOSX/MachThread.h @@ -92,6 +92,9 @@ public: bool SetRegisterValue ( uint32_t reg_set_idx, uint32_t reg_idx, const DNBRegisterValue *reg_value ); nub_size_t GetRegisterContext (void *buf, nub_size_t buf_len); nub_size_t SetRegisterContext (const void *buf, nub_size_t buf_len); + uint32_t SaveRegisterState (); + bool RestoreRegisterState (uint32_t save_id); + void NotifyBreakpointChanged (const DNBBreakpoint *bp) { } diff --git a/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp b/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp index b5ce58d3438..adad95f2f7c 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp +++ b/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp @@ -200,6 +200,25 @@ MachThreadList::SetRegisterContext (nub_thread_t tid, const void *buf, size_t bu return 0; } +uint32_t +MachThreadList::SaveRegisterState (nub_thread_t tid) +{ + MachThreadSP thread_sp (GetThreadByID (tid)); + if (thread_sp) + return thread_sp->SaveRegisterState (); + return 0; +} + +bool +MachThreadList::RestoreRegisterState (nub_thread_t tid, uint32_t save_id) +{ + MachThreadSP thread_sp (GetThreadByID (tid)); + if (thread_sp) + return thread_sp->RestoreRegisterState (save_id); + return 0; +} + + nub_size_t MachThreadList::NumThreads () const { diff --git a/lldb/tools/debugserver/source/MacOSX/MachThreadList.h b/lldb/tools/debugserver/source/MacOSX/MachThreadList.h index 85097314b02..46bccfee8de 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachThreadList.h +++ b/lldb/tools/debugserver/source/MacOSX/MachThreadList.h @@ -30,6 +30,8 @@ public: bool SetRegisterValue (nub_thread_t tid, uint32_t reg_set_idx, uint32_t reg_idx, const DNBRegisterValue *reg_value) const; nub_size_t GetRegisterContext (nub_thread_t tid, void *buf, size_t buf_len); nub_size_t SetRegisterContext (nub_thread_t tid, const void *buf, size_t buf_len); + uint32_t SaveRegisterState (nub_thread_t tid); + bool RestoreRegisterState (nub_thread_t tid, uint32_t save_id); const char * GetThreadInfo (nub_thread_t tid) const; void ProcessWillResume (MachProcess *process, const DNBThreadResumeActions &thread_actions); uint32_t ProcessDidStop (MachProcess *process); diff --git a/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp b/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp index 75282c5966c..88073afee00 100644 --- a/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp +++ b/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp @@ -1805,5 +1805,57 @@ DNBArchMachARM::SetRegisterContext (const void *buf, nub_size_t buf_len) } +uint32_t +DNBArchMachARM::SaveRegisterState () +{ + kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber()); + DNBLogThreadedIf (LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u (SetGPRState() for stop_count = %u)", m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount()); + + // Always re-read the registers because above we call thread_abort_safely(); + bool force = true; + + if ((kret = GetGPRState(force)) != KERN_SUCCESS) + { + DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM::SaveRegisterState () error: GPR regs failed to read: %u ", kret); + } + else if ((kret = GetFPUState(force)) != KERN_SUCCESS) + { + DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM::SaveRegisterState () error: %s regs failed to read: %u", CPUHasAVX() ? "AVX" : "FPU", kret); + } + else + { + const uint32_t save_id = GetNextRegisterStateSaveID (); + m_saved_register_states[save_id] = m_state.context; + return save_id; + } + return UINT32_MAX; +} +bool +DNBArchMachARM::RestoreRegisterState (uint32_t save_id) +{ + SaveRegiterStates::iterator pos = m_saved_register_states.find(save_id); + if (pos != m_saved_register_states.end()) + { + m_state.context.gpr = pos->second.gpr; + m_state.context.vfp = pos->second.vfp; + kern_return_t kret; + bool success = true; + if ((kret = SetGPRState()) != KERN_SUCCESS) + { + DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM::RestoreRegisterState (save_id = %u) error: GPR regs failed to write: %u", save_id, kret); + success = false; + } + else if ((kret = SetFPUState()) != KERN_SUCCESS) + { + DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM::RestoreRegisterState (save_id = %u) error: %s regs failed to write: %u", save_id, CPUHasAVX() ? "AVX" : "FPU", kret); + success = false; + } + m_saved_register_states.erase(pos); + return success; + } + return false; +} + + #endif // #if defined (__arm__) diff --git a/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h b/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h index 7aeba6e9f18..4021fd5668e 100644 --- a/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h +++ b/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h @@ -18,6 +18,8 @@ #include "DNBArch.h" +#include <map> + class MachThread; class DNBArchMachARM : public DNBArchProtocol diff --git a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp index f76ec0da021..9c708f31359 100644 --- a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp +++ b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp @@ -515,6 +515,10 @@ DNBArchImplI386::GetEXCState(bool force) kern_return_t DNBArchImplI386::SetGPRState() { + kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber()); + DNBLogThreadedIf (LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u (SetGPRState() for stop_count = %u)", m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount()); + + m_state.SetError(e_regSetGPR, Write, ::thread_set_state(m_thread->MachPortNumber(), __i386_THREAD_STATE, (thread_state_t)&m_state.context.gpr, e_regSetWordSizeGPR)); return m_state.GetError(e_regSetGPR, Write); } @@ -1793,6 +1797,60 @@ DNBArchImplI386::SetRegisterContext (const void *buf, nub_size_t buf_len) } +uint32_t +DNBArchImplI386::SaveRegisterState () +{ + kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber()); + DNBLogThreadedIf (LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u (SetGPRState() for stop_count = %u)", m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount()); + + bool force = true; + + if ((kret = GetGPRState(force)) != KERN_SUCCESS) + { + DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::SaveRegisterState () error: GPR regs failed to read: %u ", kret); + } + else if ((kret = GetFPUState(force)) != KERN_SUCCESS) + { + DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::SaveRegisterState () error: %s regs failed to read: %u", CPUHasAVX() ? "AVX" : "FPU", kret); + } + else + { + const uint32_t save_id = GetNextRegisterStateSaveID (); + m_saved_register_states[save_id] = m_state.context; + return save_id; + } + return 0; +} +bool +DNBArchImplI386::RestoreRegisterState (uint32_t save_id) +{ + SaveRegiterStates::iterator pos = m_saved_register_states.find(save_id); + if (pos != m_saved_register_states.end()) + { + m_state.context.gpr = pos->second.gpr; + m_state.context.fpu = pos->second.fpu; + m_state.context.exc = pos->second.exc; + m_state.SetError(e_regSetGPR, Read, 0); + m_state.SetError(e_regSetFPU, Read, 0); + m_state.SetError(e_regSetEXC, Read, 0); + kern_return_t kret; + bool success = true; + if ((kret = SetGPRState()) != KERN_SUCCESS) + { + DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::RestoreRegisterState (save_id = %u) error: GPR regs failed to write: %u", save_id, kret); + success = false; + } + else if ((kret = SetFPUState()) != KERN_SUCCESS) + { + DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::RestoreRegisterState (save_id = %u) error: %s regs failed to write: %u", save_id, CPUHasAVX() ? "AVX" : "FPU", kret); + success = false; + } + m_saved_register_states.erase(pos); + return success; + } + return false; +} + kern_return_t DNBArchImplI386::GetRegisterState(int set, bool force) diff --git a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h index 6b526f35914..ae9ef4980fc 100644 --- a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h +++ b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h @@ -20,16 +20,20 @@ #include "../HasAVX.h" #include "MachRegisterStatesI386.h" +#include <map> + class MachThread; class DNBArchImplI386 : public DNBArchProtocol { public: DNBArchImplI386(MachThread *thread) : + DNBArchProtocol(), m_thread(thread), m_state(), m_2pc_dbg_checkpoint(), - m_2pc_trans_state(Trans_Done) + m_2pc_trans_state(Trans_Done), + m_saved_register_states() { } virtual ~DNBArchImplI386() @@ -42,6 +46,9 @@ public: virtual bool SetRegisterValue(int set, int reg, const DNBRegisterValue *value); virtual nub_size_t GetRegisterContext (void *buf, nub_size_t buf_len); virtual nub_size_t SetRegisterContext (const void *buf, nub_size_t buf_len); + virtual uint32_t SaveRegisterState (); + virtual bool RestoreRegisterState (uint32_t save_id); + virtual kern_return_t GetRegisterState (int set, bool force); virtual kern_return_t SetRegisterState (int set); virtual bool RegisterSetStateIsValid (int set) const; @@ -240,6 +247,8 @@ protected: State m_state; DBG m_2pc_dbg_checkpoint; uint32_t m_2pc_trans_state; // Is transaction of DBG state change: Pedning (0), Done (1), or Rolled Back (2)? + typedef std::map<uint32_t, Context> SaveRegiterStates; + SaveRegiterStates m_saved_register_states; }; #endif // #if defined (__i386__) || defined (__x86_64__) diff --git a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp index 20e91961b47..0ceabc56547 100644 --- a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp +++ b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp @@ -447,7 +447,7 @@ kern_return_t DNBArchImplX86_64::SetGPRState() { kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber()); - DNBLogThreadedIf (LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u (SetGPRState() for stop_count = %u)", m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount()); + DNBLogThreadedIf (LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u (SetGPRState() for stop_count = %u)", m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount()); m_state.SetError(e_regSetGPR, Write, ::thread_set_state(m_thread->MachPortNumber(), __x86_64_THREAD_STATE, (thread_state_t)&m_state.context.gpr, e_regSetWordSizeGPR)); DNBLogThreadedIf (LOG_THREAD, "::thread_set_state (0x%4.4x, %u, &gpr, %u) => 0x%8.8x" @@ -2189,6 +2189,59 @@ DNBArchImplX86_64::SetRegisterContext (const void *buf, nub_size_t buf_len) return size; } +uint32_t +DNBArchImplX86_64::SaveRegisterState () +{ + kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber()); + DNBLogThreadedIf (LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u (SetGPRState() for stop_count = %u)", m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount()); + + // Always re-read the registers because above we call thread_abort_safely(); + bool force = true; + + if ((kret = GetGPRState(force)) != KERN_SUCCESS) + { + DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::SaveRegisterState () error: GPR regs failed to read: %u ", kret); + } + else if ((kret = GetFPUState(force)) != KERN_SUCCESS) + { + DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::SaveRegisterState () error: %s regs failed to read: %u", CPUHasAVX() ? "AVX" : "FPU", kret); + } + else + { + const uint32_t save_id = GetNextRegisterStateSaveID (); + m_saved_register_states[save_id] = m_state.context; + return save_id; + } + return 0; +} +bool +DNBArchImplX86_64::RestoreRegisterState (uint32_t save_id) +{ + SaveRegiterStates::iterator pos = m_saved_register_states.find(save_id); + if (pos != m_saved_register_states.end()) + { + m_state.context.gpr = pos->second.gpr; + m_state.context.fpu = pos->second.fpu; + m_state.SetError(e_regSetGPR, Read, 0); + m_state.SetError(e_regSetFPU, Read, 0); + kern_return_t kret; + bool success = true; + if ((kret = SetGPRState()) != KERN_SUCCESS) + { + DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::RestoreRegisterState (save_id = %u) error: GPR regs failed to write: %u", save_id, kret); + success = false; + } + else if ((kret = SetFPUState()) != KERN_SUCCESS) + { + DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::RestoreRegisterState (save_id = %u) error: %s regs failed to write: %u", save_id, CPUHasAVX() ? "AVX" : "FPU", kret); + success = false; + } + m_saved_register_states.erase(pos); + return success; + } + return false; +} + kern_return_t DNBArchImplX86_64::GetRegisterState(int set, bool force) diff --git a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h index 895bfa97491..4302c6b319d 100644 --- a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h +++ b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h @@ -19,16 +19,20 @@ #include "../HasAVX.h" #include "MachRegisterStatesX86_64.h" +#include <map> + class MachThread; class DNBArchImplX86_64 : public DNBArchProtocol { public: DNBArchImplX86_64(MachThread *thread) : + DNBArchProtocol(), m_thread(thread), m_state(), m_2pc_dbg_checkpoint(), - m_2pc_trans_state(Trans_Done) + m_2pc_trans_state(Trans_Done), + m_saved_register_states() { } virtual ~DNBArchImplX86_64() @@ -36,10 +40,13 @@ public: } static void Initialize(); + virtual bool GetRegisterValue(int set, int reg, DNBRegisterValue *value); virtual bool SetRegisterValue(int set, int reg, const DNBRegisterValue *value); virtual nub_size_t GetRegisterContext (void *buf, nub_size_t buf_len); virtual nub_size_t SetRegisterContext (const void *buf, nub_size_t buf_len); + virtual uint32_t SaveRegisterState (); + virtual bool RestoreRegisterState (uint32_t save_id); virtual kern_return_t GetRegisterState (int set, bool force); virtual kern_return_t SetRegisterState (int set); @@ -246,6 +253,8 @@ protected: State m_state; DBG m_2pc_dbg_checkpoint; uint32_t m_2pc_trans_state; // Is transaction of DBG state change: Pedning (0), Done (1), or Rolled Back (2)? + typedef std::map<uint32_t, Context> SaveRegiterStates; + SaveRegiterStates m_saved_register_states; }; #endif // #if defined (__i386__) || defined (__x86_64__) |

