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
}
Пример #2
0
//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);
}
Пример #3
0
Файл: init.c Проект: aviks/julia
//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;
    }
}
Пример #4
0
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

}
Пример #5
0
/*++
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);
}
Пример #7
0
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);
    }
}
Пример #8
0
// 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)&regs,
				&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)&regs,
				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)&regs,
				&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)&regs,
				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;
}
Пример #9
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;
}
Пример #10
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;
}
Пример #12
0
/*
 * 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);
}
Пример #13
0
/* 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);
}
Пример #14
0
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);
}
Пример #15
0
/* 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;
    }
}
Пример #16
0
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);
    }
}
Пример #17
0
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);
    }
}
Пример #18
0
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;
}
Пример #19
0
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;
}
Пример #20
0
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);
}
Пример #21
0
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;
}
Пример #22
0
/*
 * 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);
}
Пример #23
0
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;
}
Пример #24
0
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);
}
Пример #25
0
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;
}
Пример #26
0
/*
 * 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);
}
Пример #27
0
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;
		}
        }

}
Пример #28
0
/* 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;
}
Пример #29
0
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;
}
Пример #30
0
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;
}