Fix debugging programs statically linked against the thread library.

* thread-db.c: Various comment fixes and additions.
Include "bfd.h", "symfile.h" and "objfiles.h".
(keep_thread_db): New variable.
(find_new_threads_callback): Remove prototype.
(thread_db_find_new_threads): New prototype.
(thread_db_push_target, thread_db_unpush_target): Remove
functions.
(deactivate_target): New function.
(thread_db_new_objfile): If OBJFILE == NULL, force deactivation of
target vector.  Activate target vector directly instead of calling
thread_db_push_target.  Set keep_thread_db if thread library is
detected in the main symbol file.  Only enable thread event
reporting if there actually is a child process.  Likewise for
detecting new threads, done by calling thread_db_find_new_threads
instead of iterating over the threads ourselves.
(thread_db_detach): Call deactivate_target instead of
thread_db_unpush_target.
(thread_db_wait): Bail out early if we're not debugging the
multi-threaded child process yet.
(thread_db_post_startup_inferior): New function.
(thread_db_mourn_inferior): Call deactivate_target instead of
thread_db_unpush_target.
(init_thread_db_ops): Add thread_db_post_startup_inferior to
thread_db_ops.
This commit is contained in:
Mark Kettenis 2000-12-27 21:37:57 +00:00
parent b6f6b44d62
commit bda9cb723c
2 changed files with 107 additions and 45 deletions

View file

@ -1,3 +1,31 @@
2000-12-27 Mark Kettenis <kettenis@gnu.org>
Fix debugging programs statically linked against the thread library.
* thread-db.c: Various comment fixes and additions.
Include "bfd.h", "symfile.h" and "objfiles.h".
(keep_thread_db): New variable.
(find_new_threads_callback): Remove prototype.
(thread_db_find_new_threads): New prototype.
(thread_db_push_target, thread_db_unpush_target): Remove
functions.
(deactivate_target): New function.
(thread_db_new_objfile): If OBJFILE == NULL, force deactivation of
target vector. Activate target vector directly instead of calling
thread_db_push_target. Set keep_thread_db if thread library is
detected in the main symbol file. Only enable thread event
reporting if there actually is a child process. Likewise for
detecting new threads, done by calling thread_db_find_new_threads
instead of iterating over the threads ourselves.
(thread_db_detach): Call deactivate_target instead of
thread_db_unpush_target.
(thread_db_wait): Bail out early if we're not debugging the
multi-threaded child process yet.
(thread_db_post_startup_inferior): New function.
(thread_db_mourn_inferior): Call deactivate_target instead of
thread_db_unpush_target.
(init_thread_db_ops): Add thread_db_post_startup_inferior to
thread_db_ops.
2000-12-22 Mark Kettenis <kettenis@gnu.org> 2000-12-22 Mark Kettenis <kettenis@gnu.org>
* solib.c (solib_open): If path is relative, look for it * solib.c (solib_open): If path is relative, look for it

View file

