Exemplo n.º 1
0
int initialize_thread_db(pid_t pid, struct gdb_target_s *t)
{
  int ret;
  ret = td_init ();
  if (ret != TD_OK)
    return RET_ERR;

  _target.ph.pid = pid;
  _target.ph.target = t;
  ret = td_ta_new (&_target.ph, &_target.thread_agent);
  switch (ret)
    {
    case TD_NOLIBTHREAD:
      /* Thread library not detected */
      _target.ph.pid = 0;
      _target.ph.target = NULL;
      return RET_ERR;
      
    case TD_OK:
      /* Thread library detected */
      return RET_OK;

    default:
      fprintf(stderr, "Error initializing thread_db library\n");
      _target.ph.pid = 0;
      _target.ph.target = NULL;
      return RET_ERR;
    }
  return RET_OK;
}
Exemplo n.º 2
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.º 3
0
// pid is already attached to. use this function to attach to the rest of
// threads that belong to the same overall process.
bool attach_threads(pid_t pid) {
  td_err_e err;
  td_thragent_t *thread_agent;
  struct ps_prochandle proc_handle;

  guarantee(debuggee.pid == pid, "wrong pid value");

  proc_handle.pid = pid;
  err = td_ta_new(&proc_handle, &thread_agent);
  
  // assume "pid" is already attached to. we need to figure out all other LWPs 
  // that belong to the process and then attach to each of them.
  err = td_ta_thr_iter(thread_agent, new_thread_callback, NULL,
                       TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
                       TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);

  return (err = TD_OK ? true : false);
}
Exemplo n.º 4
0
int
thread_db_init ()
{
  int err;

  /* FIXME drow/2004-10-16: This is the "overall process ID", which
     GNU/Linux calls tgid, "thread group ID".  When we support
     attaching to threads, the original thread may not be the correct
     thread.  We would have to get the process ID from /proc for NPTL.
     For LinuxThreads we could do something similar: follow the chain
     of parent processes until we find the highest one we're attached
     to, and use its tgid.

     This isn't the only place in gdbserver that assumes that the first
     process in the list is the thread group leader.  */
  proc_handle.pid = ((struct inferior_list_entry *)current_inferior)->id;

  /* Allow new symbol lookups.  */
  all_symbols_looked_up = 0;

  err = td_ta_new (&proc_handle, &thread_agent);
  switch (err)
    {
    case TD_NOLIBTHREAD:
      /* No thread library was detected.  */
      return 0;

    case TD_OK:
      /* The thread library was detected.  */

      if (thread_db_enable_reporting () == 0)
	return 0;
      thread_db_find_new_threads ();
      thread_db_look_up_symbols ();
      all_symbols_looked_up = 1;
      return 1;

    default:
      warning ("error initializing thread_db library: %s",
	       thread_db_err_str (err));
    }

  return 0;
}
Exemplo n.º 5
0
// read thread_info using libthread_db
bool read_thread_info(struct ps_prochandle* ph, thread_info_callback cb) {
  struct thread_db_client_data mydata;
  td_thragent_t* thread_agent = NULL;
  if (td_ta_new(ph, &thread_agent) != TD_OK) {
     print_debug("can't create libthread_db agent\n");
     return false;
  }

  mydata.ph = ph;
  mydata.callback = cb;

  // we use libthread_db iterator to iterate thru list of threads.
  if (td_ta_thr_iter(thread_agent, thread_db_callback, &mydata,
                 TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
                 TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS) != TD_OK) {
     td_ta_delete(thread_agent);
     return false;
  }

  // delete thread agent
  td_ta_delete(thread_agent);
  return true;
}
Exemplo n.º 6
0
ThreadDbHandle *
mono_debugger_thread_db_init (guint32 pid, GlobalLookupFunc global_lookup,
			      ReadMemoryFunc read_memory, WriteMemoryFunc write_memory)
{
	ThreadDbHandle *handle;
	td_err_e e;

	e = td_init ();
	if (e)
		return NULL;

	handle = g_new0 (ThreadDbHandle, 1);
	handle->pid = pid;
	handle->global_lookup = global_lookup;
	handle->read_memory = read_memory;
	handle->write_memory = write_memory;

	e = td_ta_new (handle, &handle->thread_agent);
	if (e)
		return NULL;

	return handle;
}