From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 31955 invoked by alias); 24 Jun 2009 15:02:49 -0000 Received: (qmail 31395 invoked by uid 22791); 24 Jun 2009 15:02:45 -0000 X-SWARE-Spam-Status: No, hits=-1.6 required=5.0 tests=AWL,BAYES_00,KAM_STOCKGEN,SPF_PASS X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (65.74.133.4) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 24 Jun 2009 15:02:38 +0000 Received: (qmail 27840 invoked from network); 24 Jun 2009 15:02:36 -0000 Received: from unknown (HELO orlando.local) (pedro@127.0.0.2) by mail.codesourcery.com with ESMTPA; 24 Jun 2009 15:02:36 -0000 From: Pedro Alves To: gdb-patches@sourceware.org Subject: Re: [rfc] longjmp breakpoints (Re: [00/19] Eliminate some more current_gdbarch uses) Date: Wed, 24 Jun 2009 15:02:00 -0000 User-Agent: KMail/1.9.10 Cc: "Ulrich Weigand" , tromey@redhat.com References: <200906231804.n5NI4DTB028821@d12av02.megacenter.de.ibm.com> In-Reply-To: <200906231804.n5NI4DTB028821@d12av02.megacenter.de.ibm.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline Message-Id: <200906241603.34227.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: 2009-06/txt/msg00640.txt.bz2 On Tuesday 23 June 2009 19:04:13, Ulrich Weigand wrote: > Pedro Alves wrote: > > On Monday 08 June 2009 15:38:39, Ulrich Weigand wrote: > > > and/or > > > - keeping them always disabled, but installing momentary clones in > > > =A0 threads that are stepping > > > > Yeah, sounds sort of good too. I've added a momentary breakpoint > > cloning function just a few days ago. This requires looking up which > > threads in the same address space are stepping. I'm not certain which > > version would be uglier. Currently, it's the address lookup part > > that's ineficient. We could tackle that with per-objfile data, without > > making the breakpoints module much aware of stepping. > > This patch implements the idea of maintaining "master copies" of the > longjmp breakpoints that are created at the same places where overlay > event breakpoints are created today, and then installing momentary > clones while we want them to be active within a thread. > > What do you think? Looks good to me. Thanks! > > Tested on spu-elf. > > Bye, > Ulrich > > > ChangeLog: > > * breakpoint.h (set_longjmp_breakpoint): Add THREAD argument. > (enum bptype): Add bp_longjmp_master. > > * breakpoint.c (create_longjmp_master_breakpoint): New function. > (update_breakpoints_after_exec): Handle bp_longjmp_master > breakpoints. Call create_longjmp_master_breakpoint. > (print_it_typical, bpstat_stop_status, bpstat_what, > print_one_breakpoint_location, allocate_bp_location, mention, > delete_command, breakpoint_re_set_one): Handle bp_longjmp_master. > (breakpoint_re_set): Call create_longjmp_master_breakpoint. > (create_longjmp_breakpoint): Delete. > (set_longjmp_breakpoint): Add THREAD argument. Reimplement > to install momentary clones of bp_longjmp_master breakpoints. > > * infcmd.c (step_1): Pass thread to set_longjmp_breakpoint. > > > Index: gdb-head/gdb/breakpoint.c > =================================================================== > --- gdb-head.orig/gdb/breakpoint.c > +++ gdb-head/gdb/breakpoint.c > @@ -1507,6 +1507,31 @@ create_overlay_event_breakpoint (char *f > update_global_location_list (1); > } > > +static void > +create_longjmp_master_breakpoint (char *func_name) > +{ > + struct objfile *objfile; > + > + ALL_OBJFILES (objfile) > + { > + struct breakpoint *b; > + struct minimal_symbol *m; > + > + if (!gdbarch_get_longjmp_target_p (get_objfile_arch (objfile))) > + continue; > + > + m = lookup_minimal_symbol_text (func_name, objfile); > + if (m == NULL) > + continue; > + > + b = create_internal_breakpoint (SYMBOL_VALUE_ADDRESS (m), > + bp_longjmp_master); > + b->addr_string = xstrdup (func_name); > + b->enable_state = bp_disabled; > + } > + update_global_location_list (1); > +} > + > void > update_breakpoints_after_exec (void) > { > @@ -1535,8 +1560,9 @@ update_breakpoints_after_exec (void) > } > > /* Thread event breakpoints must be set anew after an exec(), > - as must overlay event breakpoints. */ > - if (b->type == bp_thread_event || b->type == bp_overlay_event) > + as must overlay event and longjmp master breakpoints. */ > + if (b->type == bp_thread_event || b->type == bp_overlay_event > + || b->type == bp_longjmp_master) > { > delete_breakpoint (b); > continue; > @@ -1608,6 +1634,10 @@ update_breakpoints_after_exec (void) > } > /* FIXME what about longjmp breakpoints? Re-create them here? */ > create_overlay_event_breakpoint ("_ovly_debug_event"); > + create_longjmp_master_breakpoint ("longjmp"); > + create_longjmp_master_breakpoint ("_longjmp"); > + create_longjmp_master_breakpoint ("siglongjmp"); > + create_longjmp_master_breakpoint ("_siglongjmp"); > } > > int > @@ -2426,6 +2456,12 @@ print_it_typical (bpstat bs) > result = PRINT_NOTHING; > break; > > + case bp_longjmp_master: > + /* These should never be enabled. */ > + printf_filtered (_("Longjmp Master Breakpoint: gdb should not stop!\n")); > + result = PRINT_NOTHING; > + break; > + > case bp_watchpoint: > case bp_hardware_watchpoint: > annotate_watchpoint (b->number); > @@ -3119,7 +3155,8 @@ bpstat_stop_status (CORE_ADDR bp_addr, p > if (!bs->stop) > continue; > > - if (b->type == bp_thread_event || b->type == bp_overlay_event) > + if (b->type == bp_thread_event || b->type == bp_overlay_event > + || b->type == bp_longjmp_master) > /* We do not stop for these. */ > bs->stop = 0; > else > @@ -3403,6 +3440,7 @@ bpstat_what (bpstat bs) > break; > case bp_thread_event: > case bp_overlay_event: > + case bp_longjmp_master: > bs_class = bp_nostop; > break; > case bp_catchpoint: > @@ -3529,6 +3567,7 @@ print_one_breakpoint_location (struct br > {bp_shlib_event, "shlib events"}, > {bp_thread_event, "thread events"}, > {bp_overlay_event, "overlay events"}, > + {bp_longjmp_master, "longjmp master"}, > {bp_catchpoint, "catchpoint"}, > {bp_tracepoint, "tracepoint"}, > }; > @@ -3657,6 +3696,7 @@ print_one_breakpoint_location (struct br > case bp_shlib_event: > case bp_thread_event: > case bp_overlay_event: > + case bp_longjmp_master: > case bp_tracepoint: > if (opts.addressprint) > { > @@ -4274,6 +4314,7 @@ allocate_bp_location (struct breakpoint > case bp_shlib_event: > case bp_thread_event: > case bp_overlay_event: > + case bp_longjmp_master: > loc->loc_type = bp_loc_software_breakpoint; > break; > case bp_hardware_breakpoint: > @@ -4428,32 +4469,26 @@ make_breakpoint_permanent (struct breakp > bl->inserted = 1; > } > > -static void > -create_longjmp_breakpoint (char *func_name) > -{ > - struct minimal_symbol *m; > - > - m = lookup_minimal_symbol_text (func_name, NULL); > - if (m == NULL) > - return; > - set_momentary_breakpoint_at_pc (SYMBOL_VALUE_ADDRESS (m), bp_longjmp); > - update_global_location_list (1); > -} > - > /* Call this routine when stepping and nexting to enable a breakpoint > - if we do a longjmp(). When we hit that breakpoint, call > + if we do a longjmp() in THREAD. When we hit that breakpoint, call > set_longjmp_resume_breakpoint() to figure out where we are going. */ > > void > -set_longjmp_breakpoint (void) > +set_longjmp_breakpoint (int thread) > { > - if (gdbarch_get_longjmp_target_p (current_gdbarch)) > - { > - create_longjmp_breakpoint ("longjmp"); > - create_longjmp_breakpoint ("_longjmp"); > - create_longjmp_breakpoint ("siglongjmp"); > - create_longjmp_breakpoint ("_siglongjmp"); > - } > + struct breakpoint *b, *temp; > + > + /* To avoid having to rescan all objfile symbols at every step, > + we maintain a list of continually-inserted but always disabled > + longjmp "master" breakpoints. Here, we simply create momentary > + clones of those and enable them for the requested thread. */ > + ALL_BREAKPOINTS_SAFE (b, temp) > + if (b->type == bp_longjmp_master) > + { > + struct breakpoint *clone = clone_momentary_breakpoint (b); > + b->type = bp_longjmp; > + b->thread = thread; > + } > } > > /* Delete all longjmp breakpoints from THREAD. */ > @@ -5164,6 +5199,7 @@ mention (struct breakpoint *b) > case bp_shlib_event: > case bp_thread_event: > case bp_overlay_event: > + case bp_longjmp_master: > break; > } > > @@ -7432,6 +7468,7 @@ delete_command (char *arg, int from_tty) > && b->type != bp_shlib_event > && b->type != bp_thread_event > && b->type != bp_overlay_event > + && b->type != bp_longjmp_master > && b->number >= 0) > { > breaks_to_delete = 1; > @@ -7449,6 +7486,7 @@ delete_command (char *arg, int from_tty) > && b->type != bp_shlib_event > && b->type != bp_thread_event > && b->type != bp_overlay_event > + && b->type != bp_longjmp_master > && b->number >= 0) > delete_breakpoint (b); > } > @@ -7743,9 +7781,10 @@ breakpoint_re_set_one (void *bint) > default: > printf_filtered (_("Deleting unknown breakpoint type %d\n"), b->type); > /* fall through */ > - /* Delete overlay event breakpoints; they will be reset later by > - breakpoint_re_set. */ > + /* Delete overlay event and longjmp master breakpoints; they will be > + reset later by breakpoint_re_set. */ > case bp_overlay_event: > + case bp_longjmp_master: > delete_breakpoint (b); > break; > > @@ -7797,6 +7836,10 @@ breakpoint_re_set (void) > input_radix = save_input_radix; > > create_overlay_event_breakpoint ("_ovly_debug_event"); > + create_longjmp_master_breakpoint ("longjmp"); > + create_longjmp_master_breakpoint ("_longjmp"); > + create_longjmp_master_breakpoint ("siglongjmp"); > + create_longjmp_master_breakpoint ("_siglongjmp"); > } > > /* Reset the thread number of this breakpoint: > Index: gdb-head/gdb/breakpoint.h > =================================================================== > --- gdb-head.orig/gdb/breakpoint.h > +++ gdb-head/gdb/breakpoint.h > @@ -110,6 +110,13 @@ enum bptype > > bp_overlay_event, > > + /* Master copies of longjmp breakpoints. These are always installed > + as soon as an objfile containing longjmp is loaded, but they are > + always disabled. While necessary, temporary clones of bp_longjmp > + type will be created and enabled. */ > + > + bp_longjmp_master, > + > bp_catchpoint, > > bp_tracepoint, > @@ -765,7 +772,7 @@ extern void update_breakpoints_after_exe > inferior_ptid. */ > extern int detach_breakpoints (int); > > -extern void set_longjmp_breakpoint (void); > +extern void set_longjmp_breakpoint (int thread); > extern void delete_longjmp_breakpoint (int thread); > > extern void enable_overlay_breakpoints (void); > Index: gdb-head/gdb/infcmd.c > =================================================================== > --- gdb-head.orig/gdb/infcmd.c > +++ gdb-head/gdb/infcmd.c > @@ -831,7 +831,7 @@ step_1 (int skip_subroutines, int single > if (in_thread_list (inferior_ptid)) > thread = pid_to_thread_id (inferior_ptid); > > - set_longjmp_breakpoint (); > + set_longjmp_breakpoint (thread); > > make_cleanup (delete_longjmp_breakpoint_cleanup, &thread); > } > -- Pedro Alves