Exemplo 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;
}
Exemplo n.º 2
0
static int
thread_db_enable_reporting ()
{
  td_thr_events_t events;
  td_notify_t notify;
  td_err_e err;

  /* Set the process wide mask saying which events we're interested in.  */
  td_event_emptyset (&events);
  td_event_addset (&events, TD_CREATE);

#if 0
  /* This is reported to be broken in glibc 2.1.3.  A different approach
     will be necessary to support that.  */
  td_event_addset (&events, TD_DEATH);
#endif

  err = td_ta_set_event (thread_agent, &events);
  if (err != TD_OK)
    {
      warning ("Unable to set global thread event mask: %s",
               thread_db_err_str (err));
      return 0;
    }

  /* Get address for thread creation breakpoint.  */
  err = td_ta_event_addr (thread_agent, TD_CREATE, &notify);
  if (err != TD_OK)
    {
      warning ("Unable to get location for thread creation breakpoint: %s",
	       thread_db_err_str (err));
      return 0;
    }
  set_breakpoint_at ((CORE_ADDR) (unsigned long) notify.u.bptaddr,
		     thread_db_create_event);

#if 0
  /* Don't concern ourselves with reported thread deaths, only
     with actual thread deaths (via wait).  */

  /* Get address for thread death breakpoint.  */
  err = td_ta_event_addr (thread_agent, TD_DEATH, &notify);
  if (err != TD_OK)
    {
      warning ("Unable to get location for thread death breakpoint: %s",
	       thread_db_err_str (err));
      return;
    }
  set_breakpoint_at ((CORE_ADDR) (unsigned long) notify.u.bptaddr,
		     thread_db_death_event);
#endif

  return 1;
}