diff options
author | Francis Ricci <francisjricci@gmail.com> | 2017-04-19 14:00:42 +0000 |
---|---|---|
committer | Francis Ricci <francisjricci@gmail.com> | 2017-04-19 14:00:42 +0000 |
commit | 02099e22a3330b4ce41d236b6c6af5dd6f70ffa9 (patch) | |
tree | d891504162519367b46eb4a0100f790bc015de22 /lib/sanitizer_common/sanitizer_stoptheworld_mac.cc | |
parent | 57da2deeb0e6cf80adb9d45218918c88966c01f7 (diff) | |
download | compiler-rt-02099e22a3330b4ce41d236b6c6af5dd6f70ffa9.tar.gz |
Implement function to get registers from suspended thread on darwin
Reviewers: kubamracek, alekseyshl
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D32182
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@300691 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/sanitizer_common/sanitizer_stoptheworld_mac.cc')
-rw-r--r-- | lib/sanitizer_common/sanitizer_stoptheworld_mac.cc | 45 |
1 files changed, 43 insertions, 2 deletions
diff --git a/lib/sanitizer_common/sanitizer_stoptheworld_mac.cc b/lib/sanitizer_common/sanitizer_stoptheworld_mac.cc index ab33ba641..281db96f6 100644 --- a/lib/sanitizer_common/sanitizer_stoptheworld_mac.cc +++ b/lib/sanitizer_common/sanitizer_stoptheworld_mac.cc @@ -48,6 +48,29 @@ void StopTheWorld(StopTheWorldCallback callback, void *argument) { CHECK(0 && "unimplemented"); } +#if defined(__x86_64__) +typedef x86_thread_state64_t regs_struct; + +#define SP_REG __rsp + +#elif defined(__aarch64__) +typedef arm_thread_state64_t regs_struct; + +# if __DARWIN_UNIX03 +# define SP_REG __sp +# else +# define SP_REG sp +# endif + +#elif defined(__i386) +typedef x86_thread_state32_t regs_struct; + +#define SP_REG __esp + +#else +#error "Unsupported architecture" +#endif + tid_t SuspendedThreadsListMac::GetThreadID(uptr index) const { CHECK_LT(index, threads_.size()); return threads_[index].tid; @@ -83,8 +106,26 @@ void SuspendedThreadsListMac::Append(thread_t thread) { PtraceRegistersStatus SuspendedThreadsListMac::GetRegistersAndSP( uptr index, uptr *buffer, uptr *sp) const { - CHECK(0 && "unimplemented"); - return REGISTERS_UNAVAILABLE_FATAL; + thread_t thread = GetThread(index); + regs_struct regs; + int err; + mach_msg_type_number_t reg_count = MACHINE_THREAD_STATE_COUNT; + err = thread_get_state(thread, MACHINE_THREAD_STATE, (thread_state_t)®s, + ®_count); + if (err != KERN_SUCCESS) { + VReport(1, "Error - unable to get registers for a thread\n"); + // KERN_INVALID_ARGUMENT indicates that either the flavor is invalid, + // or the thread does not exist. The other possible error case, + // MIG_ARRAY_TOO_LARGE, means that the state is too large, but it's + // still safe to proceed. + return err == KERN_INVALID_ARGUMENT ? REGISTERS_UNAVAILABLE_FATAL + : REGISTERS_UNAVAILABLE; + } + + internal_memcpy(buffer, ®s, sizeof(regs)); + *sp = regs.SP_REG; + + return REGISTERS_AVAILABLE; } uptr SuspendedThreadsListMac::RegisterCount() const { |