* 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,63 +4984,44 @@ 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 /* Create a breakpoint with SAL as location. Use ADDR_STRING
the basis of the breakpoints currently being created. The pending as textual description of the location, and COND_STRING
breakpoint may contain a separate condition string or commands as condition expression.
that were added after the initial pending breakpoint was created.
NOTE: If the function succeeds, the caller is expected to cleanup The paramter PENDING_BP is same as for the
the arrays ADDR_STRING, COND_STRING, COND and SALS (but not the create_breakpoints function. */
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 static void
create_breakpoints (struct symtabs_and_lines sals, char **addr_string, create_breakpoint (struct symtab_and_line sal, 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)
{ {
struct breakpoint *b;
if (type == bp_hardware_breakpoint) if (type == bp_hardware_breakpoint)
{ {
int i = hw_breakpoint_used_count (); int i = hw_breakpoint_used_count ();
int target_resources_ok = int target_resources_ok =
TARGET_CAN_USE_HARDWARE_WATCHPOINT (bp_hardware_breakpoint, TARGET_CAN_USE_HARDWARE_WATCHPOINT (bp_hardware_breakpoint,
i + sals.nelts, 0); i + 1, 0);
if (target_resources_ok == 0) if (target_resources_ok == 0)
error (_("No hardware breakpoint support in the target.")); error (_("No hardware breakpoint support in the target."));
else if (target_resources_ok < 0) else if (target_resources_ok < 0)
error (_("Hardware breakpoints used exceeds limit.")); 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) if (from_tty)
describe_other_breakpoints (sal.pc, sal.section, thread); describe_other_breakpoints (sal.pc, sal.section, thread);
b = set_raw_breakpoint (sal, type); b = set_raw_breakpoint (sal, type);
set_breakpoint_count (breakpoint_count + 1); set_breakpoint_count (breakpoint_count + 1);
b->number = breakpoint_count; b->number = breakpoint_count;
b->loc->cond = cond[i];
b->thread = thread; b->thread = thread;
if (addr_string[i])
b->addr_string = addr_string[i]; b->cond_string = cond_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));
b->cond_string = cond_string[i];
b->ignore_count = ignore_count; b->ignore_count = ignore_count;
b->enable_state = bp_enabled; b->enable_state = bp_enabled;
b->disposition = disposition; b->disposition = disposition;
@ -5050,15 +5031,10 @@ create_breakpoints (struct symtabs_and_lines sals, char **addr_string,
initially specified with the initial breakpoint command. */ initially specified with the initial breakpoint command. */
if (pending_bp) if (pending_bp)
{ {
char *arg;
if (pending_bp->cond_string) if (pending_bp->cond_string)
{ b->cond_string = savestring (pending_bp->cond_string,
arg = pending_bp->cond_string; strlen (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 /* If there are commands associated with the breakpoint, they should
be copied too. */ be copied too. */
if (pending_bp->commands) if (pending_bp->commands)
@ -5068,9 +5044,65 @@ create_breakpoints (struct symtabs_and_lines sals, char **addr_string,
b->ignore_count = pending_bp->ignore_count; b->ignore_count = pending_bp->ignore_count;
b->thread = pending_bp->thread; b->thread = pending_bp->thread;
} }
mention (b);
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 /* 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
breakpoints. */
for (i = 0; i < sals.nelts; i++)
{
if (args->condition != NULL) if (args->condition != NULL)
{ {
char *tok = args->condition; cond_string = xstrdup (args->condition);
cond[i] = parse_exp_1 (&tok, block_for_pc (sals.sals[i].pc), 0); make_cleanup (xfree, cond_string);
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*/,