Esempio n. 1
0
static void
arm_linux_fetch_inferior_registers (struct target_ops *ops,
				    struct regcache *regcache, int regno)
{
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);

  if (-1 == regno)
    {
      fetch_regs (regcache);
      fetch_fpregs (regcache);
      if (tdep->have_wmmx_registers)
	fetch_wmmx_regs (regcache);
      if (tdep->vfp_register_count > 0)
	fetch_vfp_regs (regcache);
    }
  else 
    {
      if (regno < ARM_F0_REGNUM || regno == ARM_PS_REGNUM)
	fetch_regs (regcache);
      else if (regno >= ARM_F0_REGNUM && regno <= ARM_FPS_REGNUM)
	fetch_fpregs (regcache);
      else if (tdep->have_wmmx_registers
	       && regno >= ARM_WR0_REGNUM && regno <= ARM_WCGR7_REGNUM)
	fetch_wmmx_regs (regcache);
      else if (tdep->vfp_register_count > 0
	       && regno >= ARM_D0_REGNUM
	       && regno <= ARM_D0_REGNUM + tdep->vfp_register_count)
	fetch_vfp_regs (regcache);
    }
}
Esempio n. 2
0
static void
m68k_linux_fetch_inferior_registers (struct target_ops *ops,
				     struct regcache *regcache, int regno)
{
  int tid;

  /* Use the old method of peeking around in `struct user' if the
     GETREGS request isn't available.  */
  if (! have_ptrace_getregs)
    {
      old_fetch_inferior_registers (regcache, regno);
      return;
    }

  /* GNU/Linux LWP ID's are process ID's.  */
  tid = TIDGET (inferior_ptid);
  if (tid == 0)
    tid = PIDGET (inferior_ptid);	/* Not a threaded program.  */

  /* Use the PTRACE_GETFPXREGS request whenever possible, since it
     transfers more registers in one system call, and we'll cache the
     results.  But remember that fetch_fpxregs can fail, and return
     zero.  */
  if (regno == -1)
    {
      fetch_regs (regcache, tid);

      /* The call above might reset `have_ptrace_getregs'.  */
      if (! have_ptrace_getregs)
	{
	  old_fetch_inferior_registers (regcache, -1);
	  return;
	}

      fetch_fpregs (regcache, tid);
      return;
    }

  if (getregs_supplies (regno))
    {
      fetch_regs (regcache, tid);
      return;
    }

  if (getfpregs_supplies (regno))
    {
      fetch_fpregs (regcache, tid);
      return;
    }

  internal_error (__FILE__, __LINE__,
		  _("Got request for bad register number %d."), regno);
}
Esempio n. 3
0
static void
arm_linux_fetch_inferior_registers (struct target_ops *ops,
				    struct regcache *regcache, int regno)
{
  if (-1 == regno)
    {
      fetch_regs (regcache);
      fetch_fpregs (regcache);
      if (arm_linux_has_wmmx_registers)
	fetch_wmmx_regs (regcache);
      if (arm_linux_vfp_register_count > 0)
	fetch_vfp_regs (regcache);
    }
  else 
    {
      if (regno < ARM_F0_REGNUM || regno == ARM_PS_REGNUM)
        fetch_register (regcache, regno);
      else if (regno >= ARM_F0_REGNUM && regno <= ARM_FPS_REGNUM)
        fetch_fpregister (regcache, regno);
      else if (arm_linux_has_wmmx_registers
	       && regno >= ARM_WR0_REGNUM && regno <= ARM_WCGR7_REGNUM)
	fetch_wmmx_regs (regcache);
      else if (arm_linux_vfp_register_count > 0
	       && regno >= ARM_D0_REGNUM
	       && regno <= ARM_D0_REGNUM + arm_linux_vfp_register_count)
	fetch_vfp_regs (regcache);
    }
}
Esempio n. 4
0
/* Fetch register REGNUM from the child process.  If REGNUM is -1, do
   this for all registers.  */
void
fetch_inferior_registers (int regnum)
{
  int tid = s390_inferior_tid ();

  if (regnum == -1 
      || (regnum < S390_NUM_REGS && regmap_gregset[regnum] != -1))
    fetch_regs (tid);

  if (regnum == -1 
      || (regnum < S390_NUM_REGS && regmap_fpregset[regnum] != -1))
    fetch_fpregs (tid);
}
/* Fetch register REGNUM from the child process.  If REGNUM is -1, do
   this for all registers.  */
