From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 2127 invoked by alias); 25 Mar 2003 03:01:10 -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 2108 invoked from network); 25 Mar 2003 03:01:09 -0000 Received: from unknown (HELO crack.them.org) (65.125.64.184) by sources.redhat.com with SMTP; 25 Mar 2003 03:01: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 18xga2-0005fw-00 for ; Mon, 24 Mar 2003 23:02:35 -0600 Received: from drow by nevyn.them.org with local (Exim 3.36 #1 (Debian)) id 18xegV-0001Hf-00 for ; Mon, 24 Mar 2003 22:01:07 -0500 Date: Tue, 25 Mar 2003 03:01:00 -0000 From: Daniel Jacobowitz To: gdb-patches@sources.redhat.com Subject: [rfc breakpoint] Catch exceptions Message-ID: <20030325030107.GA3889@nevyn.them.org> Mail-Followup-To: gdb-patches@sources.redhat.com Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.1i X-SW-Source: 2003-03/txt/msg00482.txt.bz2 I'm just looking for feedback on this patch. It's mostly complete except for some mass re-indenting that some of the changes would require; I'm not entirely happy with the design yet though, so I'm looking for comments. 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. The basic idea is that these "catchpoints" are just normal breakpoints and should be handled as such. But we'd like to print them a little differently, for clarity. Here's the interesting bit, from struct breakpoint: + enum print_stop_action (*print) (struct breakpoint *); + + void (*print_one) (struct breakpoint *, CORE_ADDR *); + + void (*print_mention) (struct breakpoint *); i.e. it adds function pointers to the breakpoint to describe the action to take. Logical next steps include a function to determine whether to stop (for catch throw TYPE) and maybe even a function to take action when hit (to simplify longjmp and step_resume breakpoints, etc. - breakpoint.c could be simplified by this mechanism long-term). [Why three subtly different print functions? Because there were three places I needed a hook and they were all different. This sucks. At least two of them can be condensed... I think... eventually. I'm not interested in doing that level of cleanup right now, particularly.] Comments? If no one has any, I'll look to commit this (with reformatting) in a while. Maybe a week or so. -- Daniel Jacobowitz MontaVista Software Debian GNU/Linux Developer Index: breakpoint.c =================================================================== RCS file: /big/fsf/rsync/src-cvs/src/gdb/breakpoint.c,v retrieving revision 1.114 diff -u -p -r1.114 breakpoint.c --- breakpoint.c 11 Mar 2003 19:07:01 -0000 1.114 +++ breakpoint.c 25 Mar 2003 02:49:23 -0000 @@ -2017,6 +2013,9 @@ print_it_typical (bpstat bs) if (bs->breakpoint_at == NULL) return PRINT_UNKNOWN; + if (bs->breakpoint_at->print != NULL) + return (*bs->breakpoint_at->print) (bs->breakpoint_at); + switch (bs->breakpoint_at->type) { case bp_breakpoint: @@ -3272,7 +3271,10 @@ print_one_breakpoint (struct breakpoint else strcat (wrap_indent, " "); } - switch (b->type) + + if (b->print_one != NULL) + (*b->print_one) (b, last_addr); + else switch (b->type) { case bp_none: internal_error (__FILE__, __LINE__, @@ -4420,7 +4423,9 @@ mention (struct breakpoint *b) create_breakpoint_hook (b); breakpoint_create_event (b->number); - switch (b->type) + if (b->print_mention != NULL) + (*b->print_mention) (b); + else switch (b->type) { case bp_none: printf_filtered ("(apparently deleted?) Eventpoint %d: ", b->number); @@ -6192,6 +6016,84 @@ 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 int +handle_gnu_v3_exceptions (int tempflag, char *cond_string, + enum exception_event_kind ex_event, int from_tty) +{ + struct minimal_symbol *trigger_func; + const char *trigger_func_name; + struct symtab_and_line sal; + struct breakpoint *b; + + if (ex_event == EX_EVENT_CATCH) + trigger_func_name = "__cxa_begin_catch"; + else + trigger_func_name = "__cxa_throw"; + + trigger_func = lookup_minimal_symbol (trigger_func_name, NULL, NULL); + if (trigger_func == 0) + return 0; + sal = find_msymbol_start_sal (trigger_func, 1); + + b = set_raw_breakpoint (sal, 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 = xstrdup (trigger_func_name); + b->enable_state = bp_enabled; + b->disposition = tempflag ? disp_del : disp_donttouch; + mention (b); + b->ep_type = ep_gnuv3; + + b->print = print_exception_catchpoint; + b->print_one = print_one_exception_catchpoint; + b->print_mention = print_mention_exception_catchpoint; + return 1; +} + /* Deal with "catch catch" and "catch throw" commands */ static void @@ -6212,6 +6114,9 @@ catch_exception_command_1 (enum exceptio (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.19 diff -u -p -r1.19 breakpoint.h --- breakpoint.h 20 Feb 2003 00:01:05 -0000 1.19 +++ breakpoint.h 25 Mar 2003 02:46:57 -0000 @@ -305,6 +305,14 @@ struct breakpoint triggered. */ char *exec_pathname; + enum {ep_normal, ep_gnuv2, ep_gnuv3} ep_type; + + enum print_stop_action (*print) (struct breakpoint *); + + void (*print_one) (struct breakpoint *, CORE_ADDR *); + + void (*print_mention) (struct breakpoint *); + asection *section; }; Index: linespec.c =================================================================== RCS file: /big/fsf/rsync/src-cvs/src/gdb/linespec.c,v retrieving revision 1.45 diff -u -p -r1.45 linespec.c --- linespec.c 3 Mar 2003 17:20:24 -0000 1.45 +++ linespec.c 17 Mar 2003 17:06:34 -0000 @@ -1543,14 +1543,7 @@ minsym_found (int funfirstline, struct m values.sals = (struct symtab_and_line *) xmalloc (sizeof (struct symtab_and_line)); - values.sals[0] = find_pc_sect_line (SYMBOL_VALUE_ADDRESS (msymbol), - (struct sec *) 0, 0); - values.sals[0].section = SYMBOL_BFD_SECTION (msymbol); - if (funfirstline) - { - values.sals[0].pc += FUNCTION_START_OFFSET; - values.sals[0].pc = SKIP_PROLOGUE (values.sals[0].pc); - } + values.sals[0] = find_msymbol_start_sal (msymbol, funfirstline); values.nelts = 1; return values; } Index: symtab.c =================================================================== RCS file: /big/fsf/rsync/src-cvs/src/gdb/symtab.c,v retrieving revision 1.99 diff -u -p -r1.99 symtab.c --- symtab.c 4 Mar 2003 17:06:21 -0000 1.99 +++ symtab.c 17 Mar 2003 17:08:01 -0000 @@ -2462,6 +2462,27 @@ find_function_start_sal (struct symbol * return sal; } +/* Given a minimal symbol MSYMBOL, build a corresponding struct + symtabs_and_lines. + If the argument FUNFIRSTLINE is nonzero, we want the first line + of real code inside the function, so skip the prologue. */ + +struct symtab_and_line +find_msymbol_start_sal (struct minimal_symbol *msymbol, int funfirstline) +{ + struct symtab_and_line sal; + + sal = find_pc_sect_line (SYMBOL_VALUE_ADDRESS (msymbol), + (struct sec *) 0, 0); + sal.section = SYMBOL_BFD_SECTION (msymbol); + if (funfirstline) + { + sal.pc += FUNCTION_START_OFFSET; + sal.pc = SKIP_PROLOGUE (sal.pc); + } + return sal; +} + /* If P is of the form "operator[ \t]+..." where `...' is some legitimate operator text, return a pointer to the beginning of the substring of the operator text. Index: symtab.h =================================================================== RCS file: /big/fsf/rsync/src-cvs/src/gdb/symtab.h,v retrieving revision 1.65 diff -u -p -r1.65 symtab.h --- symtab.h 3 Mar 2003 18:34:12 -0000 1.65 +++ symtab.h 17 Mar 2003 17:07:03 -0000 @@ -1272,6 +1272,9 @@ extern struct symtab *find_line_symtab ( extern struct symtab_and_line find_function_start_sal (struct symbol *sym, int); +extern struct symtab_and_line find_msymbol_start_sal (struct minimal_symbol *, + int); + /* symfile.c */ extern void clear_symtab_users (void);