Esempio n. 1
0
static struct btrace_insn_iterator *
record_btrace_start_replaying (struct thread_info *tp)
{
  volatile struct gdb_exception except;
  struct btrace_insn_iterator *replay;
  struct btrace_thread_info *btinfo;
  int executing;

  btinfo = &tp->btrace;
  replay = NULL;

  /* We can't start replaying without trace.  */
  if (btinfo->begin == NULL)
    return NULL;

  /* Clear the executing flag to allow changes to the current frame.
     We are not actually running, yet.  We just started a reverse execution
     command or a record goto command.
     For the latter, EXECUTING is false and this has no effect.
     For the former, EXECUTING is true and we're in to_wait, about to
     move the thread.  Since we need to recompute the stack, we temporarily
     set EXECUTING to flase.  */
  executing = is_executing (tp->ptid);
  set_executing (tp->ptid, 0);

  /* GDB stores the current frame_id when stepping in order to detects steps
     into subroutines.
     Since frames are computed differently when we're replaying, we need to
     recompute those stored frames and fix them up so we can still detect
     subroutines after we started replaying.  */
  TRY_CATCH (except, RETURN_MASK_ALL)
    {
      struct frame_info *frame;
      struct frame_id frame_id;
      int upd_step_frame_id, upd_step_stack_frame_id;

      /* The current frame without replaying - computed via normal unwind.  */
      frame = get_current_frame ();
      frame_id = get_frame_id (frame);

      /* Check if we need to update any stepping-related frame id's.  */
      upd_step_frame_id = frame_id_eq (frame_id,
				       tp->control.step_frame_id);
      upd_step_stack_frame_id = frame_id_eq (frame_id,
					     tp->control.step_stack_frame_id);

      /* We start replaying at the end of the branch trace.  This corresponds
	 to the current instruction.  */
      replay = xmalloc (sizeof (*replay));
      btrace_insn_end (replay, btinfo);

      /* We're not replaying, yet.  */
      gdb_assert (btinfo->replay == NULL);
      btinfo->replay = replay;

      /* Make sure we're not using any stale registers.  */
      registers_changed_ptid (tp->ptid);

      /* The current frame with replaying - computed via btrace unwind.  */
      frame = get_current_frame ();
      frame_id = get_frame_id (frame);

      /* Replace stepping related frames where necessary.  */
      if (upd_step_frame_id)
	tp->control.step_frame_id = frame_id;
      if (upd_step_stack_frame_id)
	tp->control.step_stack_frame_id = frame_id;
    }

  /* Restore the previous execution state.  */
  set_executing (tp->ptid, executing);

  if (except.reason < 0)
    {
      xfree (btinfo->replay);
      btinfo->replay = NULL;

      registers_changed_ptid (tp->ptid);

      throw_exception (except);
    }

  return replay;
}
Esempio n. 2
0
void
inf_ptrace_target::attach (const char *args, int from_tty)
{
  char *exec_file;
  pid_t pid;
  struct inferior *inf;

  /* Do not change either targets above or the same target if already present.
     The reason is the target stack is shared across multiple inferiors.  */
  int ops_already_pushed = target_is_pushed (this);

  pid = parse_pid_to_attach (args);

  if (pid == getpid ())		/* Trying to m********e?  */
    error (_("I refuse to debug myself!"));

  target_unpush_up unpusher;
  if (! ops_already_pushed)
    {
      /* target_pid_to_str already uses the target.  Also clear possible core
	 file with its process_stratum.  */
      push_target (this);
      unpusher.reset (this);
    }

  if (from_tty)
    {
      exec_file = get_exec_file (0);

      if (exec_file)
	printf_unfiltered (_("Attaching to program: %s, %s\n"), exec_file,
			   target_pid_to_str (ptid_t (pid)));
      else
	printf_unfiltered (_("Attaching to %s\n"),
			   target_pid_to_str (ptid_t (pid)));

      gdb_flush (gdb_stdout);
    }

#ifdef PT_ATTACH
  errno = 0;
  ptrace (PT_ATTACH, pid, (PTRACE_TYPE_ARG3)0, 0);
  if (errno != 0)
    perror_with_name (("ptrace"));
#else
  error (_("This system does not support attaching to a process"));
#endif

  inf = current_inferior ();
  inferior_appeared (inf, pid);
  inf->attach_flag = 1;
  inferior_ptid = ptid_t (pid);

  /* Always add a main thread.  If some target extends the ptrace
     target, it should decorate the ptid later with more info.  */
  thread_info *thr = add_thread_silent (inferior_ptid);
  /* Don't consider the thread stopped until we've processed its
     initial SIGSTOP stop.  */
  set_executing (thr->ptid, true);

  unpusher.release ();
}
Esempio n. 3
0
void
startup_inferior (int ntraps)
{
  int pending_execs = ntraps;
  int terminal_initted = 0;
  ptid_t resume_ptid;

  if (startup_with_shell)
    {
      /* One trap extra for exec'ing the shell.  */
      pending_execs++;
    }

  if (target_supports_multi_process ())
    resume_ptid = pid_to_ptid (ptid_get_pid (inferior_ptid));
  else
    resume_ptid = minus_one_ptid;

  /* The process was started by the fork that created it, but it will
     have stopped one instruction after execing the shell.  Here we
     must get it up to actual execution of the real program.  */

  if (exec_wrapper)
    pending_execs++;

  while (1)
    {
      enum gdb_signal resume_signal = GDB_SIGNAL_0;
      ptid_t event_ptid;

      struct target_waitstatus ws;
      memset (&ws, 0, sizeof (ws));
      event_ptid = target_wait (resume_ptid, &ws, 0);

      if (ws.kind == TARGET_WAITKIND_IGNORE)
	/* The inferior didn't really stop, keep waiting.  */
	continue;

      switch (ws.kind)
	{
	  case TARGET_WAITKIND_SPURIOUS:
	  case TARGET_WAITKIND_LOADED:
	  case TARGET_WAITKIND_FORKED:
	  case TARGET_WAITKIND_VFORKED:
	  case TARGET_WAITKIND_SYSCALL_ENTRY:
	  case TARGET_WAITKIND_SYSCALL_RETURN:
	    /* Ignore gracefully during startup of the inferior.  */
	    switch_to_thread (event_ptid);
	    break;

	  case TARGET_WAITKIND_SIGNALLED:
	    target_terminal_ours ();
	    target_mourn_inferior ();
	    error (_("During startup program terminated with signal %s, %s."),
		   gdb_signal_to_name (ws.value.sig),
		   gdb_signal_to_string (ws.value.sig));
	    return;

	  case TARGET_WAITKIND_EXITED:
	    target_terminal_ours ();
	    target_mourn_inferior ();
	    if (ws.value.integer)
	      error (_("During startup program exited with code %d."),
		     ws.value.integer);
	    else
	      error (_("During startup program exited normally."));
	    return;

	  case TARGET_WAITKIND_EXECD:
	    /* Handle EXEC signals as if they were SIGTRAP signals.  */
	    xfree (ws.value.execd_pathname);
	    resume_signal = GDB_SIGNAL_TRAP;
	    switch_to_thread (event_ptid);
	    break;

	  case TARGET_WAITKIND_STOPPED:
	    resume_signal = ws.value.sig;
	    switch_to_thread (event_ptid);
	    break;
	}

      if (resume_signal != GDB_SIGNAL_TRAP)
	{
	  /* Let shell child handle its own signals in its own way.  */
	  target_resume (resume_ptid, 0, resume_signal);
	}
      else
	{
	  /* We handle SIGTRAP, however; it means child did an exec.  */
	  if (!terminal_initted)
	    {
	      /* Now that the child has exec'd we know it has already
	         set its process group.  On POSIX systems, tcsetpgrp
	         will fail with EPERM if we try it before the child's
	         setpgid.  */

	      /* Set up the "saved terminal modes" of the inferior
	         based on what modes we are starting it with.  */
	      target_terminal_init ();

	      /* Install inferior's terminal modes.  */
	      target_terminal_inferior ();

	      terminal_initted = 1;
	    }

	  if (--pending_execs == 0)
	    break;

	  /* Just make it go on.  */
	  target_resume (resume_ptid, 0, GDB_SIGNAL_0);
	}
    }

  /* Mark all threads non-executing.  */
  set_executing (resume_ptid, 0);
}