From 018d34a46b565ceaf494bcf8f3a8a9ec488bb69a Mon Sep 17 00:00:00 2001 From: Vladimir Prus Date: Sat, 22 Sep 2007 19:10:05 +0000 Subject: [PATCH] * breakpoint.c (create_breakpoint): Split from create_breakpoints, implementing most of its logic. Take just a single sal, single address string and single condition. Do not take parsed condition at all. (create_breakpoints): Just call create_breakpoint for each sal. (find_condition_and_thread): New. (break_command_1): Use find_condition_and_thread. Do not keep parsed conditions. (do_captured_breakpoint): Don't convert condition string to struct expression. --- gdb/ChangeLog | 16 ++- gdb/breakpoint.c | 317 +++++++++++++++++++++++++---------------------- 2 files changed, 187 insertions(+), 146 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index c3dd35ed19..0a6d886b88 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,6 +1,20 @@ 2007-09-22 Vladimir Prus - gdb/ + * breakpoint.c (create_breakpoint): Split from + create_breakpoints, implementing most of its logic. + Take just a single sal, single address string and + single condition. Do not take parsed condition at + all. + (create_breakpoints): Just call create_breakpoint + for each sal. + (find_condition_and_thread): New. + (break_command_1): Use find_condition_and_thread. + Do not keep parsed conditions. + (do_captured_breakpoint): Don't convert + condition string to struct expression. + +2007-09-22 Vladimir Prus + * breakpoint.h (struct breakpoint): Move the cond field to... (struct bp_location): Here. diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 333242a101..e9b99ccf5f 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -4984,93 +4984,125 @@ mention (struct breakpoint *b) } -/* Add SALS.nelts breakpoints to the breakpoint table. For each - SALS.sal[i] breakpoint, include the corresponding ADDR_STRING[i], - COND[i] and COND_STRING[i] values. - The parameter PENDING_BP points to a pending breakpoint that is - the basis of the breakpoints currently being created. The pending - breakpoint may contain a separate condition string or commands - that were added after the initial pending breakpoint was created. +/* Create a breakpoint with SAL as location. Use ADDR_STRING + as textual description of the location, and COND_STRING + as condition expression. - NOTE: If the function succeeds, the caller is expected to cleanup - the arrays ADDR_STRING, COND_STRING, COND and SALS (but not the - array contents). If the function fails (error() is called), the - caller is expected to cleanups both the ADDR_STRING, COND_STRING, - COND and SALS arrays and each of those arrays contents. */ + The paramter PENDING_BP is same as for the + create_breakpoints function. */ static void -create_breakpoints (struct symtabs_and_lines sals, char **addr_string, - struct expression **cond, char **cond_string, - enum bptype type, enum bpdisp disposition, - int thread, int ignore_count, int from_tty, - struct breakpoint *pending_bp) +create_breakpoint (struct symtab_and_line sal, char *addr_string, + char *cond_string, + enum bptype type, enum bpdisp disposition, + int thread, int ignore_count, int from_tty, + struct breakpoint *pending_bp) { + struct breakpoint *b; + if (type == bp_hardware_breakpoint) { int i = hw_breakpoint_used_count (); int target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT (bp_hardware_breakpoint, - i + sals.nelts, 0); + i + 1, 0); if (target_resources_ok == 0) error (_("No hardware breakpoint support in the target.")); else if (target_resources_ok < 0) error (_("Hardware breakpoints used exceeds limit.")); } - /* Now set all the breakpoints. */ - { - int i; - for (i = 0; i < sals.nelts; i++) - { - struct breakpoint *b; - struct symtab_and_line sal = sals.sals[i]; - - if (from_tty) - describe_other_breakpoints (sal.pc, sal.section, thread); - - b = set_raw_breakpoint (sal, type); - set_breakpoint_count (breakpoint_count + 1); - b->number = breakpoint_count; - b->loc->cond = cond[i]; - b->thread = thread; - if (addr_string[i]) - b->addr_string = addr_string[i]; - else - /* addr_string has to be used or breakpoint_re_set will delete - me. */ - b->addr_string = xstrprintf ("*0x%s", paddr (b->loc->address)); - b->cond_string = cond_string[i]; - b->ignore_count = ignore_count; - b->enable_state = bp_enabled; - b->disposition = disposition; - /* If resolving a pending breakpoint, a check must be made to see if - the user has specified a new condition or commands for the - breakpoint. A new condition will override any condition that was - initially specified with the initial breakpoint command. */ - if (pending_bp) - { - char *arg; - if (pending_bp->cond_string) - { - arg = pending_bp->cond_string; - b->cond_string = savestring (arg, strlen (arg)); - b->loc->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0); - if (*arg) - error (_("Junk at end of pending breakpoint condition expression")); - } - /* If there are commands associated with the breakpoint, they should - be copied too. */ - if (pending_bp->commands) - b->commands = copy_command_lines (pending_bp->commands); + if (from_tty) + describe_other_breakpoints (sal.pc, sal.section, thread); + + b = set_raw_breakpoint (sal, type); + set_breakpoint_count (breakpoint_count + 1); + b->number = breakpoint_count; + b->thread = thread; + + b->cond_string = cond_string; + b->ignore_count = ignore_count; + b->enable_state = bp_enabled; + b->disposition = disposition; + /* If resolving a pending breakpoint, a check must be made to see if + the user has specified a new condition or commands for the + breakpoint. A new condition will override any condition that was + initially specified with the initial breakpoint command. */ + if (pending_bp) + { + if (pending_bp->cond_string) + b->cond_string = savestring (pending_bp->cond_string, + strlen (pending_bp->cond_string)); + + /* If there are commands associated with the breakpoint, they should + be copied too. */ + if (pending_bp->commands) + b->commands = copy_command_lines (pending_bp->commands); - /* We have to copy over the ignore_count and thread as well. */ - b->ignore_count = pending_bp->ignore_count; - b->thread = pending_bp->thread; - } - mention (b); - } - } + /* We have to copy over the ignore_count and thread as well. */ + b->ignore_count = pending_bp->ignore_count; + b->thread = pending_bp->thread; + } + + if (b->cond_string) + { + char *arg = b->cond_string; + b->loc->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0); + if (*arg) + { + if (pending_bp) + error (_("Junk at end of pending breakpoint condition expression")); + else + error (_("Garbage %s follows condition"), arg); + } + } + + if (addr_string) + b->addr_string = addr_string; + else + /* addr_string has to be used or breakpoint_re_set will delete + me. */ + b->addr_string = xstrprintf ("*0x%s", paddr (b->loc->address)); + + mention (b); +} + +/* Add SALS.nelts breakpoints to the breakpoint table. For each + SALS.sal[i] breakpoint, include the corresponding ADDR_STRING[i] + value. COND_STRING, if not NULL, specified the condition to be + used for all breakpoints. Essentially the only case where + SALS.nelts is not 1 is when we set a breakpoint on an overloaded + function. In that case, it's still not possible to specify + separate conditions for different overloaded functions, so + we take just a single condition string. + + The parameter PENDING_BP points to a pending breakpoint that is + the basis of the breakpoints currently being created. The pending + breakpoint may contain a separate condition string or commands + that were added after the initial pending breakpoint was created. + + NOTE: If the function succeeds, the caller is expected to cleanup + the arrays ADDR_STRING, COND_STRING, and SALS (but not the + array contents). If the function fails (error() is called), the + caller is expected to cleanups both the ADDR_STRING, COND_STRING, + COND and SALS arrays and each of those arrays contents. */ + +static void +create_breakpoints (struct symtabs_and_lines sals, char **addr_string, + char *cond_string, + enum bptype type, enum bpdisp disposition, + int thread, int ignore_count, int from_tty, + struct breakpoint *pending_bp) +{ + int i; + for (i = 0; i < sals.nelts; ++i) + { + create_breakpoint (sals.sals[i], addr_string[i], + cond_string, type, disposition, + thread, ignore_count, from_tty, + pending_bp); + } } /* Parse ARG which is assumed to be a SAL specification possibly @@ -5192,6 +5224,59 @@ do_captured_parse_breakpoint (struct ui_out *ui, void *data) args->not_found_ptr); } +/* Given TOK, a string specification of condition and thread, as + accepted by the 'break' command, extract the condition + string and thread number and set *COND_STRING and *THREAD. + PC identifies the context at which the condition should be parsed. + If no condition is found, *COND_STRING is set to NULL. + If no thread is found, *THREAD is set to -1. */ +static void +find_condition_and_thread (char *tok, CORE_ADDR pc, + char **cond_string, int *thread) +{ + *cond_string = NULL; + *thread = -1; + while (tok && *tok) + { + char *end_tok; + int toklen; + char *cond_start = NULL; + char *cond_end = NULL; + while (*tok == ' ' || *tok == '\t') + tok++; + + end_tok = tok; + + while (*end_tok != ' ' && *end_tok != '\t' && *end_tok != '\000') + end_tok++; + + toklen = end_tok - tok; + + if (toklen >= 1 && strncmp (tok, "if", toklen) == 0) + { + tok = cond_start = end_tok + 1; + parse_exp_1 (&tok, block_for_pc (pc), 0); + cond_end = tok; + *cond_string = savestring (cond_start, + cond_end - cond_start); + } + else if (toklen >= 1 && strncmp (tok, "thread", toklen) == 0) + { + char *tmptok; + + tok = end_tok + 1; + tmptok = tok; + *thread = strtol (tok, &tok, 0); + if (tok == tmptok) + error (_("Junk after thread keyword.")); + if (!valid_thread_id (*thread)) + error (_("Unknown thread %d."), *thread); + } + else + error (_("Junk at end of arguments.")); + } +} + /* Set a breakpoint according to ARG (function, linenum or *address) flag: first bit : 0 non-temporary, 1 temporary. second bit : 0 normal breakpoint, 1 hardware breakpoint. @@ -5205,9 +5290,8 @@ break_command_1 (char *arg, int flag, int from_tty, struct breakpoint *pending_b struct gdb_exception e; int tempflag, hardwareflag; struct symtabs_and_lines sals; - struct expression **cond = 0; struct symtab_and_line pending_sal; - char **cond_string = (char **) NULL; + char *cond_string = NULL; char *copy_arg; char *err_msg; char *addr_start = arg; @@ -5297,14 +5381,6 @@ break_command_1 (char *arg, int flag, int from_tty, struct breakpoint *pending_b make_cleanup (xfree, addr_string); } - /* Allocate space for all the cond expressions. */ - cond = xcalloc (sals.nelts, sizeof (struct expression *)); - make_cleanup (xfree, cond); - - /* Allocate space for all the cond strings. */ - cond_string = xcalloc (sals.nelts, sizeof (char **)); - make_cleanup (xfree, cond_string); - /* ----------------------------- SNIP ----------------------------- Anything added to the cleanup chain beyond this point is assumed to be part of a breakpoint. If the breakpoint create succeeds @@ -5328,56 +5404,16 @@ break_command_1 (char *arg, int flag, int from_tty, struct breakpoint *pending_b /* Verify that condition can be parsed, before setting any breakpoints. Allocate a separate condition expression for each breakpoint. */ - thread = -1; /* No specific thread yet */ if (!pending) { - for (i = 0; i < sals.nelts; i++) - { - char *tok = arg; - while (tok && *tok) - { - char *end_tok; - int toklen; - char *cond_start = NULL; - char *cond_end = NULL; - while (*tok == ' ' || *tok == '\t') - tok++; - - end_tok = tok; - - while (*end_tok != ' ' && *end_tok != '\t' && *end_tok != '\000') - end_tok++; - - toklen = end_tok - tok; - - if (toklen >= 1 && strncmp (tok, "if", toklen) == 0) - { - tok = cond_start = end_tok + 1; - cond[i] = parse_exp_1 (&tok, block_for_pc (sals.sals[i].pc), - 0); - make_cleanup (xfree, cond[i]); - cond_end = tok; - cond_string[i] = savestring (cond_start, - cond_end - cond_start); - make_cleanup (xfree, cond_string[i]); - } - else if (toklen >= 1 && strncmp (tok, "thread", toklen) == 0) - { - char *tmptok; - - tok = end_tok + 1; - tmptok = tok; - thread = strtol (tok, &tok, 0); - if (tok == tmptok) - error (_("Junk after thread keyword.")); - if (!valid_thread_id (thread)) - error (_("Unknown thread %d."), thread); - } - else - error (_("Junk at end of arguments.")); - } - } - create_breakpoints (sals, addr_string, cond, cond_string, + /* Here we only parse 'arg' to separate condition + from thread number, so parsing in context of first + sal is OK. When setting the breakpoint we'll + re-parse it in context of each sal. */ + find_condition_and_thread (arg, sals.sals[0].pc, &cond_string, &thread); + if (cond_string) + make_cleanup (xfree, cond_string); + create_breakpoints (sals, addr_string, cond_string, hardwareflag ? bp_hardware_breakpoint : bp_breakpoint, tempflag ? disp_del : disp_donttouch, @@ -5398,10 +5434,10 @@ break_command_1 (char *arg, int flag, int from_tty, struct breakpoint *pending_b : bp_breakpoint); set_breakpoint_count (breakpoint_count + 1); b->number = breakpoint_count; - b->loc->cond = *cond; + b->loc->cond = NULL; b->thread = thread; - b->addr_string = *addr_string; - b->cond_string = *cond_string; + b->addr_string = addr_string[0]; + b->cond_string = cond_string; b->ignore_count = ignore_count; b->pending = 1; b->disposition = tempflag ? disp_del : disp_donttouch; @@ -5445,7 +5481,7 @@ do_captured_breakpoint (struct ui_out *uiout, void *data) struct cleanup *breakpoint_chain = NULL; int i; char **addr_string; - char **cond_string; + char *cond_string; char *address_end; @@ -5502,22 +5538,13 @@ do_captured_breakpoint (struct ui_out *uiout, void *data) /* Resolve all line numbers to PC's. */ breakpoint_sals_to_pc (&sals, args->address); - /* Verify that conditions can be parsed, before setting any - breakpoints. */ - for (i = 0; i < sals.nelts; i++) + if (args->condition != NULL) { - if (args->condition != NULL) - { - char *tok = args->condition; - cond[i] = parse_exp_1 (&tok, block_for_pc (sals.sals[i].pc), 0); - if (*tok != '\0') - error (_("Garbage %s follows condition"), tok); - make_cleanup (xfree, cond[i]); - cond_string[i] = xstrdup (args->condition); - } + cond_string = xstrdup (args->condition); + make_cleanup (xfree, cond_string); } - create_breakpoints (sals, addr_string, cond, cond_string, + create_breakpoints (sals, addr_string, args->condition, args->hardwareflag ? bp_hardware_breakpoint : bp_breakpoint, args->tempflag ? disp_del : disp_donttouch, args->thread, args->ignore_count, 0/*from-tty*/,