You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openwrt/toolchain/gdb/patches/710-debian_thread-db-multip...

594 lines
21 KiB
Diff

Support loading two libthread_db DSOs. In this case, the LinuxThreads
and NPTL ones.
Index: gdb-6.3/gdb/thread-db.c
===================================================================
--- gdb-6.3.orig/gdb/thread-db.c 2004-11-10 10:46:24.000000000 -0500
+++ gdb-6.3/gdb/thread-db.c 2004-11-10 11:22:34.858812426 -0500
@@ -79,53 +79,63 @@ static td_thragent_t *thread_agent;
/* Pointers to the libthread_db functions. */
-static td_err_e (*td_init_p) (void);
+struct thread_db_pointers
+{
+ const char *filename;
+
+ td_err_e (*td_init_p) (void);
-static td_err_e (*td_ta_new_p) (struct ps_prochandle * ps,
- td_thragent_t **ta);
-static td_err_e (*td_ta_map_id2thr_p) (const td_thragent_t *ta, thread_t pt,
- td_thrhandle_t *__th);
-static td_err_e (*td_ta_map_lwp2thr_p) (const td_thragent_t *ta,
- lwpid_t lwpid, td_thrhandle_t *th);
-static td_err_e (*td_ta_thr_iter_p) (const td_thragent_t *ta,
- td_thr_iter_f *callback, void *cbdata_p,
- td_thr_state_e state, int ti_pri,
- sigset_t *ti_sigmask_p,
- unsigned int ti_user_flags);
-static td_err_e (*td_ta_event_addr_p) (const td_thragent_t *ta,
- td_event_e event, td_notify_t *ptr);
-static td_err_e (*td_ta_set_event_p) (const td_thragent_t *ta,
- td_thr_events_t *event);
-static td_err_e (*td_ta_event_getmsg_p) (const td_thragent_t *ta,
- td_event_msg_t *msg);
-
-static td_err_e (*td_thr_validate_p) (const td_thrhandle_t *th);
-static td_err_e (*td_thr_get_info_p) (const td_thrhandle_t *th,
- td_thrinfo_t *infop);
-static td_err_e (*td_thr_getfpregs_p) (const td_thrhandle_t *th,
- gdb_prfpregset_t *regset);
-static td_err_e (*td_thr_getgregs_p) (const td_thrhandle_t *th,
- prgregset_t gregs);
-static td_err_e (*td_thr_setfpregs_p) (const td_thrhandle_t *th,
- const gdb_prfpregset_t *fpregs);
-static td_err_e (*td_thr_setgregs_p) (const td_thrhandle_t *th,
- prgregset_t gregs);
-static td_err_e (*td_thr_event_enable_p) (const td_thrhandle_t *th,
- int event);
-
-static td_err_e (*td_thr_tls_get_addr_p) (const td_thrhandle_t *th,
- void *map_address,
- size_t offset, void **address);
+ td_err_e (*td_ta_new_p) (struct ps_prochandle * ps,
+ td_thragent_t **ta);
+ td_err_e (*td_ta_map_id2thr_p) (const td_thragent_t *ta, thread_t pt,
+ td_thrhandle_t *__th);
+ td_err_e (*td_ta_map_lwp2thr_p) (const td_thragent_t *ta,
+ lwpid_t lwpid, td_thrhandle_t *th);
+
+ td_err_e (*td_ta_thr_iter_p) (const td_thragent_t *ta,
+ td_thr_iter_f *callback, void *cbdata_p,
+ td_thr_state_e state, int ti_pri,
+ sigset_t *ti_sigmask_p,
+ unsigned int ti_user_flags);
+ td_err_e (*td_ta_event_addr_p) (const td_thragent_t *ta,
+ td_event_e event, td_notify_t *ptr);
+ td_err_e (*td_ta_set_event_p) (const td_thragent_t *ta,
+ td_thr_events_t *event);
+ td_err_e (*td_ta_event_getmsg_p) (const td_thragent_t *ta,
+ td_event_msg_t *msg);
+
+ td_err_e (*td_thr_validate_p) (const td_thrhandle_t *th);
+ td_err_e (*td_thr_get_info_p) (const td_thrhandle_t *th,
+ td_thrinfo_t *infop);
+ td_err_e (*td_thr_getfpregs_p) (const td_thrhandle_t *th,
+ gdb_prfpregset_t *regset);
+ td_err_e (*td_thr_getgregs_p) (const td_thrhandle_t *th,
+ prgregset_t gregs);
+ td_err_e (*td_thr_setfpregs_p) (const td_thrhandle_t *th,
+ const gdb_prfpregset_t *fpregs);
+ td_err_e (*td_thr_setgregs_p) (const td_thrhandle_t *th,
+ prgregset_t gregs);
+ td_err_e (*td_thr_event_enable_p) (const td_thrhandle_t *th,
+ int event);
+
+ td_err_e (*td_thr_tls_get_addr_p) (const td_thrhandle_t *th,
+ void *map_address,
+ size_t offset, void **address);
+
+ struct thread_db_pointers *next;
+};
/* Location of the thread creation event breakpoint. The code at this
location in the child process will be called by the pthread library
whenever a new thread is created. By setting a special breakpoint
at this location, GDB can detect when a new thread is created. We
obtain this location via the td_ta_event_addr call. */
-static CORE_ADDR td_create_bp_addr;
+CORE_ADDR td_create_bp_addr;
/* Location of the thread death event breakpoint. */
-static CORE_ADDR td_death_bp_addr;
+CORE_ADDR td_death_bp_addr;
+
+static struct thread_db_pointers *current_pointers, *all_pointers;
/* Prototypes for local functions. */
static void thread_db_find_new_threads (void);
@@ -262,7 +272,7 @@ thread_get_info_callback (const td_thrha
struct thread_info *thread_info;
ptid_t thread_ptid;
- err = td_thr_get_info_p (thp, &ti);
+ err = current_pointers->td_thr_get_info_p (thp, &ti);
if (err != TD_OK)
error ("thread_get_info_callback: cannot get thread info: %s",
thread_db_err_str (err));
@@ -316,8 +326,9 @@ thread_db_map_id2thr (struct thread_info
if (thread_info->private->th_valid)
return;
- err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (thread_info->ptid),
- &thread_info->private->th);
+ err = current_pointers->td_ta_map_id2thr_p (thread_agent,
+ GET_THREAD (thread_info->ptid),
+ &thread_info->private->th);
if (err != TD_OK)
{
if (fatal)
@@ -340,8 +351,8 @@ thread_db_get_info (struct thread_info *
if (!thread_info->private->th_valid)
thread_db_map_id2thr (thread_info, 1);
- err =
- td_thr_get_info_p (&thread_info->private->th, &thread_info->private->ti);
+ err = current_pointers->td_thr_get_info_p (&thread_info->private->th,
+ &thread_info->private->ti);
if (err != TD_OK)
error ("thread_db_get_info: cannot get thread info: %s",
thread_db_err_str (err));
@@ -365,7 +376,8 @@ thread_from_lwp (ptid_t ptid)
gdb_assert (is_lwp (ptid));
- err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th);
+ err = current_pointers->td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid),
+ &th);
if (err != TD_OK)
error ("Cannot find user-level thread for LWP %ld: %s",
GET_LWP (ptid), thread_db_err_str (err));
@@ -420,85 +432,102 @@ verbose_dlsym (void *handle, const char
return sym;
}
-static int
-thread_db_load (void)
+static struct thread_db_pointers *
+thread_db_load (const char *name)
{
+ struct thread_db_pointers *ptrs;
+ Dl_info info;
void *handle;
td_err_e err;
- handle = dlopen (LIBTHREAD_DB_SO, RTLD_NOW);
+ ptrs = xcalloc (1, sizeof (struct thread_db_pointers));
+
+ handle = dlopen (name, RTLD_NOW);
if (handle == NULL)
{
- fprintf_filtered (gdb_stderr, "\n\ndlopen failed on '%s' - %s\n",
- LIBTHREAD_DB_SO, dlerror ());
- fprintf_filtered (gdb_stderr,
- "GDB will not be able to debug pthreads.\n\n");
+ if (all_pointers == NULL)
+ {
+ fprintf_filtered (gdb_stderr, "\n\ndlopen failed on '%s' - %s\n",
+ name, dlerror ());
+ fprintf_filtered (gdb_stderr,
+ "GDB will not be able to debug pthreads.\n\n");
+ }
return 0;
}
/* Initialize pointers to the dynamic library functions we will use.
Essential functions first. */
- td_init_p = verbose_dlsym (handle, "td_init");
- if (td_init_p == NULL)
+ ptrs->td_init_p = verbose_dlsym (handle, "td_init");
+ if (ptrs->td_init_p == NULL)
return 0;
- td_ta_new_p = verbose_dlsym (handle, "td_ta_new");
- if (td_ta_new_p == NULL)
+ ptrs->td_ta_new_p = verbose_dlsym (handle, "td_ta_new");
+ if (ptrs->td_ta_new_p == NULL)
return 0;
- td_ta_map_id2thr_p = verbose_dlsym (handle, "td_ta_map_id2thr");
- if (td_ta_map_id2thr_p == NULL)
+ ptrs->td_ta_map_id2thr_p = verbose_dlsym (handle, "td_ta_map_id2thr");
+ if (ptrs->td_ta_map_id2thr_p == NULL)
return 0;
- td_ta_map_lwp2thr_p = verbose_dlsym (handle, "td_ta_map_lwp2thr");
- if (td_ta_map_lwp2thr_p == NULL)
+ ptrs->td_ta_map_lwp2thr_p = verbose_dlsym (handle, "td_ta_map_lwp2thr");
+ if (ptrs->td_ta_map_lwp2thr_p == NULL)
return 0;
- td_ta_thr_iter_p = verbose_dlsym (handle, "td_ta_thr_iter");
- if (td_ta_thr_iter_p == NULL)
+ ptrs->td_ta_thr_iter_p = verbose_dlsym (handle, "td_ta_thr_iter");
+ if (ptrs->td_ta_thr_iter_p == NULL)
return 0;
- td_thr_validate_p = verbose_dlsym (handle, "td_thr_validate");
- if (td_thr_validate_p == NULL)
+ ptrs->td_thr_validate_p = verbose_dlsym (handle, "td_thr_validate");
+ if (ptrs->td_thr_validate_p == NULL)
return 0;
- td_thr_get_info_p = verbose_dlsym (handle, "td_thr_get_info");
- if (td_thr_get_info_p == NULL)
+ ptrs->td_thr_get_info_p = verbose_dlsym (handle, "td_thr_get_info");
+ if (ptrs->td_thr_get_info_p == NULL)
return 0;
- td_thr_getfpregs_p = verbose_dlsym (handle, "td_thr_getfpregs");
- if (td_thr_getfpregs_p == NULL)
+ ptrs->td_thr_getfpregs_p = verbose_dlsym (handle, "td_thr_getfpregs");
+ if (ptrs->td_thr_getfpregs_p == NULL)
return 0;
- td_thr_getgregs_p = verbose_dlsym (handle, "td_thr_getgregs");
- if (td_thr_getgregs_p == NULL)
+ ptrs->td_thr_getgregs_p = verbose_dlsym (handle, "td_thr_getgregs");
+ if (ptrs->td_thr_getgregs_p == NULL)
return 0;
- td_thr_setfpregs_p = verbose_dlsym (handle, "td_thr_setfpregs");
- if (td_thr_setfpregs_p == NULL)
+ ptrs->td_thr_setfpregs_p = verbose_dlsym (handle, "td_thr_setfpregs");
+ if (ptrs->td_thr_setfpregs_p == NULL)
return 0;
- td_thr_setgregs_p = verbose_dlsym (handle, "td_thr_setgregs");
- if (td_thr_setgregs_p == NULL)
+ ptrs->td_thr_setgregs_p = verbose_dlsym (handle, "td_thr_setgregs");
+ if (ptrs->td_thr_setgregs_p == NULL)
return 0;
/* Initialize the library. */
- err = td_init_p ();
+ err = ptrs->td_init_p ();
if (err != TD_OK)
{
warning ("Cannot initialize libthread_db: %s", thread_db_err_str (err));
+ xfree (ptrs);
return 0;
}
/* These are not essential. */
- td_ta_event_addr_p = dlsym (handle, "td_ta_event_addr");
- td_ta_set_event_p = dlsym (handle, "td_ta_set_event");
- td_ta_event_getmsg_p = dlsym (handle, "td_ta_event_getmsg");
- td_thr_event_enable_p = dlsym (handle, "td_thr_event_enable");
- td_thr_tls_get_addr_p = dlsym (handle, "td_thr_tls_get_addr");
+ ptrs->td_ta_event_addr_p = dlsym (handle, "td_ta_event_addr");
+ ptrs->td_ta_set_event_p = dlsym (handle, "td_ta_set_event");
+ ptrs->td_ta_event_getmsg_p = dlsym (handle, "td_ta_event_getmsg");
+ ptrs->td_thr_event_enable_p = dlsym (handle, "td_thr_event_enable");
+ ptrs->td_thr_tls_get_addr_p = dlsym (handle, "td_thr_tls_get_addr");
+
+ if (dladdr (ptrs->td_ta_new_p, &info) != 0)
+ ptrs->filename = info.dli_fname;
+
+ /* Try dlinfo? */
+
+ if (ptrs->filename == NULL)
+ /* Paranoid - don't let a NULL path slip through. */
+ ptrs->filename = name;
- return 1;
+ return ptrs;
}
static td_err_e
@@ -508,7 +537,7 @@ enable_thread_event (td_thragent_t *thre
td_err_e err;
/* Get the breakpoint address for thread EVENT. */
- err = td_ta_event_addr_p (thread_agent, event, &notify);
+ err = current_pointers->td_ta_event_addr_p (thread_agent, event, &notify);
if (err != TD_OK)
return err;
@@ -534,8 +563,10 @@ enable_thread_event_reporting (void)
/* We cannot use the thread event reporting facility if these
functions aren't available. */
- if (td_ta_event_addr_p == NULL || td_ta_set_event_p == NULL
- || td_ta_event_getmsg_p == NULL || td_thr_event_enable_p == NULL)
+ if (current_pointers->td_ta_event_addr_p == NULL
+ || current_pointers->td_ta_set_event_p == NULL
+ || current_pointers->td_ta_event_getmsg_p == NULL
+ || current_pointers->td_thr_event_enable_p == NULL)
return;
/* Set the process wide mask saying which events we're interested in. */
@@ -552,7 +583,7 @@ enable_thread_event_reporting (void)
#endif
td_event_addset (&events, TD_DEATH);
- err = td_ta_set_event_p (thread_agent, &events);
+ err = current_pointers->td_ta_set_event_p (thread_agent, &events);
if (err != TD_OK)
{
warning ("Unable to set global thread event mask: %s",
@@ -592,7 +623,7 @@ disable_thread_event_reporting (void)
/* Set the process wide mask saying we aren't interested in any
events anymore. */
td_event_emptyset (&events);
- td_ta_set_event_p (thread_agent, &events);
+ current_pointers->td_ta_set_event_p (thread_agent, &events);
/* Delete thread event breakpoints, if any. */
remove_thread_event_breakpoints ();
@@ -635,7 +666,6 @@ check_thread_signals (void)
static void
check_for_thread_db (void)
{
- td_err_e err;
static int already_loaded;
/* First time through, report that libthread_db was successfuly
@@ -644,19 +674,8 @@ check_for_thread_db (void)
if (!already_loaded)
{
- Dl_info info;
- const char *library = NULL;
- if (dladdr ((*td_ta_new_p), &info) != 0)
- library = info.dli_fname;
-
- /* Try dlinfo? */
-
- if (library == NULL)
- /* Paranoid - don't let a NULL path slip through. */
- library = LIBTHREAD_DB_SO;
-
printf_unfiltered ("Using host libthread_db library \"%s\".\n",
- library);
+ all_pointers->filename);
already_loaded = 1;
}
@@ -674,28 +693,34 @@ check_for_thread_db (void)
proc_handle.pid = GET_PID (inferior_ptid);
/* Now attempt to open a connection to the thread library. */
- err = td_ta_new_p (&proc_handle, &thread_agent);
- switch (err)
+ for (current_pointers = all_pointers;
+ current_pointers != NULL;
+ current_pointers = current_pointers->next)
{
- case TD_NOLIBTHREAD:
- /* No thread library was detected. */
- break;
-
- case TD_OK:
- printf_unfiltered ("[Thread debugging using libthread_db enabled]\n");
+ td_err_e err;
+ err = current_pointers->td_ta_new_p (&proc_handle, &thread_agent);
+ switch (err)
+ {
+ case TD_NOLIBTHREAD:
+ /* No thread library was detected. */
+ break;
- /* The thread library was detected. Activate the thread_db target. */
- push_target (&thread_db_ops);
- using_thread_db = 1;
+ case TD_OK:
+ printf_unfiltered ("[Thread debugging using libthread_db enabled]\n");
- enable_thread_event_reporting ();
- thread_db_find_new_threads ();
- break;
+ /* The thread library was detected. Activate the thread_db target. */
+ push_target (&thread_db_ops);
+ using_thread_db = 1;
+
+ enable_thread_event_reporting ();
+ thread_db_find_new_threads ();
+ return;
- default:
- warning ("Cannot initialize thread debugging library: %s",
- thread_db_err_str (err));
- break;
+ default:
+ warning ("Cannot initialize thread debugging library: %s",
+ thread_db_err_str (err));
+ break;
+ }
}
}
@@ -766,7 +791,7 @@ attach_thread (ptid_t ptid, const td_thr
#endif
/* Enable thread event reporting for this thread. */
- err = td_thr_event_enable_p (th_p, 1);
+ err = current_pointers->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));
@@ -892,7 +917,7 @@ check_event (ptid_t ptid)
do
{
- err = td_ta_event_getmsg_p (thread_agent, &msg);
+ err = current_pointers->td_ta_event_getmsg_p (thread_agent, &msg);
if (err != TD_OK)
{
if (err == TD_NOMSG)
@@ -902,7 +927,7 @@ check_event (ptid_t ptid)
thread_db_err_str (err));
}
- err = td_thr_get_info_p (msg.th_p, &ti);
+ err = current_pointers->td_thr_get_info_p (msg.th_p, &ti);
if (err != TD_OK)
error ("Cannot get thread info: %s", thread_db_err_str (err));
@@ -1015,12 +1040,14 @@ thread_db_fetch_registers (int regno)
thread_info = find_thread_pid (inferior_ptid);
thread_db_map_id2thr (thread_info, 1);
- err = td_thr_getgregs_p (&thread_info->private->th, gregset);
+ err = current_pointers->td_thr_getgregs_p (&thread_info->private->th,
+ gregset);
if (err != TD_OK)
error ("Cannot fetch general-purpose registers for thread %ld: %s",
(long) GET_THREAD (inferior_ptid), thread_db_err_str (err));
- err = td_thr_getfpregs_p (&thread_info->private->th, &fpregset);
+ err = current_pointers->td_thr_getfpregs_p (&thread_info->private->th,
+ &fpregset);
if (err != TD_OK)
error ("Cannot get floating-point registers for thread %ld: %s",
(long) GET_THREAD (inferior_ptid), thread_db_err_str (err));
@@ -1062,11 +1089,13 @@ thread_db_store_registers (int regno)
fill_gregset ((gdb_gregset_t *) gregset, -1);
fill_fpregset (&fpregset, -1);
- err = td_thr_setgregs_p (&thread_info->private->th, gregset);
+ err = current_pointers->td_thr_setgregs_p (&thread_info->private->th,
+ gregset);
if (err != TD_OK)
error ("Cannot store general-purpose registers for thread %ld: %s",
(long) GET_THREAD (inferior_ptid), thread_db_err_str (err));
- err = td_thr_setfpregs_p (&thread_info->private->th, &fpregset);
+ err = current_pointers->td_thr_setfpregs_p (&thread_info->private->th,
+ &fpregset);
if (err != TD_OK)
error ("Cannot store floating-point registers for thread %ld: %s",
(long) GET_THREAD (inferior_ptid), thread_db_err_str (err));
@@ -1136,15 +1165,14 @@ thread_db_thread_alive (ptid_t ptid)
if (!thread_info->private->th_valid)
return 0;
- err = td_thr_validate_p (&thread_info->private->th);
+ err = current_pointers->td_thr_validate_p (&thread_info->private->th);
if (err != TD_OK)
return 0;
if (!thread_info->private->ti_valid)
{
- err =
- td_thr_get_info_p (&thread_info->private->th,
- &thread_info->private->ti);
+ err = current_pointers->td_thr_get_info_p
+ (&thread_info->private->th, &thread_info->private->ti);
if (err != TD_OK)
return 0;
thread_info->private->ti_valid = 1;
@@ -1170,7 +1198,7 @@ find_new_threads_callback (const td_thrh
td_err_e err;
ptid_t ptid;
- err = td_thr_get_info_p (th_p, &ti);
+ err = current_pointers->td_thr_get_info_p (th_p, &ti);
if (err != TD_OK)
error ("find_new_threads_callback: cannot get thread info: %s",
thread_db_err_str (err));
@@ -1192,9 +1220,10 @@ 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_p (thread_agent, find_new_threads_callback, NULL,
- TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
- TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
+ err = current_pointers->td_ta_thr_iter_p
+ (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));
}
@@ -1257,7 +1286,7 @@ thread_db_get_thread_local_address (ptid
struct thread_info *thread_info;
/* glibc doesn't provide the needed interface. */
- if (!td_thr_tls_get_addr_p)
+ if (!current_pointers->td_thr_tls_get_addr_p)
error ("Cannot find thread-local variables in this thread library.");
/* Get the address of the link map for this objfile. */
@@ -1279,8 +1308,8 @@ thread_db_get_thread_local_address (ptid
thread_db_map_id2thr (thread_info, 1);
/* Finally, get the address of the variable. */
- err = td_thr_tls_get_addr_p (&thread_info->private->th, (void *) lm,
- offset, &address);
+ err = current_pointers->td_thr_tls_get_addr_p
+ (&thread_info->private->th, (void *) lm, offset, &address);
#ifdef THREAD_DB_HAS_TD_NOTALLOC
/* The memory hasn't been allocated, yet. */
@@ -1360,17 +1389,49 @@ init_thread_db_ops (void)
void
_initialize_thread_db (void)
{
+ struct thread_db_pointers *ptrs;
+ const char *p;
+
/* Only initialize the module if we can load libthread_db. */
- if (thread_db_load ())
- {
- init_thread_db_ops ();
- add_target (&thread_db_ops);
+ ptrs = thread_db_load (LIBTHREAD_DB_SO);
+ if (ptrs == NULL)
+ return;
+
+ all_pointers = ptrs;
- /* Add ourselves to objfile event chain. */
- target_new_objfile_chain = deprecated_target_new_objfile_hook;
- deprecated_target_new_objfile_hook = thread_db_new_objfile;
+ /* Some GNU/Linux systems have more than one binary-compatible copy
+ of libthread_db. If we can find a second one, load that too.
+ The inferior may force the use of a different threading package
+ than we expect. Our guess for the location is somewhat hokey:
+ strip out anything between /lib (or /lib64) and LIBTHREAD_DB_SO.
+ If we loaded the NPTL libthread_db by default, this may find us
+ the LinuxThreads copy. */
+ p = strrchr (ptrs->filename, '/');
+ while (p != NULL && p > ptrs->filename)
+ {
+ const char *component;
- /* Register ourselves for the new inferior observer. */
- observer_attach_inferior_created (check_for_thread_db_observer);
+ component = memrchr (ptrs->filename, '/', p - ptrs->filename);
+ if (component != NULL && strncmp (component, "/lib", 4) == 0)
+ {
+ char *new_name = xmalloc (p - ptrs->filename + 2
+ + strlen (LIBTHREAD_DB_SO));
+ memcpy (new_name, ptrs->filename, p - ptrs->filename + 1);
+ strcpy (new_name + (p - ptrs->filename) + 1, LIBTHREAD_DB_SO);
+ ptrs->next = thread_db_load (new_name);
+ xfree (new_name);
+ break;
+ }
+ p = component;
}
+
+ init_thread_db_ops ();
+ add_target (&thread_db_ops);
+
+ /* Add ourselves to objfile event chain. */
+ target_new_objfile_chain = deprecated_target_new_objfile_hook;
+ deprecated_target_new_objfile_hook = thread_db_new_objfile;
+
+ /* Register ourselves for the new inferior observer. */
+ observer_attach_inferior_created (check_for_thread_db_observer);
}