static void
s390_linux_fetch_inferior_registers (struct regcache *regcache, int regnum)
{
  int tid = s390_inferior_tid ();

  if (regnum == -1 
      || (regnum < S390_NUM_REGS && regmap_gregset[regnum] != -1))
    fetch_regs (regcache, tid);

  if (regnum == -1 
      || (regnum < S390_NUM_REGS && regmap_fpregset[regnum] != -1))
    fetch_fpregs (regcache, tid);
}
Esempio n. 6
0
void
fetch_inferior_registers (int regno)
{
  if (regno >= 0)
    {
      if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
	fetch_register (regno);
      else
	fetch_fp_register (regno);
    }
  else
    {
      fetch_regs ();
      fetch_fp_regs ();
    }
}
Esempio n. 7
0
void
fetch_inferior_registers (int regno)
{
  if (-1 == regno)
    {
      fetch_regs ();
      fetch_fpregs ();
    }
  else 
    {
      if (regno < F0_REGNUM || regno > FPS_REGNUM)
        fetch_register (regno);

      if (regno >= F0_REGNUM && regno <= FPS_REGNUM)
        fetch_fpregister (regno);
    }
}
Esempio n. 8
0
static void
armnbsd_fetch_registers (struct target_ops *ops,
			 struct regcache *regcache, int regno)
{
  if (regno >= 0)
    {
      if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
	fetch_register (regcache, regno);
      else
	fetch_fp_register (regcache, regno);
    }
  else
    {
      fetch_regs (regcache);
      fetch_fp_regs (regcache);
    }
}
Esempio n. 9
0
void translate_syscall(Tracee *tracee)
{
	const bool is_enter_stage = (tracee->status == 0);
	int status;

	assert(tracee->exe != NULL);

	status = fetch_regs(tracee);
	if (status < 0)
		return;

	if (is_enter_stage) {
		/* Never restore original register values at the end
		 * of this stage.  */
		tracee->restore_original_regs = false;

		print_current_regs(tracee, 3, "sysenter start");
		save_current_regs(tracee, ORIGINAL);

		translate_syscall_enter(tracee);

		print_current_regs(tracee, 5, "sysenter end");
		save_current_regs(tracee, MODIFIED);

		/* Restore tracee's stack pointer now if it won't hit
		 * the sysexit stage (i.e. when seccomp is enabled and
		 * there's nothing else to do).  */
		if (tracee->restart_how == PTRACE_CONT) {
			tracee->status = 0;
			poke_reg(tracee, STACK_POINTER, peek_reg(tracee, ORIGINAL, STACK_POINTER));
		}
	}
	else {
		/* By default, restore original register values at the
		 * end of this stage.  */
		tracee->restore_original_regs = true;

		print_current_regs(tracee, 5, "sysexit start");

		translate_syscall_exit(tracee);

		print_current_regs(tracee, 4, "sysexit end");
	}

	(void) push_regs(tracee);
}
Esempio n. 10
0
void translate_syscall(Tracee *tracee)
{
	const bool is_enter_stage = IS_IN_SYSENTER(tracee);
	int status;

	assert(tracee->exe != NULL);

	status = fetch_regs(tracee);
	if (status < 0)
		return;

	if (is_enter_stage) {
		/* Never restore original register values at the end
		 * of this stage.  */
		tracee->restore_original_regs = false;

		print_current_regs(tracee, 3, "sysenter start");

		/* Translate the syscall only if it was actually
		 * requested by the tracee, it is not a syscall
		 * chained by PRoot.  */
		if (tracee->chain.syscalls == NULL) {
			save_current_regs(tracee, ORIGINAL);
			status = translate_syscall_enter(tracee);
			save_current_regs(tracee, MODIFIED);
		}
		else {
			status = notify_extensions(tracee, SYSCALL_CHAINED_ENTER, 0, 0);
			tracee->restart_how = PTRACE_SYSCALL;
		}

		/* Remember the tracee status for the "exit" stage and
		 * avoid the actual syscall if an error was reported
		 * by the translation/extension. */
		if (status < 0) {
			set_sysnum(tracee, PR_void);
			poke_reg(tracee, SYSARG_RESULT, (word_t) status);
			tracee->status = status;
		}
		else
			tracee->status = 1;

		/* Restore tracee's stack pointer now if it won't hit
		 * the sysexit stage (i.e. when seccomp is enabled and
		 * there's nothing else to do).  */
		if (tracee->restart_how == PTRACE_CONT) {
			tracee->status = 0;
			poke_reg(tracee, STACK_POINTER, peek_reg(tracee, ORIGINAL, STACK_POINTER));
		}
	}
	else {
		/* By default, restore original register values at the
		 * end of this stage.  */
		tracee->restore_original_regs = true;

		print_current_regs(tracee, 5, "sysexit start");

		/* Translate the syscall only if it was actually
		 * requested by the tracee, it is not a syscall
		 * chained by PRoot.  */
		if (tracee->chain.syscalls == NULL)
			translate_syscall_exit(tracee);
		else
			(void) notify_extensions(tracee, SYSCALL_CHAINED_EXIT, 0, 0);

		/* Reset the tracee's status. */
		tracee->status = 0;

		/* Insert the next chained syscall, if any.  */
		if (tracee->chain.syscalls != NULL)
			chain_next_syscall(tracee);
	}

	(void) push_regs(tracee);

	if (is_enter_stage)
		print_current_regs(tracee, 5, "sysenter end" );
	else
		print_current_regs(tracee, 4, "sysexit end");
}
static void
i386_linux_fetch_inferior_registers (struct target_ops *ops,
				     struct regcache *regcache, int regno)
{
  int tid;

