Beispiel #1
0
CORE_ADDR
fbsd_thread_get_local_address(struct target_ops *ops,
			      ptid_t ptid,
			      CORE_ADDR lm,
                              CORE_ADDR offset)
{
  td_thrhandle_t th;
  void *address;
  int ret;

  if (IS_THREAD (ptid))
    {
      if (!td_thr_tls_get_addr_p)
        error ("Cannot find thread-local interface in thread_db library.");

      ret = td_ta_map_id2thr_p (thread_agent, GET_THREAD(ptid), &th);

      /* get the address of the variable. */
      ret = td_thr_tls_get_addr_p (&th, (void *)lm, offset, &address);

      if (ret != TD_OK)
        {
            error ("Cannot find thread-local storage for thread %ld\n%s",
                   (long) GET_THREAD (ptid), thread_db_err_str (ret));
        }

      /* Cast assuming host == target. */
      return extract_data_ptr (&address);
    }
  return (0);
}
Beispiel #2
0
CORE_ADDR
fbsd_thread_get_local_address(ptid_t ptid, struct objfile *objfile,
                              CORE_ADDR offset)
{
  td_thrhandle_t th;
  void *address;
  CORE_ADDR lm;
  void *lm2;
  int ret, is_library = (objfile->flags & OBJF_SHARED);

  if (IS_THREAD (ptid))
    {
      if (!td_thr_tls_get_addr_p)
        error ("Cannot find thread-local interface in thread_db library.");

      /* Get the address of the link map for this objfile. */
      lm = svr4_fetch_objfile_link_map (objfile);

      /* Couldn't find link map. Bail out. */
      if (!lm)
        {
          if (is_library)
            error ("Cannot find shared library `%s' link_map in dynamic"
                   " linker's module list", objfile->name);
          else
            error ("Cannot find executable file `%s' link_map in dynamic"
                   " linker's module list", objfile->name);
        }

      ret = td_ta_map_id2thr_p (thread_agent, GET_THREAD(ptid), &th);

      /* get the address of the variable. */
      store_typed_address(&lm2, builtin_type_void_data_ptr, lm);
      ret = td_thr_tls_get_addr_p (&th, lm2, offset, &address);

      if (ret != TD_OK)
        {
          if (is_library)
            error ("Cannot find thread-local storage for thread %ld, "
                   "shared library %s:\n%s",
                   (long) GET_THREAD (ptid),
                   objfile->name, thread_db_err_str (ret));
          else
            error ("Cannot find thread-local storage for thread %ld, "
                   "executable file %s:\n%s",
                   (long) GET_THREAD (ptid),
                   objfile->name, thread_db_err_str (ret));
        }

      /* Cast assuming host == target. */
      return extract_typed_address(&address, builtin_type_void_data_ptr);
    }
  return (0);
}
Beispiel #3
0
static int
fbsd_thread_alive (ptid_t ptid)
{
  td_thrhandle_t th;
  td_thrinfo_t ti;
  td_err_e err;
  gregset_t gregs;
  lwpid_t lwp;

  if (IS_THREAD (ptid))
    {
      err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (ptid), &th);
      if (err != TD_OK)
        return 0;

      err = td_thr_get_info_p (&th, &ti);
      if (err != TD_OK)
        return 0;

      /* A zombie thread. */
      if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE)
        return 0;

      return 1;
    }
  else if (GET_LWP (ptid) == 0)
    {
      /* we sometimes are called with lwp == 0 */
      return 1;
    }

  if (fbsd_thread_active)
    {
      err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th);

      /*
       * if the lwp was already mapped to user thread, don't use it
       * directly, please use user thread id instead.
       */
      if (err == TD_OK)
        return 0;
    }

  if (!target_has_execution)
    {
      lwp = GET_LWP (ptid);
      bfd_map_over_sections (core_bfd, fbsd_core_check_lwp, &lwp);
      return (lwp == 0); 
    }

  /* check lwp in kernel */
  return ptrace (PT_GETREGS, GET_LWP (ptid), (caddr_t)&gregs, 0) == 0;
}
Beispiel #4
0
static void
fbsd_thread_fetch_registers (struct target_ops *ops,
			     struct regcache *regcache, int regnum)
{
  prgregset_t gregset;
  prfpregset_t fpregset;
  td_thrhandle_t th;
  td_err_e err;
#ifdef PT_GETXMMREGS
  char xmmregs[512];
#endif

