From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 4167 invoked by alias); 25 Apr 2008 16:16:24 -0000 Received: (qmail 4156 invoked by uid 22791); 25 Apr 2008 16:16:22 -0000 X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (65.74.133.4) by sourceware.org (qpsmtpd/0.31) with ESMTP; Fri, 25 Apr 2008 16:15:52 +0000 Received: (qmail 30053 invoked from network); 25 Apr 2008 16:15:47 -0000 Received: from unknown (HELO orlando.local) (pedro@127.0.0.2) by mail.codesourcery.com with ESMTPA; 25 Apr 2008 16:15:47 -0000 From: Pedro Alves To: Daniel Jacobowitz Subject: Re: 3/5 - Rework stepping over longjmp support Date: Fri, 25 Apr 2008 18:29:00 -0000 User-Agent: KMail/1.9.6 (enterprise 0.20070907.709405) Cc: gdb-patches@sourceware.org References: <200804070331.14538.pedro@codesourcery.com> <20080414184106.GF1968@caradoc.them.org> In-Reply-To: <20080414184106.GF1968@caradoc.them.org> MIME-Version: 1.0 Content-Type: Multipart/Mixed; boundary="Boundary-00=_xOgEIizv3Vlz5/A" Message-Id: <200804251715.45780.pedro@codesourcery.com> X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2008-04/txt/msg00576.txt.bz2 --Boundary-00=_xOgEIizv3Vlz5/A Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Content-Disposition: inline Content-length: 823 A Monday 14 April 2008 19:41:06, Daniel Jacobowitz wrote: > On Mon, Apr 07, 2008 at 03:31:14AM +0100, Pedro Alves wrote: > > 2008-04-07 Pedro Alves > > > > * breakpoint.c (update_breakpoints_after_exec): Delete bp_longjmp > > and bp_longjmp_resume breakpoints. > > ... > > OK, thanks. I've readjusted the patch now that the always-inserted breakpoints work is in, and the exec-cleanup infrastructure is gone. Most of the changes are mechanic. One addition I've done is that I saw one XFAIL -> FAIL in the annota2.exp test, and I thought it was sporadic but is not. The longjmp breakpoint inserting/removing changes the places the breakpoints-invalid annotation is emitted so the test needs fixing up. Still OK? I'll check the new longjmp.exp test in along with this one. -- Pedro Alves --Boundary-00=_xOgEIizv3Vlz5/A Content-Type: text/x-diff; charset="iso-8859-1"; name="longjmp_rewrite.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="longjmp_rewrite.diff" Content-length: 27274 2008-04-25 Pedro Alves gdb/ * breakpoint.c (update_breakpoints_after_exec): Delete bp_longjmp and bp_longjmp_resume breakpoints. (breakpoint_address_is_meaningful): Claim bp_longjmp_resume as meaningful. (create_longjmp_breakpoint): Don't create bp_longjmp_resume breakpoints. Create bp_longjmp breakpoints as momentary breakpoints. (enable_longjmp_breakpoint): Delete. (set_longjmp_breakpoint): New. (disable_longjmp_breakpoint): Delete. (delete_longjmp_breakpoint): New. (set_longjmp_resume_breakpoint): Delete. (set_momentary_breakpoint_at_pc): New. (breakpoint_re_set_one): Don't delete bp_longjmp and bp_longjmp_resume breakpoints. (breakpoint_re_set): Don't create longjmp and longjmp-resume breakpoints. * infrun.c (step_resume_breakpoint): Add comment. (struct execution_control_state): Delete handling_longjmp member. (init_execution_control_state). Don't clear handling_longjmp. (context_switch): Don't context switch handling_longjmp. (handle_inferior_event): If handling a bp_longjmp breakpoint, create a bp_longjmp_resume breakpoint, and set it as current step_resume_breakpoint, then step over the longjmp breakpoint. If handling a bp_longjmp_resume breakpoint, don't delete the longjmp breakpoint, delete the longjmp-resume breakpoint, and stop stepping. (currently_stepping): Remove handling_longjmp from expression. (insert_step_resume_breakpoint_at_sal): Update comment. (insert_longjmp_resume_breakpoint): New. * breakpoint.h (set_momentary_breakpoint_at_pc): Declare. (enable_longjmp_breakpoint, disable_longjmp_breakpoint): Delete declarations. (set_longjmp_breakpoint, delete_longjmp_breakpoint): Declare. (set_longjmp_resume_breakpoint): Delete declaration. * gdbthread.h (save_infrun_state): Remove handling_longjmp parameter. (load_infrun_state): Delete *handling_longjmp parameter. * thread.c (save_infrun_state): Remove handling_longjmp parameter. Update body. (load_infrun_state): Delete *handling_longjmp parameter. Update body. * infcmd.c Include "gdbthread.h". (disable_longjmp_breakpoint_cleanup): Delete. (delete_longjmp_breakpoint_cleanup): New. (step_1): Call set_longjmp_breakpoint instead of enable_longjmp_breakpoint. Use delete_longjmp_breakpoint_cleanup instead of disable_longjmp_breakpoint_cleanup when making cleanup. (step_1_continuation): Pass thread id in the continuation args to step_once. (step_once): Add thread parameter. Pass thread id the the continuation. * Makefile.in (infcmd.o): Update. gdb/testsuite: * gdb.cp/annota2.exp: Adjust to breakpoints invalidations at different times. --- gdb/Makefile.in | 2 gdb/breakpoint.c | 112 ++++++++++++++------------------------- gdb/breakpoint.h | 9 ++- gdb/gdbthread.h | 3 - gdb/infcmd.c | 42 ++++++++++---- gdb/infrun.c | 86 ++++++++++++++++++++--------- gdb/testsuite/gdb.cp/annota2.exp | 4 - gdb/thread.c | 4 - 8 files changed, 143 insertions(+), 119 deletions(-) Index: src/gdb/breakpoint.c =================================================================== --- src.orig/gdb/breakpoint.c 2008-04-25 14:54:13.000000000 +0100 +++ src/gdb/breakpoint.c 2008-04-25 14:54:13.000000000 +0100 @@ -152,8 +152,6 @@ static int watchpoint_check (void *); static void maintenance_info_breakpoints (char *, int); -static void create_longjmp_breakpoint (char *); - static void create_overlay_event_breakpoint (char *); static int hw_breakpoint_used_count (void); @@ -1499,6 +1497,14 @@ update_breakpoints_after_exec (void) continue; } + /* Longjmp and longjmp-resume breakpoints are also meaningless + after an exec. */ + if (b->type == bp_longjmp || b->type == bp_longjmp_resume) + { + delete_breakpoint (b); + continue; + } + /* Don't delete an exec catchpoint, because else the inferior won't stop when it ought! @@ -4093,7 +4099,6 @@ set_default_breakpoint (int valid, CORE_ bp_read_watchpoint bp_access_watchpoint bp_catch_exec - bp_longjmp_resume bp_catch_fork bp_catch_vork */ @@ -4107,7 +4112,6 @@ breakpoint_address_is_meaningful (struct && type != bp_read_watchpoint && type != bp_access_watchpoint && type != bp_catch_exec - && type != bp_longjmp_resume && type != bp_catch_fork && type != bp_catch_vfork); } @@ -4465,20 +4469,9 @@ create_longjmp_breakpoint (char *func_na struct breakpoint *b; struct minimal_symbol *m; - if (func_name == NULL) - b = create_internal_breakpoint (0, bp_longjmp_resume); - else - { - if ((m = lookup_minimal_symbol_text (func_name, NULL)) == NULL) - return; - - b = create_internal_breakpoint (SYMBOL_VALUE_ADDRESS (m), bp_longjmp); - } - - b->enable_state = bp_disabled; - b->silent = 1; - if (func_name) - b->addr_string = xstrdup (func_name); + if ((m = lookup_minimal_symbol_text (func_name, NULL)) == NULL) + return; + set_momentary_breakpoint_at_pc (SYMBOL_VALUE_ADDRESS (m), bp_longjmp); update_global_location_list (); } @@ -4487,30 +4480,31 @@ create_longjmp_breakpoint (char *func_na set_longjmp_resume_breakpoint() to figure out where we are going. */ void -enable_longjmp_breakpoint (void) +set_longjmp_breakpoint (void) { struct breakpoint *b; - ALL_BREAKPOINTS (b) - if (b->type == bp_longjmp) + if (gdbarch_get_longjmp_target_p (current_gdbarch)) { - b->enable_state = bp_enabled; - update_global_location_list (); + create_longjmp_breakpoint ("longjmp"); + create_longjmp_breakpoint ("_longjmp"); + create_longjmp_breakpoint ("siglongjmp"); + create_longjmp_breakpoint ("_siglongjmp"); } } +/* Delete all longjmp breakpoints from THREAD. */ void -disable_longjmp_breakpoint (void) +delete_longjmp_breakpoint (int thread) { - struct breakpoint *b; + struct breakpoint *b, *temp; - ALL_BREAKPOINTS (b) - if (b->type == bp_longjmp - || b->type == bp_longjmp_resume) - { - b->enable_state = bp_disabled; - update_global_location_list (); - } + ALL_BREAKPOINTS_SAFE (b, temp) + if (b->type == bp_longjmp) + { + if (b->thread == thread) + delete_breakpoint (b); + } } static void @@ -4803,30 +4797,6 @@ hw_watchpoint_used_count (enum bptype ty return i; } -/* Call this after hitting the longjmp() breakpoint. Use this to set - a new breakpoint at the target of the jmp_buf. - - FIXME - This ought to be done by setting a temporary breakpoint - that gets deleted automatically... */ - -void -set_longjmp_resume_breakpoint (CORE_ADDR pc, struct frame_id frame_id) -{ - struct breakpoint *b; - - ALL_BREAKPOINTS (b) - if (b->type == bp_longjmp_resume) - { - b->loc->requested_address = pc; - b->loc->address = adjust_breakpoint_address (b->loc->requested_address, - b->type); - b->enable_state = bp_enabled; - b->frame_id = frame_id; - update_global_location_list (); - return; - } -} - void disable_watchpoints_before_interactive_call_start (void) { @@ -4890,6 +4860,19 @@ set_momentary_breakpoint (struct symtab_ return b; } + +struct breakpoint * +set_momentary_breakpoint_at_pc (CORE_ADDR pc, enum bptype type) +{ + struct symtab_and_line sal; + + sal = find_pc_line (pc, 0); + sal.pc = pc; + sal.section = find_pc_overlay (pc); + sal.explicit_pc = 1; + + return set_momentary_breakpoint (sal, null_frame_id, type); +} /* Tell the user we have just set a breakpoint B. */ @@ -7547,10 +7530,8 @@ breakpoint_re_set_one (void *bint) default: printf_filtered (_("Deleting unknown breakpoint type %d\n"), b->type); /* fall through */ - /* Delete longjmp and overlay event breakpoints; they will be - reset later by breakpoint_re_set. */ - case bp_longjmp: - case bp_longjmp_resume: + /* Delete overlay event breakpoints; they will be reset later by + breakpoint_re_set. */ case bp_overlay_event: delete_breakpoint (b); break; @@ -7572,6 +7553,8 @@ breakpoint_re_set_one (void *bint) case bp_watchpoint_scope: case bp_call_dummy: case bp_step_resume: + case bp_longjmp: + case bp_longjmp_resume: break; } @@ -7599,15 +7582,6 @@ breakpoint_re_set (void) } set_language (save_language); input_radix = save_input_radix; - - if (gdbarch_get_longjmp_target_p (current_gdbarch)) - { - create_longjmp_breakpoint ("longjmp"); - create_longjmp_breakpoint ("_longjmp"); - create_longjmp_breakpoint ("siglongjmp"); - create_longjmp_breakpoint ("_siglongjmp"); - create_longjmp_breakpoint (NULL); - } create_overlay_event_breakpoint ("_ovly_debug_event"); } Index: src/gdb/infrun.c =================================================================== --- src.orig/gdb/infrun.c 2008-04-25 14:54:13.000000000 +0100 +++ src/gdb/infrun.c 2008-04-25 14:54:13.000000000 +0100 @@ -271,6 +271,7 @@ struct regcache *stop_registers; static int stop_print_frame; +/* Step-resume or longjmp-resume breakpoint. */ static struct breakpoint *step_resume_breakpoint = NULL; /* This is a cached copy of the pid/waitstatus of the last event @@ -954,7 +955,6 @@ struct execution_control_state struct symtab_and_line sal; int current_line; struct symtab *current_symtab; - int handling_longjmp; /* FIXME */ ptid_t ptid; ptid_t saved_inferior_ptid; int step_after_step_resume_breakpoint; @@ -976,6 +976,8 @@ static void insert_step_resume_breakpoin static void insert_step_resume_breakpoint_at_caller (struct frame_info *); static void insert_step_resume_breakpoint_at_sal (struct symtab_and_line sr_sal, struct frame_id sr_id); +static void insert_longjmp_resume_breakpoint (CORE_ADDR); + static void stop_stepping (struct execution_control_state *ecs); static void prepare_to_wait (struct execution_control_state *ecs); static void keep_going (struct execution_control_state *ecs); @@ -1120,7 +1122,6 @@ init_execution_control_state (struct exe ecs->stepping_over_breakpoint = 0; ecs->random_signal = 0; ecs->step_after_step_resume_breakpoint = 0; - ecs->handling_longjmp = 0; /* FIXME */ ecs->stepping_through_solib_after_catch = 0; ecs->stepping_through_solib_catchpoints = NULL; ecs->sal = find_pc_line (prev_pc, 0); @@ -1175,7 +1176,7 @@ context_switch (struct execution_control stepping_over_breakpoint, step_resume_breakpoint, step_range_start, step_range_end, &step_frame_id, - ecs->handling_longjmp, ecs->stepping_over_breakpoint, + ecs->stepping_over_breakpoint, ecs->stepping_through_solib_after_catch, ecs->stepping_through_solib_catchpoints, ecs->current_line, ecs->current_symtab); @@ -1185,7 +1186,7 @@ context_switch (struct execution_control &stepping_over_breakpoint, &step_resume_breakpoint, &step_range_start, &step_range_end, &step_frame_id, - &ecs->handling_longjmp, &ecs->stepping_over_breakpoint, + &ecs->stepping_over_breakpoint, &ecs->stepping_through_solib_after_catch, &ecs->stepping_through_solib_catchpoints, &ecs->current_line, &ecs->current_symtab); @@ -2104,38 +2105,50 @@ process_event_stop_test: switch (what.main_action) { case BPSTAT_WHAT_SET_LONGJMP_RESUME: - /* If we hit the breakpoint at longjmp, disable it for the - duration of this command. Then, install a temporary - breakpoint at the target of the jmp_buf. */ - if (debug_infrun) - fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME\n"); - disable_longjmp_breakpoint (); + /* If we hit the breakpoint at longjmp while stepping, we + install a momentary breakpoint at the target of the + jmp_buf. */ + + if (debug_infrun) + fprintf_unfiltered (gdb_stdlog, + "infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME\n"); + + ecs->stepping_over_breakpoint = 1; + if (!gdbarch_get_longjmp_target_p (current_gdbarch) || !gdbarch_get_longjmp_target (current_gdbarch, get_current_frame (), &jmp_buf_pc)) { + if (debug_infrun) + fprintf_unfiltered (gdb_stdlog, "\ +infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n"); keep_going (ecs); return; } - /* Need to blow away step-resume breakpoint, as it - interferes with us */ + /* We're going to replace the current step-resume breakpoint + with a longjmp-resume breakpoint. */ if (step_resume_breakpoint != NULL) - { - delete_step_resume_breakpoint (&step_resume_breakpoint); - } + delete_step_resume_breakpoint (&step_resume_breakpoint); + + /* Insert a breakpoint at resume address. */ + insert_longjmp_resume_breakpoint (jmp_buf_pc); - set_longjmp_resume_breakpoint (jmp_buf_pc, null_frame_id); - ecs->handling_longjmp = 1; /* FIXME */ keep_going (ecs); return; case BPSTAT_WHAT_CLEAR_LONGJMP_RESUME: if (debug_infrun) - fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_CLEAR_LONGJMP_RESUME\n"); - disable_longjmp_breakpoint (); - ecs->handling_longjmp = 0; /* FIXME */ - break; + fprintf_unfiltered (gdb_stdlog, + "infrun: BPSTAT_WHAT_CLEAR_LONGJMP_RESUME\n"); + + gdb_assert (step_resume_breakpoint != NULL); + delete_step_resume_breakpoint (&step_resume_breakpoint); + + stop_step = 1; + print_stop_reason (END_STEPPING_RANGE, 0); + stop_stepping (ecs); + return; case BPSTAT_WHAT_SINGLE: if (debug_infrun) @@ -2698,9 +2711,8 @@ process_event_stop_test: static int currently_stepping (struct execution_control_state *ecs) { - return ((!ecs->handling_longjmp - && ((step_range_end && step_resume_breakpoint == NULL) - || stepping_over_breakpoint)) + return (((step_range_end && step_resume_breakpoint == NULL) + || stepping_over_breakpoint) || ecs->stepping_through_solib_after_catch || bpstat_should_step ()); } @@ -2787,8 +2799,8 @@ static void insert_step_resume_breakpoint_at_sal (struct symtab_and_line sr_sal, struct frame_id sr_id) { - /* There should never be more than one step-resume breakpoint per - thread, so we should never be setting a new + /* There should never be more than one step-resume or longjmp-resume + breakpoint per thread, so we should never be setting a new step_resume_breakpoint when one is already active. */ gdb_assert (step_resume_breakpoint == NULL); @@ -2856,6 +2868,28 @@ insert_step_resume_breakpoint_at_caller insert_step_resume_breakpoint_at_sal (sr_sal, frame_unwind_id (next_frame)); } +/* Insert a "longjmp-resume" breakpoint at PC. This is used to set a + new breakpoint at the target of a jmp_buf. The handling of + longjmp-resume uses the same mechanisms used for handling + "step-resume" breakpoints. */ + +static void +insert_longjmp_resume_breakpoint (CORE_ADDR pc) +{ + /* There should never be more than one step-resume or longjmp-resume + breakpoint per thread, so we should never be setting a new + longjmp_resume_breakpoint when one is already active. */ + gdb_assert (step_resume_breakpoint == NULL); + + if (debug_infrun) + fprintf_unfiltered (gdb_stdlog, + "infrun: inserting longjmp-resume breakpoint at 0x%s\n", + paddr_nz (pc)); + + step_resume_breakpoint = + set_momentary_breakpoint_at_pc (pc, bp_longjmp_resume); +} + static void stop_stepping (struct execution_control_state *ecs) { Index: src/gdb/breakpoint.h =================================================================== --- src.orig/gdb/breakpoint.h 2008-04-25 14:54:13.000000000 +0100 +++ src/gdb/breakpoint.h 2008-04-25 14:54:13.000000000 +0100 @@ -689,6 +689,9 @@ extern int ep_is_exception_catchpoint (s extern struct breakpoint *set_momentary_breakpoint (struct symtab_and_line, struct frame_id, enum bptype); +extern struct breakpoint *set_momentary_breakpoint_at_pc + (CORE_ADDR pc, enum bptype type); + extern void set_ignore_count (int, int, int); extern void set_default_breakpoint (int, CORE_ADDR, struct symtab *, int); @@ -757,12 +760,12 @@ extern void update_breakpoints_after_exe inferior_ptid. */ extern int detach_breakpoints (int); -extern void enable_longjmp_breakpoint (void); -extern void disable_longjmp_breakpoint (void); +extern void set_longjmp_breakpoint (void); +extern void delete_longjmp_breakpoint (int thread); + extern void enable_overlay_breakpoints (void); extern void disable_overlay_breakpoints (void); -extern void set_longjmp_resume_breakpoint (CORE_ADDR, struct frame_id); /* These functions respectively disable or reenable all currently enabled watchpoints. When disabled, the watchpoints are marked call_disabled. When reenabled, they are marked enabled. Index: src/gdb/gdbthread.h =================================================================== --- src.orig/gdb/gdbthread.h 2008-04-25 14:50:20.000000000 +0100 +++ src/gdb/gdbthread.h 2008-04-25 14:54:13.000000000 +0100 @@ -50,7 +50,6 @@ struct thread_info int current_line; struct symtab *current_symtab; int trap_expected; - int handling_longjmp; int stepping_over_breakpoint; /* This is set TRUE when a catchpoint of a shared library event @@ -123,7 +122,6 @@ extern void save_infrun_state (ptid_t pt CORE_ADDR step_range_start, CORE_ADDR step_range_end, const struct frame_id *step_frame_id, - int handling_longjmp, int another_trap, int stepping_through_solib_after_catch, bpstat stepping_through_solib_catchpoints, @@ -139,7 +137,6 @@ extern void load_infrun_state (ptid_t pt CORE_ADDR *step_range_start, CORE_ADDR *step_range_end, struct frame_id *step_frame_id, - int *handling_longjmp, int *another_trap, int *stepping_through_solib_affter_catch, bpstat *stepping_through_solib_catchpoints, Index: src/gdb/thread.c =================================================================== --- src.orig/gdb/thread.c 2008-04-25 14:50:20.000000000 +0100 +++ src/gdb/thread.c 2008-04-25 14:54:13.000000000 +0100 @@ -316,7 +316,6 @@ load_infrun_state (ptid_t ptid, CORE_ADDR *step_range_start, CORE_ADDR *step_range_end, struct frame_id *step_frame_id, - int *handling_longjmp, int *stepping_over_breakpoint, int *stepping_through_solib_after_catch, bpstat *stepping_through_solib_catchpoints, @@ -337,7 +336,6 @@ load_infrun_state (ptid_t ptid, *step_range_start = tp->step_range_start; *step_range_end = tp->step_range_end; *step_frame_id = tp->step_frame_id; - *handling_longjmp = tp->handling_longjmp; *stepping_over_breakpoint = tp->stepping_over_breakpoint; *stepping_through_solib_after_catch = tp->stepping_through_solib_after_catch; @@ -357,7 +355,6 @@ save_infrun_state (ptid_t ptid, CORE_ADDR step_range_start, CORE_ADDR step_range_end, const struct frame_id *step_frame_id, - int handling_longjmp, int stepping_over_breakpoint, int stepping_through_solib_after_catch, bpstat stepping_through_solib_catchpoints, @@ -378,7 +375,6 @@ save_infrun_state (ptid_t ptid, tp->step_range_start = step_range_start; tp->step_range_end = step_range_end; tp->step_frame_id = (*step_frame_id); - tp->handling_longjmp = handling_longjmp; tp->stepping_over_breakpoint = stepping_over_breakpoint; tp->stepping_through_solib_after_catch = stepping_through_solib_after_catch; tp->stepping_through_solib_catchpoints = stepping_through_solib_catchpoints; Index: src/gdb/infcmd.c =================================================================== --- src.orig/gdb/infcmd.c 2008-04-25 14:50:20.000000000 +0100 +++ src/gdb/infcmd.c 2008-04-25 14:54:13.000000000 +0100 @@ -50,6 +50,7 @@ #include "user-regs.h" #include "exceptions.h" #include "cli/cli-decode.h" +#include "gdbthread.h" /* Functions exported for general use, in inferior.h: */ @@ -106,7 +107,7 @@ static void signal_command (char *, int) static void jump_command (char *, int); static void step_1 (int, int, char *); -static void step_once (int skip_subroutines, int single_inst, int count); +static void step_once (int skip_subroutines, int single_inst, int count, int thread); static void step_1_continuation (struct continuation_arg *arg, int error_p); static void next_command (char *, int); @@ -692,9 +693,10 @@ nexti_command (char *count_string, int f } static void -disable_longjmp_breakpoint_cleanup (void *ignore) +delete_longjmp_breakpoint_cleanup (void *arg) { - disable_longjmp_breakpoint (); + int thread = * (int *) arg; + delete_longjmp_breakpoint (thread); } static void @@ -704,6 +706,7 @@ step_1 (int skip_subroutines, int single struct frame_info *frame; struct cleanup *cleanups = make_cleanup (null_cleanup, NULL); int async_exec = 0; + int *thread_p = NULL; ERROR_NO_INFERIOR; @@ -727,8 +730,17 @@ step_1 (int skip_subroutines, int single if (!single_inst || skip_subroutines) /* leave si command alone */ { - enable_longjmp_breakpoint (); - make_cleanup (disable_longjmp_breakpoint_cleanup, 0 /*ignore*/); + thread_p = xmalloc (sizeof (int)); + make_cleanup (xfree, thread_p); + + if (in_thread_list (inferior_ptid)) + *thread_p = pid_to_thread_id (inferior_ptid); + else + *thread_p = -1; + + set_longjmp_breakpoint (); + + make_cleanup (delete_longjmp_breakpoint_cleanup, thread_p); } /* In synchronous case, all is well, just use the regular for loop. */ @@ -789,10 +801,11 @@ which has no line number information.\n" and handle them one at the time, through step_once(). */ else { - step_once (skip_subroutines, single_inst, count); - /* We are running, and the contination is installed. It will + step_once (skip_subroutines, single_inst, count, *thread_p); + /* We are running, and the continuation is installed. It will disable the longjmp breakpoint as appropriate. */ discard_cleanups (cleanups); + xfree (thread_p); } } @@ -807,10 +820,12 @@ step_1_continuation (struct continuation int count; int skip_subroutines; int single_inst; + int thread; skip_subroutines = arg->data.integer; single_inst = arg->next->data.integer; count = arg->next->next->data.integer; + thread = arg->next->next->next->data.integer; if (error_p || !step_multi || !stop_step) { @@ -818,11 +833,11 @@ step_1_continuation (struct continuation that is not stepping, or there are no further steps to make. Cleanup. */ if (!single_inst || skip_subroutines) - disable_longjmp_breakpoint (); + delete_longjmp_breakpoint (thread); step_multi = 0; } else - step_once (skip_subroutines, single_inst, count - 1); + step_once (skip_subroutines, single_inst, count - 1, thread); } /* Do just one step operation. If count >1 we will have to set up a @@ -833,11 +848,12 @@ step_1_continuation (struct continuation called in case of step n with n>1, after the first step operation has been completed.*/ static void -step_once (int skip_subroutines, int single_inst, int count) +step_once (int skip_subroutines, int single_inst, int count, int thread) { struct continuation_arg *arg1; struct continuation_arg *arg2; struct continuation_arg *arg3; + struct continuation_arg *arg4; struct frame_info *frame; if (count > 0) @@ -893,12 +909,16 @@ which has no line number information.\n" (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg)); arg3 = (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg)); + arg4 = + (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg)); arg1->next = arg2; arg1->data.integer = skip_subroutines; arg2->next = arg3; arg2->data.integer = single_inst; - arg3->next = NULL; + arg3->next = arg4; arg3->data.integer = count; + arg4->next = NULL; + arg4->data.integer = thread; add_intermediate_continuation (step_1_continuation, arg1); } } Index: src/gdb/Makefile.in =================================================================== --- src.orig/gdb/Makefile.in 2008-04-25 14:50:20.000000000 +0100 +++ src/gdb/Makefile.in 2008-04-25 15:27:19.000000000 +0100 @@ -2315,7 +2315,7 @@ infcmd.o: infcmd.c $(defs_h) $(gdb_strin $(objfiles_h) $(completer_h) $(ui_out_h) $(event_top_h) \ $(parser_defs_h) $(regcache_h) $(reggroups_h) $(block_h) \ $(solib_h) $(gdb_assert_h) $(observer_h) $(target_descriptions_h) \ - $(user_regs_h) $(exceptions_h) $(cli_decode_h) + $(user_regs_h) $(exceptions_h) $(cli_decode_h) $(gdbthread_h) inf-loop.o: inf-loop.c $(defs_h) $(inferior_h) $(target_h) $(event_loop_h) \ $(event_top_h) $(inf_loop_h) $(remote_h) $(exceptions_h) \ $(language_h) Index: src/gdb/testsuite/gdb.cp/annota2.exp =================================================================== --- src.orig/gdb/testsuite/gdb.cp/annota2.exp 2008-04-25 15:27:33.000000000 +0100 +++ src/gdb/testsuite/gdb.cp/annota2.exp 2008-04-25 15:28:04.000000000 +0100 @@ -190,9 +190,9 @@ gdb_expect { # send_gdb "next\n" gdb_expect { - -re "\r\n\032\032post-prompt\r\n\r\n\032\032starting\r\n\r\n(\032\032frames-invalid\r\n\r\n)*\032\032watchpoint 3\r\n.*atchpoint 3: a.x\r\n\r\nOld value = 0\r\nNew value = 1\r\n\r\n\032\032frame-begin 0 $hex\r\n\r\n\032\032frame-function-name\r\nmain\r\n\032\032frame-args\r\n \\(\\)\r\n\032\032frame-source-begin\r\n at \r\n\032\032frame-source-file\r\n.*$srcfile\r\n\032\032frame-source-file-end\r\n:\r\n\032\032frame-source-line\r\n$decimal\r\n\032\032frame-source-end\r\n\r\n\r\n\032\032source .*$srcfile.*beg:$hex\r\n\r\n\032\032frame-end\r\n\r\n\032\032stopped\r\n.*$gdb_prompt$" \ + -re "\r\n\032\032post-prompt\r\n\r\n(\032\032breakpoints-invalid\r\n\r\n)*\032\032starting\r\n\r\n(\032\032frames-invalid\r\n\r\n)*\032\032watchpoint 3\r\n.*atchpoint 3: a.x\r\n\r\nOld value = 0\r\nNew value = 1\r\n\r\n\032\032frame-begin 0 $hex\r\n\r\n\032\032frame-function-name\r\nmain\r\n\032\032frame-args\r\n \\(\\)\r\n\032\032frame-source-begin\r\n at \r\n\032\032frame-source-file\r\n.*$srcfile\r\n\032\032frame-source-file-end\r\n:\r\n\032\032frame-source-line\r\n$decimal\r\n\032\032frame-source-end\r\n\r\n\r\n\032\032source .*$srcfile.*beg:$hex\r\n\r\n\032\032frame-end\r\n\r\n\032\032stopped\r\n.*$gdb_prompt$" \ { pass "watch triggered on a.x" } - -re "\r\n\032\032post-prompt\r\n\r\n\032\032starting\r\n\r\n\032\032frames-invalid\r\n\r\n\032\032source .*$srcfile.*beg:$hex\r\n\r\n\032\032frame-end\r\n\r\n\032\032stopped\r\n$gdb_prompt$" \ + -re "\r\n\032\032post-prompt\r\n\r\n(\032\032breakpoints-invalid\r\n\r\n)*\032\032starting\r\n\r\n\032\032frames-invalid\r\n\r\n\032\032source .*$srcfile.*beg:$hex\r\n\r\n\032\032frame-end\r\n\r\n\032\032stopped\r\n$gdb_prompt$" \ { kfail "gdb/38" "watch triggered on a.x" } -re ".*$gdb_prompt$" { fail "watch triggered on a.x" } timeout { fail "watch triggered on a.x (timeout)" } --Boundary-00=_xOgEIizv3Vlz5/A--