static char *libthread_db_search_path;
+/* If non-zero, print details of libthread_db processing. */
+
+static int libthread_db_debug;
+
+static void
+show_libthread_db_debug (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ fprintf_filtered (file, _("libthread-db debugging is %s.\n"), value);
+}
+
+
/* If we're running on GNU/Linux, we must explicitly attach to any new
threads. */
info = xcalloc (1, sizeof (*info));
info->pid = ptid_get_pid (inferior_ptid);
info->handle = handle;
- info->need_stale_parent_threads_check = 1;
+
+ /* The workaround works by reading from /proc/pid/status, so it is
+ disabled for core files. */
+ if (target_has_execution)
+ info->need_stale_parent_threads_check = 1;
info->next = thread_db_list;
thread_db_list = info;
thread_db_find_new_threads_2 (ptid, 1);
}
- if (except.reason < 0 && info_verbose)
+ if (except.reason < 0 && libthread_db_debug)
{
exception_fprintf (gdb_stderr, except,
"Warning: thread_db_find_new_threads_silently: ");
err = info->td_ta_new_p (&info->proc_handle, &info->thread_agent);
if (err != TD_OK)
{
- if (info_verbose)
+ if (libthread_db_debug)
printf_unfiltered (_("td_ta_new failed: %s\n"),
thread_db_err_str (err));
else
printf_unfiltered (_("[Thread debugging using libthread_db enabled]\n"));
- if (info_verbose || *libthread_db_search_path)
+ if (libthread_db_debug || *libthread_db_search_path)
{
const char *library;
if (thread_db_list->next == NULL)
push_target (&thread_db_ops);
- enable_thread_event_reporting ();
+ /* Enable event reporting, but not when debugging a core file. */
+ if (target_has_execution)
+ enable_thread_event_reporting ();
/* There appears to be a bug in glibc-2.3.6: calls to td_thr_get_info fail
with TD_ERR for statically linked executables if td_thr_get_info is
void *handle;
struct thread_db_info *info;
- if (info_verbose)
+ if (libthread_db_debug)
printf_unfiltered (_("Trying host libthread_db library: %s.\n"),
library);
handle = dlopen (library, RTLD_NOW);
if (handle == NULL)
{
- if (info_verbose)
+ if (libthread_db_debug)
printf_unfiltered (_("dlopen failed: %s.\n"), dlerror ());
return 0;
}
- if (info_verbose && strchr (library, '/') == NULL)
+ if (libthread_db_debug && strchr (library, '/') == NULL)
{
void *td_init;
if (info != NULL)
return 1;
- /* Don't attempt to use thread_db on targets which can not run
- (executables not running yet, core files) for now. */
- if (!target_has_execution)
+ /* Don't attempt to use thread_db on executables not running
+ yet. */
+ if (!target_has_registers)
return 0;
/* Don't attempt to use thread_db for remote targets. */
- if (!target_can_run (¤t_target))
+ if (!(target_can_run (¤t_target) || core_bfd))
return 0;
if (thread_db_load_search ())
static void
check_thread_signals (void)
{
-#ifdef GET_THREAD_SIGNALS
if (!thread_signals)
{
sigset_t mask;
int i;
- GET_THREAD_SIGNALS (&mask);
+ lin_thread_get_thread_signals (&mask);
sigemptyset (&thread_stop_set);
sigemptyset (&thread_print_set);
}
}
}
-#endif
}
/* Check whether thread_db is usable. This function is called when
}
}
- check_thread_signals ();
+ if (target_has_execution)
+ check_thread_signals ();
if (ti_p->ti_state == TD_THR_UNKNOWN || ti_p->ti_state == TD_THR_ZOMBIE)
return 0; /* A zombie thread -- do not attach. */
/* Under GNU/Linux, we have to attach to each and every thread. */
- if (tp == NULL
+ if (target_has_execution
+ && tp == NULL
&& lin_lwp_attach_lwp (BUILD_LWP (ti_p->ti_lid, GET_PID (ptid))) < 0)
return 0;
info = get_thread_db_info (GET_PID (ptid));
- /* Enable thread event reporting for this thread. */
- err = info->td_thr_event_enable_p (th_p, 1);
- if (err != TD_OK)
- error (_("Cannot enable thread event reporting for %s: %s"),
- target_pid_to_str (ptid), thread_db_err_str (err));
+ /* Enable thread event reporting for this thread, except when
+ debugging a core file. */
+ if (target_has_execution)
+ {
+ err = info->td_thr_event_enable_p (th_p, 1);
+ if (err != TD_OK)
+ error (_("Cannot enable thread event reporting for %s: %s"),
+ target_pid_to_str (ptid), thread_db_err_str (err));
+ }
+
return 1;
}
if (info)
{
- disable_thread_event_reporting (info);
-
- /* Delete the old thread event breakpoints. Note that unlike
- when mourning, we can remove them here because there's still
- a live inferior to poke at. In any case, GDB will not try to
- insert anything in the inferior when removing a
- breakpoint. */
- remove_thread_event_breakpoints ();
+ if (target_has_execution)
+ {
+ disable_thread_event_reporting (info);
+
+ /* Delete the old thread event breakpoints. Note that
+ unlike when mourning, we can remove them here because
+ there's still a live inferior to poke at. In any case,
+ GDB will not try to insert anything in the inferior when
+ removing a breakpoint. */
+ remove_thread_event_breakpoints ();
+ }
delete_thread_db_info (GET_PID (inferior_ptid));
}
if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE)
return 0; /* A zombie -- ignore. */
- if (ti.ti_tid == 0)
+ if (ti.ti_tid == 0 && target_has_execution)
{
/* A thread ID of zero means that this is the main thread, but
glibc has not yet initialized thread-local storage and the
TD_THR_ANY_USER_FLAGS);
}
- if (info_verbose)
+ if (libthread_db_debug)
{
if (except.reason < 0)
exception_fprintf (gdb_stderr, except,
thread_db_find_new_threads_2 (ptid_t ptid, int until_no_new)
{
td_err_e err;
- struct lwp_info *lp;
struct thread_db_info *info;
int pid = ptid_get_pid (ptid);
int i, loop;
- /* In linux, we can only read memory through a stopped lwp. */
- ALL_LWPS (lp, ptid)
- if (lp->stopped && ptid_get_pid (lp->ptid) == pid)
- break;
+ if (target_has_execution)
+ {
+ struct lwp_info *lp;
- if (!lp)
- /* There is no stopped thread. Bail out. */
- return;
+ /* In linux, we can only read memory through a stopped lwp. */
+ ALL_LWPS (lp, ptid)
+ if (lp->stopped && ptid_get_pid (lp->ptid) == pid)
+ break;
+
+ if (!lp)
+ /* There is no stopped thread. Bail out. */
+ return;
+ }
info = get_thread_db_info (GET_PID (ptid));
thread_db_find_new_threads_1 (inferior_ptid);
- iterate_over_lwps (minus_one_ptid /* iterate over all */,
- update_thread_core, NULL);
+ if (target_has_execution)
+ iterate_over_lwps (minus_one_ptid /* iterate over all */,
+ update_thread_core, NULL);
}
static char *
NULL,
NULL,
&setlist, &showlist);
+
+ add_setshow_zinteger_cmd ("libthread-db", class_maintenance,
+ &libthread_db_debug, _("\
+Set libthread-db debugging."), _("\
+Show libthread-db debugging."), _("\
+When non-zero, libthread-db debugging is enabled."),
+ NULL,
+ show_libthread_db_debug,
+ &setdebuglist, &showdebuglist);
+
/* Add ourselves to objfile event chain. */
observer_attach_new_objfile (thread_db_new_objfile);
}