2008-04-16 15:00:25 +00:00
|
|
|
|
2008-03-30 Daniel Jacobowitz <dan@codesourcery.com>
|
|
|
|
|
|
|
|
|
|
* ia64-tdep.c (examine_prologue): Correct array access.
|
|
|
|
|
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /cvs/src/src/gdb/ia64-tdep.c,v
|
|
|
|
|
retrieving revision 1.172
|
|
|
|
|
retrieving revision 1.173
|
|
|
|
|
diff -u -r1.172 -r1.173
|
|
|
|
|
--- src/gdb/ia64-tdep.c 2008/02/20 14:31:40 1.172
|
|
|
|
|
+++ src/gdb/ia64-tdep.c 2008/03/31 03:38:48 1.173
|
|
|
|
|
@@ -1234,7 +1234,7 @@
|
|
|
|
|
spill_reg = rN;
|
|
|
|
|
last_prologue_pc = next_pc;
|
|
|
|
|
}
|
|
|
|
|
- else if (qp == 0 && rM >= 32 && rM < 40 && !instores[rM] &&
|
|
|
|
|
+ else if (qp == 0 && rM >= 32 && rM < 40 && !instores[rM-32] &&
|
|
|
|
|
rN < 256 && imm == 0)
|
|
|
|
|
{
|
|
|
|
|
/* mov rN, rM where rM is an input register */
|
2008-04-22 22:13:56 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
https://bugzilla.redhat.com/show_bug.cgi?id=442765
|
|
|
|
|
|
|
|
|
|
http://sourceware.org/ml/gdb-patches/2008-03/msg00281.html
|
|
|
|
|
http://sourceware.org/ml/gdb-cvs/2008-03/msg00114.html
|
|
|
|
|
|
|
|
|
|
2008-03-21 Daniel Jacobowitz <dan@codesourcery.com>
|
|
|
|
|
|
|
|
|
|
* gdbthread.h (add_thread_with_info): New.
|
|
|
|
|
* linux-thread-db.c: Add some documentation.
|
|
|
|
|
(GET_LWP, GET_PID, GET_THREAD, is_lwp, is_thread, BUILD_LWP): Delete.
|
|
|
|
|
(struct private_thread_info): Remove th_valid and ti_valid.
|
|
|
|
|
Replace ti with tid.
|
|
|
|
|
(thread_get_info_callback): Do not add TID to the new ptid. Do
|
|
|
|
|
not cache th or ti.
|
|
|
|
|
(thread_db_map_id2thr, lwp_from_thread): Delete functions.
|
|
|
|
|
(thread_from_lwp): Assert that the LWP is set. Do not add TID to the
|
|
|
|
|
new PTID.
|
|
|
|
|
(attach_thread): Handle an already-existing thread. Use
|
|
|
|
|
add_thread_with_info. Cache the th and tid.
|
|
|
|
|
(detach_thread): Verify that private was set. Remove verbose
|
|
|
|
|
argument and printing. Update caller.
|
|
|
|
|
(thread_db_detach): Do not adjust inferior_ptid.
|
|
|
|
|
(clear_lwpid_callback, thread_db_resume, thread_db_kill): Delete.
|
|
|
|
|
(check_event, find_new_threads_callback): Do not add TID to the new PTID.
|
|
|
|
|
(thread_db_wait): Do not use lwp_from_thread.
|
|
|
|
|
(thread_db_pid_to_str): Use the cached TID.
|
|
|
|
|
(thread_db_extra_thread_info): Check that private is set.
|
|
|
|
|
(same_ptid_callback): Delete.
|
|
|
|
|
(thread_db_get_thread_local_address): Do not use it or check
|
|
|
|
|
is_thread. Check that private is set. Assume that the thread
|
|
|
|
|
handle is already cached.
|
|
|
|
|
(init_thread_db_ops): Remove to_resume and to_kill.
|
|
|
|
|
* thread.c (add_thread_with_info): New.
|
|
|
|
|
(add_thread): Use it.
|
|
|
|
|
* linux-nat.c (find_thread_from_lwp): Delete.
|
|
|
|
|
(exit_lwp): Do not use it. Check print_thread_events. Print before
|
|
|
|
|
deleting the thread.
|
|
|
|
|
(GET_PID, GET_LWP, BUILD_LWP, is_lwp): Move to...
|
|
|
|
|
* linux-nat.h (GET_PID, GET_LWP, BUILD_LWP, is_lwp): ...here.
|
|
|
|
|
* inf-ttrace.c (inf_ttrace_wait): Use print_thread_events and
|
|
|
|
|
printf_unfiltered for thread exits.
|
|
|
|
|
* procfs.c (procfs_wait): Likewise.
|
|
|
|
|
|
|
|
|
|
2008-03-21 Pedro Alves <pedro@codesourcery.com>
|
|
|
|
|
|
|
|
|
|
* gdb.threads/fork-child-threads.exp: Test next over fork.
|
|
|
|
|
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /cvs/src/src/gdb/gdbthread.h,v
|
|
|
|
|
retrieving revision 1.20
|
|
|
|
|
retrieving revision 1.21
|
|
|
|
|
diff -u -r1.20 -r1.21
|
|
|
|
|
--- src/gdb/gdbthread.h 2008/03/15 13:53:25 1.20
|
|
|
|
|
+++ src/gdb/gdbthread.h 2008/03/21 15:44:53 1.21
|
|
|
|
|
@@ -81,6 +81,10 @@
|
|
|
|
|
about new thread. */
|
|
|
|
|
extern struct thread_info *add_thread_silent (ptid_t ptid);
|
|
|
|
|
|
|
|
|
|
+/* Same as add_thread, and sets the private info. */
|
|
|
|
|
+extern struct thread_info *add_thread_with_info (ptid_t ptid,
|
|
|
|
|
+ struct private_thread_info *);
|
|
|
|
|
+
|
|
|
|
|
/* Delete an existing thread list entry. */
|
|
|
|
|
extern void delete_thread (ptid_t);
|
|
|
|
|
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /cvs/src/src/gdb/inf-ttrace.c,v
|
|
|
|
|
retrieving revision 1.27
|
|
|
|
|
retrieving revision 1.28
|
|
|
|
|
diff -u -r1.27 -r1.28
|
|
|
|
|
--- src/gdb/inf-ttrace.c 2008/01/29 21:11:24 1.27
|
|
|
|
|
+++ src/gdb/inf-ttrace.c 2008/03/21 15:44:53 1.28
|
|
|
|
|
@@ -964,7 +964,8 @@
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case TTEVT_LWP_EXIT:
|
|
|
|
|
- printf_filtered(_("[%s exited]\n"), target_pid_to_str (ptid));
|
|
|
|
|
+ if (print_thread_events)
|
|
|
|
|
+ printf_unfiltered (_("[%s exited]\n"), target_pid_to_str (ptid));
|
|
|
|
|
ti = find_thread_pid (ptid);
|
|
|
|
|
gdb_assert (ti != NULL);
|
|
|
|
|
((struct inf_ttrace_private_thread_info *)ti->private)->dying = 1;
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /cvs/src/src/gdb/linux-nat.c,v
|
|
|
|
|
retrieving revision 1.76
|
|
|
|
|
retrieving revision 1.77
|
|
|
|
|
diff -u -r1.76 -r1.77
|
|
|
|
|
--- src/gdb/linux-nat.c 2008/03/17 14:54:07 1.76
|
|
|
|
|
+++ src/gdb/linux-nat.c 2008/03/21 15:44:53 1.77
|
|
|
|
|
@@ -588,11 +588,6 @@
|
|
|
|
|
static int num_lwps;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-#define GET_LWP(ptid) ptid_get_lwp (ptid)
|
|
|
|
|
-#define GET_PID(ptid) ptid_get_pid (ptid)
|
|
|
|
|
-#define is_lwp(ptid) (GET_LWP (ptid) != 0)
|
|
|
|
|
-#define BUILD_LWP(lwp, pid) ptid_build (pid, lwp, 0)
|
|
|
|
|
-
|
|
|
|
|
/* If the last reported event was a SIGTRAP, this variable is set to
|
|
|
|
|
the process id of the LWP/thread that got it. */
|
|
|
|
|
ptid_t trap_ptid;
|
|
|
|
|
@@ -813,20 +808,6 @@
|
|
|
|
|
p = &(*p)->next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
-/* Callback for iterate_over_threads that finds a thread corresponding
|
|
|
|
|
- to the given LWP. */
|
|
|
|
|
-
|
|
|
|
|
-static int
|
|
|
|
|
-find_thread_from_lwp (struct thread_info *thr, void *dummy)
|
|
|
|
|
-{
|
|
|
|
|
- ptid_t *ptid_p = dummy;
|
|
|
|
|
-
|
|
|
|
|
- if (GET_LWP (thr->ptid) && GET_LWP (thr->ptid) == GET_LWP (*ptid_p))
|
|
|
|
|
- return 1;
|
|
|
|
|
- else
|
|
|
|
|
- return 0;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
/* Handle the exit of a single thread LP. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
@@ -834,32 +815,14 @@
|
|
|
|
|
{
|
|
|
|
|
if (in_thread_list (lp->ptid))
|
|
|
|
|
{
|
|
|
|
|
+ if (print_thread_events)
|
|
|
|
|
+ printf_unfiltered (_("[%s exited]\n"), target_pid_to_str (lp->ptid));
|
|
|
|
|
+
|
|
|
|
|
/* Core GDB cannot deal with us deleting the current thread. */
|
|
|
|
|
if (!ptid_equal (lp->ptid, inferior_ptid))
|
|
|
|
|
delete_thread (lp->ptid);
|
|
|
|
|
else
|
|
|
|
|
record_dead_thread (lp->ptid);
|
|
|
|
|
- printf_unfiltered (_("[%s exited]\n"),
|
|
|
|
|
- target_pid_to_str (lp->ptid));
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- /* Even if LP->PTID is not in the global GDB thread list, the
|
|
|
|
|
- LWP may be - with an additional thread ID. We don't need
|
|
|
|
|
- to print anything in this case; thread_db is in use and
|
|
|
|
|
- already took care of that. But it didn't delete the thread
|
|
|
|
|
- in order to handle zombies correctly. */
|
|
|
|
|
-
|
|
|
|
|
- struct thread_info *thr;
|
|
|
|
|
-
|
|
|
|
|
- thr = iterate_over_threads (find_thread_from_lwp, &lp->ptid);
|
|
|
|
|
- if (thr)
|
|
|
|
|
- {
|
|
|
|
|
- if (!ptid_equal (thr->ptid, inferior_ptid))
|
|
|
|
|
- delete_thread (thr->ptid);
|
|
|
|
|
- else
|
|
|
|
|
- record_dead_thread (thr->ptid);
|
|
|
|
|
- }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
delete_lwp (lp->ptid);
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /cvs/src/src/gdb/linux-nat.h,v
|
|
|
|
|
retrieving revision 1.22
|
|
|
|
|
retrieving revision 1.23
|
|
|
|
|
diff -u -r1.22 -r1.23
|
|
|
|
|
--- src/gdb/linux-nat.h 2008/01/23 11:26:28 1.22
|
|
|
|
|
+++ src/gdb/linux-nat.h 2008/03/21 15:44:53 1.23
|
|
|
|
|
@@ -83,6 +83,11 @@
|
|
|
|
|
(LP) != NULL; \
|
|
|
|
|
(LP) = (LP)->next, (PTID) = (LP) ? (LP)->ptid : (PTID))
|
|
|
|
|
|
|
|
|
|
+#define GET_LWP(ptid) ptid_get_lwp (ptid)
|
|
|
|
|
+#define GET_PID(ptid) ptid_get_pid (ptid)
|
|
|
|
|
+#define is_lwp(ptid) (GET_LWP (ptid) != 0)
|
|
|
|
|
+#define BUILD_LWP(lwp, pid) ptid_build (pid, lwp, 0)
|
|
|
|
|
+
|
|
|
|
|
/* Attempt to initialize libthread_db. */
|
|
|
|
|
void check_for_thread_db (void);
|
|
|
|
|
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /cvs/src/src/gdb/linux-thread-db.c,v
|
|
|
|
|
retrieving revision 1.37
|
|
|
|
|
retrieving revision 1.38
|
|
|
|
|
diff -u -r1.37 -r1.38
|
|
|
|
|
--- src/gdb/linux-thread-db.c 2008/01/23 11:26:28 1.37
|
|
|
|
|
+++ src/gdb/linux-thread-db.c 2008/03/21 15:44:53 1.38
|
|
|
|
|
@@ -48,6 +48,32 @@
|
|
|
|
|
#define LIBTHREAD_DB_SO "libthread_db.so.1"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
+/* GNU/Linux libthread_db support.
|
|
|
|
|
+
|
|
|
|
|
+ libthread_db is a library, provided along with libpthread.so, which
|
|
|
|
|
+ exposes the internals of the thread library to a debugger. It
|
|
|
|
|
+ allows GDB to find existing threads, new threads as they are
|
|
|
|
|
+ created, thread IDs (usually, the result of pthread_self), and
|
|
|
|
|
+ thread-local variables.
|
|
|
|
|
+
|
|
|
|
|
+ The libthread_db interface originates on Solaris, where it is
|
|
|
|
|
+ both more powerful and more complicated. This implementation
|
|
|
|
|
+ only works for LinuxThreads and NPTL, the two glibc threading
|
|
|
|
|
+ libraries. It assumes that each thread is permanently assigned
|
|
|
|
|
+ to a single light-weight process (LWP).
|
|
|
|
|
+
|
|
|
|
|
+ libthread_db-specific information is stored in the "private" field
|
|
|
|
|
+ of struct thread_info. When the field is NULL we do not yet have
|
|
|
|
|
+ information about the new thread; this could be temporary (created,
|
|
|
|
|
+ but the thread library's data structures do not reflect it yet)
|
|
|
|
|
+ or permanent (created using clone instead of pthread_create).
|
|
|
|
|
+
|
|
|
|
|
+ Process IDs managed by linux-thread-db.c match those used by
|
|
|
|
|
+ linux-nat.c: a common PID for all processes, an LWP ID for each
|
|
|
|
|
+ thread, and no TID. We save the TID in private. Keeping it out
|
|
|
|
|
+ of the ptid_t prevents thread IDs changing when libpthread is
|
|
|
|
|
+ loaded or unloaded. */
|
|
|
|
|
+
|
|
|
|
|
/* If we're running on GNU/Linux, we must explicitly attach to any new
|
|
|
|
|
threads. */
|
|
|
|
|
|
|
|
|
|
@@ -119,19 +145,7 @@
|
|
|
|
|
static void thread_db_find_new_threads (void);
|
|
|
|
|
static void attach_thread (ptid_t ptid, const td_thrhandle_t *th_p,
|
|
|
|
|
const td_thrinfo_t *ti_p);
|
|
|
|
|
-static void detach_thread (ptid_t ptid, int verbose);
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-/* Building process ids. */
|
|
|
|
|
-
|
|
|
|
|
-#define GET_PID(ptid) ptid_get_pid (ptid)
|
|
|
|
|
-#define GET_LWP(ptid) ptid_get_lwp (ptid)
|
|
|
|
|
-#define GET_THREAD(ptid) ptid_get_tid (ptid)
|
|
|
|
|
-
|
|
|
|
|
-#define is_lwp(ptid) (GET_LWP (ptid) != 0)
|
|
|
|
|
-#define is_thread(ptid) (GET_THREAD (ptid) != 0)
|
|
|
|
|
-
|
|
|
|
|
-#define BUILD_LWP(lwp, pid) ptid_build (pid, lwp, 0)
|
|
|
|
|
+static void detach_thread (ptid_t ptid);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Use "struct private_thread_info" to cache thread state. This is
|
|
|
|
|
@@ -143,11 +157,8 @@
|
|
|
|
|
unsigned int dying:1;
|
|
|
|
|
|
|
|
|
|
/* Cached thread state. */
|
|
|
|
|
- unsigned int th_valid:1;
|
|
|
|
|
- unsigned int ti_valid:1;
|
|
|
|
|
-
|
|
|
|
|
td_thrhandle_t th;
|
|
|
|
|
- td_thrinfo_t ti;
|
|
|
|
|
+ thread_t tid;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -257,7 +268,7 @@
|
|
|
|
|
thread_db_err_str (err));
|
|
|
|
|
|
|
|
|
|
/* Fill the cache. */
|
|
|
|
|
- thread_ptid = ptid_build (GET_PID (inferior_ptid), ti.ti_lid, ti.ti_tid);
|
|
|
|
|
+ thread_ptid = ptid_build (GET_PID (inferior_ptid), ti.ti_lid, 0);
|
|
|
|
|
thread_info = find_thread_pid (thread_ptid);
|
|
|
|
|
|
|
|
|
|
/* In the case of a zombie thread, don't continue. We don't want to
|
|
|
|
|
@@ -266,13 +277,6 @@
|
|
|
|
|
{
|
|
|
|
|
if (infop != NULL)
|
|
|
|
|
*(struct thread_info **) infop = thread_info;
|
|
|
|
|
- if (thread_info != NULL)
|
|
|
|
|
- {
|
|
|
|
|
- memcpy (&thread_info->private->th, thp, sizeof (*thp));
|
|
|
|
|
- thread_info->private->th_valid = 1;
|
|
|
|
|
- memcpy (&thread_info->private->ti, &ti, sizeof (ti));
|
|
|
|
|
- thread_info->private->ti_valid = 1;
|
|
|
|
|
- }
|
|
|
|
|
return TD_THR_ZOMBIE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -284,39 +288,11 @@
|
|
|
|
|
gdb_assert (thread_info != NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- memcpy (&thread_info->private->th, thp, sizeof (*thp));
|
|
|
|
|
- thread_info->private->th_valid = 1;
|
|
|
|
|
- memcpy (&thread_info->private->ti, &ti, sizeof (ti));
|
|
|
|
|
- thread_info->private->ti_valid = 1;
|
|
|
|
|
-
|
|
|
|
|
if (infop != NULL)
|
|
|
|
|
*(struct thread_info **) infop = thread_info;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
-
|
|
|
|
|
-/* Accessor functions for the thread_db information, with caching. */
|
|
|
|
|
-
|
|
|
|
|
-static void
|
|
|
|
|
-thread_db_map_id2thr (struct thread_info *thread_info, int fatal)
|
|
|
|
|
-{
|
|
|
|
|
- td_err_e err;
|
|
|
|
|
-
|
|
|
|
|
- if (thread_info->private->th_valid)
|
|
|
|
|
- return;
|
|
|
|
|
-
|
|
|
|
|
- err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (thread_info->ptid),
|
|
|
|
|
- &thread_info->private->th);
|
|
|
|
|
- if (err != TD_OK)
|
|
|
|
|
- {
|
|
|
|
|
- if (fatal)
|
|
|
|
|
- error (_("Cannot find thread %ld: %s"),
|
|
|
|
|
- (long) GET_THREAD (thread_info->ptid),
|
|
|
|
|
- thread_db_err_str (err));
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- thread_info->private->th_valid = 1;
|
|
|
|
|
-}
|
|
|
|
|
|
|
|
|
|
/* Convert between user-level thread ids and LWP ids. */
|
|
|
|
|
|
|
|
|
|
@@ -328,10 +304,9 @@
|
|
|
|
|
struct thread_info *thread_info;
|
|
|
|
|
ptid_t thread_ptid;
|
|
|
|
|
|
|
|
|
|
- if (GET_LWP (ptid) == 0)
|
|
|
|
|
- ptid = BUILD_LWP (GET_PID (ptid), GET_PID (ptid));
|
|
|
|
|
-
|
|
|
|
|
- gdb_assert (is_lwp (ptid));
|
|
|
|
|
+ /* This ptid comes from linux-nat.c, which should always fill in the
|
|
|
|
|
+ LWP. */
|
|
|
|
|
+ gdb_assert (GET_LWP (ptid) != 0);
|
|
|
|
|
|
|
|
|
|
err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th);
|
|
|
|
|
if (err != TD_OK)
|
|
|
|
|
@@ -352,16 +327,8 @@
|
|
|
|
|
&& thread_info == NULL)
|
|
|
|
|
return pid_to_ptid (-1);
|
|
|
|
|
|
|
|
|
|
- gdb_assert (thread_info && thread_info->private->ti_valid);
|
|
|
|
|
-
|
|
|
|
|
- return ptid_build (GET_PID (ptid), GET_LWP (ptid),
|
|
|
|
|
- thread_info->private->ti.ti_tid);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-static ptid_t
|
|
|
|
|
-lwp_from_thread (ptid_t ptid)
|
|
|
|
|
-{
|
|
|
|
|
- return BUILD_LWP (GET_LWP (ptid), GET_PID (ptid));
|
|
|
|
|
+ gdb_assert (ptid_get_tid (ptid) == 0);
|
|
|
|
|
+ return ptid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -672,7 +639,8 @@
|
|
|
|
|
attach_thread (ptid_t ptid, const td_thrhandle_t *th_p,
|
|
|
|
|
const td_thrinfo_t *ti_p)
|
|
|
|
|
{
|
|
|
|
|
- struct thread_info *tp;
|
|
|
|
|
+ struct private_thread_info *private;
|
|
|
|
|
+ struct thread_info *tp = NULL;
|
|
|
|
|
td_err_e err;
|
|
|
|
|
|
|
|
|
|
/* If we're being called after a TD_CREATE event, we may already
|
|
|
|
|
@@ -690,10 +658,21 @@
|
|
|
|
|
tp = find_thread_pid (ptid);
|
|
|
|
|
gdb_assert (tp != NULL);
|
|
|
|
|
|
|
|
|
|
- if (!tp->private->dying)
|
|
|
|
|
- return;
|
|
|
|
|
+ /* If tp->private is NULL, then GDB is already attached to this
|
|
|
|
|
+ thread, but we do not know anything about it. We can learn
|
|
|
|
|
+ about it here. This can only happen if we have some other
|
|
|
|
|
+ way besides libthread_db to notice new threads (i.e.
|
|
|
|
|
+ PTRACE_EVENT_CLONE); assume the same mechanism notices thread
|
|
|
|
|
+ exit, so this can not be a stale thread recreated with the
|
|
|
|
|
+ same ID. */
|
|
|
|
|
+ if (tp->private != NULL)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (!tp->private->dying)
|
|
|
|
|
+ return;
|
|
|
|
|
|
|
|
|
|
- delete_thread (ptid);
|
|
|
|
|
+ delete_thread (ptid);
|
|
|
|
|
+ tp = NULL;
|
|
|
|
|
+ }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
check_thread_signals ();
|
|
|
|
|
@@ -702,13 +681,28 @@
|
|
|
|
|
return; /* A zombie thread -- do not attach. */
|
|
|
|
|
|
|
|
|
|
/* Under GNU/Linux, we have to attach to each and every thread. */
|
|
|
|
|
- if (lin_lwp_attach_lwp (BUILD_LWP (ti_p->ti_lid, GET_PID (ptid))) < 0)
|
|
|
|
|
+ if (tp == NULL
|
|
|
|
|
+ && lin_lwp_attach_lwp (BUILD_LWP (ti_p->ti_lid, GET_PID (ptid))) < 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
+ /* Construct the thread's private data. */
|
|
|
|
|
+ private = xmalloc (sizeof (struct private_thread_info));
|
|
|
|
|
+ memset (private, 0, sizeof (struct private_thread_info));
|
|
|
|
|
+
|
|
|
|
|
+ /* A thread ID of zero may mean the thread library has not initialized
|
|
|
|
|
+ yet. But we shouldn't even get here if that's the case. FIXME:
|
|
|
|
|
+ if we change GDB to always have at least one thread in the thread
|
|
|
|
|
+ list this will have to go somewhere else; maybe private == NULL
|
|
|
|
|
+ until the thread_db target claims it. */
|
|
|
|
|
+ gdb_assert (ti_p->ti_tid != 0);
|
|
|
|
|
+ private->th = *th_p;
|
|
|
|
|
+ private->tid = ti_p->ti_tid;
|
|
|
|
|
+
|
|
|
|
|
/* Add the thread to GDB's thread list. */
|
|
|
|
|
- tp = add_thread (ptid);
|
|
|
|
|
- tp->private = xmalloc (sizeof (struct private_thread_info));
|
|
|
|
|
- memset (tp->private, 0, sizeof (struct private_thread_info));
|
|
|
|
|
+ if (tp == NULL)
|
|
|
|
|
+ tp = add_thread_with_info (ptid, private);
|
|
|
|
|
+ else
|
|
|
|
|
+ tp->private = private;
|
|
|
|
|
|
|
|
|
|
/* Enable thread event reporting for this thread. */
|
|
|
|
|
err = td_thr_event_enable_p (th_p, 1);
|
|
|
|
|
@@ -718,22 +712,20 @@
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
-detach_thread (ptid_t ptid, int verbose)
|
|
|
|
|
+detach_thread (ptid_t ptid)
|
|
|
|
|
{
|
|
|
|
|
struct thread_info *thread_info;
|
|
|
|
|
|
|
|
|
|
- if (verbose)
|
|
|
|
|
- printf_unfiltered (_("[%s exited]\n"), target_pid_to_str (ptid));
|
|
|
|
|
-
|
|
|
|
|
/* Don't delete the thread now, because it still reports as active
|
|
|
|
|
until it has executed a few instructions after the event
|
|
|
|
|
breakpoint - if we deleted it now, "info threads" would cause us
|
|
|
|
|
to re-attach to it. Just mark it as having had a TD_DEATH
|
|
|
|
|
event. This means that we won't delete it from our thread list
|
|
|
|
|
until we notice that it's dead (via prune_threads), or until
|
|
|
|
|
- something re-uses its thread ID. */
|
|
|
|
|
+ something re-uses its thread ID. We'll report the thread exit
|
|
|
|
|
+ when the underlying LWP dies. */
|
|
|
|
|
thread_info = find_thread_pid (ptid);
|
|
|
|
|
- gdb_assert (thread_info != NULL);
|
|
|
|
|
+ gdb_assert (thread_info != NULL && thread_info->private != NULL);
|
|
|
|
|
thread_info->private->dying = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -742,47 +734,12 @@
|
|
|
|
|
{
|
|
|
|
|
disable_thread_event_reporting ();
|
|
|
|
|
|
|
|
|
|
- /* There's no need to save & restore inferior_ptid here, since the
|
|
|
|
|
- inferior is not supposed to survive this function call. */
|
|
|
|
|
- inferior_ptid = lwp_from_thread (inferior_ptid);
|
|
|
|
|
-
|
|
|
|
|
target_beneath->to_detach (args, from_tty);
|
|
|
|
|
|
|
|
|
|
/* Should this be done by detach_command? */
|
|
|
|
|
target_mourn_inferior ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
-static int
|
|
|
|
|
-clear_lwpid_callback (struct thread_info *thread, void *dummy)
|
|
|
|
|
-{
|
|
|
|
|
- /* If we know that our thread implementation is 1-to-1, we could save
|
|
|
|
|
- a certain amount of information; it's not clear how much, so we
|
|
|
|
|
- are always conservative. */
|
|
|
|
|
-
|
|
|
|
|
- thread->private->th_valid = 0;
|
|
|
|
|
- thread->private->ti_valid = 0;
|
|
|
|
|
-
|
|
|
|
|
- return 0;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-static void
|
|
|
|
|
-thread_db_resume (ptid_t ptid, int step, enum target_signal signo)
|
|
|
|
|
-{
|
|
|
|
|
- struct cleanup *old_chain = save_inferior_ptid ();
|
|
|
|
|
-
|
|
|
|
|
- if (GET_PID (ptid) == -1)
|
|
|
|
|
- inferior_ptid = lwp_from_thread (inferior_ptid);
|
|
|
|
|
- else if (is_thread (ptid))
|
|
|
|
|
- ptid = lwp_from_thread (ptid);
|
|
|
|
|
-
|
|
|
|
|
- /* Clear cached data which may not be valid after the resume. */
|
|
|
|
|
- iterate_over_threads (clear_lwpid_callback, NULL);
|
|
|
|
|
-
|
|
|
|
|
- target_beneath->to_resume (ptid, step, signo);
|
|
|
|
|
-
|
|
|
|
|
- do_cleanups (old_chain);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
/* Check if PID is currently stopped at the location of a thread event
|
|
|
|
|
breakpoint location. If it is, read the event message and act upon
|
|
|
|
|
the event. */
|
|
|
|
|
@@ -833,7 +790,7 @@
|
|
|
|
|
if (err != TD_OK)
|
|
|
|
|
error (_("Cannot get thread info: %s"), thread_db_err_str (err));
|
|
|
|
|
|
|
|
|
|
- ptid = ptid_build (GET_PID (ptid), ti.ti_lid, ti.ti_tid);
|
|
|
|
|
+ ptid = ptid_build (GET_PID (ptid), ti.ti_lid, 0);
|
|
|
|
|
|
|
|
|
|
switch (msg.event)
|
|
|
|
|
{
|
|
|
|
|
@@ -849,7 +806,7 @@
|
|
|
|
|
if (!in_thread_list (ptid))
|
|
|
|
|
error (_("Spurious thread death event."));
|
|
|
|
|
|
|
|
|
|
- detach_thread (ptid, print_thread_events);
|
|
|
|
|
+ detach_thread (ptid);
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
@@ -865,9 +822,6 @@
|
|
|
|
|
{
|
|
|
|
|
extern ptid_t trap_ptid;
|
|
|
|
|
|
|
|
|
|
- if (GET_PID (ptid) != -1 && is_thread (ptid))
|
|
|
|
|
- ptid = lwp_from_thread (ptid);
|
|
|
|
|
-
|
|
|
|
|
ptid = target_beneath->to_wait (ptid, ourstatus);
|
|
|
|
|
|
|
|
|
|
if (ourstatus->kind == TARGET_WAITKIND_EXITED
|
|
|
|
|
@@ -913,15 +867,6 @@
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
-thread_db_kill (void)
|
|
|
|
|
-{
|
|
|
|
|
- /* There's no need to save & restore inferior_ptid here, since the
|
|
|
|
|
- inferior isn't supposed to survive this function call. */
|
|
|
|
|
- inferior_ptid = lwp_from_thread (inferior_ptid);
|
|
|
|
|
- target_beneath->to_kill ();
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-static void
|
|
|
|
|
thread_db_mourn_inferior (void)
|
|
|
|
|
{
|
|
|
|
|
/* Forget about the child's process ID. We shouldn't need it
|
|
|
|
|
@@ -954,7 +899,7 @@
|
|
|
|
|
if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE)
|
|
|
|
|
return 0; /* A zombie -- ignore. */
|
|
|
|
|
|
|
|
|
|
- ptid = ptid_build (GET_PID (inferior_ptid), ti.ti_lid, ti.ti_tid);
|
|
|
|
|
+ ptid = ptid_build (GET_PID (inferior_ptid), ti.ti_lid, 0);
|
|
|
|
|
|
|
|
|
|
if (ti.ti_tid == 0)
|
|
|
|
|
{
|
|
|
|
|
@@ -994,18 +939,17 @@
|
|
|
|
|
static char *
|
|
|
|
|
thread_db_pid_to_str (ptid_t ptid)
|
|
|
|
|
{
|
|
|
|
|
- if (is_thread (ptid))
|
|
|
|
|
+ struct thread_info *thread_info = find_thread_pid (ptid);
|
|
|
|
|
+
|
|
|
|
|
+ if (thread_info != NULL && thread_info->private != NULL)
|
|
|
|
|
{
|
|
|
|
|
static char buf[64];
|
|
|
|
|
- struct thread_info *thread_info;
|
|
|
|
|
+ thread_t tid;
|
|
|
|
|
|
|
|
|
|
+ tid = thread_info->private->tid;
|
|
|
|
|
thread_info = find_thread_pid (ptid);
|
|
|
|
|
- if (thread_info == NULL)
|
|
|
|
|
- snprintf (buf, sizeof (buf), "Thread 0x%lx (LWP %ld) (Missing)",
|
|
|
|
|
- GET_THREAD (ptid), GET_LWP (ptid));
|
|
|
|
|
- else
|
|
|
|
|
- snprintf (buf, sizeof (buf), "Thread 0x%lx (LWP %ld)",
|
|
|
|
|
- GET_THREAD (ptid), GET_LWP (ptid));
|
|
|
|
|
+ snprintf (buf, sizeof (buf), "Thread 0x%lx (LWP %ld)",
|
|
|
|
|
+ tid, GET_LWP (ptid));
|
|
|
|
|
|
|
|
|
|
return buf;
|
|
|
|
|
}
|
|
|
|
|
@@ -1022,22 +966,15 @@
|
|
|
|
|
static char *
|
|
|
|
|
thread_db_extra_thread_info (struct thread_info *info)
|
|
|
|
|
{
|
|
|
|
|
+ if (info->private == NULL)
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+
|
|
|
|
|
if (info->private->dying)
|
|
|
|
|
return "Exiting";
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
is stored at OFFSET within the thread local storage for thread PTID. */
|
|
|
|
|
|
|
|
|
|
@@ -1046,26 +983,19 @@
|
|
|
|
|
CORE_ADDR lm,
|
|
|
|
|
CORE_ADDR offset)
|
|
|
|
|
{
|
|
|
|
|
+ struct thread_info *thread_info;
|
|
|
|
|
+
|
|
|
|
|
/* If we have not discovered any threads yet, check now. */
|
|
|
|
|
- if (!is_thread (ptid) && !have_threads ())
|
|
|
|
|
+ if (!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;
|
|
|
|
|
- }
|
|
|
|
|
+ /* Find the matching thread. */
|
|
|
|
|
+ thread_info = find_thread_pid (ptid);
|
|
|
|
|
|
|
|
|
|
- if (is_thread (ptid))
|
|
|
|
|
+ if (thread_info != NULL && thread_info->private != NULL)
|
|
|
|
|
{
|
|
|
|
|
td_err_e err;
|
|
|
|
|
void *address;
|
|
|
|
|
- struct thread_info *thread_info;
|
|
|
|
|
|
|
|
|
|
/* glibc doesn't provide the needed interface. */
|
|
|
|
|
if (!td_thr_tls_get_addr_p)
|
|
|
|
|
@@ -1075,11 +1005,6 @@
|
|
|
|
|
/* Caller should have verified that lm != 0. */
|
|
|
|
|
gdb_assert (lm != 0);
|
|
|
|
|
|
|
|
|
|
- /* Get info about the thread. */
|
|
|
|
|
- thread_info = find_thread_pid (ptid);
|
|
|
|
|
- gdb_assert (thread_info);
|
|
|
|
|
- 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 *)(size_t) lm,
|
|
|
|
|
@@ -1122,9 +1047,7 @@
|
|
|
|
|
thread_db_ops.to_longname = "multi-threaded child process.";
|
|
|
|
|
thread_db_ops.to_doc = "Threads and pthreads support.";
|
|
|
|
|
thread_db_ops.to_detach = thread_db_detach;
|
|
|
|
|
- thread_db_ops.to_resume = thread_db_resume;
|
|
|
|
|
thread_db_ops.to_wait = thread_db_wait;
|
|
|
|
|
- thread_db_ops.to_kill = thread_db_kill;
|
|
|
|
|
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_pid_to_str = thread_db_pid_to_str;
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /cvs/src/src/gdb/procfs.c,v
|
|
|
|
|
retrieving revision 1.86
|
|
|
|
|
retrieving revision 1.87
|
|
|
|
|
diff -u -r1.86 -r1.87
|
|
|
|
|
--- src/gdb/procfs.c 2008/03/12 20:00:21 1.86
|
|
|
|
|
+++ src/gdb/procfs.c 2008/03/21 15:44:53 1.87
|
|
|
|
|
@@ -4034,8 +4034,9 @@
|
|
|
|
|
case PR_SYSENTRY:
|
|
|
|
|
if (syscall_is_lwp_exit (pi, what))
|
|
|
|
|
{
|
|
|
|
|
- printf_filtered (_("[%s exited]\n"),
|
|
|
|
|
- target_pid_to_str (retval));
|
|
|
|
|
+ if (print_thread_events)
|
|
|
|
|
+ printf_unfiltered (_("[%s exited]\n"),
|
|
|
|
|
+ target_pid_to_str (retval));
|
|
|
|
|
delete_thread (retval);
|
|
|
|
|
status->kind = TARGET_WAITKIND_SPURIOUS;
|
|
|
|
|
return retval;
|
|
|
|
|
@@ -4165,8 +4166,9 @@
|
|
|
|
|
}
|
|
|
|
|
else if (syscall_is_lwp_exit (pi, what))
|
|
|
|
|
{
|
|
|
|
|
- printf_filtered (_("[%s exited]\n"),
|
|
|
|
|
- target_pid_to_str (retval));
|
|
|
|
|
+ if (print_thread_events)
|
|
|
|
|
+ printf_unfiltered (_("[%s exited]\n"),
|
|
|
|
|
+ target_pid_to_str (retval));
|
|
|
|
|
delete_thread (retval);
|
|
|
|
|
status->kind = TARGET_WAITKIND_SPURIOUS;
|
|
|
|
|
return retval;
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /cvs/src/src/gdb/thread.c,v
|
|
|
|
|
retrieving revision 1.63
|
|
|
|
|
retrieving revision 1.64
|
|
|
|
|
diff -u -r1.63 -r1.64
|
|
|
|
|
--- src/gdb/thread.c 2008/03/17 18:41:29 1.63
|
|
|
|
|
+++ src/gdb/thread.c 2008/03/21 15:44:53 1.64
|
|
|
|
|
@@ -132,10 +132,12 @@
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct thread_info *
|
|
|
|
|
-add_thread (ptid_t ptid)
|
|
|
|
|
+add_thread_with_info (ptid_t ptid, struct private_thread_info *private)
|
|
|
|
|
{
|
|
|
|
|
struct thread_info *result = add_thread_silent (ptid);
|
|
|
|
|
|
|
|
|
|
+ result->private = private;
|
|
|
|
|
+
|
|
|
|
|
if (print_thread_events)
|
|
|
|
|
printf_unfiltered (_("[New %s]\n"), target_pid_to_str (ptid));
|
|
|
|
|
|
|
|
|
|
@@ -144,6 +146,12 @@
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+struct thread_info *
|
|
|
|
|
+add_thread (ptid_t ptid)
|
|
|
|
|
+{
|
|
|
|
|
+ return add_thread_with_info (ptid, NULL);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
void
|
|
|
|
|
delete_thread (ptid_t ptid)
|
|
|
|
|
{
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /cvs/src/src/gdb/testsuite/gdb.threads/fork-child-threads.exp,v
|
|
|
|
|
retrieving revision 1.1
|
|
|
|
|
retrieving revision 1.2
|
|
|
|
|
diff -u -r1.1 -r1.2
|
|
|
|
|
--- src/gdb/testsuite/gdb.threads/fork-child-threads.exp 2008/01/02 13:36:38 1.1
|
|
|
|
|
+++ src/gdb/testsuite/gdb.threads/fork-child-threads.exp 2008/03/21 15:44:53 1.2
|
|
|
|
|
@@ -38,6 +38,10 @@
|
|
|
|
|
|
|
|
|
|
gdb_test "set follow-fork-mode child"
|
|
|
|
|
gdb_breakpoint "start"
|
|
|
|
|
+
|
|
|
|
|
+# Make sure we can step over fork without losing our breakpoint.
|
|
|
|
|
+gdb_test "next" ".*pthread_create \\(&thread, NULL, start, NULL\\);.*" "next over fork"
|
|
|
|
|
+
|
|
|
|
|
gdb_test "continue" "Breakpoint 2, start.*" "get to the spawned thread"
|
|
|
|
|
|
|
|
|
|
# Wrong:
|
|
|
|
|
|
|
|
|
|
http://sourceware.org/ml/gdb-patches/2008-04/msg00238.html
|
|
|
|
|
http://sourceware.org/ml/gdb-cvs/2008-04/msg00068.html
|
|
|
|
|
|
|
|
|
|
2008-04-14 Daniel Jacobowitz <dan@codesourcery.com>
|
|
|
|
|
|
|
|
|
|
* linux-thread-db.c (have_threads_callback): Check thread->private.
|
|
|
|
|
|
|
|
|
|
===================================================================
|
|
|
|
|
RCS file: /cvs/src/src/gdb/linux-thread-db.c,v
|
|
|
|
|
retrieving revision 1.40
|
|
|
|
|
retrieving revision 1.41
|
|
|
|
|
diff -u -r1.40 -r1.41
|
|
|
|
|
--- src/gdb/linux-thread-db.c 2008/03/25 12:26:21 1.40
|
|
|
|
|
+++ src/gdb/linux-thread-db.c 2008/04/14 14:02:23 1.41
|
|
|
|
|
@@ -235,7 +235,7 @@
|
|
|
|
|
static int
|
|
|
|
|
have_threads_callback (struct thread_info *thread, void *dummy)
|
|
|
|
|
{
|
|
|
|
|
- return 1;
|
|
|
|
|
+ return thread->private != NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|