@ -25,8 +25,11 @@
#include "gdb_proc_service.h" #include "gdb_proc_service.h"
#include "gdb_thread_db.h" #include "gdb_thread_db.h"
#include "bfd.h"
#include "gdbthread.h" #include "gdbthread.h"
#include "inferior.h" #include "inferior.h"
#include "symfile.h"
#include "objfiles.h"
#include "target.h" #include "target.h"
#ifndef LIBTHREAD_DB_SO #ifndef LIBTHREAD_DB_SO
@ -52,6 +55,9 @@ static void (*target_new_objfile_chain) (struct objfile *objfile);
/* Non-zero if we're using this module's target vector. */ /* Non-zero if we're using this module's target vector. */
static int using_thread_db; static int using_thread_db;
/* Non-zero if we musn't deactivate this module's target vector. */
static int keep_thread_db;
/* Non-zero if we have determined the signals used by the threads /* Non-zero if we have determined the signals used by the threads
library. */ library. */
static int thread_signals; static int thread_signals;
@ -110,7 +116,7 @@ static CORE_ADDR td_create_bp_addr;
static CORE_ADDR td_death_bp_addr; static CORE_ADDR td_death_bp_addr;
/* Prototypes for local functions. */ /* Prototypes for local functions. */
static int find_new_threads_callback (const td_thrhandle_t *th_p, void *data); static void thread_db_find_new_threads (void);
/* Building process ids. */ /* Building process ids. */
@ -499,23 +505,17 @@ disable_thread_signals (void)
} }
static void static void
thread_db_push_target (void) deactivate_target (void)
{ {
using_thread_db = 1; /* Forget about the child's process ID. We shouldn't need it
anymore. */
proc_handle.pid = 0;
/* Push this target vector. */ if (! keep_thread_db)
push_target (&thread_db_ops); {
using_thread_db = 0;
enable_thread_event_reporting (); unpush_target (&thread_db_ops);
} }
static void
thread_db_unpush_target (void)
{
/* Unpush this target vector. */
unpush_target (&thread_db_ops);
using_thread_db = 0;
} }
static void static void
@ -523,39 +523,61 @@ thread_db_new_objfile (struct objfile *objfile)
{ {
td_err_e err; td_err_e err;
if (objfile == NULL)
{
/* All symbols have been discarded. If the thread_db target is
active, deactivate it now, even if the application was linked
statically against the thread library. */
keep_thread_db = 0;
if (using_thread_db)
deactivate_target ();
goto quit;
}
if (using_thread_db) if (using_thread_db)
/* Nothing to do. The thread library was already detected and the /* Nothing to do. The thread library was already detected and the
target vector was already activated. */ target vector was already activated. */
goto quit; goto quit;
if (objfile == NULL) /* Initialize the structure that identifies the child process. Note
/* Un-interesting object file. */ that at this point there is no guarantee that we actually have a
goto quit; child process. */
/* Initialize the structure that identifies the child process. */
proc_handle.pid = GET_PID (inferior_pid); proc_handle.pid = GET_PID (inferior_pid);
/* Now attempt to open a connection to the thread library running in /* Now attempt to open a connection to the thread library. */
the child process. */
err = td_ta_new_p (&proc_handle, &thread_agent); err = td_ta_new_p (&proc_handle, &thread_agent);
switch (err) switch (err)
{ {
case TD_NOLIBTHREAD: case TD_NOLIBTHREAD:
/* No thread library found in the child process, probably /* No thread library was detected. */
because the child process isn't running yet. */
break; break;
case TD_OK: case TD_OK:
/* The thread library was detected in the child; we go live now! */ /* The thread library was detected. Activate the thread_db target. */
thread_db_push_target (); push_target (&thread_db_ops);
using_thread_db = 1;
/* Find all user-space threads. */ /* If the thread library was detected in the main symbol file
err = td_ta_thr_iter_p (thread_agent, find_new_threads_callback, itself, we assume that the program was statically linked
&inferior_pid, TD_THR_ANY_STATE, against the thread library and well have to keep this
TD_THR_LOWEST_PRIORITY, TD_SIGNO_MASK, module's target vector activated until forever... Well, at
TD_THR_ANY_USER_FLAGS); least until all symbols have been discarded anyway (see
if (err != TD_OK) above). */
error ("Finding new threads failed: %s", thread_db_err_str (err)); if (objfile == symfile_objfile)
{
gdb_assert (proc_handle.pid == 0);
keep_thread_db = 1;
}
/* We can only poke around if there actually is a child process.
If there is no child process alive, postpone the steps below
until one has been created. */
if (proc_handle.pid != 0)
{
enable_thread_event_reporting ();
thread_db_find_new_threads ();
}
break; break;
default: default:
@ -610,7 +632,7 @@ static void
thread_db_detach (char *args, int from_tty) thread_db_detach (char *args, int from_tty)
{ {
disable_thread_event_reporting (); disable_thread_event_reporting ();
thread_db_unpush_target (); deactivate_target ();
target_beneath->to_detach (args, from_tty); target_beneath->to_detach (args, from_tty);
} }
@ -709,6 +731,12 @@ thread_db_wait (int pid, struct target_waitstatus *ourstatus)
pid = target_beneath->to_wait (pid, ourstatus); pid = target_beneath->to_wait (pid, ourstatus);
if (proc_handle.pid == 0)
/* The current child process isn't the actual multi-threaded
program yet, so don't try to do any special thread-specific
post-processing and bail out early. */
return pid;
if (ourstatus->kind == TARGET_WAITKIND_EXITED) if (ourstatus->kind == TARGET_WAITKIND_EXITED)
return -1; return -1;
@ -834,24 +862,29 @@ thread_db_kill (void)
static void static void
thread_db_create_inferior (char *exec_file, char *allargs, char **env) thread_db_create_inferior (char *exec_file, char *allargs, char **env)
{ {
/* We never want to actually create the inferior! If this is ever target_beneath->to_create_inferior (exec_file, allargs, env);
called, it means we were on the target stack when the user said }
"run". But we don't want to be on the new inferior's target
stack until the libthread_db connection is ready to be made. So
we unpush ourselves from the stack, and then invoke
find_default_create_inferior, which will invoke the appropriate
process_stratum target to do the create. */
thread_db_unpush_target (); static void
thread_db_post_startup_inferior (int pid)
{
if (proc_handle.pid == 0)
{
/* The child process is now the actual multi-threaded
program. Snatch its process ID... */
proc_handle.pid = GET_PID (pid);
find_default_create_inferior (exec_file, allargs, env); /* ...and perform the remaining initialization steps. */
enable_thread_event_reporting ();
thread_db_find_new_threads();
}
} }
static void static void
thread_db_mourn_inferior (void) thread_db_mourn_inferior (void)
{ {
remove_thread_event_breakpoints (); remove_thread_event_breakpoints ();
thread_db_unpush_target (); deactivate_target ();
target_beneath->to_mourn_inferior (); target_beneath->to_mourn_inferior ();
} }
@ -967,6 +1000,7 @@ init_thread_db_ops (void)
thread_db_ops.to_xfer_memory = thread_db_xfer_memory; thread_db_ops.to_xfer_memory = thread_db_xfer_memory;
thread_db_ops.to_kill = thread_db_kill; thread_db_ops.to_kill = thread_db_kill;
thread_db_ops.to_create_inferior = thread_db_create_inferior; thread_db_ops.to_create_inferior = thread_db_create_inferior;
thread_db_ops.to_post_startup_inferior = thread_db_post_startup_inferior;
thread_db_ops.to_mourn_inferior = thread_db_mourn_inferior; thread_db_ops.to_mourn_inferior = thread_db_mourn_inferior;
thread_db_ops.to_thread_alive = thread_db_thread_alive; thread_db_ops.to_thread_alive = thread_db_thread_alive;
thread_db_ops.to_find_new_threads = thread_db_find_new_threads; thread_db_ops.to_find_new_threads = thread_db_find_new_threads;