mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-12-02 06:43:58 +08:00
* linux-thread-db.c (thread_db_attach): Delete.
(thread_db_detach): Typo fix. Call target_mourn_inferior instead of fixing up proc_handle. (have_threads_callback, have_threads): New functions. (thread_db_wait): Remove dead proc_handle.pid check. Only translate PTIDs if we have registered threads. Check for new threads if we have none. (thread_db_create_inferior, thread_db_post_startup_inferior): Delete. (find_new_threads_callback): Only enable event reporting if TID == 0. (same_ptid_callback): New. (thread_db_get_thread_local_address): Check for new threads. (init_thread_db_ops): Don't set to_attach, to_create_inferior, or to_post_startup_inferior. * thread-db.c (thread_db_find_new_threads): Add prototype. (thread_db_create_event): Check for the main thread before adding a new thread. (maybe_attach_thread): Only enable event reporting if TID == 0. (thread_db_get_tls_address): Check for new threads.
This commit is contained in:
parent
58eb693ef1
commit
4105de343e
@ -1,3 +1,19 @@
|
|||||||
|
2007-06-27 Daniel Jacobowitz <dan@codesourcery.com>
|
||||||
|
|
||||||
|
* linux-thread-db.c (thread_db_attach): Delete.
|
||||||
|
(thread_db_detach): Typo fix. Call target_mourn_inferior
|
||||||
|
instead of fixing up proc_handle.
|
||||||
|
(have_threads_callback, have_threads): New functions.
|
||||||
|
(thread_db_wait): Remove dead proc_handle.pid check. Only
|
||||||
|
translate PTIDs if we have registered threads. Check for new
|
||||||
|
threads if we have none.
|
||||||
|
(thread_db_create_inferior, thread_db_post_startup_inferior): Delete.
|
||||||
|
(find_new_threads_callback): Only enable event reporting if TID == 0.
|
||||||
|
(same_ptid_callback): New.
|
||||||
|
(thread_db_get_thread_local_address): Check for new threads.
|
||||||
|
(init_thread_db_ops): Don't set to_attach, to_create_inferior,
|
||||||
|
or to_post_startup_inferior.
|
||||||
|
|
||||||
2007-06-22 Ulrich Weigand <uweigand@de.ibm.com>
|
2007-06-22 Ulrich Weigand <uweigand@de.ibm.com>
|
||||||
|
|
||||||
* infrun.c (adjust_pc_after_break): Do not assume software single-step
|
* infrun.c (adjust_pc_after_break): Do not assume software single-step
|
||||||
|
@ -1,3 +1,11 @@
|
|||||||
|
2007-06-27 Daniel Jacobowitz <dan@codesourcery.com>
|
||||||
|
|
||||||
|
* thread-db.c (thread_db_find_new_threads): Add prototype.
|
||||||
|
(thread_db_create_event): Check for the main thread before adding
|
||||||
|
a new thread.
|
||||||
|
(maybe_attach_thread): Only enable event reporting if TID == 0.
|
||||||
|
(thread_db_get_tls_address): Check for new threads.
|
||||||
|
|
||||||
2007-06-20 Daniel Jacobowitz <dan@codesourcery.com>
|
2007-06-20 Daniel Jacobowitz <dan@codesourcery.com>
|
||||||
|
|
||||||
* linux-low.c (linux_create_inferior): Try execv before execvp.
|
* linux-low.c (linux_create_inferior): Try execv before execvp.
|
||||||
|
@ -41,6 +41,7 @@ static struct ps_prochandle proc_handle;
|
|||||||
/* Connection to the libthread_db library. */
|
/* Connection to the libthread_db library. */
|
||||||
static td_thragent_t *thread_agent;
|
static td_thragent_t *thread_agent;
|
||||||
|
|
||||||
|
static void thread_db_find_new_threads (void);
|
||||||
static int find_new_threads_callback (const td_thrhandle_t *th_p, void *data);
|
static int find_new_threads_callback (const td_thrhandle_t *th_p, void *data);
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
@ -135,6 +136,8 @@ thread_db_create_event (CORE_ADDR where)
|
|||||||
td_event_msg_t msg;
|
td_event_msg_t msg;
|
||||||
td_err_e err;
|
td_err_e err;
|
||||||
struct inferior_linux_data *tdata;
|
struct inferior_linux_data *tdata;
|
||||||
|
struct thread_info *inferior;
|
||||||
|
struct process_info *process;
|
||||||
|
|
||||||
if (debug_threads)
|
if (debug_threads)
|
||||||
fprintf (stderr, "Thread creation event.\n");
|
fprintf (stderr, "Thread creation event.\n");
|
||||||
@ -150,6 +153,14 @@ thread_db_create_event (CORE_ADDR where)
|
|||||||
fprintf (stderr, "thread getmsg err: %s\n",
|
fprintf (stderr, "thread getmsg err: %s\n",
|
||||||
thread_db_err_str (err));
|
thread_db_err_str (err));
|
||||||
|
|
||||||
|
/* If we do not know about the main thread yet, this would be a good time to
|
||||||
|
find it. We need to do this to pick up the main thread before any newly
|
||||||
|
created threads. */
|
||||||
|
inferior = (struct thread_info *) all_threads.head;
|
||||||
|
process = get_thread_process (inferior);
|
||||||
|
if (process->thread_known == 0)
|
||||||
|
thread_db_find_new_threads ();
|
||||||
|
|
||||||
/* msg.event == TD_EVENT_CREATE */
|
/* msg.event == TD_EVENT_CREATE */
|
||||||
|
|
||||||
find_new_threads_callback (msg.th_p, NULL);
|
find_new_threads_callback (msg.th_p, NULL);
|
||||||
@ -232,8 +243,24 @@ maybe_attach_thread (const td_thrhandle_t *th_p, td_thrinfo_t *ti_p)
|
|||||||
{
|
{
|
||||||
inferior = (struct thread_info *) all_threads.head;
|
inferior = (struct thread_info *) all_threads.head;
|
||||||
process = get_thread_process (inferior);
|
process = get_thread_process (inferior);
|
||||||
|
|
||||||
if (process->thread_known == 0)
|
if (process->thread_known == 0)
|
||||||
{
|
{
|
||||||
|
/* If the new thread ID is zero, a final thread ID will be
|
||||||
|
available later. Do not enable thread debugging yet. */
|
||||||
|
if (ti_p->ti_tid == 0)
|
||||||
|
{
|
||||||
|
err = td_thr_event_enable (th_p, 1);
|
||||||
|
if (err != TD_OK)
|
||||||
|
error ("Cannot enable thread event reporting for %d: %s",
|
||||||
|
ti_p->ti_lid, thread_db_err_str (err));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process->lwpid != ti_p->ti_lid)
|
||||||
|
fatal ("PID mismatch! Expected %ld, got %ld",
|
||||||
|
(long) process->lwpid, (long) ti_p->ti_lid);
|
||||||
|
|
||||||
/* Switch to indexing the threads list by TID. */
|
/* Switch to indexing the threads list by TID. */
|
||||||
change_inferior_id (&all_threads, ti_p->ti_tid);
|
change_inferior_id (&all_threads, ti_p->ti_tid);
|
||||||
goto found;
|
goto found;
|
||||||
@ -331,6 +358,8 @@ thread_db_get_tls_address (struct thread_info *thread, CORE_ADDR offset,
|
|||||||
struct process_info *process;
|
struct process_info *process;
|
||||||
|
|
||||||
process = get_thread_process (thread);
|
process = get_thread_process (thread);
|
||||||
|
if (!process->thread_known)
|
||||||
|
thread_db_find_new_threads ();
|
||||||
if (!process->thread_known)
|
if (!process->thread_known)
|
||||||
return TD_NOTHR;
|
return TD_NOTHR;
|
||||||
|
|
||||||
|
@ -220,6 +220,21 @@ thread_db_err_str (td_err_e err)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return 1 if any threads have been registered. There may be none if
|
||||||
|
the threading library is not fully initialized yet. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
have_threads_callback (struct thread_info *thread, void *dummy)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
have_threads (void)
|
||||||
|
{
|
||||||
|
return iterate_over_threads (have_threads_callback, NULL) != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* A callback function for td_ta_thr_iter, which we use to map all
|
/* A callback function for td_ta_thr_iter, which we use to map all
|
||||||
threads to LWPs.
|
threads to LWPs.
|
||||||
|
|
||||||
@ -706,23 +721,6 @@ attach_thread (ptid_t ptid, const td_thrhandle_t *th_p,
|
|||||||
target_pid_to_str (ptid), thread_db_err_str (err));
|
target_pid_to_str (ptid), thread_db_err_str (err));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
thread_db_attach (char *args, int from_tty)
|
|
||||||
{
|
|
||||||
target_beneath->to_attach (args, from_tty);
|
|
||||||
|
|
||||||
/* Destroy thread info; it's no longer valid. */
|
|
||||||
init_thread_list ();
|
|
||||||
|
|
||||||
/* The child process is now the actual multi-threaded
|
|
||||||
program. Snatch its process ID... */
|
|
||||||
proc_handle.pid = GET_PID (inferior_ptid);
|
|
||||||
|
|
||||||
/* ...and perform the remaining initialization steps. */
|
|
||||||
enable_thread_event_reporting ();
|
|
||||||
thread_db_find_new_threads ();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
detach_thread (ptid_t ptid, int verbose)
|
detach_thread (ptid_t ptid, int verbose)
|
||||||
{
|
{
|
||||||
@ -749,14 +747,13 @@ thread_db_detach (char *args, int from_tty)
|
|||||||
disable_thread_event_reporting ();
|
disable_thread_event_reporting ();
|
||||||
|
|
||||||
/* There's no need to save & restore inferior_ptid here, since the
|
/* There's no need to save & restore inferior_ptid here, since the
|
||||||
inferior is supposed to be survive this function call. */
|
inferior is not supposed to survive this function call. */
|
||||||
inferior_ptid = lwp_from_thread (inferior_ptid);
|
inferior_ptid = lwp_from_thread (inferior_ptid);
|
||||||
|
|
||||||
/* Forget about the child's process ID. We shouldn't need it
|
|
||||||
anymore. */
|
|
||||||
proc_handle.pid = 0;
|
|
||||||
|
|
||||||
target_beneath->to_detach (args, from_tty);
|
target_beneath->to_detach (args, from_tty);
|
||||||
|
|
||||||
|
/* Should this be done by detach_command? */
|
||||||
|
target_mourn_inferior ();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -877,12 +874,6 @@ thread_db_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
|
|||||||
|
|
||||||
ptid = target_beneath->to_wait (ptid, ourstatus);
|
ptid = target_beneath->to_wait (ptid, 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 ptid;
|
|
||||||
|
|
||||||
if (ourstatus->kind == TARGET_WAITKIND_EXITED
|
if (ourstatus->kind == TARGET_WAITKIND_EXITED
|
||||||
|| ourstatus->kind == TARGET_WAITKIND_SIGNALLED)
|
|| ourstatus->kind == TARGET_WAITKIND_SIGNALLED)
|
||||||
return pid_to_ptid (-1);
|
return pid_to_ptid (-1);
|
||||||
@ -896,23 +887,32 @@ thread_db_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
|
|||||||
return pid_to_ptid (GET_PID (ptid));
|
return pid_to_ptid (GET_PID (ptid));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If we do not know about the main thread yet, this would be a good time to
|
||||||
|
find it. */
|
||||||
|
if (ourstatus->kind == TARGET_WAITKIND_STOPPED && !have_threads ())
|
||||||
|
thread_db_find_new_threads ();
|
||||||
|
|
||||||
if (ourstatus->kind == TARGET_WAITKIND_STOPPED
|
if (ourstatus->kind == TARGET_WAITKIND_STOPPED
|
||||||
&& ourstatus->value.sig == TARGET_SIGNAL_TRAP)
|
&& ourstatus->value.sig == TARGET_SIGNAL_TRAP)
|
||||||
/* Check for a thread event. */
|
/* Check for a thread event. */
|
||||||
check_event (ptid);
|
check_event (ptid);
|
||||||
|
|
||||||
if (!ptid_equal (trap_ptid, null_ptid))
|
if (have_threads ())
|
||||||
trap_ptid = thread_from_lwp (trap_ptid);
|
{
|
||||||
|
/* Change ptids back into the higher level PID + TID format. If
|
||||||
|
the thread is dead and no longer on the thread list, we will
|
||||||
|
get back a dead ptid. This can occur if the thread death
|
||||||
|
event gets postponed by other simultaneous events. In such a
|
||||||
|
case, we want to just ignore the event and continue on. */
|
||||||
|
|
||||||
|
if (!ptid_equal (trap_ptid, null_ptid))
|
||||||
|
trap_ptid = thread_from_lwp (trap_ptid);
|
||||||
|
|
||||||
|
ptid = thread_from_lwp (ptid);
|
||||||
|
if (GET_PID (ptid) == -1)
|
||||||
|
ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
|
||||||
|
}
|
||||||
|
|
||||||
/* Change the ptid back into the higher level PID + TID format.
|
|
||||||
If the thread is dead and no longer on the thread list, we will
|
|
||||||
get back a dead ptid. This can occur if the thread death event
|
|
||||||
gets postponed by other simultaneous events. In such a case,
|
|
||||||
we want to just ignore the event and continue on. */
|
|
||||||
ptid = thread_from_lwp (ptid);
|
|
||||||
if (GET_PID (ptid) == -1)
|
|
||||||
ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
|
|
||||||
|
|
||||||
return ptid;
|
return ptid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -925,30 +925,6 @@ thread_db_kill (void)
|
|||||||
target_beneath->to_kill ();
|
target_beneath->to_kill ();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
thread_db_create_inferior (char *exec_file, char *allargs, char **env,
|
|
||||||
int from_tty)
|
|
||||||
{
|
|
||||||
unpush_target (&thread_db_ops);
|
|
||||||
using_thread_db = 0;
|
|
||||||
target_beneath->to_create_inferior (exec_file, allargs, env, from_tty);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
thread_db_post_startup_inferior (ptid_t ptid)
|
|
||||||
{
|
|
||||||
if (proc_handle.pid == 0)
|
|
||||||
{
|
|
||||||
/* The child process is now the actual multi-threaded
|
|
||||||
program. Snatch its process ID... */
|
|
||||||
proc_handle.pid = GET_PID (ptid);
|
|
||||||
|
|
||||||
/* ...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)
|
||||||
{
|
{
|
||||||
@ -984,6 +960,22 @@ find_new_threads_callback (const td_thrhandle_t *th_p, void *data)
|
|||||||
|
|
||||||
ptid = ptid_build (GET_PID (inferior_ptid), ti.ti_lid, ti.ti_tid);
|
ptid = ptid_build (GET_PID (inferior_ptid), ti.ti_lid, ti.ti_tid);
|
||||||
|
|
||||||
|
if (ti.ti_tid == 0)
|
||||||
|
{
|
||||||
|
/* A thread ID of zero means that this is the main thread, but
|
||||||
|
glibc has not yet initialized thread-local storage and the
|
||||||
|
pthread library. We do not know what the thread's TID will
|
||||||
|
be yet. Just enable event reporting and otherwise ignore
|
||||||
|
it. */
|
||||||
|
|
||||||
|
err = 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 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!in_thread_list (ptid))
|
if (!in_thread_list (ptid))
|
||||||
attach_thread (ptid, th_p, &ti, 1);
|
attach_thread (ptid, th_p, &ti, 1);
|
||||||
|
|
||||||
@ -1040,6 +1032,16 @@ thread_db_extra_thread_info (struct thread_info *info)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return 1 if this thread has the same LWP as the passed PTID. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
same_ptid_callback (struct thread_info *thread, void *arg)
|
||||||
|
{
|
||||||
|
ptid_t *ptid_p = arg;
|
||||||
|
|
||||||
|
return GET_LWP (thread->ptid) == GET_LWP (*ptid_p);
|
||||||
|
}
|
||||||
|
|
||||||
/* Get the address of the thread local variable in load module LM which
|
/* Get the address of the thread local variable in load module LM which
|
||||||
is stored at OFFSET within the thread local storage for thread PTID. */
|
is stored at OFFSET within the thread local storage for thread PTID. */
|
||||||
|
|
||||||
@ -1048,6 +1050,21 @@ thread_db_get_thread_local_address (ptid_t ptid,
|
|||||||
CORE_ADDR lm,
|
CORE_ADDR lm,
|
||||||
CORE_ADDR offset)
|
CORE_ADDR offset)
|
||||||
{
|
{
|
||||||
|
/* If we have not discovered any threads yet, check now. */
|
||||||
|
if (!is_thread (ptid) && !have_threads ())
|
||||||
|
thread_db_find_new_threads ();
|
||||||
|
|
||||||
|
/* Try to find a matching thread if we still have the LWP ID instead
|
||||||
|
of the thread ID. */
|
||||||
|
if (!is_thread (ptid))
|
||||||
|
{
|
||||||
|
struct thread_info *thread;
|
||||||
|
|
||||||
|
thread = iterate_over_threads (same_ptid_callback, &ptid);
|
||||||
|
if (thread != NULL)
|
||||||
|
ptid = thread->ptid;
|
||||||
|
}
|
||||||
|
|
||||||
if (is_thread (ptid))
|
if (is_thread (ptid))
|
||||||
{
|
{
|
||||||
td_err_e err;
|
td_err_e err;
|
||||||
@ -1107,13 +1124,10 @@ init_thread_db_ops (void)
|
|||||||
thread_db_ops.to_shortname = "multi-thread";
|
thread_db_ops.to_shortname = "multi-thread";
|
||||||
thread_db_ops.to_longname = "multi-threaded child process.";
|
thread_db_ops.to_longname = "multi-threaded child process.";
|
||||||
thread_db_ops.to_doc = "Threads and pthreads support.";
|
thread_db_ops.to_doc = "Threads and pthreads support.";
|
||||||
thread_db_ops.to_attach = thread_db_attach;
|
|
||||||
thread_db_ops.to_detach = thread_db_detach;
|
thread_db_ops.to_detach = thread_db_detach;
|
||||||
thread_db_ops.to_resume = thread_db_resume;
|
thread_db_ops.to_resume = thread_db_resume;
|
||||||
thread_db_ops.to_wait = thread_db_wait;
|
thread_db_ops.to_wait = thread_db_wait;
|
||||||
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_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_find_new_threads = thread_db_find_new_threads;
|
thread_db_ops.to_find_new_threads = thread_db_find_new_threads;
|
||||||
thread_db_ops.to_pid_to_str = thread_db_pid_to_str;
|
thread_db_ops.to_pid_to_str = thread_db_pid_to_str;
|
||||||
|
Loading…
Reference in New Issue
Block a user