From b2aa984743cb568f8e6a634a1536bf65950167db Mon Sep 17 00:00:00 2001 From: Charles Davis Date: Thu, 4 Jun 2015 16:52:27 -0600 Subject: [PATCH] server: Get debug registers on 64-bit Mac OS. --- server/mach.c | 129 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 90 insertions(+), 39 deletions(-) diff --git a/server/mach.c b/server/mach.c index be844578359..2ef6e59c583 100644 --- a/server/mach.c +++ b/server/mach.c @@ -151,8 +151,8 @@ void finish_process_tracing( struct process *process ) /* retrieve the thread x86 registers */ void get_thread_context( struct thread *thread, context_t *context, unsigned int flags ) { -#ifdef __i386__ - x86_debug_state32_t state; +#if defined(__i386__) || defined(__x86_64__) + x86_debug_state_t state; mach_msg_type_number_t count = sizeof(state) / sizeof(int); mach_msg_type_name_t type; mach_port_t port, process_port = get_process_port( thread->process ); @@ -168,24 +168,45 @@ void get_thread_context( struct thread *thread, context_t *context, unsigned int return; } - if (!thread_get_state( port, x86_DEBUG_STATE32, (thread_state_t)&state, &count )) + if (!thread_get_state( port, x86_DEBUG_STATE, (thread_state_t)&state, &count )) { +#ifdef __x86_64__ + assert( state.dsh.flavor == x86_DEBUG_STATE32 || + state.dsh.flavor == x86_DEBUG_STATE64 ); +#else + assert( state.dsh.flavor == x86_DEBUG_STATE32 ); +#endif + +#ifdef __x86_64__ + if (state.dsh.flavor == x86_DEBUG_STATE64) + { + context->debug.x86_64_regs.dr0 = state.uds.ds64.__dr0; + context->debug.x86_64_regs.dr1 = state.uds.ds64.__dr1; + context->debug.x86_64_regs.dr2 = state.uds.ds64.__dr2; + context->debug.x86_64_regs.dr3 = state.uds.ds64.__dr3; + context->debug.x86_64_regs.dr6 = state.uds.ds64.__dr6; + context->debug.x86_64_regs.dr7 = state.uds.ds64.__dr7; + } + else +#endif + { /* work around silly renaming of struct members in OS X 10.5 */ #if __DARWIN_UNIX03 && defined(_STRUCT_X86_DEBUG_STATE32) - context->debug.i386_regs.dr0 = state.__dr0; - context->debug.i386_regs.dr1 = state.__dr1; - context->debug.i386_regs.dr2 = state.__dr2; - context->debug.i386_regs.dr3 = state.__dr3; - context->debug.i386_regs.dr6 = state.__dr6; - context->debug.i386_regs.dr7 = state.__dr7; + context->debug.i386_regs.dr0 = state.uds.ds32.__dr0; + context->debug.i386_regs.dr1 = state.uds.ds32.__dr1; + context->debug.i386_regs.dr2 = state.uds.ds32.__dr2; + context->debug.i386_regs.dr3 = state.uds.ds32.__dr3; + context->debug.i386_regs.dr6 = state.uds.ds32.__dr6; + context->debug.i386_regs.dr7 = state.uds.ds32.__dr7; #else - context->debug.i386_regs.dr0 = state.dr0; - context->debug.i386_regs.dr1 = state.dr1; - context->debug.i386_regs.dr2 = state.dr2; - context->debug.i386_regs.dr3 = state.dr3; - context->debug.i386_regs.dr6 = state.dr6; - context->debug.i386_regs.dr7 = state.dr7; + context->debug.i386_regs.dr0 = state.uds.ds32.dr0; + context->debug.i386_regs.dr1 = state.uds.ds32.dr1; + context->debug.i386_regs.dr2 = state.uds.ds32.dr2; + context->debug.i386_regs.dr3 = state.uds.ds32.dr3; + context->debug.i386_regs.dr6 = state.uds.ds32.dr6; + context->debug.i386_regs.dr7 = state.uds.ds32.dr7; #endif + } context->flags |= SERVER_CTX_DEBUG_REGISTERS; } mach_port_deallocate( mach_task_self(), port ); @@ -195,8 +216,8 @@ void get_thread_context( struct thread *thread, context_t *context, unsigned int /* set the thread x86 registers */ void set_thread_context( struct thread *thread, const context_t *context, unsigned int flags ) { -#ifdef __i386__ - x86_debug_state32_t state; +#if defined(__i386__) || defined(__x86_64__) + x86_debug_state_t state; mach_msg_type_number_t count = sizeof(state) / sizeof(int); mach_msg_type_name_t type; mach_port_t port, process_port = get_process_port( thread->process ); @@ -213,32 +234,62 @@ void set_thread_context( struct thread *thread, const context_t *context, unsign return; } - /* Mac OS doesn't allow setting the global breakpoint flags */ - dr7 = (context->debug.i386_regs.dr7 & ~0xaa) | ((context->debug.i386_regs.dr7 & 0xaa) >> 1); -#if __DARWIN_UNIX03 && defined(_STRUCT_X86_DEBUG_STATE32) - state.__dr0 = context->debug.i386_regs.dr0; - state.__dr1 = context->debug.i386_regs.dr1; - state.__dr2 = context->debug.i386_regs.dr2; - state.__dr3 = context->debug.i386_regs.dr3; - state.__dr4 = 0; - state.__dr5 = 0; - state.__dr6 = context->debug.i386_regs.dr6; - state.__dr7 = dr7; -#else - state.dr0 = context->debug.i386_regs.dr0; - state.dr1 = context->debug.i386_regs.dr1; - state.dr2 = context->debug.i386_regs.dr2; - state.dr3 = context->debug.i386_regs.dr3; - state.dr4 = 0; - state.dr5 = 0; - state.dr6 = context->debug.i386_regs.dr6; - state.dr7 = dr7; +#ifdef __x86_64__ + if (thread->process->cpu == CPU_x86_64) + { + /* Mac OS doesn't allow setting the global breakpoint flags */ + dr7 = (context->debug.x86_64_regs.dr7 & ~0xaa) | ((context->debug.x86_64_regs.dr7 & 0xaa) >> 1); + + state.dsh.flavor = x86_DEBUG_STATE64; + state.dsh.count = sizeof(state.uds.ds64) / sizeof(int); + state.uds.ds64.__dr0 = context->debug.x86_64_regs.dr0; + state.uds.ds64.__dr1 = context->debug.x86_64_regs.dr1; + state.uds.ds64.__dr2 = context->debug.x86_64_regs.dr2; + state.uds.ds64.__dr3 = context->debug.x86_64_regs.dr3; + state.uds.ds64.__dr4 = 0; + state.uds.ds64.__dr5 = 0; + state.uds.ds64.__dr6 = context->debug.x86_64_regs.dr6; + state.uds.ds64.__dr7 = dr7; + } + else #endif - if (!thread_set_state( port, x86_DEBUG_STATE32, (thread_state_t)&state, count )) + { + dr7 = (context->debug.i386_regs.dr7 & ~0xaa) | ((context->debug.i386_regs.dr7 & 0xaa) >> 1); + + state.dsh.flavor = x86_DEBUG_STATE32; + state.dsh.count = sizeof(state.uds.ds32) / sizeof(int); +#if __DARWIN_UNIX03 && defined(_STRUCT_X86_DEBUG_STATE32) + state.uds.ds32.__dr0 = context->debug.i386_regs.dr0; + state.uds.ds32.__dr1 = context->debug.i386_regs.dr1; + state.uds.ds32.__dr2 = context->debug.i386_regs.dr2; + state.uds.ds32.__dr3 = context->debug.i386_regs.dr3; + state.uds.ds32.__dr4 = 0; + state.uds.ds32.__dr5 = 0; + state.uds.ds32.__dr6 = context->debug.i386_regs.dr6; + state.uds.ds32.__dr7 = dr7; +#else + state.uds.ds32.dr0 = context->debug.i386_regs.dr0; + state.uds.ds32.dr1 = context->debug.i386_regs.dr1; + state.uds.ds32.dr2 = context->debug.i386_regs.dr2; + state.uds.ds32.dr3 = context->debug.i386_regs.dr3; + state.uds.ds32.dr4 = 0; + state.uds.ds32.dr5 = 0; + state.uds.ds32.dr6 = context->debug.i386_regs.dr6; + state.uds.ds32.dr7 = dr7; +#endif + } + if (!thread_set_state( port, x86_DEBUG_STATE, (thread_state_t)&state, count )) { if (thread->context) /* update the cached values */ - thread->context->debug.i386_regs = context->debug.i386_regs; + { +#ifdef __x86_64__ + if (thread->process->cpu == CPU_x86_64) + thread->context->debug.x86_64_regs = context->debug.x86_64_regs; + else +#endif + thread->context->debug.i386_regs = context->debug.i386_regs; + } } mach_port_deallocate( mach_task_self(), port ); #endif