Пример #1
0
static void
fbsd_thread_mourn_inferior (struct target_ops *ops)
{
  struct target_ops *beneath = find_target_beneath (ops);

  fbsd_thread_deactivate ();

  beneath->to_mourn_inferior (beneath);

  /* Delete thread event breakpoints, if any.  */
  remove_thread_event_breakpoints ();

  unpush_target (ops);
}
Пример #2
0
static void
fbsd_thread_detach (struct target_ops *ops, char *args, int from_tty)
{
  struct target_ops *beneath = find_target_beneath (ops);

  fbsd_thread_deactivate ();

  /* Delete thread event breakpoints, if any.  */
  remove_thread_event_breakpoints ();

  unpush_target (&fbsd_thread_ops);

  beneath->to_detach (beneath, args, from_tty);
}
Пример #3
0
static void
nbsd_thread_create_inferior (struct target_ops *ops, char *exec_file,
			     char *allargs, char **env, int from_tty)
{
  struct target_ops *beneath = find_target_beneath (ops);
  nbsd_thread_core = 0;

  if (nbsd_thread_present && !nbsd_thread_active)
    push_target(&nbsd_thread_ops);

  beneath->to_create_inferior (beneath, exec_file, allargs, env, from_tty);

  if (nbsd_thread_present && !nbsd_thread_active)
    nbsd_thread_activate();
}
Пример #4
0
static int
nbsd_thread_proc_getregs (void *arg, int regset, int lwp, void *buf)
{
  struct nbsd_thread_proc_arg *a = (struct nbsd_thread_proc_arg *) arg; 
  struct regcache *cache = a->cache;
  struct target_ops *ops = a->ops;
  struct cleanup *old_chain;
  struct target_ops *beneath = find_target_beneath (ops);
  int ret;

  old_chain = save_inferior_ptid ();

  if (target_has_execution)
    {
      /* Fetching registers from a live process requires that
	 inferior_ptid is a LWP value rather than a thread value. */
      inferior_ptid = ptid_build (ptid_get_pid (main_ptid), lwp, 0);
      beneath->to_fetch_registers (beneath, cache, -1);
    }
  else
    {
      /* Fetching registers from a core process requires that
	 the PID value of inferior_ptid have the funky value that
	 the kernel drops rather than the real PID. Gross. */
      inferior_ptid = pid_to_ptid ((lwp << 16) | ptid_get_pid (main_ptid));
      beneath->to_fetch_registers (ops, cache, -1);
    }

  ret = 0;
  switch (regset)
    {
    case 0:
      fill_gregset (cache, (gregset_t *)buf, -1);
      break;
    case 1:
#ifdef HAVE_FPREGS
      fill_fpregset (cache, (fpregset_t *)buf, -1);
#endif
      break;
    default: /* XXX need to handle other reg sets: SSE, AltiVec, etc. */
      ret = TD_ERR_INVAL;
    }

  do_cleanups (old_chain);

  return ret;
}
Пример #5
0
static int
kgdb_trgt_xfer_memory(CORE_ADDR memaddr, char *myaddr, int len, int write,
    struct mem_attrib *attrib, struct target_ops *target)
{
	struct target_ops *tb;

	if (kvm != NULL) {
		if (len == 0)
			return (0);
		if (!write)
			return (kvm_read(kvm, memaddr, myaddr, len));
		else
			return (kvm_write(kvm, memaddr, myaddr, len));
	}
	tb = find_target_beneath(target);
	return (tb->to_xfer_memory(memaddr, myaddr, len, write, attrib, tb));
}
Пример #6
0
static ptid_t
fbsd_thread_wait (struct target_ops *ops,
		  ptid_t ptid, struct target_waitstatus *ourstatus, int options)
{
  struct target_ops *beneath = find_target_beneath (ops);
  ptid_t ret;
  long lwp;
  CORE_ADDR stop_pc;
  td_thrhandle_t th;
  td_thrinfo_t ti;

  ret = beneath->to_wait (beneath, ptid, ourstatus, options);
  if (GET_PID(ret) >= 0 && ourstatus->kind == TARGET_WAITKIND_STOPPED)
    {
      lwp = get_current_lwp (GET_PID(ret));
      ret = thread_from_lwp (BUILD_LWP(lwp, GET_PID(ret)),
         &th, &ti);
      if (!in_thread_list(ret)) {
        /*
         * We have to enable event reporting for initial thread
         * which was not mapped before.
	 */
        attach_thread(ret, &th, &ti, 1);
      }
      if (ourstatus->value.sig == TARGET_SIGNAL_TRAP)
        check_event(ret);
      /* this is a hack, if an event won't cause gdb to stop, for example,
         SIGALRM, gdb resumes the process immediatly without setting
         inferior_ptid to the new thread returned here, this is a bug
         because inferior_ptid may already not exist there, and passing
         a non-existing thread to fbsd_thread_resume causes error. However,
         if the exiting thread is the currently selected thread,
         then that is handled later in handle_inferior_event(), and we must
         not delete the currently selected thread. 
      */
      if (!fbsd_thread_alive (ops, inferior_ptid) && !ptid_equal(inferior_ptid, ret))
        {
          delete_thread (inferior_ptid);
          inferior_ptid = ret;
        }
    }

  return (ret);
}
Пример #7
0
static void
nbsd_thread_resume (struct target_ops *ops, ptid_t ptid, int step,
    enum gdb_signal signo)
{
  struct target_ops *beneath = find_target_beneath (ops);

