mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2025-02-24 11:30:50 +00:00
2004-02-02 Jeff Johnston <jjohnstn@redhat.com>
* breakpoint.h (struct breakpoint): Add new flag, from_tty, and pending fields for pending breakpoint support. * breakpoint.c (breakpoint_enabled): Add check for not pending. (condition_command): Only parse condition if not a pending breakpoint. (print_one_breakpoint): Add support for pending breakpoints. (describe_other_breakpoints): Add checks to verify we are not dealing with pending breakpoints. (check_duplicates): Don't check pending breakpoints. (set_raw_breakpoint): Initialize pending flag. (do_restore_lang_radix_cleanup): New cleanup routine. (resolve_pending_breakpoint): New function. (re_enable_breakpoints_in_shlibs): Try and resolve any pending breakpoints via resolve_pending_breakpoint. (mention): Add pending breakpoint support. (parse_breakpoint_sals): Add new parameter to pass to decode_line_1 to indicate silent errors when files or functions are not found. Change all callers. (do_captured_parse_breakpoint): New function. (break_command_1): Change prototype to return an rc value and to take an optional pending breakpoint pointer. Support creating a pending breakpoint if a "not found" form of error occurs when parsing the breakpoint. Also support resolving an existing pending breakpoint and be silent if the resolution fails. (create_breakpoints): Change prototype to take pending breakpoint pointer. When resolving a pending breakpoint, use the new pointer to provide a conditional or commands added by the end-user. (delete_breakpoint): Add appropriate check for pending. (breakpoint_re_set_one): Ditto. (do_enable_breakpoint): Ditto.
This commit is contained in:
parent
2650777c07
commit
0101ce28cf
@ -1,3 +1,36 @@
|
||||
2004-02-02 Jeff Johnston <jjohnstn@redhat.com>
|
||||
|
||||
* breakpoint.h (struct breakpoint): Add new flag, from_tty,
|
||||
and pending fields for pending breakpoint support.
|
||||
* breakpoint.c (breakpoint_enabled): Add check for not pending.
|
||||
(condition_command): Only parse condition if not a pending
|
||||
breakpoint.
|
||||
(print_one_breakpoint): Add support for pending breakpoints.
|
||||
(describe_other_breakpoints): Add checks to verify we are not
|
||||
dealing with pending breakpoints.
|
||||
(check_duplicates): Don't check pending breakpoints.
|
||||
(set_raw_breakpoint): Initialize pending flag.
|
||||
(do_restore_lang_radix_cleanup): New cleanup routine.
|
||||
(resolve_pending_breakpoint): New function.
|
||||
(re_enable_breakpoints_in_shlibs): Try and resolve any
|
||||
pending breakpoints via resolve_pending_breakpoint.
|
||||
(mention): Add pending breakpoint support.
|
||||
(parse_breakpoint_sals): Add new parameter to pass to
|
||||
decode_line_1 to indicate silent errors when files or functions
|
||||
are not found. Change all callers.
|
||||
(do_captured_parse_breakpoint): New function.
|
||||
(break_command_1): Change prototype to return an rc value and to
|
||||
take an optional pending breakpoint pointer. Support creating
|
||||
a pending breakpoint if a "not found" form of error occurs when
|
||||
parsing the breakpoint. Also support resolving an existing pending
|
||||
breakpoint and be silent if the resolution fails.
|
||||
(create_breakpoints): Change prototype to take pending breakpoint
|
||||
pointer. When resolving a pending breakpoint, use the new pointer
|
||||
to provide a conditional or commands added by the end-user.
|
||||
(delete_breakpoint): Add appropriate check for pending.
|
||||
(breakpoint_re_set_one): Ditto.
|
||||
(do_enable_breakpoint): Ditto.
|
||||
|
||||
2004-02-02 David Carlton <carlton@kealia.com>
|
||||
|
||||
* valops.c (enum oload_classification): New.
|
||||
|
541
gdb/breakpoint.c
541
gdb/breakpoint.c
@ -89,7 +89,7 @@ extern void break_at_finish_at_depth_command (char *, int);
|
||||
|
||||
extern void tbreak_at_finish_command (char *, int);
|
||||
|
||||
static void break_command_1 (char *, int, int);
|
||||
static int break_command_1 (char *, int, int, struct breakpoint *);
|
||||
|
||||
static void mention (struct breakpoint *);
|
||||
|
||||
@ -119,6 +119,8 @@ static void condition_command (char *, int);
|
||||
|
||||
static int get_number_trailer (char **, int);
|
||||
|
||||
static int do_captured_parse_breakpoint (struct ui_out *, void *);
|
||||
|
||||
void set_breakpoint_count (int);
|
||||
|
||||
typedef enum
|
||||
@ -322,7 +324,7 @@ int exception_support_initialized = 0;
|
||||
static int
|
||||
breakpoint_enabled (struct breakpoint *b)
|
||||
{
|
||||
return b->enable_state == bp_enabled;
|
||||
return (b->enable_state == bp_enabled && !b->pending);
|
||||
}
|
||||
|
||||
/* Set breakpoint count to NUM. */
|
||||
@ -556,9 +558,12 @@ condition_command (char *arg, int from_tty)
|
||||
/* I don't know if it matters whether this is the string the user
|
||||
typed in or the decompiled expression. */
|
||||
b->cond_string = savestring (arg, strlen (arg));
|
||||
b->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0);
|
||||
if (*arg)
|
||||
error ("Junk at end of expression");
|
||||
if (!b->pending)
|
||||
{
|
||||
b->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0);
|
||||
if (*arg)
|
||||
error ("Junk at end of expression");
|
||||
}
|
||||
}
|
||||
breakpoints_changed ();
|
||||
breakpoint_modify_event (b->number);
|
||||
@ -3465,7 +3470,16 @@ print_one_breakpoint (struct breakpoint *b,
|
||||
if (addressprint)
|
||||
{
|
||||
annotate_field (4);
|
||||
ui_out_field_core_addr (uiout, "addr", b->loc->address);
|
||||
if (b->pending)
|
||||
{
|
||||
ui_out_field_string (uiout, "addr", "<PENDING>");
|
||||
if (TARGET_ADDR_BIT <= 32)
|
||||
ui_out_spaces (uiout, 2);
|
||||
else
|
||||
ui_out_spaces (uiout, 8);
|
||||
}
|
||||
else
|
||||
ui_out_field_core_addr (uiout, "addr", b->loc->address);
|
||||
}
|
||||
annotate_field (5);
|
||||
*last_addr = b->loc->address;
|
||||
@ -3484,6 +3498,10 @@ print_one_breakpoint (struct breakpoint *b,
|
||||
ui_out_text (uiout, ":");
|
||||
ui_out_field_int (uiout, "line", b->line_number);
|
||||
}
|
||||
else if (b->pending)
|
||||
{
|
||||
ui_out_field_string (uiout, "pending", b->addr_string);
|
||||
}
|
||||
else
|
||||
{
|
||||
print_address_symbolic (b->loc->address, stb->stream, demangle, "");
|
||||
@ -3520,7 +3538,15 @@ print_one_breakpoint (struct breakpoint *b,
|
||||
ui_out_field_stream (uiout, "cond", stb);
|
||||
ui_out_text (uiout, "\n");
|
||||
}
|
||||
|
||||
|
||||
if (b->pending && b->cond_string)
|
||||
{
|
||||
annotate_field (7);
|
||||
ui_out_text (uiout, "\tstop only if ");
|
||||
ui_out_field_string (uiout, "cond", b->cond_string);
|
||||
ui_out_text (uiout, "\n");
|
||||
}
|
||||
|
||||
if (b->thread != -1)
|
||||
{
|
||||
/* FIXME should make an annotation for this */
|
||||
@ -3751,14 +3777,14 @@ describe_other_breakpoints (CORE_ADDR pc, asection *section)
|
||||
|
||||
ALL_BREAKPOINTS (b)
|
||||
if (b->loc->address == pc) /* address match / overlay match */
|
||||
if (!overlay_debugging || b->loc->section == section)
|
||||
if (!b->pending && (!overlay_debugging || b->loc->section == section))
|
||||
others++;
|
||||
if (others > 0)
|
||||
{
|
||||
printf_filtered ("Note: breakpoint%s ", (others > 1) ? "s" : "");
|
||||
ALL_BREAKPOINTS (b)
|
||||
if (b->loc->address == pc) /* address match / overlay match */
|
||||
if (!overlay_debugging || b->loc->section == section)
|
||||
if (!b->pending && (!overlay_debugging || b->loc->section == section))
|
||||
{
|
||||
others--;
|
||||
printf_filtered ("%d%s%s ",
|
||||
@ -3847,6 +3873,7 @@ check_duplicates (struct breakpoint *bpt)
|
||||
ALL_BP_LOCATIONS (b)
|
||||
if (b->owner->enable_state != bp_disabled
|
||||
&& b->owner->enable_state != bp_shlib_disabled
|
||||
&& !b->owner->pending
|
||||
&& b->owner->enable_state != bp_call_disabled
|
||||
&& b->address == address /* address / overlay match */
|
||||
&& (!overlay_debugging || b->section == section)
|
||||
@ -3881,6 +3908,7 @@ check_duplicates (struct breakpoint *bpt)
|
||||
{
|
||||
if (b->owner->enable_state != bp_disabled
|
||||
&& b->owner->enable_state != bp_shlib_disabled
|
||||
&& !b->owner->pending
|
||||
&& b->owner->enable_state != bp_call_disabled
|
||||
&& b->address == address /* address / overlay match */
|
||||
&& (!overlay_debugging || b->section == section)
|
||||
@ -4057,6 +4085,7 @@ set_raw_breakpoint (struct symtab_and_line sal, enum bptype bptype)
|
||||
b->forked_inferior_pid = 0;
|
||||
b->exec_pathname = NULL;
|
||||
b->ops = NULL;
|
||||
b->pending = 0;
|
||||
|
||||
/* Add this breakpoint to the end of the chain
|
||||
so that a list of breakpoints will come out in order
|
||||
@ -4295,23 +4324,90 @@ disable_breakpoints_in_shlibs (int silent)
|
||||
}
|
||||
}
|
||||
|
||||
struct captured_parse_breakpoint_args
|
||||
{
|
||||
char **arg_p;
|
||||
struct symtabs_and_lines *sals_p;
|
||||
char ***addr_string_p;
|
||||
int *not_found_ptr;
|
||||
};
|
||||
|
||||
struct lang_and_radix
|
||||
{
|
||||
enum language lang;
|
||||
int radix;
|
||||
};
|
||||
|
||||
/* Cleanup helper routine to restore the current language and
|
||||
input radix. */
|
||||
static void
|
||||
do_restore_lang_radix_cleanup (void *old)
|
||||
{
|
||||
struct lang_and_radix *p = old;
|
||||
set_language (p->lang);
|
||||
input_radix = p->radix;
|
||||
}
|
||||
|
||||
/* Try and resolve a pending breakpoint. */
|
||||
static int
|
||||
resolve_pending_breakpoint (struct breakpoint *b)
|
||||
{
|
||||
/* Try and reparse the breakpoint in case the shared library
|
||||
is now loaded. */
|
||||
struct symtabs_and_lines sals;
|
||||
struct symtab_and_line pending_sal;
|
||||
char **cond_string = (char **) NULL;
|
||||
char *copy_arg = b->addr_string;
|
||||
char **addr_string;
|
||||
char *errmsg;
|
||||
int rc;
|
||||
int not_found = 0;
|
||||
struct ui_file *old_gdb_stderr;
|
||||
struct lang_and_radix old_lr;
|
||||
struct cleanup *old_chain;
|
||||
|
||||
/* Set language, input-radix, then reissue breakpoint command.
|
||||
Ensure the language and input-radix are restored afterwards. */
|
||||
old_lr.lang = current_language->la_language;
|
||||
old_lr.radix = input_radix;
|
||||
old_chain = make_cleanup (do_restore_lang_radix_cleanup, &old_lr);
|
||||
|
||||
set_language (b->language);
|
||||
input_radix = b->input_radix;
|
||||
rc = break_command_1 (b->addr_string, b->flag, b->from_tty, b);
|
||||
|
||||
if (rc == GDB_RC_OK)
|
||||
/* Pending breakpoint has been resolved. */
|
||||
printf_filtered ("Pending breakpoint \"%s\" resolved\n", b->addr_string);
|
||||
|
||||
do_cleanups (old_chain);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Try to reenable any breakpoints in shared libraries. */
|
||||
void
|
||||
re_enable_breakpoints_in_shlibs (void)
|
||||
{
|
||||
struct breakpoint *b;
|
||||
struct breakpoint *b, *tmp;
|
||||
|
||||
ALL_BREAKPOINTS (b)
|
||||
ALL_BREAKPOINTS_SAFE (b, tmp)
|
||||
{
|
||||
if (b->enable_state == bp_shlib_disabled)
|
||||
{
|
||||
char buf[1], *lib;
|
||||
|
||||
/* Do not reenable the breakpoint if the shared library
|
||||
is still not mapped in. */
|
||||
lib = PC_SOLIB (b->loc->address);
|
||||
if (lib != NULL && target_read_memory (b->loc->address, buf, 1) == 0)
|
||||
b->enable_state = bp_enabled;
|
||||
}
|
||||
{
|
||||
char buf[1], *lib;
|
||||
|
||||
/* Do not reenable the breakpoint if the shared library
|
||||
is still not mapped in. */
|
||||
lib = PC_SOLIB (b->loc->address);
|
||||
if (lib != NULL && target_read_memory (b->loc->address, buf, 1) == 0)
|
||||
b->enable_state = bp_enabled;
|
||||
}
|
||||
else if (b->pending && (b->enable_state == bp_enabled))
|
||||
{
|
||||
if (resolve_pending_breakpoint (b) == GDB_RC_OK)
|
||||
delete_breakpoint (b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -4723,14 +4819,21 @@ mention (struct breakpoint *b)
|
||||
|
||||
if (say_where)
|
||||
{
|
||||
if (addressprint || b->source_file == NULL)
|
||||
if (b->pending)
|
||||
{
|
||||
printf_filtered (" at ");
|
||||
print_address_numeric (b->loc->address, 1, gdb_stdout);
|
||||
printf_filtered (" (%s) pending.", b->addr_string);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (addressprint || b->source_file == NULL)
|
||||
{
|
||||
printf_filtered (" at ");
|
||||
print_address_numeric (b->loc->address, 1, gdb_stdout);
|
||||
}
|
||||
if (b->source_file)
|
||||
printf_filtered (": file %s, line %d.",
|
||||
b->source_file, b->line_number);
|
||||
}
|
||||
if (b->source_file)
|
||||
printf_filtered (": file %s, line %d.",
|
||||
b->source_file, b->line_number);
|
||||
}
|
||||
do_cleanups (old_chain);
|
||||
if (ui_out_is_mi_like_p (uiout))
|
||||
@ -4743,6 +4846,11 @@ mention (struct breakpoint *b)
|
||||
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.
|
||||
|
||||
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
|
||||
@ -4753,7 +4861,8 @@ 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)
|
||||
int thread, int ignore_count, int from_tty,
|
||||
struct breakpoint *pending_bp)
|
||||
{
|
||||
if (type == bp_hardware_breakpoint)
|
||||
{
|
||||
@ -4793,6 +4902,26 @@ create_breakpoints (struct symtabs_and_lines sals, char **addr_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)
|
||||
{
|
||||
char *arg;
|
||||
if (pending_bp->cond_string)
|
||||
{
|
||||
arg = pending_bp->cond_string;
|
||||
b->cond_string = savestring (arg, strlen (arg));
|
||||
b->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);
|
||||
}
|
||||
mention (b);
|
||||
}
|
||||
}
|
||||
@ -4806,7 +4935,8 @@ create_breakpoints (struct symtabs_and_lines sals, char **addr_string,
|
||||
static void
|
||||
parse_breakpoint_sals (char **address,
|
||||
struct symtabs_and_lines *sals,
|
||||
char ***addr_string)
|
||||
char ***addr_string,
|
||||
int *not_found_ptr)
|
||||
{
|
||||
char *addr_start = *address;
|
||||
*addr_string = NULL;
|
||||
@ -4847,9 +4977,11 @@ parse_breakpoint_sals (char **address,
|
||||
|| ((strchr ("+-", (*address)[0]) != NULL)
|
||||
&& ((*address)[1] != '['))))
|
||||
*sals = decode_line_1 (address, 1, default_breakpoint_symtab,
|
||||
default_breakpoint_line, addr_string, NULL);
|
||||
default_breakpoint_line, addr_string,
|
||||
not_found_ptr);
|
||||
else
|
||||
*sals = decode_line_1 (address, 1, (struct symtab *) NULL, 0, addr_string, NULL);
|
||||
*sals = decode_line_1 (address, 1, (struct symtab *) NULL, 0,
|
||||
addr_string, not_found_ptr);
|
||||
}
|
||||
/* For any SAL that didn't have a canonical string, fill one in. */
|
||||
if (sals->nelts > 0 && *addr_string == NULL)
|
||||
@ -4903,26 +5035,44 @@ breakpoint_sals_to_pc (struct symtabs_and_lines *sals,
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
do_captured_parse_breakpoint (struct ui_out *ui, void *data)
|
||||
{
|
||||
struct captured_parse_breakpoint_args *args = data;
|
||||
|
||||
parse_breakpoint_sals (args->arg_p, args->sals_p, args->addr_string_p,
|
||||
args->not_found_ptr);
|
||||
|
||||
return GDB_RC_OK;
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
second bit : 0 normal breakpoint, 1 hardware breakpoint.
|
||||
|
||||
static void
|
||||
break_command_1 (char *arg, int flag, int from_tty)
|
||||
PENDING_BP is non-NULL when this function is being called to resolve
|
||||
a pending breakpoint. */
|
||||
|
||||
static int
|
||||
break_command_1 (char *arg, int flag, int from_tty, struct breakpoint *pending_bp)
|
||||
{
|
||||
int tempflag, hardwareflag;
|
||||
struct symtabs_and_lines sals;
|
||||
struct expression **cond = 0;
|
||||
/* Pointers in arg to the start, and one past the end, of the
|
||||
condition. */
|
||||
struct symtab_and_line pending_sal;
|
||||
char **cond_string = (char **) NULL;
|
||||
char *copy_arg;
|
||||
char *err_msg;
|
||||
char *addr_start = arg;
|
||||
char **addr_string;
|
||||
struct cleanup *old_chain;
|
||||
struct cleanup *breakpoint_chain = NULL;
|
||||
int i;
|
||||
struct captured_parse_breakpoint_args parse_args;
|
||||
int i, rc;
|
||||
int pending = 0;
|
||||
int thread = -1;
|
||||
int ignore_count = 0;
|
||||
int not_found = 0;
|
||||
|
||||
hardwareflag = flag & BP_HARDWAREFLAG;
|
||||
tempflag = flag & BP_TEMPFLAG;
|
||||
@ -4930,19 +5080,55 @@ break_command_1 (char *arg, int flag, int from_tty)
|
||||
sals.sals = NULL;
|
||||
sals.nelts = 0;
|
||||
addr_string = NULL;
|
||||
parse_breakpoint_sals (&arg, &sals, &addr_string);
|
||||
|
||||
if (!sals.nelts)
|
||||
return;
|
||||
parse_args.arg_p = &arg;
|
||||
parse_args.sals_p = &sals;
|
||||
parse_args.addr_string_p = &addr_string;
|
||||
parse_args.not_found_ptr = ¬_found;
|
||||
|
||||
rc = catch_exceptions_with_msg (uiout, do_captured_parse_breakpoint,
|
||||
&parse_args, NULL, &err_msg,
|
||||
RETURN_MASK_ALL);
|
||||
|
||||
/* If caller is interested in rc value from parse, set value. */
|
||||
|
||||
if (rc != GDB_RC_OK)
|
||||
{
|
||||
/* Check for file or function not found. */
|
||||
if (not_found)
|
||||
{
|
||||
/* If called to resolve pending breakpoint, just return error code. */
|
||||
if (pending_bp)
|
||||
return rc;
|
||||
|
||||
error_output_message (NULL, err_msg);
|
||||
xfree (err_msg);
|
||||
if (!query ("Make breakpoint pending on future shared library load? "))
|
||||
return rc;
|
||||
copy_arg = xstrdup (addr_start);
|
||||
addr_string = ©_arg;
|
||||
sals.nelts = 1;
|
||||
sals.sals = &pending_sal;
|
||||
pending_sal.pc = 0;
|
||||
pending = 1;
|
||||
}
|
||||
else
|
||||
return rc;
|
||||
}
|
||||
else if (!sals.nelts)
|
||||
return GDB_RC_FAIL;
|
||||
|
||||
/* Create a chain of things that always need to be cleaned up. */
|
||||
old_chain = make_cleanup (null_cleanup, 0);
|
||||
|
||||
/* Make sure that all storage allocated to SALS gets freed. */
|
||||
make_cleanup (xfree, sals.sals);
|
||||
|
||||
/* Cleanup the addr_string array but not its contents. */
|
||||
make_cleanup (xfree, addr_string);
|
||||
if (!pending)
|
||||
{
|
||||
/* Make sure that all storage allocated to SALS gets freed. */
|
||||
make_cleanup (xfree, sals.sals);
|
||||
|
||||
/* Cleanup the addr_string array but not its contents. */
|
||||
make_cleanup (xfree, addr_string);
|
||||
}
|
||||
|
||||
/* Allocate space for all the cond expressions. */
|
||||
cond = xcalloc (sals.nelts, sizeof (struct expression *));
|
||||
@ -4969,62 +5155,94 @@ break_command_1 (char *arg, int flag, int from_tty)
|
||||
|
||||
/* Resolve all line numbers to PC's and verify that the addresses
|
||||
are ok for the target. */
|
||||
breakpoint_sals_to_pc (&sals, addr_start);
|
||||
if (!pending)
|
||||
breakpoint_sals_to_pc (&sals, addr_start);
|
||||
|
||||
/* Verify that condition can be parsed, before setting any
|
||||
breakpoints. Allocate a separate condition expression for each
|
||||
breakpoint. */
|
||||
thread = -1; /* No specific thread yet */
|
||||
for (i = 0; i < sals.nelts; i++)
|
||||
if (!pending)
|
||||
{
|
||||
char *tok = arg;
|
||||
while (tok && *tok)
|
||||
for (i = 0; i < sals.nelts; i++)
|
||||
{
|
||||
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)
|
||||
char *tok = arg;
|
||||
while (tok && *tok)
|
||||
{
|
||||
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]);
|
||||
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\n", thread);
|
||||
}
|
||||
else
|
||||
error ("Junk at end of arguments.");
|
||||
}
|
||||
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\n", thread);
|
||||
}
|
||||
else
|
||||
error ("Junk at end of arguments.");
|
||||
}
|
||||
create_breakpoints (sals, addr_string, cond, cond_string,
|
||||
hardwareflag ? bp_hardware_breakpoint
|
||||
: bp_breakpoint,
|
||||
tempflag ? disp_del : disp_donttouch,
|
||||
thread, ignore_count, from_tty,
|
||||
pending_bp);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct symtab_and_line sal;
|
||||
struct breakpoint *b;
|
||||
|
||||
create_breakpoints (sals, addr_string, cond, cond_string,
|
||||
hardwareflag ? bp_hardware_breakpoint : bp_breakpoint,
|
||||
tempflag ? disp_del : disp_donttouch,
|
||||
thread, ignore_count, from_tty);
|
||||
sal.symtab = NULL;
|
||||
sal.pc = 0;
|
||||
|
||||
make_cleanup (xfree, copy_arg);
|
||||
|
||||
b = set_raw_breakpoint (sal, hardwareflag ? bp_hardware_breakpoint
|
||||
: bp_breakpoint);
|
||||
set_breakpoint_count (breakpoint_count + 1);
|
||||
b->number = breakpoint_count;
|
||||
b->cond = *cond;
|
||||
b->thread = thread;
|
||||
b->addr_string = *addr_string;
|
||||
b->cond_string = *cond_string;
|
||||
b->ignore_count = ignore_count;
|
||||
b->pending = 1;
|
||||
b->disposition = tempflag ? disp_del : disp_donttouch;
|
||||
b->from_tty = from_tty;
|
||||
b->flag = flag;
|
||||
mention (b);
|
||||
}
|
||||
|
||||
if (sals.nelts > 1)
|
||||
{
|
||||
warning ("Multiple breakpoints were set.");
|
||||
@ -5035,6 +5253,8 @@ break_command_1 (char *arg, int flag, int from_tty)
|
||||
discard_cleanups (breakpoint_chain);
|
||||
/* But cleanup everything else. */
|
||||
do_cleanups (old_chain);
|
||||
|
||||
return GDB_RC_OK;
|
||||
}
|
||||
|
||||
/* Set a breakpoint of TYPE/DISPOSITION according to ARG (function,
|
||||
@ -5071,7 +5291,7 @@ do_captured_breakpoint (void *data)
|
||||
sals.nelts = 0;
|
||||
address_end = args->address;
|
||||
addr_string = NULL;
|
||||
parse_breakpoint_sals (&address_end, &sals, &addr_string);
|
||||
parse_breakpoint_sals (&address_end, &sals, &addr_string, 0);
|
||||
|
||||
if (!sals.nelts)
|
||||
return GDB_RC_NONE;
|
||||
@ -5135,7 +5355,8 @@ do_captured_breakpoint (void *data)
|
||||
create_breakpoints (sals, addr_string, cond, cond_string,
|
||||
args->hardwareflag ? bp_hardware_breakpoint : bp_breakpoint,
|
||||
args->tempflag ? disp_del : disp_donttouch,
|
||||
args->thread, args->ignore_count, 0/*from-tty*/);
|
||||
args->thread, args->ignore_count, 0/*from-tty*/,
|
||||
NULL/*pending_bp*/);
|
||||
|
||||
/* That's it. Discard the cleanups for data inserted into the
|
||||
breakpoint. */
|
||||
@ -5227,7 +5448,7 @@ break_at_finish_at_depth_command_1 (char *arg, int flag, int from_tty)
|
||||
addr_string = xstrprintf ("*0x%s %s", paddr_nz (high), extra_args);
|
||||
else
|
||||
addr_string = xstrprintf ("*0x%s", paddr_nz (high));
|
||||
break_command_1 (addr_string, flag, from_tty);
|
||||
break_command_1 (addr_string, flag, from_tty, NULL);
|
||||
xfree (addr_string);
|
||||
}
|
||||
else
|
||||
@ -5310,7 +5531,7 @@ break_at_finish_command_1 (char *arg, int flag, int from_tty)
|
||||
extra_args);
|
||||
else
|
||||
break_string = xstrprintf ("*0x%s", paddr_nz (high));
|
||||
break_command_1 (break_string, flag, from_tty);
|
||||
break_command_1 (break_string, flag, from_tty, NULL);
|
||||
xfree (break_string);
|
||||
}
|
||||
else
|
||||
@ -5377,7 +5598,7 @@ resolve_sal_pc (struct symtab_and_line *sal)
|
||||
void
|
||||
break_command (char *arg, int from_tty)
|
||||
{
|
||||
break_command_1 (arg, 0, from_tty);
|
||||
break_command_1 (arg, 0, from_tty, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
@ -5395,7 +5616,7 @@ break_at_finish_at_depth_command (char *arg, int from_tty)
|
||||
void
|
||||
tbreak_command (char *arg, int from_tty)
|
||||
{
|
||||
break_command_1 (arg, BP_TEMPFLAG, from_tty);
|
||||
break_command_1 (arg, BP_TEMPFLAG, from_tty, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
@ -5407,13 +5628,13 @@ tbreak_at_finish_command (char *arg, int from_tty)
|
||||
static void
|
||||
hbreak_command (char *arg, int from_tty)
|
||||
{
|
||||
break_command_1 (arg, BP_HARDWAREFLAG, from_tty);
|
||||
break_command_1 (arg, BP_HARDWAREFLAG, from_tty, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
thbreak_command (char *arg, int from_tty)
|
||||
{
|
||||
break_command_1 (arg, (BP_TEMPFLAG | BP_HARDWAREFLAG), from_tty);
|
||||
break_command_1 (arg, (BP_TEMPFLAG | BP_HARDWAREFLAG), from_tty, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -5454,7 +5675,7 @@ stopin_command (char *arg, int from_tty)
|
||||
if (badInput)
|
||||
printf_filtered ("Usage: stop in <function | address>\n");
|
||||
else
|
||||
break_command_1 (arg, 0, from_tty);
|
||||
break_command_1 (arg, 0, from_tty, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -5486,7 +5707,7 @@ stopat_command (char *arg, int from_tty)
|
||||
if (badInput)
|
||||
printf_filtered ("Usage: stop at <line>\n");
|
||||
else
|
||||
break_command_1 (arg, 0, from_tty);
|
||||
break_command_1 (arg, 0, from_tty, NULL);
|
||||
}
|
||||
|
||||
/* accessflag: hw_write: watch write,
|
||||
@ -6693,6 +6914,7 @@ delete_breakpoint (struct breakpoint *bpt)
|
||||
&& !b->loc->duplicate
|
||||
&& b->enable_state != bp_disabled
|
||||
&& b->enable_state != bp_shlib_disabled
|
||||
&& !b->pending
|
||||
&& b->enable_state != bp_call_disabled)
|
||||
{
|
||||
int val;
|
||||
@ -6898,6 +7120,10 @@ breakpoint_re_set_one (void *bint)
|
||||
shlib_disabled breakpoint though. There's a fair chance we
|
||||
can't re-set it if the shared library it's in hasn't been
|
||||
loaded yet. */
|
||||
|
||||
if (b->pending)
|
||||
break;
|
||||
|
||||
save_enable = b->enable_state;
|
||||
if (b->enable_state != bp_shlib_disabled)
|
||||
b->enable_state = bp_disabled;
|
||||
@ -7313,70 +7539,91 @@ do_enable_breakpoint (struct breakpoint *bpt, enum bpdisp disposition)
|
||||
error ("Hardware breakpoints used exceeds limit.");
|
||||
}
|
||||
|
||||
if (bpt->enable_state != bp_permanent)
|
||||
bpt->enable_state = bp_enabled;
|
||||
bpt->disposition = disposition;
|
||||
check_duplicates (bpt);
|
||||
breakpoints_changed ();
|
||||
|
||||
if (bpt->type == bp_watchpoint ||
|
||||
bpt->type == bp_hardware_watchpoint ||
|
||||
bpt->type == bp_read_watchpoint ||
|
||||
bpt->type == bp_access_watchpoint)
|
||||
if (bpt->pending)
|
||||
{
|
||||
if (bpt->exp_valid_block != NULL)
|
||||
if (bpt->enable_state != bp_enabled)
|
||||
{
|
||||
struct frame_info *fr =
|
||||
fr = frame_find_by_id (bpt->watchpoint_frame);
|
||||
if (fr == NULL)
|
||||
/* When enabling a pending breakpoint, we need to check if the breakpoint
|
||||
is resolvable since shared libraries could have been loaded
|
||||
after the breakpoint was disabled. */
|
||||
breakpoints_changed ();
|
||||
if (resolve_pending_breakpoint (bpt) == GDB_RC_OK)
|
||||
{
|
||||
printf_filtered ("\
|
||||
Cannot enable watchpoint %d because the block in which its expression\n\
|
||||
is valid is not currently in scope.\n", bpt->number);
|
||||
bpt->enable_state = bp_disabled;
|
||||
delete_breakpoint (bpt);
|
||||
return;
|
||||
}
|
||||
|
||||
save_selected_frame = deprecated_selected_frame;
|
||||
save_selected_frame_level = frame_relative_level (deprecated_selected_frame);
|
||||
select_frame (fr);
|
||||
bpt->enable_state = bp_enabled;
|
||||
bpt->disposition = disposition;
|
||||
}
|
||||
|
||||
value_free (bpt->val);
|
||||
mark = value_mark ();
|
||||
bpt->val = evaluate_expression (bpt->exp);
|
||||
release_value (bpt->val);
|
||||
if (VALUE_LAZY (bpt->val))
|
||||
value_fetch_lazy (bpt->val);
|
||||
|
||||
if (bpt->type == bp_hardware_watchpoint ||
|
||||
bpt->type == bp_read_watchpoint ||
|
||||
}
|
||||
else /* Not a pending breakpoint. */
|
||||
{
|
||||
if (bpt->enable_state != bp_permanent)
|
||||
bpt->enable_state = bp_enabled;
|
||||
bpt->disposition = disposition;
|
||||
check_duplicates (bpt);
|
||||
breakpoints_changed ();
|
||||
|
||||
if (bpt->type == bp_watchpoint ||
|
||||
bpt->type == bp_hardware_watchpoint ||
|
||||
bpt->type == bp_read_watchpoint ||
|
||||
bpt->type == bp_access_watchpoint)
|
||||
{
|
||||
int i = hw_watchpoint_used_count (bpt->type, &other_type_used);
|
||||
int mem_cnt = can_use_hardware_watchpoint (bpt->val);
|
||||
|
||||
/* Hack around 'unused var' error for some targets here */
|
||||
(void) mem_cnt, i;
|
||||
target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT (
|
||||
bpt->type, i + mem_cnt, other_type_used);
|
||||
/* we can consider of type is bp_hardware_watchpoint, convert to
|
||||
bp_watchpoint in the following condition */
|
||||
if (target_resources_ok < 0)
|
||||
if (bpt->exp_valid_block != NULL)
|
||||
{
|
||||
printf_filtered ("\
|
||||
struct frame_info *fr =
|
||||
fr = frame_find_by_id (bpt->watchpoint_frame);
|
||||
if (fr == NULL)
|
||||
{
|
||||
printf_filtered ("\
|
||||
Cannot enable watchpoint %d because the block in which its expression\n\
|
||||
is valid is not currently in scope.\n", bpt->number);
|
||||
bpt->enable_state = bp_disabled;
|
||||
return;
|
||||
}
|
||||
|
||||
save_selected_frame = deprecated_selected_frame;
|
||||
save_selected_frame_level = frame_relative_level (deprecated_selected_frame);
|
||||
select_frame (fr);
|
||||
}
|
||||
|
||||
value_free (bpt->val);
|
||||
mark = value_mark ();
|
||||
bpt->val = evaluate_expression (bpt->exp);
|
||||
release_value (bpt->val);
|
||||
if (VALUE_LAZY (bpt->val))
|
||||
value_fetch_lazy (bpt->val);
|
||||
|
||||
if (bpt->type == bp_hardware_watchpoint ||
|
||||
bpt->type == bp_read_watchpoint ||
|
||||
bpt->type == bp_access_watchpoint)
|
||||
{
|
||||
int i = hw_watchpoint_used_count (bpt->type, &other_type_used);
|
||||
int mem_cnt = can_use_hardware_watchpoint (bpt->val);
|
||||
|
||||
/* Hack around 'unused var' error for some targets here */
|
||||
(void) mem_cnt, i;
|
||||
target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT (
|
||||
bpt->type, i + mem_cnt, other_type_used);
|
||||
/* we can consider of type is bp_hardware_watchpoint, convert to
|
||||
bp_watchpoint in the following condition */
|
||||
if (target_resources_ok < 0)
|
||||
{
|
||||
printf_filtered ("\
|
||||
Cannot enable watchpoint %d because target watch resources\n\
|
||||
have been allocated for other watchpoints.\n", bpt->number);
|
||||
bpt->enable_state = bp_disabled;
|
||||
value_free_to_mark (mark);
|
||||
return;
|
||||
bpt->enable_state = bp_disabled;
|
||||
value_free_to_mark (mark);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (save_selected_frame_level >= 0)
|
||||
select_frame (save_selected_frame);
|
||||
value_free_to_mark (mark);
|
||||
}
|
||||
|
||||
if (save_selected_frame_level >= 0)
|
||||
select_frame (save_selected_frame);
|
||||
value_free_to_mark (mark);
|
||||
}
|
||||
|
||||
if (modify_breakpoint_hook)
|
||||
modify_breakpoint_hook (bpt);
|
||||
breakpoint_modify_event (bpt->number);
|
||||
|
@ -386,6 +386,17 @@ struct breakpoint
|
||||
|
||||
/* Methods associated with this breakpoint. */
|
||||
struct breakpoint_ops *ops;
|
||||
|
||||
/* Was breakpoint issued from a tty? Saved for the use of pending breakpoints. */
|
||||
int from_tty;
|
||||
|
||||
/* Flag value for pending breakpoint.
|
||||
first bit : 0 non-temporary, 1 temporary.
|
||||
second bit : 0 normal breakpoint, 1 hardware breakpoint. */
|
||||
int flag;
|
||||
|
||||
/* Is breakpoint pending on shlib loads? */
|
||||
int pending;
|
||||
};
|
||||
|
||||
/* The following stuff is an abstract data type "bpstat" ("breakpoint
|
||||
|
Loading…
x
Reference in New Issue
Block a user