  if (!IS_THREAD (inferior_ptid))
    {
      fbsd_lwp_fetch_registers (ops, regcache, regnum);
      return;
    }

  err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (inferior_ptid), &th);
  if (err != TD_OK)
    error ("Cannot find thread %d: Thread ID=%ld, %s",
           pid_to_thread_id (inferior_ptid),           
           GET_THREAD (inferior_ptid), thread_db_err_str (err));

  err = td_thr_getgregs_p (&th, gregset);
  if (err != TD_OK)
    error ("Cannot fetch general-purpose registers for thread %d: Thread ID=%ld, %s",
           pid_to_thread_id (inferior_ptid),
           GET_THREAD (inferior_ptid), thread_db_err_str (err));
#ifdef PT_GETXMMREGS
  err = td_thr_getxmmregs_p (&th, xmmregs);
  if (err == TD_OK)
    {
      i387_supply_fxsave (regcache, -1, xmmregs);
    }
  else
    {
#endif
      err = td_thr_getfpregs_p (&th, &fpregset);
      if (err != TD_OK)
	error ("Cannot get floating-point registers for thread %d: Thread ID=%ld, %s",
	       pid_to_thread_id (inferior_ptid),
	       GET_THREAD (inferior_ptid), thread_db_err_str (err));
      supply_fpregset (regcache, &fpregset);
#ifdef PT_GETXMMREGS
    }
#endif

  supply_gregset (regcache, gregset);
}
Beispiel #5
0
static char *
fbsd_thread_pid_to_str (ptid_t ptid)
{
  static char buf[64 + MAXCOMLEN];

  if (IS_THREAD (ptid))
    {
      td_thrhandle_t th;
      td_thrinfo_t ti;
      td_err_e err;

      err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (ptid), &th);
      if (err != TD_OK)
        error ("Cannot find thread, Thread ID=%ld, %s",
                GET_THREAD (ptid), thread_db_err_str (err));

      err = td_thr_get_info_p (&th, &ti);
      if (err != TD_OK)
        error ("Cannot get thread info, Thread ID=%ld, %s",
               GET_THREAD (ptid), thread_db_err_str (err));

      if (ti.ti_lid != 0)
        {
          snprintf (buf, sizeof (buf), "Thread %llx (LWP %d/%s)",
                    (unsigned long long)th.th_thread, ti.ti_lid,
                    fbsd_thread_get_name (ti.ti_lid));
        }
      else
        {
          snprintf (buf, sizeof (buf), "Thread %llx (%s)",
		    (unsigned long long)th.th_thread,
		    thread_db_state_str (ti.ti_state));
        }

      return buf;
    }
  else if (IS_LWP (ptid))
    {
      snprintf (buf, sizeof (buf), "LWP %d", (int) GET_LWP (ptid));
      return buf;
    }
  return normal_pid_to_str (ptid);
}
Beispiel #6
0
static void
fbsd_thread_store_registers (int regno)
{
  prgregset_t gregset;
  prfpregset_t fpregset;
  td_thrhandle_t th;
  td_err_e err;
#ifdef PT_GETXMMREGS
  char xmmregs[512];
#endif

  if (!IS_THREAD (inferior_ptid))
    {
      fbsd_lwp_store_registers (regno);
      return;
    }

  err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (inferior_ptid), &th);
  if (err != TD_OK)
    error ("Cannot find thread %d: Thread ID=%ld, %s",
           pid_to_thread_id (inferior_ptid),
           GET_THREAD (inferior_ptid),
           thread_db_err_str (err));

  if (regno != -1)
    {
      char old_value[MAX_REGISTER_SIZE];

      regcache_collect (regno, old_value);
      err = td_thr_getgregs_p (&th, gregset);
      if (err != TD_OK)
        error ("%s: td_thr_getgregs %s", __func__, thread_db_err_str (err));
#ifdef PT_GETXMMREGS
      err = td_thr_getxmmregs_p (&th, xmmregs);
      if (err != TD_OK)
        {
#endif
          err = td_thr_getfpregs_p (&th, &fpregset);
          if (err != TD_OK)
            error ("%s: td_thr_getfpgregs %s", __func__, thread_db_err_str (err));
#ifdef PT_GETXMMREGS
        }
#endif
      supply_register (regno, old_value);
    }

  fill_gregset (gregset, regno);
  err = td_thr_setgregs_p (&th, gregset);
  if (err != TD_OK)
    error ("Cannot store general-purpose registers for thread %d: Thread ID=%d, %s",
           pid_to_thread_id (inferior_ptid), GET_THREAD (inferior_ptid),
           thread_db_err_str (err));

