2008-03-30 Daniel Jacobowitz * 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 */ 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 * 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 * 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; Index: gdb-6.8/gdb/thread.c =================================================================== --- gdb-6.8.orig/gdb/thread.c 2008-03-12 23:22:06.000000000 +0100 +++ gdb-6.8/gdb/thread.c 2008-07-14 10:24:32.000000000 +0200 @@ -131,16 +131,24 @@ add_thread_silent (ptid_t ptid) } 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)); 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 * 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 2008-05-03 Jan Kratochvil * gdb.base/dfp-test.exp: Fix random FAIL risk on calling functions. =================================================================== RCS file: /cvs/src/src/gdb/testsuite/gdb.base/dfp-test.exp,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- src/gdb/testsuite/gdb.base/dfp-test.exp 2008/01/30 03:19:26 1.5 +++ src/gdb/testsuite/gdb.base/dfp-test.exp 2008/05/03 21:56:38 1.6 @@ -252,16 +252,16 @@ # Test calling inferior function with DFP arguments or return value. -send_gdb "call arg0_32 (1.2df, 2.2df, 3.2df, 4.2df, 5.2df, 6.2df)\n" -gdb_test "backtrace 1" "\n#\[0-9\]+ arg0_32 \\(arg0=1.2, arg1=2.2, arg2=3.2, arg3=4.2, arg4=5.2, arg5=6.2\\).*" "Call function with correct _Decimal32 arguments." +gdb_test "call arg0_32 (1.2df, 2.2df, 3.2df, 4.2df, 5.2df, 6.2df)" "Breakpoint.*arg0_32.*" "Call function with correct _Decimal32 arguments." +gdb_test "backtrace 1" "\n#\[0-9\]+ arg0_32 \\(arg0=1.2, arg1=2.2, arg2=3.2, arg3=4.2, arg4=5.2, arg5=6.2\\).*" "Backtrace function with correct _Decimal32 arguments." gdb_test "finish" " = 1.2" "Correct _Decimal32 return value from called function." -send_gdb "call arg0_64 (1.2dd, 2.2dd, 3.2dd, 4.2dd, 5.2dd, 6.2dd)\n" -gdb_test "backtrace 1" "\n#\[0-9\]+ arg0_64 \\(arg0=1.2, arg1=2.2, arg2=3.2, arg3=4.2, arg4=5.2, arg5=6.2\\).*" "Call function with correct _Decimal64 arguments." +gdb_test "call arg0_64 (1.2dd, 2.2dd, 3.2dd, 4.2dd, 5.2dd, 6.2dd)" "Breakpoint.*arg0_64.*" "Call function with correct _Decimal64 arguments." +gdb_test "backtrace 1" "\n#\[0-9\]+ arg0_64 \\(arg0=1.2, arg1=2.2, arg2=3.2, arg3=4.2, arg4=5.2, arg5=6.2\\).*" "Backtrace function with correct _Decimal64 arguments." gdb_test "finish" " = 1.2" "Correct _Decimal64 return value from called function." -send_gdb "call arg0_128 (1.2dl, 2.2dl, 3.2dl, 4.2dl, 5.2dl, 6.2dl)\n" -gdb_test "backtrace 1" "\n#\[0-9\]+ arg0_128 \\(arg0=1.2, arg1=2.2, arg2=3.2, arg3=4.2, arg4=5.2, arg5=6.2\\).*" "Call function with correct _Decimal128 arguments." +gdb_test "call arg0_128 (1.2dl, 2.2dl, 3.2dl, 4.2dl, 5.2dl, 6.2dl)" "Breakpoint.*arg0_128.*" "Call function with correct _Decimal128 arguments." +gdb_test "backtrace 1" "\n#\[0-9\]+ arg0_128 \\(arg0=1.2, arg1=2.2, arg2=3.2, arg3=4.2, arg4=5.2, arg5=6.2\\).*" "Backtrace function with correct _Decimal128 arguments." gdb_test "finish" " = 1.2" "Correct _Decimal128 return value from called function." gdb_test "call decimal_dec128_align (double_val1, dec128_val2, double_val3, double_val4, double_val5, double_val6, double_val7, double_val8, double_val9, double_val10, double_val11, double_val12, double_val13, double_val14)" " = 1" \ gdb/ 2008-07-07 Jan Kratochvil * breakpoint.c (bpstat_copy): Call RELEASE_VALUE on the new OLD_VAL. gdb/testsuite/ 2008-07-07 Jan Kratochvil * gdb.base/value-double-free.exp, gdb.base/value-double-free.c: New. =================================================================== RCS file: /cvs/src/src/gdb/breakpoint.c,v retrieving revision 1.327 retrieving revision 1.328 diff -u -r1.327 -r1.328 --- src/gdb/breakpoint.c 2008/06/28 09:42:15 1.327 +++ src/gdb/breakpoint.c 2008/07/07 22:39:58 1.328 @@ -1996,7 +1996,10 @@ if (bs->commands != NULL) tmp->commands = copy_command_lines (bs->commands); if (bs->old_val != NULL) - tmp->old_val = value_copy (bs->old_val); + { + tmp->old_val = value_copy (bs->old_val); + release_value (tmp->old_val); + } if (p == NULL) /* This is the first thing in the chain. */ /cvs/src/src/gdb/testsuite/gdb.base/value-double-free.c,v --> standard output revision 1.1 --- src/gdb/testsuite/gdb.base/value-double-free.c +++ src/gdb/testsuite/gdb.base/value-double-free.c 2008-07-07 22:40:47.485459000 +0000 @@ -0,0 +1,36 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2008 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Please email any bugs, comments, and/or additions to this file to: + bug-gdb@prep.ai.mit.edu */ + +volatile int var; + +void +empty (void) +{ +} + +int +main (void) +{ + var = 1; + /* Workaround PR 38: We may miss the first watchpoint hit as we stop on the + exact instruction which would cause the watchpoint hit. */ + var = 2; + return 0; +} /cvs/src/src/gdb/testsuite/gdb.base/value-double-free.exp,v --> standard output revision 1.1 --- src/gdb/testsuite/gdb.base/value-double-free.exp +++ src/gdb/testsuite/gdb.base/value-double-free.exp 2008-07-07 22:40:48.139680000 +0000 @@ -0,0 +1,38 @@ +# Copyright 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +set testfile value-double-free +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] { + return -1 +} +gdb_test "watch var" "atchpoint \[0-9\]+: var" +gdb_test "continue" "atchpoint \[0-9\]+: var.*Old value = 0.*New value = \[12\].*" +gdb_test "print empty()" " = void" +# We did segfault here. +gdb_test "help help" http://sourceware.org/ml/gdb-patches/2008-03/msg00356.html http://sourceware.org/ml/gdb-cvs/2008-03/msg00130.html 2008-03-24 Jan Kratochvil Fix random false FAILs on i386. * gdb.base/prelink.exp: Use `--no-exec-shield' for prelink. =================================================================== RCS file: /cvs/src/src/gdb/testsuite/gdb.base/prelink.exp,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- src/gdb/testsuite/gdb.base/prelink.exp 2008/01/01 22:53:19 1.7 +++ src/gdb/testsuite/gdb.base/prelink.exp 2008/03/24 15:16:12 1.8 @@ -47,7 +47,15 @@ return -1 } -if {[catch "system \"prelink -qNR ${libfile}\""] != 0} { +# `--no-exec-shield' is for i386 where prelink in the exec-shield mode is +# forced to push all the libraries tight together to fit into the first two +# memory areas (either the ASCII Shield area or at least below the executable). +# In this case its -R option cannot be applied and we falsely FAIL here as if +# the system is already prelinked prelink has no choice how to randomize the +# single new unprelinked library address without wasting the first one/two +# memory areas. We do not care of the efficiency of loading such resulting +# exec-shield unfriendly prelinked library. +if {[catch "system \"prelink -qNR --no-exec-shield ${libfile}\""] != 0} { # Maybe we don't have prelink. return -1 } @@ -92,7 +100,7 @@ untested "${testfile}.so was not prelinked, maybe system libraries are not prelinked?" return 0 } -catch "system \"prelink -qNR ${libfile}\"" +catch "system \"prelink -qNR --no-exec-shield ${libfile}\"" # Start with a fresh gdb