Esempio n. 1
0
/*++
Function:
  SetThreadContextOnPort

  Helper for CONTEXT_SetThreadContext
--*/
kern_return_t
CONTEXT_SetThreadContextOnPort(
           mach_port_t Port,
           IN CONST CONTEXT *lpContext)
{
    kern_return_t MachRet = KERN_SUCCESS;
    mach_msg_type_number_t StateCount;
    thread_state_flavor_t StateFlavor;

    if (lpContext->ContextFlags & (CONTEXT_CONTROL|CONTEXT_INTEGER)) 
    {
#ifdef _X86_
        x86_thread_state32_t State;
        StateFlavor = x86_THREAD_STATE32;
        
        State.eax = lpContext->Eax;
        State.ebx = lpContext->Ebx;
        State.ecx = lpContext->Ecx;
        State.edx = lpContext->Edx;
        State.edi = lpContext->Edi;
        State.esi = lpContext->Esi;
        State.ebp = lpContext->Ebp;
        State.esp = lpContext->Esp;
        State.ss = lpContext->SegSs;
        State.eflags = lpContext->EFlags;
        State.eip = lpContext->Eip;
        State.cs = lpContext->SegCs;
        State.ds = lpContext->SegDs_PAL_Undefined;
        State.es = lpContext->SegEs_PAL_Undefined;
        State.fs = lpContext->SegFs_PAL_Undefined;
        State.gs = lpContext->SegGs_PAL_Undefined;
#elif defined(_AMD64_)
        x86_thread_state64_t State;
        StateFlavor = x86_THREAD_STATE64;

        State.__rax = lpContext->Rax;
        State.__rbx = lpContext->Rbx;
        State.__rcx = lpContext->Rcx;
        State.__rdx = lpContext->Rdx;
        State.__rdi = lpContext->Rdi;
        State.__rsi = lpContext->Rsi;
        State.__rbp = lpContext->Rbp;
        State.__rsp = lpContext->Rsp;
        State.__r8 = lpContext->R8;
        State.__r9 = lpContext->R9;
        State.__r10 = lpContext->R10;
        State.__r11 = lpContext->R11;
        State.__r12 = lpContext->R12;
        State.__r13 = lpContext->R13;
        State.__r14 = lpContext->R14;
        State.__r15 = lpContext->R15;
//        State.ss = lpContext->SegSs;
        State.__rflags = lpContext->EFlags;
        State.__rip = lpContext->Rip;
        State.__cs = lpContext->SegCs;
//        State.ds = lpContext->SegDs_PAL_Undefined;
//        State.es = lpContext->SegEs_PAL_Undefined;
        State.__fs = lpContext->SegFs;
        State.__gs = lpContext->SegGs;
#else
#error Unexpected architecture.
#endif

        StateCount = sizeof(State) / sizeof(natural_t);

        MachRet = thread_set_state(Port,
                                   StateFlavor,
                                   (thread_state_t)&State,
                                   StateCount);
        if (MachRet != KERN_SUCCESS)
        {
            ASSERT("thread_set_state(THREAD_STATE) failed: %d\n", MachRet);
            goto EXIT;
        }
    }

    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);

        // If we're setting only one of the floating point or extended registers (of which Mach supports only
        // the xmm values) then we don't have values for the other set. This is a problem since Mach only
        // supports setting both groups as a single unit. So in this case we'll need to fetch the current
        // values first.
        if ((lpContext->ContextFlags & CONTEXT_ALL_FLOATING) !=
            CONTEXT_ALL_FLOATING)
        {
            mach_msg_type_number_t StateCountGet = StateCount;
            MachRet = thread_get_state(Port,
                                       StateFlavor,
                                       (thread_state_t)&State,
                                       &StateCountGet);
            if (MachRet != KERN_SUCCESS)
            {
                ASSERT("thread_get_state(FLOAT_STATE) failed: %d\n", MachRet);
                goto EXIT;
            }
            _ASSERTE(StateCountGet == StateCount);
        }

        if (lpContext->ContextFlags & CONTEXT_FLOATING_POINT)
        {
#ifdef _X86_
            *(DWORD*)&State.fpu_fcw = lpContext->FloatSave.ControlWord;
            *(DWORD*)&State.fpu_fsw = lpContext->FloatSave.StatusWord;
            State.fpu_ftw = lpContext->FloatSave.TagWord;
            State.fpu_ip = lpContext->FloatSave.ErrorOffset;
            State.fpu_cs = lpContext->FloatSave.ErrorSelector;
            State.fpu_dp = lpContext->FloatSave.DataOffset;
            State.fpu_ds = lpContext->FloatSave.DataSelector;
            State.fpu_mxcsr = lpContext->FloatSave.Cr0NpxState;

            // Windows stores the floating point registers in a packed layout (each 10-byte register end to
            // end for a total of 80 bytes). But Mach returns each register in an 16-bit structure (presumably
            // for alignment purposes). So we can't just memcpy the registers over in a single block, we need
            // to copy them individually.
            for (int i = 0; i < 8; i++)
                memcpy((&State.fpu_stmm0)[i].mmst_reg, &lpContext->FloatSave.RegisterArea[i * 10], 10);
#elif defined(_AMD64_)
            *(DWORD*)&State.__fpu_fcw = lpContext->FltSave.ControlWord;
            *(DWORD*)&State.__fpu_fsw = lpContext->FltSave.StatusWord;
            State.__fpu_ftw = lpContext->FltSave.TagWord;
            State.__fpu_ip = lpContext->FltSave.ErrorOffset;
            State.__fpu_cs = lpContext->FltSave.ErrorSelector;
            State.__fpu_dp = lpContext->FltSave.DataOffset;
            State.__fpu_ds = lpContext->FltSave.DataSelector;
            State.__fpu_mxcsr = lpContext->FltSave.MxCsr;
            State.__fpu_mxcsrmask = lpContext->FltSave.MxCsr_Mask; // note: we don't save the mask for x86

            // Windows stores the floating point registers in a packed layout (each 10-byte register end to
            // end for a total of 80 bytes). But Mach returns each register in an 16-bit structure (presumably
            // for alignment purposes). So we can't just memcpy the registers over in a single block, we need
            // to copy them individually.
            for (int i = 0; i < 8; i++)
                memcpy((&State.__fpu_stmm0)[i].__mmst_reg, &lpContext->FltSave.FloatRegisters[i], 10);

            memcpy(&State.__fpu_xmm0, &lpContext->Xmm0, 8 * 16);
#else
#error Unexpected architecture.
#endif
        }