#ifdef PT_GETXMMREGS
  i387_fill_fxsave (xmmregs, regno);
  err = td_thr_setxmmregs_p (&th, xmmregs);
  if (err == TD_OK)
    return;
#endif

  fill_fpregset (&fpregset, regno);
  err = td_thr_setfpregs_p (&th, &fpregset);
  if (err != TD_OK)
    error ("Cannot store floating-point registers for thread %d: Thread ID=%d, %s",
           pid_to_thread_id (inferior_ptid), GET_THREAD (inferior_ptid),
           thread_db_err_str (err));
}
Beispiel #7
0
static void
fbsd_thread_resume (ptid_t ptid, int step, enum target_signal signo)
{
  td_thrhandle_t th;
  td_thrinfo_t ti;
  ptid_t work_ptid;
  int resume_all, ret;
  long lwp, thvalid = 0;

  if (!fbsd_thread_active)
    {
      child_ops.to_resume (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 (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 (thread_db_err_str (ret));
      ret = td_thr_get_info_p (&th, &ti);
      if (ret)
        error (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");
}
Beispiel #8
0
static void
fbsd_thread_signal_cmd (char *exp, int from_tty)
{
  td_thrhandle_t th;
  td_thrinfo_t ti;
  td_err_e err;
  const char *code;

  if (!fbsd_thread_active || !IS_THREAD(inferior_ptid))
    return;

  err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (inferior_ptid), &th);
  if (err != TD_OK)
    return;

  err = td_thr_get_info_p (&th, &ti);
  if (err != TD_OK)
    return;

  printf_filtered("signal mask:\n");
  fbsd_print_sigset(&ti.ti_sigmask);
  printf_filtered("signal pending:\n");
  fbsd_print_sigset(&ti.ti_pending);
  if (ti.ti_siginfo.si_signo != 0) {
   printf_filtered("si_signo %d si_errno %d", ti.ti_siginfo.si_signo,
     ti.ti_siginfo.si_errno);
   if (ti.ti_siginfo.si_errno != 0)
    printf_filtered(" (%s)", strerror(ti.ti_siginfo.si_errno));
   printf_filtered("\n");
   switch (ti.ti_siginfo.si_code) {
   case SI_NOINFO:
	code = "NOINFO";
	break;
    case SI_USER:
	code = "USER";
	break;
    case SI_QUEUE:
	code = "QUEUE";
	break;
    case SI_TIMER:
	code = "TIMER";
	break;
    case SI_ASYNCIO:
	code = "ASYNCIO";
	break;
    case SI_MESGQ:
	code = "MESGQ";
	break;
    case SI_KERNEL:
	code = "KERNEL";
	break;
    default:
	code = "UNKNOWN";
	break;
    }
    printf_filtered("si_code %s (%d) si_pid %d si_uid %d si_status %x "
      "si_addr %p\n",
      code, ti.ti_siginfo.si_code, ti.ti_siginfo.si_pid, ti.ti_siginfo.si_uid,
      ti.ti_siginfo.si_status, ti.ti_siginfo.si_addr);
  }
}