  /* Use the old method of peeking around in `struct user' if the
     GETREGS request isn't available.  */
  if (!have_ptrace_getregs)
    {
      int i;

      for (i = 0; i < gdbarch_num_regs (get_regcache_arch (regcache)); i++)
	if (regno == -1 || regno == i)
	  fetch_register (regcache, i);

      return;
    }

  /* GNU/Linux LWP ID's are process ID's.  */
  tid = ptid_get_lwp (inferior_ptid);
  if (tid == 0)
    tid = ptid_get_pid (inferior_ptid); /* Not a threaded program.  */

  /* Use the PTRACE_GETFPXREGS request whenever possible, since it
     transfers more registers in one system call, and we'll cache the
     results.  But remember that fetch_fpxregs can fail, and return
     zero.  */
  if (regno == -1)
    {
      fetch_regs (regcache, tid);

      /* The call above might reset `have_ptrace_getregs'.  */
      if (!have_ptrace_getregs)
	{
	  i386_linux_fetch_inferior_registers (ops, regcache, regno);
	  return;
	}

      if (fetch_xstateregs (regcache, tid))
	return;
      if (fetch_fpxregs (regcache, tid))
	return;
      fetch_fpregs (regcache, tid);
      return;
    }

  if (GETREGS_SUPPLIES (regno))
    {
      fetch_regs (regcache, tid);
      return;
    }

  if (GETXSTATEREGS_SUPPLIES (regno))
    {
      if (fetch_xstateregs (regcache, tid))
	return;
    }

  if (GETFPXREGS_SUPPLIES (regno))
    {
      if (fetch_fpxregs (regcache, tid))
	return;

      /* Either our processor or our kernel doesn't support the SSE
	 registers, so read the FP registers in the traditional way,
	 and fill the SSE registers with dummy values.  It would be
	 more graceful to handle differences in the register set using
	 gdbarch.  Until then, this will at least make things work
	 plausibly.  */
      fetch_fpregs (regcache, tid);
      return;
    }

  internal_error (__FILE__, __LINE__,
		  _("Got request for bad register number %d."), regno);
}
Esempio n. 12
0
File: tracee.c Progetto: AQBoy/PRoot
/**
 * Make new @parent's child inherit from it.  Depending on
 * @clone_flags, some information are copied or shared.  This function
 * returns -errno if an error occured, otherwise 0.
 */