#ifdef _X86_
        if (lpContext->ContextFlags & CONTEXT_EXTENDED_REGISTERS)
        {
            // The only extended register information that Mach will tell us about are the xmm register
            // values. Both Windows and Mach store the registers in a packed layout (each of the 8 registers
            // is 16 bytes) so we can simply memcpy them across.
            memcpy(&State.fpu_xmm0, lpContext->ExtendedRegisters + CONTEXT_EXREG_XMM_OFFSET, 8 * 16);
        }
#endif // _X86_

        MachRet = thread_set_state(Port,
                                   StateFlavor,
                                   (thread_state_t)&State,
                                   StateCount);
        if (MachRet != KERN_SUCCESS)
        {
            ASSERT("thread_set_state(FLOAT_STATE) failed: %d\n", MachRet);
            goto EXIT;
        }
    }    

EXIT:
    return MachRet;
}
Esempio n. 2
0
File: darwin.c Progetto: 8l/go-learn
// Read/write from fake register segment.
static int
machregrw(Map *map, Seg *seg, uvlong addr, void *v, uint n, int isr)
{
	uint nn, count, state;
	mach_port_t thread;
	int reg;
	char buf[100];
	union {
		x86_thread_state64_t reg64;
		x86_thread_state32_t reg32;
		uchar p[1];
	} u;
	uchar *p;

	if(n > 8){
		werrstr("asked for %d-byte register", n);
		return -1;
	}

	thread = idtothread(map->pid);
	if(thread == -1){
		werrstr("no such id");
		return -1;
	}

	if(mach == &mi386) {
		count = x86_THREAD_STATE32_COUNT;
		state = x86_THREAD_STATE32;
		if((reg = go2darwin32(addr)) < 0 || reg+n > sizeof u){
			if(isr){
				memset(v, 0, n);
				return 0;
			}
			werrstr("register %llud not available", addr);
			return -1;
		}
	} else {
		count = x86_THREAD_STATE64_COUNT;
		state = x86_THREAD_STATE64;
		if((reg = go2darwin64(addr)) < 0 || reg+n > sizeof u){
			if(isr){
				memset(v, 0, n);
				return 0;
			}
			werrstr("register %llud not available", addr);
			return -1;
		}
	}

	if(!isr && me(thread_suspend(thread)) < 0){
		werrstr("thread suspend %#x: %r", thread);
		return -1;
	}
	nn = count;
	if(me(thread_get_state(thread, state, (void*)u.p, &nn)) < 0){
		if(!isr)
			thread_resume(thread);
		rerrstr(buf, sizeof buf);
		if(strcmp(buf, "send invalid dest") == 0)
			werrstr("process exited");
		else
			werrstr("thread_get_state: %r");
		return -1;
	}

	p = u.p+reg;
	if(isr)
		memmove(v, p, n);
	else{
		memmove(p, v, n);
		nn = count;
		if(me(thread_set_state(thread, state, (void*)u.p, nn)) < 0){
			thread_resume(thread);
			werrstr("thread_set_state: %r");
			return -1;
		}

		if(me(thread_resume(thread)) < 0){
			werrstr("thread_resume: %r");
			return -1;
		}
	}
	return 0;
}
Esempio n. 3
0
static void
i386_darwin_dr_set (int regnum, CORE_ADDR value)
{
  int current_pid;
  thread_t current_thread;
  x86_debug_state_t dr_regs;
  kern_return_t ret;
  unsigned int dr_count;

  gdb_assert (regnum >= 0 && regnum <= DR_CONTROL);

  current_thread = ptid_get_tid (inferior_ptid);

  dr_regs.dsh.flavor = x86_DEBUG_STATE;
  dr_regs.dsh.count = x86_DEBUG_STATE_COUNT;
  dr_count = x86_DEBUG_STATE_COUNT;
  ret = thread_get_state (current_thread, x86_DEBUG_STATE,
                          (thread_state_t) &dr_regs, &dr_count);
  MACH_CHECK_ERROR (ret);

  switch (dr_regs.dsh.flavor)
    {
    case x86_DEBUG_STATE32:
      switch (regnum)
	{
	case 0:
	  dr_regs.uds.ds32.__dr0 = value;
	  break;
	case 1:
	  dr_regs.uds.ds32.__dr1 = value;
	  break;
	case 2:
	  dr_regs.uds.ds32.__dr2 = value;
	  break;
	case 3:
	  dr_regs.uds.ds32.__dr3 = value;
	  break;
	case 4:
	  dr_regs.uds.ds32.__dr4 = value;
	  break;
	case 5:
	  dr_regs.uds.ds32.__dr5 = value;
	  break;
	case 6:
	  dr_regs.uds.ds32.__dr6 = value;
	  break;
	case 7:
	  dr_regs.uds.ds32.__dr7 = value;
	  break;
	}
      break;
#ifdef BFD64
    case x86_DEBUG_STATE64:
      switch (regnum)
	{
	case 0:
	  dr_regs.uds.ds64.__dr0 = value;
	  break;
	case 1:
	  dr_regs.uds.ds64.__dr1 = value;
	  break;
	case 2:
	  dr_regs.uds.ds64.__dr2 = value;
	  break;
	case 3:
	  dr_regs.uds.ds64.__dr3 = value;
	  break;
	case 4:
	  dr_regs.uds.ds64.__dr4 = value;
	  break;
	case 5:
	  dr_regs.uds.ds64.__dr5 = value;
	  break;
	case 6:
	  dr_regs.uds.ds64.__dr6 = value;
	  break;
	case 7:
	  dr_regs.uds.ds64.__dr7 = value;
	  break;
	}
      break;
#endif
    }

  ret = thread_set_state (current_thread, dr_regs.dsh.flavor,
                          (thread_state_t) &dr_regs.uds, dr_count);

  MACH_CHECK_ERROR (ret);
}
Esempio n. 4
0
static void
i386_darwin_store_inferior_registers (struct target_ops *ops,
				      struct regcache *regcache, int regno)
{
  thread_t current_thread = ptid_get_tid (inferior_ptid);
  struct gdbarch *gdbarch = get_regcache_arch (regcache);

#ifdef BFD64
  if (gdbarch_ptr_bit (gdbarch) == 64)
    {
      if (regno == -1 || amd64_native_gregset_supplies_p (gdbarch, regno))
        {
          x86_thread_state_t gp_regs;
          kern_return_t ret;
	  unsigned int gp_count = x86_THREAD_STATE_COUNT;

	  ret = thread_get_state
	    (current_thread, x86_THREAD_STATE, (thread_state_t) &gp_regs,
	     &gp_count);
          MACH_CHECK_ERROR (ret);
	  gdb_assert (gp_regs.tsh.flavor == x86_THREAD_STATE64);
          gdb_assert (gp_regs.tsh.count == x86_THREAD_STATE64_COUNT);

	  amd64_collect_native_gregset (regcache, &gp_regs.uts, regno);

          ret = thread_set_state (current_thread, x86_THREAD_STATE,
                                  (thread_state_t) &gp_regs,
                                  x86_THREAD_STATE_COUNT);
          MACH_CHECK_ERROR (ret);
        }

      if (regno == -1 || !amd64_native_gregset_supplies_p (gdbarch, regno))
        {
          x86_float_state_t fp_regs;
          kern_return_t ret;
	  unsigned int fp_count = x86_FLOAT_STATE_COUNT;

	  ret = thread_get_state
	    (current_thread, x86_FLOAT_STATE, (thread_state_t) & fp_regs,
	     &fp_count);
          MACH_CHECK_ERROR (ret);
          gdb_assert (fp_regs.fsh.flavor == x86_FLOAT_STATE64);
          gdb_assert (fp_regs.fsh.count == x86_FLOAT_STATE64_COUNT);

	  amd64_collect_fxsave (regcache, regno, &fp_regs.ufs.fs64.__fpu_fcw);

	  ret = thread_set_state (current_thread, x86_FLOAT_STATE,
				  (thread_state_t) & fp_regs,
				  x86_FLOAT_STATE_COUNT);
	  MACH_CHECK_ERROR (ret);
        }
    }
  else
#endif
    {
      if (regno == -1 || regno < I386_NUM_GREGS)
        {
          x86_thread_state32_t gp_regs;
          kern_return_t ret;
          unsigned int gp_count = x86_THREAD_STATE32_COUNT;
	  int i;

          ret = thread_get_state
            (current_thread, x86_THREAD_STATE32, (thread_state_t) &gp_regs,
             &gp_count);
	  MACH_CHECK_ERROR (ret);

	  for (i = 0; i < I386_NUM_GREGS; i++)
	    if (regno == -1 || regno == i)
	      regcache_raw_collect
		(regcache, i,
		 (char *)&gp_regs + i386_darwin_thread_state_reg_offset[i]);

          ret = thread_set_state (current_thread, x86_THREAD_STATE32,
                                  (thread_state_t) &gp_regs,
                                  x86_THREAD_STATE32_COUNT);
          MACH_CHECK_ERROR (ret);
        }

      if (regno == -1
	  || (regno >= I386_ST0_REGNUM && regno < I386_SSE_NUM_REGS))
        {
          x86_float_state32_t fp_regs;
          unsigned int fp_count = x86_FLOAT_STATE32_COUNT;
          kern_return_t ret;

	  ret = thread_get_state
            (current_thread, x86_FLOAT_STATE32, (thread_state_t) & fp_regs,
             &fp_count);
	  MACH_CHECK_ERROR (ret);

	  i387_collect_fxsave (regcache, regno, &fp_regs.__fpu_fcw);

	  ret = thread_set_state (current_thread, x86_FLOAT_STATE32,
				  (thread_state_t) &fp_regs,
				  x86_FLOAT_STATE32_COUNT);
	  MACH_CHECK_ERROR (ret);
        }
    }
}
Esempio n. 5
0
void
store_inferior_registers (register int regno)
{
  thread_state_data_t state;
  kern_return_t ret;

  if (!MACH_PORT_VALID (current_thread))
    error ("store inferior registers: Invalid thread");

  /* Check for read only regs.
   * @@ If some of these is can be changed, fix this
   */
  if (regno == ZERO_REGNUM ||
      regno == PS_REGNUM ||
      regno == BADVADDR_REGNUM ||
      regno == CAUSE_REGNUM ||
      regno == FCRIR_REGNUM)
    {
      message ("You can not alter read-only register `%s'",
	       REGISTER_NAME (regno));
      fetch_inferior_registers (regno);
      return;
    }

  if (regno == -1)
    {
      /* Don't allow these to change */

      /* ZERO_REGNUM */
      *(int *) registers = 0;

      fetch_inferior_registers (PS_REGNUM);
      fetch_inferior_registers (BADVADDR_REGNUM);
      fetch_inferior_registers (CAUSE_REGNUM);
      fetch_inferior_registers (FCRIR_REGNUM);
    }

  if (regno == -1 || (ZERO_REGNUM < regno && regno <= PC_REGNUM))
    {
#if 1
      /* Mach 3.0 saves thread's FP to MACH_FP_REGNUM.
       * GDB wants assigns a pseudo register FP_REGNUM for frame pointer.
       *
       * @@@ Here I assume (!) that gdb's FP has the value that
       *     should go to threads frame pointer. If not true, this
       *     fails badly!!!!!
       */
      memcpy (&registers[REGISTER_BYTE (MACH_FP_REGNUM)],
	      &registers[REGISTER_BYTE (FP_REGNUM)],
	      REGISTER_RAW_SIZE (FP_REGNUM));
#endif

      /* Save gdb's regs 1..31 to thread saved regs 1..31
       * Luckily, they are contiquous
       */
      STORE_REGS (state, 1, 31);

      /* Save mdlo, mdhi */
      STORE_REGS (state, LO_REGNUM, 2);

      /* Save PC */
      STORE_REGS (state, PC_REGNUM, 1);

      ret = thread_set_state (current_thread,
			      MIPS_THREAD_STATE,
			      state,
			      MIPS_FLOAT_STATE_COUNT);
      CHK ("store inferior regs : thread_set_state", ret);
    }

  if (regno == -1 || regno >= FP0_REGNUM)
    {
      /* If thread has floating state, save it */
      if (read_register (PS_REGNUM) & MIPS_STATUS_USE_COP1)
	{
	  /* Do NOT save FCRIR_REGNUM */
	  STORE_REGS (state, FP0_REGNUM, 33);

	  ret = thread_set_state (current_thread,
				  MIPS_FLOAT_STATE,
				  state,
				  MIPS_FLOAT_STATE_COUNT);
	  CHK ("store inferior registers (floats): thread_set_state", ret);
	}
      else if (regno != -1)
	message
	  ("Thread does not use floating point unit, floating regs not saved");
    }
}
/* Store our register values back into the inferior.
 * If REGNO is -1, do this for all registers.
 * Otherwise, REGNO specifies which register (so we can save time): */
