mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-23 18:14:13 +08:00
Guile: temporary breakpoints
Adds API to the Guile bindings for creating temporary breakpoints and querying whether an existing breakpoint object is temporary. This is effectively a transliteration of the Python implementation. It's worth noting that the added `is_temporary' flag is ignored in the watchpoint registration path. This replicates the behaviour of the Python implementation, but might be a bit surprising for users. gdb/ChangeLog: 2021-06-09 George Barrett <bob@bob131.so> * guile/scm-breakpoint.c (gdbscm_breakpoint_object::spec): Add is_temporary field. (temporary_keyword): Add keyword object for make-breakpoint argument parsing. (gdbscm_make_breakpoint): Accept #:temporary keyword argument and store the value in the allocated object's spec.is_temporary. (gdbscm_register_breakpoint_x): Pass the breakpoint's spec.is_temporary value to create_breakpoint. (gdbscm_breakpoint_temporary): Add breakpoint-temporary? procedure implementation. (breakpoint_functions::make-breakpoint): Update documentation string and fix a typo. (breakpoint_functions::breakpoint-temporary?): Add breakpoint-temporary? procedure. (gdbscm_initialize_breakpoints): Initialise temporary_keyword variable. NEWS (Guile API): Mention new temporary breakpoints API. gdb/doc/ChangeLog: 2021-06-09 George Barrett <bob@bob131.so> * guile.texi (Breakpoints In Guile): Update make-breakpoint documentation to reflect new #:temporary argument. Add documentation for new breakpoint-temporary? procedure. gdb/testsuite/ChangeLog: 2021-06-09 George Barrett <bob@bob131.so> * gdb.guile/scm-breakpoint.exp: Add additional tests for temporary breakpoints. Change-Id: I2de332ee7c256f5591d7141ab3ad50d31b871d17
This commit is contained in:
parent
588f5af532
commit
ad42014be2
3
gdb/NEWS
3
gdb/NEWS
@ -267,6 +267,9 @@ QMemTags
|
||||
value-reference-value, value-rvalue-reference-value and
|
||||
value-const-value.
|
||||
|
||||
** Temporary breakpoints can now be created with make-breakpoint and
|
||||
tested for using breakpoint-temporary?.
|
||||
|
||||
* Python API
|
||||
|
||||
** Inferior objects now contain a read-only 'connection_num' attribute that
|
||||
|
@ -2965,7 +2965,7 @@ The following breakpoint-related procedures are provided by the
|
||||
@code{(gdb)} module:
|
||||
|
||||
@c TODO: line length
|
||||
@deffn {Scheme Procedure} make-breakpoint location @r{[}#:type type@r{]} @r{[}#:wp-class wp-class@r{]} @r{[}#:internal internal@r{]}
|
||||
@deffn {Scheme Procedure} make-breakpoint location @r{[}#:type type@r{]} @r{[}#:wp-class wp-class@r{]} @r{[}#:internal internal@r{]} @r{[}#:temporary temporary@r{]}
|
||||
Create a new breakpoint at @var{location}, a string naming the
|
||||
location of the breakpoint, or an expression that defines a watchpoint.
|
||||
The contents can be any location recognized by the @code{break} command,
|
||||
@ -2991,6 +2991,11 @@ registered, nor will it be listed in the output from @code{info breakpoints}
|
||||
If an internal flag is not provided, the breakpoint is visible
|
||||
(non-internal).
|
||||
|
||||
The optional @var{temporary} argument makes the breakpoint a temporary
|
||||
breakpoint. Temporary breakpoints are deleted after they have been hit,
|
||||
after which the Guile breakpoint is no longer usable (although it may be
|
||||
re-registered with @code{register-breakpoint!}).
|
||||
|
||||
When a watchpoint is created, @value{GDBN} will try to create a
|
||||
hardware assisted watchpoint. If successful, the type of the watchpoint
|
||||
is changed from @code{BP_WATCHPOINT} to @code{BP_HARDWARE_WATCHPOINT}
|
||||
@ -3087,6 +3092,15 @@ Return the breakpoint's number --- the identifier used by
|
||||
the user to manipulate the breakpoint.
|
||||
@end deffn
|
||||
|
||||
@deffn {Scheme Procedure} breakpoint-temporary? breakpoint
|
||||
Return @code{#t} if the breakpoint was created as a temporary
|
||||
breakpoint. Temporary breakpoints are automatically deleted after
|
||||
they've been hit. Calling this procedure, and all other procedures
|
||||
other than @code{breakpoint-valid?} and @code{register-breakpoint!},
|
||||
will result in an error after the breakpoint has been hit (since it has
|
||||
been automatically deleted).
|
||||
@end deffn
|
||||
|
||||
@deffn {Scheme Procedure} breakpoint-type breakpoint
|
||||
Return the breakpoint's type --- the identifier used to
|
||||
determine the actual breakpoint type or use-case.
|
||||
|
@ -69,6 +69,9 @@ typedef struct gdbscm_breakpoint_object
|
||||
|
||||
/* Non-zero if the breakpoint is an "internal" breakpoint. */
|
||||
int is_internal;
|
||||
|
||||
/* Non-zero if the breakpoint is temporary. */
|
||||
int is_temporary;
|
||||
} spec;
|
||||
|
||||
/* The breakpoint number according to gdb.
|
||||
@ -103,6 +106,7 @@ static SCM pending_breakpoint_scm = SCM_BOOL_F;
|
||||
static SCM type_keyword;
|
||||
static SCM wp_class_keyword;
|
||||
static SCM internal_keyword;
|
||||
static SCM temporary_keyword;
|
||||
|
||||
/* Administrivia for breakpoint smobs. */
|
||||
|
||||
@ -332,7 +336,7 @@ bpscm_get_valid_breakpoint_smob_arg_unsafe (SCM self, int arg_pos,
|
||||
/* Breakpoint methods. */
|
||||
|
||||
/* (make-breakpoint string [#:type integer] [#:wp-class integer]
|
||||
[#:internal boolean) -> <gdb:breakpoint>
|
||||
[#:internal boolean] [#:temporary boolean]) -> <gdb:breakpoint>
|
||||
|
||||
The result is the <gdb:breakpoint> Scheme object.
|
||||
The breakpoint is not available to be used yet, however.
|
||||
@ -342,22 +346,26 @@ static SCM
|
||||
gdbscm_make_breakpoint (SCM location_scm, SCM rest)
|
||||
{
|
||||
const SCM keywords[] = {
|
||||
type_keyword, wp_class_keyword, internal_keyword, SCM_BOOL_F
|
||||
type_keyword, wp_class_keyword, internal_keyword,
|
||||
temporary_keyword, SCM_BOOL_F
|
||||
};
|
||||
char *s;
|
||||
char *location;
|
||||
int type_arg_pos = -1, access_type_arg_pos = -1, internal_arg_pos = -1;
|
||||
int type_arg_pos = -1, access_type_arg_pos = -1,
|
||||
internal_arg_pos = -1, temporary_arg_pos = -1;
|
||||
enum bptype type = bp_breakpoint;
|
||||
enum target_hw_bp_type access_type = hw_write;
|
||||
int internal = 0;
|
||||
int temporary = 0;
|
||||
SCM result;
|
||||
breakpoint_smob *bp_smob;
|
||||
|
||||
gdbscm_parse_function_args (FUNC_NAME, SCM_ARG1, keywords, "s#iit",
|
||||
gdbscm_parse_function_args (FUNC_NAME, SCM_ARG1, keywords, "s#iitt",
|
||||
location_scm, &location, rest,
|
||||
&type_arg_pos, &type,
|
||||
&access_type_arg_pos, &access_type,
|
||||
&internal_arg_pos, &internal);
|
||||
&internal_arg_pos, &internal,
|
||||
&temporary_arg_pos, &temporary);
|
||||
|
||||
result = bpscm_make_breakpoint_smob ();
|
||||
bp_smob = (breakpoint_smob *) SCM_SMOB_DATA (result);
|
||||
@ -412,6 +420,7 @@ gdbscm_make_breakpoint (SCM location_scm, SCM rest)
|
||||
bp_smob->spec.type = type;
|
||||
bp_smob->spec.access_type = access_type;
|
||||
bp_smob->spec.is_internal = internal;
|
||||
bp_smob->spec.is_temporary = temporary;
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -447,6 +456,7 @@ gdbscm_register_breakpoint_x (SCM self)
|
||||
try
|
||||
{
|
||||
int internal = bp_smob->spec.is_internal;
|
||||
int temporary = bp_smob->spec.is_temporary;
|
||||
|
||||
switch (bp_smob->spec.type)
|
||||
{
|
||||
@ -457,7 +467,7 @@ gdbscm_register_breakpoint_x (SCM self)
|
||||
create_breakpoint (get_current_arch (),
|
||||
eloc.get (), NULL, -1, NULL, false,
|
||||
0,
|
||||
0, bp_breakpoint,
|
||||
temporary, bp_breakpoint,
|
||||
0,
|
||||
AUTO_BOOLEAN_TRUE,
|
||||
ops,
|
||||
@ -1040,6 +1050,18 @@ gdbscm_breakpoint_number (SCM self)
|
||||
|
||||
return scm_from_long (bp_smob->number);
|
||||
}
|
||||
|
||||
/* (breakpoint-temporary? <gdb:breakpoint>) -> boolean */
|
||||
|
||||
static SCM
|
||||
gdbscm_breakpoint_temporary (SCM self)
|
||||
{
|
||||
breakpoint_smob *bp_smob
|
||||
= bpscm_get_valid_breakpoint_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
|
||||
|
||||
return scm_from_bool (bp_smob->bp->disposition == disp_del
|
||||
|| bp_smob->bp->disposition == disp_del_at_next_stop);
|
||||
}
|
||||
|
||||
/* Return TRUE if "stop" has been set for this breakpoint.
|
||||
|
||||
@ -1171,9 +1193,9 @@ static const scheme_function breakpoint_functions[] =
|
||||
Create a GDB breakpoint object.\n\
|
||||
\n\
|
||||
Arguments:\n\
|
||||
location [#:type <type>] [#:wp-class <wp-class>] [#:internal <bool>]\n\
|
||||
location [#:type <type>] [#:wp-class <wp-class>] [#:internal <bool>] [#:temporary <bool>]\n\
|
||||
Returns:\n\
|
||||
<gdb:breakpoint object" },
|
||||
<gdb:breakpoint> object" },
|
||||
|
||||
{ "register-breakpoint!", 1, 0, 0,
|
||||
as_a_scm_t_subr (gdbscm_register_breakpoint_x),
|
||||
@ -1202,6 +1224,10 @@ Return #t if the breakpoint has not been deleted from GDB." },
|
||||
"\
|
||||
Return the breakpoint's number." },
|
||||
|
||||
{ "breakpoint-temporary?", 1, 0, 0, as_a_scm_t_subr (gdbscm_breakpoint_temporary),
|
||||
"\
|
||||
Return #t if the breakpoint is a temporary breakpoint." },
|
||||
|
||||
{ "breakpoint-type", 1, 0, 0, as_a_scm_t_subr (gdbscm_breakpoint_type),
|
||||
"\
|
||||
Return the type of the breakpoint." },
|
||||
@ -1345,4 +1371,5 @@ gdbscm_initialize_breakpoints (void)
|
||||
type_keyword = scm_from_latin1_keyword ("type");
|
||||
wp_class_keyword = scm_from_latin1_keyword ("wp-class");
|
||||
internal_keyword = scm_from_latin1_keyword ("internal");
|
||||
temporary_keyword = scm_from_latin1_keyword ("temporary");
|
||||
}
|
||||
|
@ -485,6 +485,38 @@ proc_with_prefix test_bkpt_registration {} {
|
||||
"= #t" "breakpoint valid after re-registration"
|
||||
}
|
||||
|
||||
proc_with_prefix test_bkpt_temporary { } {
|
||||
global srcfile testfile hex decimal
|
||||
|
||||
# Start with a fresh gdb.
|
||||
clean_restart ${testfile}
|
||||
|
||||
if ![gdb_guile_runto_main] {
|
||||
fail "cannot run to main."
|
||||
return 0
|
||||
}
|
||||
delete_breakpoints
|
||||
|
||||
set ibp_location [gdb_get_line_number "Break at multiply."]
|
||||
gdb_scm_test_silent_cmd "guile (define ibp (make-breakpoint \"$ibp_location\" #:temporary #t))" \
|
||||
"create temporary breakpoint"
|
||||
gdb_scm_test_silent_cmd "guile (register-breakpoint! ibp)" \
|
||||
"register ibp"
|
||||
gdb_test "info breakpoints" \
|
||||
"2.*breakpoint.*del.*scm-breakpoint\.c:$ibp_location.*" \
|
||||
"check info breakpoints shows breakpoint with temporary status"
|
||||
gdb_test "guile (print (breakpoint-location ibp))" "scm-breakpoint\.c:$ibp_location*" \
|
||||
"check temporary breakpoint location"
|
||||
gdb_test "guile (print (breakpoint-temporary? ibp))" "#t" \
|
||||
"check breakpoint temporary status"
|
||||
gdb_continue_to_breakpoint "Break at multiply." \
|
||||
".*$srcfile:$ibp_location.*"
|
||||
gdb_test "guile (print (breakpoint-temporary? ibp))" "Invalid object: <gdb:breakpoint>.*" \
|
||||
"check temporary breakpoint is deleted after being hit"
|
||||
gdb_test "info breakpoints" "No breakpoints or watchpoints.*" \
|
||||
"check info breakpoints shows temporary breakpoint is deleted"
|
||||
}
|
||||
|
||||
proc_with_prefix test_bkpt_address {} {
|
||||
global decimal srcfile
|
||||
|
||||
@ -564,5 +596,6 @@ test_watchpoints
|
||||
test_bkpt_internal
|
||||
test_bkpt_eval_funcs
|
||||
test_bkpt_registration
|
||||
test_bkpt_temporary
|
||||
test_bkpt_address
|
||||
test_bkpt_probe
|
||||
|
Loading…
Reference in New Issue
Block a user