Ejemplo n.º 1
0
//--------------------------------------------------------------------------
// returns true: multithreaded application has been detected
bool linux_debmod_t::tdb_new(int pid)
{
  if ( ta == NULL )
  {
#ifdef LDEB
    msg("checking pid %d with thread_db\n", pid);
#endif
    prochandle.pid = pid;
    td_err_e err = td_ta_new(&prochandle, &ta);
    // the call might fail the first time if libc is not loaded yet
    // so don't show misleading message to the user
    // COMPLAIN_IF_FAILED("td_ta_new", err);
    if ( err != TD_OK )
    {
      ta = NULL;
      return false;
    }

    td_thrhandle_t th;
    err = td_ta_map_lwp2thr(ta, pid, &th);
    COMPLAIN_IF_FAILED("td_ta_map_lwp2thr", err);
    if ( err != TD_OK )
      return false;

    err = td_thr_event_enable(&th, TD_CREATE);
    DIE_IF_FAILED("td_thr_event_enable(TD_CREATE)", err);
    err = td_thr_event_enable(&th, TD_DEATH);
    DIE_IF_FAILED("td_thr_event_enable(TD_DEATH)", err);

    // set breakpoints for thread birth/death
    td_thr_events_t events;
    td_event_emptyset(&events);
    td_event_addset(&events, TD_CREATE);
    td_event_addset(&events, TD_DEATH);
    err = td_ta_set_event(ta, &events);
    DIE_IF_FAILED("td_ta_set_event", err);

    tdb_enable_event(TD_CREATE, &birth_bpt);
    tdb_enable_event(TD_DEATH, &death_bpt);
#ifdef LDEB
    msg("thread support has been detected, birth_bpt=%a death_bpt=%a\n", birth_bpt.bpt_addr, death_bpt.bpt_addr);
#endif

/*    // hack: enable thread_td debug. later: it turned out to be useless debug print.
    td_log();
    uchar *ptr = (uchar *)td_log;
    QASSERT(ptr[0] == 0xFF && ptr[1] == 0x25);
    ptr = **(uchar***)(ptr+2);
    ptr += 0x7158 - 0x1120;
    *ptr = 1; // enable
*/
    tdb_update_threads();
  }
  return true;
}
Ejemplo n.º 2
0
static void
maybe_attach_thread (const td_thrhandle_t *th_p, td_thrinfo_t *ti_p)
{
  td_err_e err;
  struct thread_info *inferior;
  struct process_info *process;

  /* If we are attaching to our first thread, things are a little
     different.  */
  if (all_threads.head == all_threads.tail)
    {
      inferior = (struct thread_info *) all_threads.head;
      process = get_thread_process (inferior);
      if (process->thread_known == 0)
	{
	  /* Switch to indexing the threads list by TID.  */
	  change_inferior_id (&all_threads, ti_p->ti_tid);
	  goto found;
	}
    }
  
  inferior = (struct thread_info *) find_inferior_id (&all_threads,
						      ti_p->ti_tid);
  if (inferior != NULL)
    return;

  if (debug_threads)
    fprintf (stderr, "Attaching to thread %ld (LWP %d)\n",
	     ti_p->ti_tid, ti_p->ti_lid);
  linux_attach_lwp (ti_p->ti_lid, ti_p->ti_tid);
  inferior = (struct thread_info *) find_inferior_id (&all_threads,
						      ti_p->ti_tid);
  if (inferior == NULL)
    {
      warning ("Could not attach to thread %ld (LWP %d)\n",
	       ti_p->ti_tid, ti_p->ti_lid);
      return;
    }

  process = inferior_target_data (inferior);

found:
  new_thread_notify (ti_p->ti_tid);

  process->tid = ti_p->ti_tid;
  process->lwpid = ti_p->ti_lid;

  process->thread_known = 1;
  process->th = *th_p;
  err = td_thr_event_enable (th_p, 1);
  if (err != TD_OK)
    error ("Cannot enable thread event reporting for %d: %s",
           ti_p->ti_lid, thread_db_err_str (err));
}
Ejemplo n.º 3
0
//--------------------------------------------------------------------------
void linux_debmod_t::new_thread(thrinfo_t *info)
{
  int tid = info->ti_lid;
  threads_t::iterator p = threads.find(tid);
  if ( p == threads.end() ) // not found
  {
#ifdef LDEB
    msg("thread %d is new\n", tid);
    ::display_thrinfo(*info);
#endif

    td_err_e err;

    td_thr_events_t events;
    td_event_emptyset(&events);
    td_event_addset(&events, TD_CREATE);
    td_event_addset(&events, TD_DEATH);
    td_event_addset(&events, TD_CATCHSIG);
    err = td_thr_set_event(info->th_p, &events);
    DIE_IF_FAILED("td_thr_set_event", err);

    err = td_thr_event_enable(info->th_p, 1);
    COMPLAIN_IF_FAILED("td_thr_event_enable", err);
    if ( err != TD_OK )
    {
#ifdef LDEB
      msg("%d: thread dead already? not adding to list.\n", tid);
#endif
      return;
    }

    sigset_t set;
    sigemptyset(&set);
    sigaddset(&set, SIGSTOP);
    td_thr_setsigpending(info->th_p, 1, &set);

    debug_event_t ev;
    ev.eid     = THREAD_START;
    ev.pid     = process_handle;
    ev.tid     = tid;
    ev.ea      = (ea_t)info->ti_startfunc;
    ev.handled = true;
    add_thread(tid);
    // attach to the thread and make is ready for debugging
    qptrace(PTRACE_ATTACH, tid, 0, 0);
    int status;
    int tid2 = waitpid(tid, &status, __WCLONE); // (must succeed) consume SIGSTOP
    QASSERT(tid2 != -1 && WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP);
    get_thread(tid)->waiting_sigstop = false;
    enqueue_event(ev, IN_FRONT);
  }
  get_thread(tid)->thr = info->th_p;
}
Ejemplo n.º 4
0
static int update_threads_cb(const td_thrhandle_t *th_p, void *data)
{
  thrinfovec_t &newlist = *(thrinfovec_t *)data;

  thrinfo_t ti;
  td_err_e err = td_thr_get_info(th_p, &ti);
  DIE_IF_FAILED("td_thr_get_info", err);

  if ( ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE )
    return 0;

  if ( ti.ti_tid != 0 )
  {
    td_thr_events_t events;
    td_event_emptyset(&events);
    td_event_addset(&events, TD_CREATE);
    td_event_addset(&events, TD_DEATH);
  //  td_event_addset(&events, TD_CATCHSIG);
    err = td_thr_set_event(th_p, &events);
    DIE_IF_FAILED("td_thr_set_event", err);

    err = td_thr_event_enable(th_p, 1);
    DIE_IF_FAILED("td_thr_event_enable", err);

    sigset_t set;
    sigemptyset(&set);
    sigaddset(&set, SIGSTOP);
    td_thr_setsigpending(th_p, 1, &set);
  }

  ti.th_p = th_p;
#ifdef LDEB
  msg("update_threads_cb: got thread %d\n", ti.ti_lid);
  //td_thr_get_info(th_p, &ti);
  //display_thrinfo(ti);
#endif

  newlist.push_back(ti);
  return 0;
}