void store_inferior_registers(int regno)
{
  int current_pid;
  thread_t current_thread;
  kern_return_t ret;

  current_pid = ptid_get_pid(inferior_ptid);
  current_thread = (thread_t)ptid_get_tid(inferior_ptid);

  if (current_pid == 0) {
    ; /* do nothing; just silence '-Wunused-but-set-variable' */
  }

  validate_inferior_registers(regno);

  if ((regno == -1) || ARM_MACOSX_IS_GP_RELATED_REGNUM(regno)) {
      struct gdb_arm_thread_state gp_regs;
      arm_macosx_store_gp_registers(&gp_regs);
      ret = thread_set_state(current_thread, GDB_ARM_THREAD_STATE,
                             (thread_state_t)&gp_regs,
                             GDB_ARM_THREAD_STATE_COUNT);
      MACH_CHECK_ERROR(ret);
  }

  if ((regno == -1) || ARM_MACOSX_IS_VFP_RELATED_REGNUM(regno)) {
      enum arm_vfp_version vfp_version;
      int fp_byte_size;
      vfp_version = new_gdbarch_tdep(current_gdbarch)->vfp_version;
      fp_byte_size = -1;

      switch (vfp_version) {
	  case ARM_VFP_UNSUPPORTED:
	    /* No VFP support, so nothing to do here: */
	    fp_byte_size = 0;
	    break;

	  case ARM_VFP_VERSION_1:
	    {
	      gdb_arm_thread_vfpv1_state_t fp_regs;
	      arm_macosx_store_vfpv1_regs(&fp_regs);
	      ret = thread_set_state(current_thread, GDB_ARM_THREAD_FPSTATE,
                                     (thread_state_t) & fp_regs,
                                     GDB_ARM_THREAD_FPSTATE_VFPV1_COUNT);
	      MACH_CHECK_ERROR(ret);
	    }
	    break;

	  case ARM_VFP_VERSION_3:
	    {
	      gdb_arm_thread_vfpv3_state_t fp_regs;
	      arm_macosx_store_vfpv3_regs(&fp_regs);
	      ret = thread_set_state(current_thread, GDB_ARM_THREAD_FPSTATE,
                                     (thread_state_t)&fp_regs,
                                     GDB_ARM_THREAD_FPSTATE_VFPV3_COUNT);
	      MACH_CHECK_ERROR(ret);
            }
	    break;

 	  default:
	    error("store_inferior_registers: unable to store ARM_THREAD_FPSTATE: "
                  "unsupported vfp version: %d", (int)vfp_version);
#ifndef __clang__
	    break;
#endif /* !__clang__ */
      }

      if (fp_byte_size >= 0) {
        ; /* ??? */
      }
  }
}