void linux_debmod_t::display_all_threads() { if ( ta != NULL ) { td_err_e err = td_ta_thr_iter(ta, display_thread_cb, NULL, TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); COMPLAIN_IF_FAILED("td_ta_thr_iter", err); } }
gboolean mono_debugger_thread_db_iterate_over_threads (ThreadDbHandle *handle, IterateOverThreadsFunc func) { td_thrhandle_t th; td_err_e e; e = td_ta_thr_iter (handle->thread_agent, iterate_over_threads_cb, func, TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); return e == PS_OK; }
static void thread_db_find_new_threads (void) { td_err_e err; /* Iterate over all user-space threads to discover new threads. */ err = td_ta_thr_iter (thread_agent, find_new_threads_callback, NULL, TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); if (err != TD_OK) error ("Cannot find new threads: %s", thread_db_err_str (err)); }
// 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); }
td_err_e td_ta_event_getmsg(td_thragent_t const * agent, td_event_msg_t * event) { td_err_e err; void * bkpt_addr; err = ps_pglobal_lookup(NULL, NULL, gSymbols[SYM_TD_CREATE], &bkpt_addr); if (err) { return err; } err = td_ta_thr_iter(agent, _event_getmsg_helper, bkpt_addr, 0, 0, NULL, 0); if (err != 0x42) { return TD_NOMSG; } event->event = TD_CREATE; event->th_p = &gEventMsgHandle; // Nasty hack, but it's the only way! return TD_OK; }
// 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; }
//-------------------------------------------------------------------------- void linux_debmod_t::tdb_update_threads(void) { if ( ta != NULL ) { thrinfovec_t newlist; td_err_e err = td_ta_thr_iter(ta, update_threads_cb, &newlist, TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); COMPLAIN_IF_FAILED("td_ta_thr_iter", err); if ( err != TD_OK ) return; // generate THREAD_EXIT events for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) { int i; int tid = p->first; for ( i=0; i < newlist.size(); i++ ) if ( newlist[i].ti_lid == tid ) break; if ( i == newlist.size() ) // not found { debug_event_t ev; ev.eid = THREAD_EXIT; ev.pid = process_handle; ev.tid = tid; ev.ea = BADADDR; ev.handled = true; ev.exit_code = 0; // ??? enqueue_event(ev, IN_BACK); } } // generate THREAD_START events for ( int i=0; i < newlist.size(); i++ ) { int tid = newlist[i].ti_lid; // display_thrinfo(tid); threads_t::iterator p = threads.find(tid); if ( p == threads.end() ) // not found { debug_event_t ev; ev.eid = THREAD_START; ev.pid = process_handle; ev.tid = tid; ev.ea = birth_bpt.bpt_addr; // just to show something ev.handled = true; add_thread(tid); enqueue_event(ev, IN_FRONT); // 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; } get_thread(tid)->thr = newlist[i].th_p; } } }