//-------------------------------------------------------------------------- // 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; }
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, ¬ify); 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, ¬ify); 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; }