  /* If a particular thread is specified, then gdb wants to resume or
     step just that thread. If it isn't on a processor, then it needs
     to be put on one, and nothing else can be on the runnable list.
     XXX If GDB asks us to step a LWP rather than a thread, there
     isn't anything we can do but pass it down to the ptrace call;
     given the flexibility of the LWP-to-thread mapping, this might or
     might not accomplish what the user wanted. */
  if (ptid_get_pid(ptid) == -1)
    ptid = inferior_ptid;
  beneath->to_resume (beneath, ptid, step, signo);

  cached_thread = minus_one_ptid;
}
Пример #8
0
/* Retrieve contents of the N'th element in the current thread's
   linked SPE context list into ID and NPC.  Return the address of
   said context element, or 0 if not found.  */
static CORE_ADDR
ppc_linux_spe_context (int wordsize, enum bfd_endian byte_order,
		       int n, int *id, unsigned int *npc)
{
  CORE_ADDR spe_context = 0;
  gdb_byte buf[16];
  int i;

  /* Quick exit if we have not found __spe_current_active_context.  */
  if (!spe_context_objfile)
    return 0;

  /* Look up cached address of thread-local variable.  */
  if (!ptid_equal (spe_context_cache_ptid, inferior_ptid))
    {
      struct target_ops *target = &current_target;
      volatile struct gdb_exception ex;

      while (target && !target->to_get_thread_local_address)
	target = find_target_beneath (target);
      if (!target)
	return 0;

      TRY_CATCH (ex, RETURN_MASK_ERROR)
	{
	  /* We do not call target_translate_tls_address here, because
	     svr4_fetch_objfile_link_map may invalidate the frame chain,
	     which must not do while inside a frame sniffer.

	     Instead, we have cached the lm_addr value, and use that to
	     directly call the target's to_get_thread_local_address.  */
	  spe_context_cache_address
	    = target->to_get_thread_local_address (target, inferior_ptid,
						   spe_context_lm_addr,
						   spe_context_offset);
	  spe_context_cache_ptid = inferior_ptid;
	}

      if (ex.reason < 0)
	return 0;
    }
Пример #9
0
static void
fbsd_lwp_fetch_registers (struct target_ops *ops,
			  struct regcache *regcache, int regnum)
{
  gregset_t gregs;
  fpregset_t fpregs;
  lwpid_t lwp;
#ifdef PT_GETXMMREGS
  char xmmregs[512];
#endif

  if (!target_has_execution)
    {
      struct target_ops *beneath = find_target_beneath (ops);

      beneath->to_fetch_registers (ops, regcache, regnum);
      return;
    }

  lwp = GET_LWP (inferior_ptid);

  if (ptrace (PT_GETREGS, lwp, (caddr_t) &gregs, 0) == -1)
    error ("Cannot get lwp %d registers: %s\n", lwp, safe_strerror (errno));
  supply_gregset (regcache, &gregs);
  
#ifdef PT_GETXMMREGS
  if (ptrace (PT_GETXMMREGS, lwp, xmmregs, 0) == 0)
    {
      i387_supply_fxsave (regcache, -1, xmmregs);
    }
  else
    {
#endif
      if (ptrace (PT_GETFPREGS, lwp, (caddr_t) &fpregs, 0) == -1)
	error ("Cannot get lwp %d registers: %s\n ", lwp, safe_strerror (errno));
      supply_fpregset (regcache, &fpregs);
#ifdef PT_GETXMMREGS
    }
#endif
}
Пример #10
0
static ptid_t
nbsd_thread_wait (struct target_ops *ops, ptid_t ptid,
  struct target_waitstatus *ourstatus, int options)
{
  ptid_t rtnval;
  struct target_ops *beneath = find_target_beneath (ops);

  rtnval = beneath->to_wait (beneath, ptid, ourstatus, options);

  nbsd_thread_unsuspend();

  if (nbsd_thread_active && (ourstatus->kind != TARGET_WAITKIND_EXITED))
    {
      rtnval = find_active_thread ();
      if (ptid_equal (rtnval, minus_one_ptid))
	error ("No active thread!\n");
      if (!in_thread_list (rtnval))
	add_thread (rtnval);
    }

  return rtnval;
}
Пример #11
0
static void
nbsd_thread_fetch_registers (struct target_ops *ops, struct regcache *cache,
    int regno)
{
  struct target_ops *beneath = find_target_beneath (ops);
  td_thread_t *thread;
  gregset_t gregs;
#ifdef HAVE_FPREGS
  fpregset_t fpregs;
#endif
  int val;
  struct cleanup *old_chain;

  old_chain = save_inferior_ptid ();

  if (!target_has_execution)
    {
      inferior_ptid = pid_to_ptid ((ptid_get_lwp (inferior_ptid) << 16) | 
				    ptid_get_pid (inferior_ptid));
    }
    beneath->to_fetch_registers (beneath, cache, regno);
  
  do_cleanups (old_chain);
}
Пример #12
0
static void
fbsd_thread_resume (struct target_ops *ops,
		    ptid_t ptid, int step, enum target_signal signo)
{
  struct target_ops *beneath = find_target_beneath (ops);
  td_thrhandle_t th;
  td_thrinfo_t ti;
  ptid_t work_ptid;
  int resume_all, ret;
  long lwp, thvalid = 0;

  if (!fbsd_thread_active)
    {
      // XXX: I don't think this can happen
      printf_unfiltered ("%s: called without active threads\n", __func__);
      beneath->to_resume (beneath, ptid, step, signo);
      return;
    }

  if (GET_PID(ptid) != -1 && step != 0)
    {
      resume_all = 0;
      work_ptid = ptid;
    }
  else
    {
      resume_all = 1;
      work_ptid = inferior_ptid;
    }

  lwp = GET_LWP (work_ptid);
  if (lwp == 0)
    {
      /* check user thread */
      ret = td_ta_map_id2thr_p (thread_agent, GET_THREAD(work_ptid), &th);
      if (ret)
        error ("%s: %s", __func__, thread_db_err_str (ret));

      /* For M:N thread, we need to tell UTS to set/unset single step
         flag at context switch time, the flag will be written into
         thread mailbox. This becauses some architecture may not have
         machine single step flag in ucontext, so we put the flag in mailbox,
         when the thread switches back, kse_switchin restores the single step
         state.  */
      ret = td_thr_sstep_p (&th, step);
      if (ret)
        error ("%s: %s", __func__, thread_db_err_str (ret));
      ret = td_thr_get_info_p (&th, &ti);
      if (ret)
        error ("%s: %s", __func__, thread_db_err_str (ret));
      thvalid = 1;
      lwp = ti.ti_lid;
    }

  if (lwp)
    {
      int req = step ? PT_SETSTEP : PT_CLEARSTEP;
      if (ptrace (req, (pid_t) lwp, (caddr_t) 1, target_signal_to_host(signo)))
        perror_with_name ("PT_SETSTEP/PT_CLEARSTEP");
    }

  if (!ptid_equal (last_single_step_thread, null_ptid))
    {
       ret = td_ta_thr_iter_p (thread_agent, resume_thread_callback, NULL,
          TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
          TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
      if (ret != TD_OK)
        error ("resume error: %s", thread_db_err_str (ret));
    }

  if (!resume_all)
    {
      ret = td_ta_thr_iter_p (thread_agent, suspend_thread_callback, NULL,
          TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
          TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
      if (ret != TD_OK)
        error ("suspend error: %s", thread_db_err_str (ret));
      last_single_step_thread = work_ptid;
    }
  else
    last_single_step_thread = null_ptid;

  if (thvalid)
    {
      ret = td_thr_dbresume_p (&th);
      if (ret != TD_OK)
        error ("resume error: %s", thread_db_err_str (ret));
    }
  else
    {
      /* it is not necessary, put it here for completness */
      ret = ptrace(PT_RESUME, lwp, 0, 0);
    }

  /* now continue the process, suspended thread wont run */
  if (ptrace (PT_CONTINUE, proc_handle.pid , (caddr_t)1,
	      target_signal_to_host(signo)))
    perror_with_name ("PT_CONTINUE");
}
Пример #13
0
static int
nbsd_core_thread_alive (struct target_ops *ops, ptid_t ptid)
{
  struct target_ops *beneath = find_target_beneath (ops);
  return beneath->to_thread_alive (beneath, ptid);
}
Пример #14
0
static void
nbsd_core_files_info (struct target_ops *ignore)
{
  struct target_ops *beneath = find_target_beneath (ignore);
  beneath->to_files_info (beneath);
}