int new_child(Tracee *parent, word_t clone_flags)
{
	unsigned long pid;
	Tracee *child;
	int status;

	/* If the tracee calls clone(2) with the CLONE_VFORK flag,
	 * PTRACE_EVENT_VFORK will be delivered instead [...];
	 * otherwise if the tracee calls clone(2) with the exit signal
	 * set to SIGCHLD, PTRACE_EVENT_FORK will be delivered [...]
	 *
	 * -- ptrace(2) man-page
	 *
	 * That means we have to check if it's actually a clone(2) in
	 * order to get the right flags.
	 */
	status = fetch_regs(parent);
	if (status >= 0 && get_sysnum(parent, CURRENT) == PR_clone)
		clone_flags = peek_reg(parent, CURRENT, SYSARG_1);

	/* Get the pid of the parent's new child.  */
	status = ptrace(PTRACE_GETEVENTMSG, parent->pid, NULL, &pid);
	if (status < 0) {
		notice(parent, WARNING, SYSTEM, "ptrace(GETEVENTMSG)");
		return status;
	}

	child = get_tracee(parent, (pid_t) pid, true);
	if (child == NULL) {
		notice(parent, WARNING, SYSTEM, "running out of memory");
		return -ENOMEM;
	}

	/* Sanity checks.  */
	assert(child != NULL
	    && child->exe == NULL
	    && child->cmdline == NULL
	    && child->fs->cwd == NULL
	    && child->fs->bindings.pending == NULL
	    && child->fs->bindings.guest == NULL
	    && child->fs->bindings.host == NULL
	    && child->qemu == NULL
	    && child->glue == NULL);

	child->verbose = parent->verbose;
	child->seccomp = parent->seccomp;
	child->sysexit_pending = parent->sysexit_pending;

	/* If CLONE_VM is set, the calling process and the child
	 * process run in the same memory space [...] any memory
	 * mapping or unmapping performed with mmap(2) or munmap(2) by
	 * the child or calling process also affects the other
	 * process.
	 *
	 * If CLONE_VM is not set, the child process runs in a
	 * separate copy of the memory space of the calling process at
	 * the time of clone().  Memory writes or file
	 * mappings/unmappings performed by one of the processes do
	 * not affect the other, as with fork(2).
	 *
	 * -- clone(2) man-page
	 */
	TALLOC_FREE(child->heap);
	child->heap = ((clone_flags & CLONE_VM) != 0)
		? talloc_reference(child, parent->heap)
		: talloc_memdup(child, parent->heap, sizeof(Heap));
	if (child->heap == NULL)
		return -ENOMEM;

	/* If CLONE_FS is set, the parent and the child process share
	 * the same file system information.  This includes the root
	 * of the file system, the current working directory, and the
	 * umask.  Any call to chroot(2), chdir(2), or umask(2)
	 * performed by the parent process or the child process also
	 * affects the other process.
	 *
	 * If CLONE_FS is not set, the child process works on a copy
	 * of the file system information of the parent process at the
	 * time of the clone() call.  Calls to chroot(2), chdir(2),
	 * umask(2) performed later by one of the processes do not
	 * affect the other process.
	 *
	 * -- clone(2) man-page
	 */
	TALLOC_FREE(child->fs);
	if ((clone_flags & CLONE_FS) != 0) {
		/* File-system name-space is shared.  */
		child->fs = talloc_reference(child, parent->fs);
	}
	else {
		/* File-system name-space is copied.  */
		child->fs = talloc_zero(child, FileSystemNameSpace);
		if (child->fs == NULL)
			return -ENOMEM;

		child->fs->cwd = talloc_strdup(child->fs, parent->fs->cwd);
		if (child->fs->cwd == NULL)
			return -ENOMEM;
		talloc_set_name_const(child->fs->cwd, "$cwd");

		/* Bindings are shared across file-system name-spaces since a
		 * "mount --bind" made by a process affects all other processes
		 * under Linux.  Actually they are copied when a sub
		 * reconfiguration occured (nested proot or chroot(2)).  */
		child->fs->bindings.guest = talloc_reference(child->fs, parent->fs->bindings.guest);
		child->fs->bindings.host  = talloc_reference(child->fs, parent->fs->bindings.host);
	}

	/* The path to the executable and the command-line are unshared only
	 * once the child process does a call to execve(2).  */
	child->exe = talloc_reference(child, parent->exe);
	child->cmdline = talloc_reference(child, parent->cmdline);

	child->qemu_pie_workaround = parent->qemu_pie_workaround;
	child->qemu = talloc_reference(child, parent->qemu);
	child->glue = talloc_reference(child, parent->glue);

	child->host_ldso_paths  = talloc_reference(child, parent->host_ldso_paths);
	child->guest_ldso_paths = talloc_reference(child, parent->guest_ldso_paths);

	inherit_extensions(child, parent, false);

	/* Restart the child tracee if it was already alive but
	 * stopped until that moment.  */
	if (child->sigstop == SIGSTOP_PENDING) {
		int status;

		child->sigstop = SIGSTOP_ALLOWED;
		status = ptrace(PTRACE_SYSCALL, child->pid, NULL, 0);
		if (status < 0)
			TALLOC_FREE(child);
	}

	return 0;
}