bool GetThreadBacktraceContext( uint64_t iID, BacktraceContext *ctx ) { /* Can't GetThreadBacktraceContext the current thread. */ ASSERT( iID != GetCurrentThreadId() ); SuspendThread( iID ); thread_act_t thread = thread_act_t( iID ); #if defined(__ppc__) ppc_thread_state_t state; mach_msg_type_number_t count = PPC_THREAD_STATE_COUNT; if( thread_get_state(thread, PPC_THREAD_STATE, thread_state_t(&state), &count) ) return false; ctx->FramePtr = (const Frame *)state.__r1; ctx->PC = (void *)state.__srr0; return true; #elif defined(__i386__) i386_thread_state_t state; mach_msg_type_number_t count = i386_THREAD_STATE_COUNT; if( thread_get_state(thread, i386_THREAD_STATE, thread_state_t(&state), &count) ) return false; ctx->ip = (void *)state.__eip; ctx->bp = (void *)state.__ebp; ctx->sp = (void *)state.__esp; return true; #else return false; #endif }
//exc_server uses dlsym to find symbol DLLEXPORT kern_return_t catch_exception_raise(mach_port_t exception_port, mach_port_t thread, mach_port_t task, exception_type_t exception, exception_data_t code, mach_msg_type_number_t code_count) { unsigned int count = MACHINE_THREAD_STATE_COUNT; unsigned int exc_count = X86_EXCEPTION_STATE64_COUNT; x86_exception_state64_t exc_state; x86_thread_state64_t state; #ifdef LIBOSXUNWIND if (thread == mach_profiler_thread) { return profiler_segv_handler(exception_port, thread, task, exception, code, code_count); } #endif kern_return_t ret = thread_get_state(thread, x86_EXCEPTION_STATE64, (thread_state_t)&exc_state, &exc_count); HANDLE_MACH_ERROR("thread_get_state", ret); uint64_t fault_addr = exc_state.__faultvaddr; #ifdef SEGV_EXCEPTION if (1) { #else if (msync((void*)(fault_addr & ~(jl_page_size - 1)), 1, MS_ASYNC) == 0) { // check if this was a valid address #endif jl_value_t *excpt; if (is_addr_on_stack((void*)fault_addr)) { excpt = jl_stackovf_exception; } #ifdef SEGV_EXCEPTION else if (msync((void*)(fault_addr & ~(jl_page_size - 1)), 1, MS_ASYNC) != 0) { // no page mapped at this address excpt = jl_segv_exception; } #endif else { if (!(exc_state.__err & WRITE_FAULT)) return KERN_INVALID_ARGUMENT; // rethrow the SEGV since it wasn't an error with writing to read-only memory excpt = jl_readonlymemory_exception; } jl_throw_in_thread(0, thread, excpt); return KERN_SUCCESS; } else { kern_return_t ret = thread_get_state(thread, x86_THREAD_STATE64, (thread_state_t)&state, &count); HANDLE_MACH_ERROR("thread_get_state", ret); jl_critical_error(SIGSEGV, (unw_context_t*)&state, jl_bt_data, &jl_bt_size); return KERN_INVALID_ARGUMENT; } } void attach_exception_port() { kern_return_t ret; // http://www.opensource.apple.com/source/xnu/xnu-2782.1.97/osfmk/man/thread_set_exception_ports.html ret = thread_set_exception_ports(mach_thread_self(), EXC_MASK_BAD_ACCESS, segv_port, EXCEPTION_DEFAULT, MACHINE_THREAD_STATE); HANDLE_MACH_ERROR("thread_set_exception_ports", ret); }
//exc_server uses dlsym to find symbol DLLEXPORT kern_return_t catch_exception_raise (mach_port_t exception_port, mach_port_t thread, mach_port_t task, exception_type_t exception, exception_data_t code, mach_msg_type_number_t code_count) { unsigned int count = MACHINE_THREAD_STATE_COUNT; unsigned int exc_count = X86_EXCEPTION_STATE64_COUNT; x86_thread_state64_t state, old_state; x86_exception_state64_t exc_state; kern_return_t ret; //memset(&state,0,sizeof(x86_thread_state64_t)); //memset(&exc_state,0,sizeof(x86_exception_state64_t)); ret = thread_get_state(thread,x86_EXCEPTION_STATE64,(thread_state_t)&exc_state,&exc_count); uint64_t fault_addr = exc_state.__faultvaddr; if ( #ifdef COPY_STACKS (char*)fault_addr > (char*)jl_stack_lo-3000000 && (char*)fault_addr < (char*)jl_stack_hi #else (char*)fault_addr > (char*)jl_current_task->stack-8192 && (char*)fault_addr < (char*)jl_current_task->stack+jl_current_task->ssize #endif ) { ret = thread_get_state(thread,x86_THREAD_STATE64,(thread_state_t)&state,&count); HANDLE_MACH_ERROR("thread_get_state",ret); old_state = state; // memset(&state,0,sizeof(x86_thread_state64_t)); // Setup libunwind information state.__rsp = (uint64_t)signal_stack + SIGSTKSZ; state.__rsp -= sizeof(unw_context_t); state.__rsp &= -16; unw_context_t *uc = (unw_context_t*)state.__rsp; state.__rsp -= 512; // This is for alignment. In particular note that the sizeof(void*) is necessary // since it would usually specify the return address (i.e. we are aligning the call // frame to a 16 byte boundary as required by the abi, but the stack pointer // to point to the byte beyond that. Not doing this leads to funny behavior on // the first access to an external function will fail due to stack misalignment state.__rsp &= -16; state.__rsp -= sizeof(void*); memset(uc,0,sizeof(unw_context_t)); memcpy(uc,&old_state,sizeof(x86_thread_state64_t)); state.__rdi = (uint64_t)uc; state.__rip = (uint64_t)darwin_stack_overflow_handler; state.__rbp = state.__rsp; ret = thread_set_state(thread,x86_THREAD_STATE64,(thread_state_t)&state,count); HANDLE_MACH_ERROR("thread_set_state",ret); return KERN_SUCCESS; } else { return -309; } }
uint64_t get_current_pc (thread_t thread, int *wordsize) { kern_return_t kr ; #if defined (__x86_64__) || defined (__i386__) x86_thread_state_t gp_regs; mach_msg_type_number_t gp_count = x86_THREAD_STATE_COUNT; kr = thread_get_state (thread, x86_THREAD_STATE, (thread_state_t) &gp_regs, &gp_count); if (kr != KERN_SUCCESS) { printf ("Error - unable to get registers for a thread\n"); exit (1); } if (gp_regs.tsh.flavor == x86_THREAD_STATE64) { *wordsize = 8; return gp_regs.uts.ts64.__rip; } else { *wordsize = 4; return gp_regs.uts.ts32.__eip; } #endif #if defined (__arm__) arm_thread_state_t gp_regs; mach_msg_type_number_t gp_count = ARM_THREAD_STATE_COUNT; kr = thread_get_state (thread, ARM_THREAD_STATE, (thread_state_t) &gp_regs, &gp_count); if (kr != KERN_SUCCESS) { printf ("Error - unable to get registers for a thread\n"); exit (1); } *wordsize = 4; return gp_regs.__pc; #endif #if defined (__arm64__) arm_thread_state64_t gp_regs; mach_msg_type_number_t gp_count = ARM_THREAD_STATE64_COUNT; kr = thread_get_state (thread, ARM_THREAD_STATE64, (thread_state_t) &gp_regs, &gp_count); if (kr != KERN_SUCCESS) { printf ("Error - unable to get registers for a thread\n"); exit (1); } *wordsize = 8; return gp_regs.__pc; #endif }
/*++ Function: CONTEXT_GetThreadContextFromPort Helper for GetThreadContext that uses a mach_port --*/ kern_return_t CONTEXT_GetThreadContextFromPort( mach_port_t Port, LPCONTEXT lpContext) { // Extract the CONTEXT from the Mach thread. kern_return_t MachRet = KERN_SUCCESS; mach_msg_type_number_t StateCount; thread_state_flavor_t StateFlavor; if (lpContext->ContextFlags & (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS)) { #ifdef _X86_ x86_thread_state32_t State; StateFlavor = x86_THREAD_STATE32; #elif defined(_AMD64_) x86_thread_state64_t State; StateFlavor = x86_THREAD_STATE64; #else #error Unexpected architecture. #endif StateCount = sizeof(State) / sizeof(natural_t); MachRet = thread_get_state(Port, StateFlavor, (thread_state_t)&State, &StateCount); if (MachRet != KERN_SUCCESS) { ASSERT("thread_get_state(THREAD_STATE) failed: %d\n", MachRet); goto exit; } CONTEXT_GetThreadContextFromThreadState(StateFlavor, (thread_state_t)&State, lpContext); } if (lpContext->ContextFlags & CONTEXT_ALL_FLOATING) { #ifdef _X86_ x86_float_state32_t State; StateFlavor = x86_FLOAT_STATE32; #elif defined(_AMD64_) x86_float_state64_t State; StateFlavor = x86_FLOAT_STATE64; #else #error Unexpected architecture. #endif StateCount = sizeof(State) / sizeof(natural_t); MachRet = thread_get_state(Port, StateFlavor, (thread_state_t)&State, &StateCount); if (MachRet != KERN_SUCCESS) { ASSERT("thread_get_state(FLOAT_STATE) failed: %d\n", MachRet); goto exit; } CONTEXT_GetThreadContextFromThreadState(StateFlavor, (thread_state_t)&State, lpContext); } exit: return MachRet; }
// PLFrameWalker API plframe_error_t plframe_cursor_thread_init (plframe_cursor_t *cursor, thread_t thread, plcrash_async_image_list_t *image_list) { kern_return_t kr; ucontext_t *uap; /* Note: This code has been left untouched when implementing libunwind(3) usage, as 1) Apple's implementation of libunwind on x86_64 doesn't handle floating-point and vector registers, 2) libunwind's general API doesn't provide access to some of the other information retrieved here. */ /* Perform basic initialization */ uap = &cursor->_uap_data; uap->uc_mcontext = (void *) &cursor->_mcontext_data; /* Zero the signal mask */ sigemptyset(&uap->uc_sigmask); /* Fetch the thread states */ mach_msg_type_number_t state_count; /* Sanity check */ assert(sizeof(cursor->_mcontext_data.__ss) == sizeof(x86_thread_state64_t)); assert(sizeof(cursor->_mcontext_data.__es) == sizeof(x86_exception_state64_t)); assert(sizeof(cursor->_mcontext_data.__fs) == sizeof(x86_float_state64_t)); // thread state state_count = x86_THREAD_STATE64_COUNT; kr = thread_get_state(thread, x86_THREAD_STATE64, (thread_state_t) &cursor->_mcontext_data.__ss, &state_count); if (kr != KERN_SUCCESS) { PLCF_DEBUG("Fetch of x86-64 thread state failed with mach error: %d", kr); return PLFRAME_INTERNAL; } // floating point state state_count = x86_FLOAT_STATE64_COUNT; kr = thread_get_state(thread, x86_FLOAT_STATE64, (thread_state_t) &cursor->_mcontext_data.__fs, &state_count); if (kr != KERN_SUCCESS) { PLCF_DEBUG("Fetch of x86-64 float state failed with mach error: %d", kr); return PLFRAME_INTERNAL; } // exception state state_count = x86_EXCEPTION_STATE64_COUNT; kr = thread_get_state(thread, x86_EXCEPTION_STATE64, (thread_state_t) &cursor->_mcontext_data.__es, &state_count); if (kr != KERN_SUCCESS) { PLCF_DEBUG("Fetch of x86-64 exception state failed with mach error: %d", kr); return PLFRAME_INTERNAL; } /* Perform standard initialization and return result */ return plframe_cursor_init(cursor, uap, image_list); }
void fetch_inferior_registers (int regno) { thread_t current_thread = ptid_get_tid (inferior_ptid); if ((regno == -1) || PPC_MACOSX_IS_GP_REGNUM (regno) || PPC_MACOSX_IS_GSP_REGNUM (regno)) { gdb_ppc_thread_state_64_t gp_regs; unsigned int gp_count = GDB_PPC_THREAD_STATE_64_COUNT; kern_return_t ret = thread_get_state (current_thread, GDB_PPC_THREAD_STATE_64, (thread_state_t) & gp_regs, &gp_count); if (ret != KERN_SUCCESS) { printf ("Error calling thread_get_state for GP registers for thread 0x%ulx", current_thread); MACH_CHECK_ERROR (ret); } ppc_macosx_fetch_gp_registers_64 (&gp_regs); } if ((regno == -1) || PPC_MACOSX_IS_FP_REGNUM (regno) || PPC_MACOSX_IS_FSP_REGNUM (regno)) { gdb_ppc_thread_fpstate_t fp_regs; unsigned int fp_count = GDB_PPC_THREAD_FPSTATE_COUNT; kern_return_t ret = thread_get_state (current_thread, GDB_PPC_THREAD_FPSTATE, (thread_state_t) & fp_regs, &fp_count); if (ret != KERN_SUCCESS) { printf ("Error calling thread_get_state for FP registers for thread 0x%ulx", current_thread); MACH_CHECK_ERROR (ret); } ppc_macosx_fetch_fp_registers (&fp_regs); } if ((regno == -1) || PPC_MACOSX_IS_VP_REGNUM (regno) || PPC_MACOSX_IS_VSP_REGNUM (regno)) { gdb_ppc_thread_vpstate_t vp_regs; unsigned int vp_count = GDB_PPC_THREAD_VPSTATE_COUNT; kern_return_t ret = thread_get_state (current_thread, GDB_PPC_THREAD_VPSTATE, (thread_state_t) & vp_regs, &vp_count); if (ret != KERN_SUCCESS) { printf ("Error calling thread_get_state for Vector registers for thread 0x%ulx", current_thread); MACH_CHECK_ERROR (ret); } ppc_macosx_fetch_vp_registers (&vp_regs); } }
// If thread t is suspended, start it up again. // If singlestep is set, only let it execute one instruction. static int threadstart(Thread *t, int singlestep) { int i; uint n; struct thread_basic_info info; if(!threadstopped(t)) return 0; // Set or clear the processor single-step flag, as appropriate. if(mach == &mi386) { x86_thread_state32_t regs; n = x86_THREAD_STATE32_COUNT; if(me(thread_get_state(t->thread, x86_THREAD_STATE32, (thread_state_t)®s, &n)) < 0) return -1; if(singlestep) regs.eflags |= FLAGS_TF; else regs.eflags &= ~FLAGS_TF; if(me(thread_set_state(t->thread, x86_THREAD_STATE32, (thread_state_t)®s, x86_THREAD_STATE32_COUNT)) < 0) return -1; } else { x86_thread_state64_t regs; n = x86_THREAD_STATE64_COUNT; if(me(thread_get_state(t->thread, x86_THREAD_STATE64, (thread_state_t)®s, &n)) < 0) return -1; if(singlestep) regs.rflags |= FLAGS_TF; else regs.rflags &= ~FLAGS_TF; if(me(thread_set_state(t->thread, x86_THREAD_STATE64, (thread_state_t)®s, x86_THREAD_STATE64_COUNT)) < 0) return -1; } // Run. n = sizeof info; if(me(thread_info(t->thread, THREAD_BASIC_INFO, (thread_info_t)&info, &n)) < 0) return -1; for(i=0; i<info.suspend_count; i++) if(me(thread_resume(t->thread)) < 0) return -1; return 0; }
// FIXME: clean the compiler tests since we are passing thread_state_t int get_context(thread_act_t thread, thread_state_t *state) { //fprintf(stderr, "get_context %x: %x\n", thread, state->eip); #if __LP64__ mach_msg_type_number_t sc = x86_THREAD_STATE64_COUNT; thread_get_state(thread, x86_THREAD_STATE64, (thread_state_t)state, &sc); #else mach_msg_type_number_t sc = i386_THREAD_STATE_COUNT; thread_get_state(thread, i386_THREAD_STATE, (thread_state_t)state, &sc); #endif return 0; }
// http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/catch_exception_raise.html kern_return_t catch_exception_raise(mach_port_t exception_port, mach_port_t thread, mach_port_t task, enum exception_type exception, exception_data_t code, mach_msg_type_number_t code_count) { // get exception state mach_msg_type_number_t state_count = x86_EXCEPTION_STATE64_COUNT; x86_exception_state64_t exc_state; if (thread_get_state(thread, x86_EXCEPTION_STATE64, (thread_state_t)&exc_state, &state_count) != KERN_SUCCESS) { return KERN_FAILURE; } // get thread state state_count = x86_THREAD_STATE64_COUNT; x86_thread_state64_t thread_state; if (thread_get_state(thread, x86_THREAD_STATE64, (thread_state_t)&thread_state, &state_count) != KERN_SUCCESS) { return KERN_FAILURE; } // convert mach exception to internal exception struct exception ex; ex.type = exception == EXC_BAD_ACCESS ? EX_ACCESS_VIOLATION : EX_INVALID_INSTRUCTION; ex.fault_addr = exc_state.__faultvaddr; ex.pc = thread_state.__rip; copy_state_to(&thread_state, &ex.thread_state); // call exception handler, letting it potentially update the thread state bool handled = exception_handler_handle(&ex); if (!handled) { return KERN_FAILURE; } // copy internal thread state back to mach thread state and restore copy_state_from(&ex.thread_state, &thread_state); if (thread_set_state(thread, x86_THREAD_STATE64, (thread_state_t)&thread_state, state_count) != KERN_SUCCESS) { return KERN_FAILURE; } return KERN_SUCCESS; }
// PLFrameWalker API plframe_error_t plframe_cursor_thread_init (plframe_cursor_t *cursor, thread_t thread) { kern_return_t kr; ucontext_t *uap; /* Perform basic initialization */ uap = &cursor->_uap_data; uap->uc_mcontext = (void *) &cursor->_mcontext_data; /* Zero the signal mask */ sigemptyset(&uap->uc_sigmask); /* Fetch the thread states */ mach_msg_type_number_t state_count; /* Sanity check */ assert(sizeof(cursor->_mcontext_data.__ss) == sizeof(x86_thread_state64_t)); assert(sizeof(cursor->_mcontext_data.__es) == sizeof(x86_exception_state64_t)); assert(sizeof(cursor->_mcontext_data.__fs) == sizeof(x86_float_state64_t)); // thread state state_count = x86_THREAD_STATE64_COUNT; kr = thread_get_state(thread, x86_THREAD_STATE64, (thread_state_t) &cursor->_mcontext_data.__ss, &state_count); if (kr != KERN_SUCCESS) { PLCF_DEBUG("Fetch of x86-64 thread state failed with mach error: %d", kr); return PLFRAME_INTERNAL; } // floating point state state_count = x86_FLOAT_STATE64_COUNT; kr = thread_get_state(thread, x86_FLOAT_STATE64, (thread_state_t) &cursor->_mcontext_data.__fs, &state_count); if (kr != KERN_SUCCESS) { PLCF_DEBUG("Fetch of x86-64 float state failed with mach error: %d", kr); return PLFRAME_INTERNAL; } // exception state state_count = x86_EXCEPTION_STATE64_COUNT; kr = thread_get_state(thread, x86_EXCEPTION_STATE64, (thread_state_t) &cursor->_mcontext_data.__es, &state_count); if (kr != KERN_SUCCESS) { PLCF_DEBUG("Fetch of x86-64 exception state failed with mach error: %d", kr); return PLFRAME_INTERNAL; } /* Perform standard initialization */ plframe_cursor_init(cursor, uap); return PLFRAME_ESUCCESS; }
/* * Set up the initial state of a MACH thread */ void _pthread_setup(pthread_t thread, void (*routine)(pthread_t), vm_address_t vsp) { struct i386_thread_state state; struct i386_thread_state *ts = &state; kern_return_t r; unsigned int count; int *sp = (int *) vsp; /* * Set up i386 registers & function call. */ count = i386_THREAD_STATE_COUNT; MACH_CALL(thread_get_state(thread->kernel_thread, i386_THREAD_STATE, (thread_state_t) &state, &count), r); ts->eip = (int) routine; *--sp = (int) thread; /* argument to function */ *--sp = 0; /* fake return address */ ts->uesp = (int) sp; /* set stack pointer */ ts->ebp = 0; /* clear frame pointer */ MACH_CALL(thread_set_state(thread->kernel_thread, i386_THREAD_STATE, (thread_state_t) &state, i386_THREAD_STATE_COUNT), r); }
/* Get the whole floating-point state of THREAD and record the values of the corresponding (pseudo) registers. */ static void fetch_fpregs (struct proc *thread) { mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT; struct i386_float_state state; error_t err; err = thread_get_state (thread->port, i386_FLOAT_STATE, (thread_state_t) &state, &count); if (err) { warning ("Couldn't fetch floating-point state from %s", proc_string (thread)); return; } if (!state.initialized) /* The floating-point state isn't initialized. */ { int i; for (i = FP0_REGNUM; i <= FOP_REGNUM; i++) supply_register (i, NULL); return; } /* Supply the floating-point registers. */ i387_supply_fsave (current_regcache, -1, state.hw_state); }
void jl_throw_in_thread(int tid, mach_port_t thread, jl_value_t *exception) { unsigned int count = MACHINE_THREAD_STATE_COUNT; x86_thread_state64_t state; kern_return_t ret = thread_get_state(thread, x86_THREAD_STATE64, (thread_state_t)&state, &count); HANDLE_MACH_ERROR("thread_get_state", ret); jl_all_task_states[tid].ptls->bt_size = rec_backtrace_ctx(jl_all_task_states[tid].ptls->bt_data, JL_MAX_BT_SIZE, (bt_context_t)&state); jl_all_task_states[tid].ptls->exception_in_transit = exception; uint64_t rsp = (uint64_t)jl_all_task_states[tid].signal_stack + sig_stack_size; rsp &= -16; // ensure 16-byte alignment // push (null) $RIP onto the stack rsp -= sizeof(void*); *(void**)rsp = NULL; state.__rsp = rsp; // set stack pointer state.__rip = (uint64_t)&jl_rethrow; // "call" the function ret = thread_set_state(thread, x86_THREAD_STATE64, (thread_state_t)&state, count); HANDLE_MACH_ERROR("thread_set_state",ret); }
/* Store the whole floating-point state into THREAD using information from the corresponding (pseudo) registers. */ static void store_fpregs (const struct regcache *regcache, struct proc *thread, int regno) { mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT; struct i386_float_state state; error_t err; err = thread_get_state (thread->port, i386_FLOAT_STATE, (thread_state_t) &state, &count); if (err) { warning (_("Couldn't fetch floating-point state from %s"), proc_string (thread)); return; } /* FIXME: kettenis/2001-07-15: Is this right? Should we somehow take into account DEPRECATED_REGISTER_VALID like the old code did? */ i387_collect_fsave (regcache, regno, state.hw_state); err = thread_set_state (thread->port, i386_FLOAT_STATE, (thread_state_t) &state, i386_FLOAT_STATE_COUNT); if (err) { warning (_("Couldn't store floating-point state into %s"), proc_string (thread)); return; } }
static void fetch_fpregs (struct regcache *regcache, struct proc *thread) { mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT; struct i386_float_state state; error_t err; err = thread_get_state (thread->port, i386_FLOAT_STATE, (thread_state_t) &state, &count); if (err) { warning (_("Couldn't fetch floating-point state from %s"), proc_string (thread)); return; } if (!state.initialized) { /* The floating-point state isn't initialized. */ i387_supply_fsave (regcache, -1, NULL); } else { /* Supply the floating-point registers. */ i387_supply_fsave (regcache, -1, state.hw_state); } }
void darwin_check_osabi (darwin_inferior *inf, thread_t thread) { if (gdbarch_osabi (target_gdbarch) == GDB_OSABI_UNKNOWN) { /* Attaching to a process. Let's figure out what kind it is. */ x86_thread_state_t gp_regs; struct gdbarch_info info; unsigned int gp_count = x86_THREAD_STATE_COUNT; kern_return_t ret; ret = thread_get_state (thread, x86_THREAD_STATE, (thread_state_t) &gp_regs, &gp_count); if (ret != KERN_SUCCESS) { MACH_CHECK_ERROR (ret); return; } gdbarch_info_init (&info); gdbarch_info_fill (&info); info.byte_order = gdbarch_byte_order (target_gdbarch); info.osabi = GDB_OSABI_DARWIN; if (gp_regs.tsh.flavor == x86_THREAD_STATE64) info.bfd_arch_info = bfd_lookup_arch (bfd_arch_i386, bfd_mach_x86_64); else info.bfd_arch_info = bfd_lookup_arch (bfd_arch_i386, bfd_mach_i386_i386); gdbarch_update_p (info); } }
gboolean gum_process_modify_thread (GumThreadId thread_id, GumModifyThreadFunc func, gpointer user_data) { gboolean success = FALSE; mach_port_t task; thread_act_array_t threads; mach_msg_type_number_t count; kern_return_t kr; task = mach_task_self (); kr = task_threads (task, &threads, &count); if (kr == KERN_SUCCESS) { guint i; for (i = 0; i != count; i++) { thread_t thread = threads[i]; if (thread == thread_id) { gum_thread_state_t state; mach_msg_type_number_t state_count = GUM_THREAD_STATE_COUNT; thread_state_flavor_t state_flavor = GUM_THREAD_STATE_FLAVOR; GumCpuContext cpu_context; kr = thread_suspend (thread); if (kr != KERN_SUCCESS) break; kr = thread_get_state (thread, state_flavor, (thread_state_t) &state, &state_count); if (kr != KERN_SUCCESS) { thread_resume (thread); break; } gum_cpu_context_from_darwin (&state, &cpu_context); func (thread_id, &cpu_context, user_data); gum_cpu_context_to_darwin (&cpu_context, &state); kr = thread_set_state (thread, state_flavor, (thread_state_t) &state, state_count); success = (thread_resume (thread) == KERN_SUCCESS && kr == KERN_SUCCESS); } } for (i = 0; i != count; i++) mach_port_deallocate (task, threads[i]); vm_deallocate (task, (vm_address_t) threads, count * sizeof (thread_t)); } return success; }
bool ZGGetDebugThreadState(x86_debug_state_t *debugState, thread_act_t thread, mach_msg_type_number_t *stateCount) { mach_msg_type_number_t localStateCount = x86_DEBUG_STATE_COUNT; bool success = (thread_get_state(thread, x86_DEBUG_STATE, (thread_state_t)debugState, &localStateCount) == KERN_SUCCESS); if (stateCount != NULL) *stateCount = localStateCount; return success; }
int NaClMachThreadIsInUntrusted(mach_port_t thread_port) { x86_thread_state_t state; thread_state_t statep = (thread_state_t) &state; mach_msg_type_number_t size = x86_THREAD_STATE_COUNT; kern_return_t kr; uint32_t nacl_thread_index; kr = thread_get_state(thread_port, x86_THREAD_STATE, statep, &size); if (kr != KERN_SUCCESS) { NaClLog(LOG_FATAL, "NaClMachThreadIsInUntrusted: " "thread_get_state() failed with error %i\n", kr); } CHECK(kr == KERN_SUCCESS); #if NACL_BUILD_SUBARCH == 32 CHECK(state.tsh.flavor == x86_THREAD_STATE32); nacl_thread_index = state.uts.ts32.__gs >> 3; #elif NACL_BUILD_SUBARCH == 64 nacl_thread_index = NaClGetThreadIndexForMachThread(thread_port); /* * If the thread isn't known to Native Client, it's not untrusted (at least * not by Native Client.) */ if (nacl_thread_index == NACL_TLS_INDEX_INVALID) { return 0; } #endif return NaClMachThreadStateIsInUntrusted(&state, nacl_thread_index); }
bool ZGGetGeneralThreadState(x86_thread_state_t *threadState, thread_act_t thread, mach_msg_type_number_t *stateCount) { mach_msg_type_number_t localStateCount = x86_THREAD_STATE_COUNT; bool success = (thread_get_state(thread, x86_THREAD_STATE, (thread_state_t)threadState, &localStateCount) == KERN_SUCCESS); if (stateCount != NULL) *stateCount = localStateCount; return success; }
/* * Set up the initial state of a MACH thread * so that it will invoke cthread_body(child) * when it is resumed. */ void cproc_setup(register cproc_t child, thread_t thread, void (*routine)(cproc_t)) { extern unsigned int __hurd_threadvar_max; /* GNU */ register int *top = (int *) cproc_stack_base (child, sizeof(ur_cthread_t *) + /* Account for GNU per-thread variables. */ __hurd_threadvar_max * sizeof (long int)); struct i386_thread_state state; register struct i386_thread_state *ts = &state; kern_return_t r; unsigned int count; /* * Set up i386 call frame and registers. * Read registers first to get correct segment values. */ count = i386_THREAD_STATE_COUNT; MACH_CALL(thread_get_state(thread,i386_THREAD_STATE,(thread_state_t) &state,&count),r); ts->eip = (int) routine; *--top = (int) child; /* argument to function */ *--top = 0; /* fake return address */ ts->uesp = (int) top; /* set stack pointer */ ts->ebp = 0; /* clear frame pointer */ MACH_CALL(thread_set_state(thread,i386_THREAD_STATE,(thread_state_t) &state,i386_THREAD_STATE_COUNT),r); }
bool osx_arch_read_registers(thread_act_t tid) { bool ret = false; if (0 == _target.reg_size) { _target.reg = malloc(sizeof(x86_thread_state64_t)); if (_target.reg) _target.reg_size = sizeof(x86_thread_state64_t); } if (0 == _target.reg_size) { fprintf(stderr, "Error allocating register buffer\n"); } else { kern_return_t kret; mach_msg_type_number_t cnt = x86_THREAD_STATE64_COUNT; kret = thread_get_state(tid, x86_THREAD_STATE64, _target.reg, &cnt); if (KERN_SUCCESS == kret) { if (cnt != x86_THREAD_STATE64_COUNT) { /* Failure ? */ fprintf(stderr, "Warning : expecting reg size %zu but got %d\n", _target.reg_size, cnt); } else { /* Success */ ret = true; } } else { fprintf(stderr, "problem getting registers\n"); } } return ret; }
static void ios_hwstep_enable64 (task_t port, int enable) { ARMDebugState64 ds; mach_msg_type_number_t count = ARM_DEBUG_STATE64_COUNT; (void) thread_get_state (port, ARM_DEBUG_STATE64, (thread_state_t)&ds, &count); // The use of __arm64__ here is not ideal. If debugserver is running on // an armv8 device, regardless of whether it was built for arch arm or // arch arm64, it needs to use the MDSCR_EL1 SS bit to single // instruction step. // MDSCR_EL1 single step bit at gpr.pc if (enable) { ds.mdscr_el1 |= 1LL; } else { ds.mdscr_el1 &= ~(1ULL); } (void) thread_set_state (port, ARM_DEBUG_STATE64, (thread_state_t)&ds, count); }
kern_return_t GC_catch_exception_raise(mach_port_t port, mach_port_t thread_port, mach_port_t task_port, exception_type_t exception_type, exception_data_t exception_data, mach_msg_type_number_t data_count) { #if GENERATIONS /* kernel return value is in exception_data[0], faulting address in exception_data[1] */ if(exception_data[0] == KERN_PROTECTION_FAILURE) { void *p; #ifndef USE_THREAD_STATE p = (void*)exception_data[1]; #else /* We have to do it this way for 64-bit mode: */ x86_exception_state64_t exc_state; mach_msg_type_number_t exc_state_count = x86_EXCEPTION_STATE64_COUNT; (void)thread_get_state(thread_port, x86_EXCEPTION_STATE64, (natural_t*)&exc_state, &exc_state_count); p = (void *)exc_state. THREAD_FLD(faultvaddr); #endif #if defined(MZ_USE_PLACES) set_thread_locals_from_mach_thread_id(thread_port); #endif if (designate_modified(p)) return KERN_SUCCESS; else return KERN_FAILURE; } else #endif return KERN_FAILURE; }
/* * Set up the initial state of a MACH thread */ void _pthread_setup(pthread_t thread, void (*routine)(pthread_t), vm_address_t vsp) { struct hp700_thread_state state; struct hp700_thread_state *ts = &state; kern_return_t r; mach_msg_type_number_t count; int *sp = (int *) vsp;; /* * Set up pa-risc registers & function call. */ count = HP700_THREAD_STATE_COUNT; MACH_CALL(thread_get_state(thread->kernel_thread, HP700_THREAD_STATE, (thread_state_t) &state, &count), r); ts->iioq_head = (int) routine; ts->iioq_tail = (int) routine + 4; ts->arg0 = (int) thread; ts->sp = vsp; ts->dp = _dp(); ts->rp = 0; ts->r3 = 0; sp[-1] = sp[-5] = 0; /* Clear saved SP and RP in frame. */ MACH_CALL(thread_set_state(thread->kernel_thread, HP700_THREAD_STATE, (thread_state_t) &state, HP700_THREAD_STATE_COUNT), r); }
void tgdb_get_registers(mach_port_t thread, struct i386_thread_state *ss, struct i386_float_state *fs) { kern_return_t kr; mach_msg_type_number_t count; kr = thread_abort(thread); if (kr == KERN_NO_THREAD) { /* No thread attach to this activation */ bzero(ss, i386_THREAD_STATE_COUNT); bzero(fs, i386_FLOAT_STATE_COUNT); return; } if (kr != KERN_SUCCESS && kr != KERN_NO_THREAD) { printf("tgdb: can't abort thread\n"); return; } count = i386_THREAD_STATE_COUNT; kr = thread_get_state(thread, i386_THREAD_STATE, (thread_state_t) ss, &count); if (kr != KERN_SUCCESS) { printf("tgdb: can't get thread state\n"); return; } if (0 && tgdb_debug_flags & 256) { printf("\ntgdb_get_registers:\n"); print_thread_state(ss); } if (fs) { count = i386_FLOAT_STATE_COUNT; kr = thread_get_state(thread, i386_FLOAT_STATE, (thread_state_t)fs, &count); if (kr != KERN_SUCCESS) { printf("tgdb: can't get float thread state\n"); return; } } }
/* The source code for Apple's GDB was used as a reference for the exception forwarding code. This code is similar to the GDB code only because there is only one way to do it. */ static kern_return_t forward_exception( mach_port_t thread, mach_port_t task, exception_type_t exception, exception_data_t data, mach_msg_type_number_t data_count ) { int i; kern_return_t r; mach_port_t port; exception_behavior_t behavior; thread_state_flavor_t flavor; thread_state_data_t thread_state; mach_msg_type_number_t thread_state_count = THREAD_STATE_MAX; for(i=0;i<old_exc_ports.count;i++) if(old_exc_ports.masks[i] & (1 << exception)) break; if(i==old_exc_ports.count) ABORT("No handler for exception!"); port = old_exc_ports.ports[i]; behavior = old_exc_ports.behaviors[i]; flavor = old_exc_ports.flavors[i]; if(behavior != EXCEPTION_DEFAULT) { r = thread_get_state(thread,flavor,thread_state,&thread_state_count); if(r != KERN_SUCCESS) ABORT("thread_get_state failed in forward_exception"); } switch(behavior) { case EXCEPTION_DEFAULT: r = exception_raise(port,thread,task,exception,data,data_count); break; case EXCEPTION_STATE: r = exception_raise_state(port,thread,task,exception,data, data_count,&flavor,thread_state,thread_state_count, thread_state,&thread_state_count); break; case EXCEPTION_STATE_IDENTITY: r = exception_raise_state_identity(port,thread,task,exception,data, data_count,&flavor,thread_state,thread_state_count, thread_state,&thread_state_count); break; default: r = KERN_FAILURE; /* make gcc happy */ ABORT("forward_exception: unknown behavior"); break; } if(behavior != EXCEPTION_DEFAULT) { r = thread_set_state(thread,flavor,thread_state,thread_state_count); if(r != KERN_SUCCESS) ABORT("thread_set_state failed in forward_exception"); } return r; }
kern_return_t mono_mach_arch_get_thread_states (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count, thread_state_t fpstate, mach_msg_type_number_t *fpcount) { x86_thread_state64_t *arch_state = (x86_thread_state64_t *)state; x86_float_state64_t *arch_fpstate = (x86_float_state64_t *)fpstate; kern_return_t ret; *count = x86_THREAD_STATE64_COUNT; *fpcount = x86_FLOAT_STATE64_COUNT; ret = thread_get_state (thread, x86_THREAD_STATE64, (thread_state_t)arch_state, count); if (ret != KERN_SUCCESS) return ret; ret = thread_get_state (thread, x86_FLOAT_STATE64, (thread_state_t)arch_fpstate, fpcount); return ret; }
static bool ZGGetFloatThreadState(x86_float_state_t *floatState, thread_act_t thread, mach_msg_type_number_t *stateCount, bool is64Bit) { mach_msg_type_number_t localStateCount = is64Bit ? x86_FLOAT_STATE64_COUNT : x86_FLOAT_STATE32_COUNT; bool success = (thread_get_state(thread, is64Bit ? x86_FLOAT_STATE64 : x86_FLOAT_STATE32, is64Bit ? (thread_state_t)&(floatState->ufs.fs64) : (thread_state_t)&(floatState->ufs.fs32), &localStateCount) == KERN_SUCCESS); if (stateCount != NULL) *stateCount = localStateCount; return success; }