* 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.
This commit is contained in:
Vladimir Prus
2007-09-22 19:10:05 +00:00
parent 511a6cd4e1
commit 018d34a46b
2 changed files with 187 additions and 146 deletions

View File

@@ -1,6 +1,20 @@
2007-09-22 Vladimir Prus <vladimir@codesourcery.com> 2007-09-22 Vladimir Prus <vladimir@codesourcery.com>
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 <vladimir@codesourcery.com>
* breakpoint.h (struct breakpoint): Move the cond * breakpoint.h (struct breakpoint): Move the cond
field to... field to...
(struct bp_location): Here. (struct bp_location): Here.

View File

@@ -4984,9 +4984,98 @@ mention (struct breakpoint *b)
} }
/* Create a breakpoint with SAL as location. Use ADDR_STRING
as textual description of the location, and COND_STRING
as condition expression.
The paramter PENDING_BP is same as for the
create_breakpoints function. */
static void
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 + 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."));
}
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;
}
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 /* Add SALS.nelts breakpoints to the breakpoint table. For each
SALS.sal[i] breakpoint, include the corresponding ADDR_STRING[i], SALS.sal[i] breakpoint, include the corresponding ADDR_STRING[i]
COND[i] and COND_STRING[i] values. 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 parameter PENDING_BP points to a pending breakpoint that is
the basis of the breakpoints currently being created. The pending the basis of the breakpoints currently being created. The pending
@@ -4994,83 +5083,26 @@ mention (struct breakpoint *b)
that were added after the initial pending breakpoint was created. that were added after the initial pending breakpoint was created.
NOTE: If the function succeeds, the caller is expected to cleanup NOTE: If the function succeeds, the caller is expected to cleanup
the arrays ADDR_STRING, COND_STRING, COND and SALS (but not the the arrays ADDR_STRING, COND_STRING, and SALS (but not the
array contents). If the function fails (error() is called), the array contents). If the function fails (error() is called), the
caller is expected to cleanups both the ADDR_STRING, COND_STRING, caller is expected to cleanups both the ADDR_STRING, COND_STRING,
COND and SALS arrays and each of those arrays contents. */ COND and SALS arrays and each of those arrays contents. */
static void static void
create_breakpoints (struct symtabs_and_lines sals, char **addr_string, create_breakpoints (struct symtabs_and_lines sals, char **addr_string,
struct expression **cond, char **cond_string, char *cond_string,
enum bptype type, enum bpdisp disposition, enum bptype type, enum bpdisp disposition,
int thread, int ignore_count, int from_tty, int thread, int ignore_count, int from_tty,
struct breakpoint *pending_bp) struct breakpoint *pending_bp)
{ {
if (type == bp_hardware_breakpoint) int i;
for (i = 0; i < sals.nelts; ++i)
{ {
int i = hw_breakpoint_used_count (); create_breakpoint (sals.sals[i], addr_string[i],
int target_resources_ok = cond_string, type, disposition,
TARGET_CAN_USE_HARDWARE_WATCHPOINT (bp_hardware_breakpoint, thread, ignore_count, from_tty,
i + sals.nelts, 0); pending_bp);
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);
/* 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);
}
}
} }
/* Parse ARG which is assumed to be a SAL specification possibly /* 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); 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) /* Set a breakpoint according to ARG (function, linenum or *address)
flag: first bit : 0 non-temporary, 1 temporary. flag: first bit : 0 non-temporary, 1 temporary.
second bit : 0 normal breakpoint, 1 hardware breakpoint. 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; struct gdb_exception e;
int tempflag, hardwareflag; int tempflag, hardwareflag;
struct symtabs_and_lines sals; struct symtabs_and_lines sals;
struct expression **cond = 0;
struct symtab_and_line pending_sal; struct symtab_and_line pending_sal;
char **cond_string = (char **) NULL; char *cond_string = NULL;
char *copy_arg; char *copy_arg;
char *err_msg; char *err_msg;
char *addr_start = arg; 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); 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 ----------------------------- /* ----------------------------- SNIP -----------------------------
Anything added to the cleanup chain beyond this point is assumed Anything added to the cleanup chain beyond this point is assumed
to be part of a breakpoint. If the breakpoint create succeeds 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 /* Verify that condition can be parsed, before setting any
breakpoints. Allocate a separate condition expression for each breakpoints. Allocate a separate condition expression for each
breakpoint. */ breakpoint. */
thread = -1; /* No specific thread yet */
if (!pending) if (!pending)
{ {
for (i = 0; i < sals.nelts; i++) /* Here we only parse 'arg' to separate condition
{ from thread number, so parsing in context of first
char *tok = arg; sal is OK. When setting the breakpoint we'll
while (tok && *tok) re-parse it in context of each sal. */
{ find_condition_and_thread (arg, sals.sals[0].pc, &cond_string, &thread);
char *end_tok; if (cond_string)
int toklen; make_cleanup (xfree, cond_string);
char *cond_start = NULL; create_breakpoints (sals, addr_string, cond_string,
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,
hardwareflag ? bp_hardware_breakpoint hardwareflag ? bp_hardware_breakpoint
: bp_breakpoint, : bp_breakpoint,
tempflag ? disp_del : disp_donttouch, 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); : bp_breakpoint);
set_breakpoint_count (breakpoint_count + 1); set_breakpoint_count (breakpoint_count + 1);
b->number = breakpoint_count; b->number = breakpoint_count;
b->loc->cond = *cond; b->loc->cond = NULL;
b->thread = thread; b->thread = thread;
b->addr_string = *addr_string; b->addr_string = addr_string[0];
b->cond_string = *cond_string; b->cond_string = cond_string;
b->ignore_count = ignore_count; b->ignore_count = ignore_count;
b->pending = 1; b->pending = 1;
b->disposition = tempflag ? disp_del : disp_donttouch; 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; struct cleanup *breakpoint_chain = NULL;
int i; int i;
char **addr_string; char **addr_string;
char **cond_string; char *cond_string;
char *address_end; char *address_end;
@@ -5502,22 +5538,13 @@ do_captured_breakpoint (struct ui_out *uiout, void *data)
/* Resolve all line numbers to PC's. */ /* Resolve all line numbers to PC's. */
breakpoint_sals_to_pc (&sals, args->address); breakpoint_sals_to_pc (&sals, args->address);
/* Verify that conditions can be parsed, before setting any if (args->condition != NULL)
breakpoints. */
for (i = 0; i < sals.nelts; i++)
{ {
if (args->condition != NULL) cond_string = xstrdup (args->condition);
{ make_cleanup (xfree, cond_string);
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);
}
} }
create_breakpoints (sals, addr_string, cond, cond_string, create_breakpoints (sals, addr_string, args->condition,
args->hardwareflag ? bp_hardware_breakpoint : bp_breakpoint, args->hardwareflag ? bp_hardware_breakpoint : bp_breakpoint,
args->tempflag ? disp_del : disp_donttouch, args->tempflag ? disp_del : disp_donttouch,
args->thread, args->ignore_count, 0/*from-tty*/, args->thread, args->ignore_count, 0/*from-tty*/,