From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 7074 invoked by alias); 27 Apr 2003 01:13:09 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 7067 invoked from network); 27 Apr 2003 01:13:09 -0000 Received: from unknown (HELO crack.them.org) (65.125.64.184) by sources.redhat.com with SMTP; 27 Apr 2003 01:13:09 -0000 Received: from nevyn.them.org ([66.93.61.169] ident=mail) by crack.them.org with asmtp (Exim 3.12 #1 (Debian)) id 199ajO-0005Zw-00 for ; Sat, 26 Apr 2003 20:13:26 -0500 Received: from drow by nevyn.them.org with local (Exim 3.36 #1 (Debian)) id 199aj5-0007ht-00 for ; Sat, 26 Apr 2003 21:13:07 -0400 Date: Sun, 27 Apr 2003 17:52:00 -0000 From: Daniel Jacobowitz To: gdb-patches@sources.redhat.com Subject: Re: [rfc breakpoint] Catch exceptions Message-ID: <20030427011306.GA4437@nevyn.them.org> Mail-Followup-To: gdb-patches@sources.redhat.com References: <20030325030107.GA3889@nevyn.them.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20030325030107.GA3889@nevyn.them.org> User-Agent: Mutt/1.5.1i X-SW-Source: 2003-04/txt/msg00510.txt.bz2 On Mon, Mar 24, 2003 at 10:01:07PM -0500, Daniel Jacobowitz wrote: > The feature being implemented here is "catch catch" and "catch throw". This > patch just does gcc v3; gcc v2.95 is easy to add afterwards, and I also have > a patch to remove the ancient GNU support for this feature for some 1.x g++ > versions (or maybe early 2.x?). HP, as usual, supports this in a completely > different way. Updated version (simplified) is below. It looks much nicer now. The support is rudimentary, but good enough to be quite useful, I think. The patch I checked in is the below, plus some reindentation where I moved two switch statements into else clauses. -- Daniel Jacobowitz MontaVista Software Debian GNU/Linux Developer 2003-04-26 Daniel Jacobowitz * breakpoint.h (struct breakpoint_ops): New. (struct breakpoint): Add ops member. * breakpoint.c (print_bp_stop_message, print_one_breakpoint) (mention): Use new breakpoint ops member. (set_raw_breakpoint): Initialize ops field to NULL. (print_exception_catchpoint, print_one_exception_catchpoint) (print_mention_exception_catchpoint, handle_gnu_v3_exceptions): New. (gnu_v3_exception_catchpoint_ops): New. (catch_exception_command_1): Call handle_gnu_v3_exceptions. Index: breakpoint.c =================================================================== RCS file: /big/fsf/rsync/src-cvs/src/gdb/breakpoint.c,v retrieving revision 1.118 diff -u -p -b -B -w -r1.118 breakpoint.c --- breakpoint.c 10 Apr 2003 03:30:36 -0000 1.118 +++ breakpoint.c 27 Apr 2003 00:58:11 -0000 @@ -2271,9 +2271,15 @@ print_bp_stop_message (bpstat bs) break; case print_it_normal: - /* Normal case, we handle everything in print_it_typical. */ + /* Normal case. Call the breakpoint's print_it method, or + print_it_typical. */ + if (bs->breakpoint_at != NULL && bs->breakpoint_at->ops != NULL + && bs->breakpoint_at->ops->print_it != NULL) + return bs->breakpoint_at->ops->print_it (bs->breakpoint_at); + else return print_it_typical (bs); break; + default: internal_error (__FILE__, __LINE__, "print_bp_stop_message: unrecognized enum value"); @@ -3265,6 +3271,10 @@ print_one_breakpoint (struct breakpoint else strcat (wrap_indent, " "); } + + if (b->ops != NULL && b->ops->print_one != NULL) + b->ops->print_one (b, last_addr); + else switch (b->type) { case bp_none: @@ -3851,6 +3861,7 @@ set_raw_breakpoint (struct symtab_and_li b->triggered_dll_pathname = NULL; b->forked_inferior_pid = 0; b->exec_pathname = NULL; + b->ops = NULL; /* Add this breakpoint to the end of the chain so that a list of breakpoints will come out in order @@ -4413,6 +4424,9 @@ mention (struct breakpoint *b) create_breakpoint_hook (b); breakpoint_create_event (b->number); + if (b->ops != NULL && b->ops->print_mention != NULL) + b->ops->print_mention (b); + else switch (b->type) { case bp_none: @@ -6004,6 +6019,90 @@ create_exception_catchpoint (int tempfla mention (b); } +static enum print_stop_action +print_exception_catchpoint (struct breakpoint *b) +{ + annotate_catchpoint (b->number); + + if (strstr (b->addr_string, "throw") != NULL) + printf_filtered ("\nCatchpoint %d (exception thrown)\n", + b->number); + else + printf_filtered ("\nCatchpoint %d (exception caught)\n", + b->number); + + return PRINT_SRC_AND_LOC; +} + +static void +print_one_exception_catchpoint (struct breakpoint *b, CORE_ADDR *last_addr) +{ + if (addressprint) + { + annotate_field (4); + ui_out_field_core_addr (uiout, "addr", b->address); + } + annotate_field (5); + *last_addr = b->address; + if (strstr (b->addr_string, "throw") != NULL) + ui_out_field_string (uiout, "what", "exception throw"); + else + ui_out_field_string (uiout, "what", "exception catch"); +} + +static void +print_mention_exception_catchpoint (struct breakpoint *b) +{ + if (strstr (b->addr_string, "throw") != NULL) + printf_filtered ("Catchpoint %d (throw)", b->number); + else + printf_filtered ("Catchpoint %d (catch)", b->number); +} + +static struct breakpoint_ops gnu_v3_exception_catchpoint_ops = { + print_exception_catchpoint, + print_one_exception_catchpoint, + print_mention_exception_catchpoint +}; + +static int +handle_gnu_v3_exceptions (int tempflag, char *cond_string, + enum exception_event_kind ex_event, int from_tty) +{ + char *trigger_func_name, *nameptr; + struct symtabs_and_lines sals; + struct breakpoint *b; + + if (ex_event == EX_EVENT_CATCH) + trigger_func_name = xstrdup ("__cxa_begin_catch"); + else + trigger_func_name = xstrdup ("__cxa_throw"); + + nameptr = trigger_func_name; + sals = decode_line_1 (&nameptr, 1, NULL, 0, NULL); + if (sals.nelts == 0) + { + free (trigger_func_name); + return 0; + } + + b = set_raw_breakpoint (sals.sals[0], bp_breakpoint); + set_breakpoint_count (breakpoint_count + 1); + b->number = breakpoint_count; + b->cond = NULL; + b->cond_string = (cond_string == NULL) ? + NULL : savestring (cond_string, strlen (cond_string)); + b->thread = -1; + b->addr_string = trigger_func_name; + b->enable_state = bp_enabled; + b->disposition = tempflag ? disp_del : disp_donttouch; + b->ops = &gnu_v3_exception_catchpoint_ops; + + free (sals.sals); + mention (b); + return 1; +} + /* Deal with "catch catch" and "catch throw" commands */ static void @@ -6023,6 +6122,9 @@ catch_exception_command_1 (enum exceptio if ((ex_event != EX_EVENT_THROW) && (ex_event != EX_EVENT_CATCH)) error ("Unsupported or unknown exception event; cannot catch it"); + + if (handle_gnu_v3_exceptions (tempflag, cond_string, ex_event, from_tty)) + return; /* See if we can find a callback routine */ sal = target_enable_exception_callback (ex_event, 1); Index: breakpoint.h =================================================================== RCS file: /big/fsf/rsync/src-cvs/src/gdb/breakpoint.h,v retrieving revision 1.20 diff -u -p -b -B -w -r1.20 breakpoint.h --- breakpoint.h 21 Apr 2003 16:48:37 -0000 1.20 +++ breakpoint.h 27 Apr 2003 00:20:28 -0000 @@ -184,6 +184,24 @@ enum target_hw_bp_type hw_execute = 3 /* Execute HW breakpoint */ }; +/* This structure is a collection of function pointers that, if available, + will be called instead of the performing the default action for this + bptype. */ + +struct breakpoint_ops +{ + /* The normal print routine for this breakpoint, called when we + hit it. */ + enum print_stop_action (*print_it) (struct breakpoint *); + + /* Display information about this breakpoint, for "info breakpoints". */ + void (*print_one) (struct breakpoint *, CORE_ADDR *); + + /* Display information about this breakpoint after setting it (roughly + speaking; this is called from "mention"). */ + void (*print_mention) (struct breakpoint *); +}; + /* Note that the ->silent field is not currently used by any commands (though the code is in there if it was to be, and set_raw_breakpoint does set it to 0). I implemented it because I thought it would be @@ -306,6 +324,9 @@ struct breakpoint char *exec_pathname; asection *section; + + /* Methods associated with this breakpoint. */ + struct breakpoint_ops *ops; }; /* The following stuff is an abstract data type "bpstat" ("breakpoint