2010-11-11 Phil Muldoon <pmuldoon@redhat.com>
* python/py-breakpoint.c (BPPY_REQUIRE_VALID): Check if bp is NULL. (BPPY_SET_REQUIRE_VALID): Ditto. (bpnum_is_valid): Delete function. (bppy_get_visibility): New function. (bppy_new): Parse for, and validate internal keyword. Pass internal keyword to breakpoint or watchpoint functions. (build_bp_list): New function. (gdbpy_breakpoints): Rewrite. Use build_bp_list and iterate_over_breakpoints. (gdbpy_breakpoint_created): Rewrite. Do not store breakpoints in a look-aside vector. (gdbpy_breakpoint_deleted): Rewrite, defer breakpoint management to internal breakpoint chain. * breakpoint.c (set_breakpoint_number): New function. (breakpoint_1): Check if breakpoint number is more than zero. (set_raw_breakpoint_without_location): Set py_bp_object to NULL. (create_breakpoint_sal): Take a new parameter called internal. Call set_breakpoint_number with internal parameter. Do not mention internal breakpoints. All callers updated. (create_breakpoint): Ditto. (create_breakpoints_sal): Ditto. (watch_command_1): Ditto. (watch_command_wrapper): Take a new parameter called internal. All callers updated. (rwatch_command_wrapper): Ditto. (awatch_command_wrapper): Ditto. (save_breakpoints): Update breakpoint save condition check. (iterate_over_breakpoints): New function. * breakpoint.h: Add conditional python includes. Add py_bp_object and comment to struct breakpoint. Update all callers. * defs.h: Add PyObject definition for GDB builds without Python. 2010-11-11 Phil Muldoon <pmuldoon@redhat.com> * gdb.texinfo (Breakpoints In Python): Document "internal" parameter, and visible attribute. 2010-11-11 Phil Muldoon <pmuldoon@redhat.com> * gdb.python/py-breakpoint.exp: Add internal watchpoint and breakpoint tests.
This commit is contained in:
parent
95a2c8d6f7
commit
84f4c1fe05
|
@ -1,3 +1,39 @@
|
|||
2010-11-11 Phil Muldoon <pmuldoon@redhat.com>
|
||||
|
||||
* python/py-breakpoint.c (BPPY_REQUIRE_VALID): Check if bp is
|
||||
NULL.
|
||||
(BPPY_SET_REQUIRE_VALID): Ditto.
|
||||
(bpnum_is_valid): Delete function.
|
||||
(bppy_get_visibility): New function.
|
||||
(bppy_new): Parse for, and validate internal keyword. Pass
|
||||
internal keyword to breakpoint or watchpoint functions.
|
||||
(build_bp_list): New function.
|
||||
(gdbpy_breakpoints): Rewrite. Use build_bp_list and
|
||||
iterate_over_breakpoints.
|
||||
(gdbpy_breakpoint_created): Rewrite. Do not store breakpoints in a
|
||||
look-aside vector.
|
||||
(gdbpy_breakpoint_deleted): Rewrite, defer breakpoint management
|
||||
to internal breakpoint chain.
|
||||
|
||||
* breakpoint.c (set_breakpoint_number): New function.
|
||||
(breakpoint_1): Check if breakpoint number is more than zero.
|
||||
(set_raw_breakpoint_without_location): Set py_bp_object to NULL.
|
||||
(create_breakpoint_sal): Take a new parameter called internal.
|
||||
Call set_breakpoint_number with internal parameter. Do not
|
||||
mention internal breakpoints. All callers updated.
|
||||
(create_breakpoint): Ditto.
|
||||
(create_breakpoints_sal): Ditto.
|
||||
(watch_command_1): Ditto.
|
||||
(watch_command_wrapper): Take a new parameter called internal.
|
||||
All callers updated.
|
||||
(rwatch_command_wrapper): Ditto.
|
||||
(awatch_command_wrapper): Ditto.
|
||||
(save_breakpoints): Update breakpoint save condition check.
|
||||
(iterate_over_breakpoints): New function.
|
||||
* breakpoint.h: Add conditional python includes. Add py_bp_object
|
||||
and comment to struct breakpoint. Update all callers.
|
||||
* defs.h: Add PyObject definition for GDB builds without Python.
|
||||
|
||||
2010-11-10 Doug Evans <dje@google.com>
|
||||
|
||||
* python/lib/gdb/command/pretty_printers.py
|
||||
|
|
137
gdb/breakpoint.c
137
gdb/breakpoint.c
|
@ -2068,6 +2068,24 @@ reattach_breakpoints (int pid)
|
|||
|
||||
static int internal_breakpoint_number = -1;
|
||||
|
||||
/* Set the breakpoint number of B, depending on the value of INTERNAL.
|
||||
If INTERNAL is non-zero, the breakpoint number will be populated
|
||||
from internal_breakpoint_number and that variable decremented.
|
||||
Otherwis the breakpoint number will be populated from
|
||||
breakpoint_count and that value incremented. Internal breakpoints
|
||||
do not set the internal var bpnum. */
|
||||
static void
|
||||
set_breakpoint_number (int internal, struct breakpoint *b)
|
||||
{
|
||||
if (internal)
|
||||
b->number = internal_breakpoint_number--;
|
||||
else
|
||||
{
|
||||
set_breakpoint_count (breakpoint_count + 1);
|
||||
b->number = breakpoint_count;
|
||||
}
|
||||
}
|
||||
|
||||
static struct breakpoint *
|
||||
create_internal_breakpoint (struct gdbarch *gdbarch,
|
||||
CORE_ADDR address, enum bptype type)
|
||||
|
@ -4939,7 +4957,8 @@ breakpoint_1 (int bnum, int allflag, int (*filter) (const struct breakpoint *))
|
|||
if (filter && !filter (b))
|
||||
continue;
|
||||
|
||||
if (allflag || user_settable_breakpoint (b))
|
||||
if (allflag || (user_settable_breakpoint (b)
|
||||
&& b->number > 0))
|
||||
{
|
||||
int addr_bit, type_len;
|
||||
|
||||
|
@ -5007,7 +5026,8 @@ breakpoint_1 (int bnum, int allflag, int (*filter) (const struct breakpoint *))
|
|||
|
||||
/* We only print out user settable breakpoints unless the
|
||||
allflag is set. */
|
||||
if (allflag || user_settable_breakpoint (b))
|
||||
if (allflag || (user_settable_breakpoint (b)
|
||||
&& b->number > 0))
|
||||
print_one_breakpoint (b, &last_loc, print_address_bits, allflag);
|
||||
}
|
||||
}
|
||||
|
@ -5456,6 +5476,7 @@ set_raw_breakpoint_without_location (struct gdbarch *gdbarch,
|
|||
b->syscalls_to_be_caught = NULL;
|
||||
b->ops = NULL;
|
||||
b->condition_not_parsed = 0;
|
||||
b->py_bp_object = NULL;
|
||||
|
||||
/* Add this breakpoint to the end of the chain
|
||||
so that a list of breakpoints will come out in order
|
||||
|
@ -6914,7 +6935,8 @@ create_breakpoint_sal (struct gdbarch *gdbarch,
|
|||
char *cond_string,
|
||||
enum bptype type, enum bpdisp disposition,
|
||||
int thread, int task, int ignore_count,
|
||||
struct breakpoint_ops *ops, int from_tty, int enabled)
|
||||
struct breakpoint_ops *ops, int from_tty,
|
||||
int enabled, int internal)
|
||||
{
|
||||
struct breakpoint *b = NULL;
|
||||
int i;
|
||||
|
@ -6951,8 +6973,7 @@ create_breakpoint_sal (struct gdbarch *gdbarch,
|
|||
if (i == 0)
|
||||
{
|
||||
b = set_raw_breakpoint (gdbarch, sal, type);
|
||||
set_breakpoint_count (breakpoint_count + 1);
|
||||
b->number = breakpoint_count;
|
||||
set_breakpoint_number (internal, b);
|
||||
b->thread = thread;
|
||||
b->task = task;
|
||||
|
||||
|
@ -7034,7 +7055,12 @@ Couldn't determine the static tracepoint marker to probe"));
|
|||
= xstrprintf ("*%s", paddress (b->loc->gdbarch, b->loc->address));
|
||||
|
||||
b->ops = ops;
|
||||
mention (b);
|
||||
if (internal)
|
||||
/* Do not mention breakpoints with a negative number, but do
|
||||
notify observers. */
|
||||
observer_notify_breakpoint_created (b->number);
|
||||
else
|
||||
mention (b);
|
||||
}
|
||||
|
||||
/* Remove element at INDEX_TO_REMOVE from SAL, shifting other
|
||||
|
@ -7190,7 +7216,7 @@ create_breakpoints_sal (struct gdbarch *gdbarch,
|
|||
enum bptype type, enum bpdisp disposition,
|
||||
int thread, int task, int ignore_count,
|
||||
struct breakpoint_ops *ops, int from_tty,
|
||||
int enabled)
|
||||
int enabled, int internal)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -7201,7 +7227,8 @@ create_breakpoints_sal (struct gdbarch *gdbarch,
|
|||
|
||||
create_breakpoint_sal (gdbarch, expanded, addr_string[i],
|
||||
cond_string, type, disposition,
|
||||
thread, task, ignore_count, ops, from_tty, enabled);
|
||||
thread, task, ignore_count, ops,
|
||||
from_tty, enabled, internal);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7470,8 +7497,10 @@ decode_static_tracepoint_spec (char **arg_p)
|
|||
parameter. If non-zero, the function will parse arg, extracting
|
||||
breakpoint location, address and thread. Otherwise, ARG is just the
|
||||
location of breakpoint, with condition and thread specified by the
|
||||
COND_STRING and THREAD parameters. Returns true if any breakpoint
|
||||
was created; false otherwise. */
|
||||
COND_STRING and THREAD parameters. If INTERNAL is non-zero, the
|
||||
breakpoint number will be allocated from the internal breakpoint
|
||||
count. Returns true if any breakpoint was created; false
|
||||
otherwise. */
|
||||
|
||||
int
|
||||
create_breakpoint (struct gdbarch *gdbarch,
|
||||
|
@ -7481,8 +7510,7 @@ create_breakpoint (struct gdbarch *gdbarch,
|
|||
int ignore_count,
|
||||
enum auto_boolean pending_break_support,
|
||||
struct breakpoint_ops *ops,
|
||||
int from_tty,
|
||||
int enabled)
|
||||
int from_tty, int enabled, int internal)
|
||||
{
|
||||
struct gdb_exception e;
|
||||
struct symtabs_and_lines sals;
|
||||
|
@ -7658,12 +7686,15 @@ create_breakpoint (struct gdbarch *gdbarch,
|
|||
cond_string, type_wanted,
|
||||
tempflag ? disp_del : disp_donttouch,
|
||||
thread, task, ignore_count, ops,
|
||||
from_tty, enabled);
|
||||
from_tty, enabled, internal);
|
||||
|
||||
do_cleanups (old_chain);
|
||||
|
||||
/* Get the tracepoint we just created. */
|
||||
tp = get_breakpoint (breakpoint_count);
|
||||
if (internal)
|
||||
tp = get_breakpoint (internal_breakpoint_number);
|
||||
else
|
||||
tp = get_breakpoint (breakpoint_count);
|
||||
gdb_assert (tp != NULL);
|
||||
|
||||
/* Given that its possible to have multiple markers with
|
||||
|
@ -7679,7 +7710,7 @@ create_breakpoint (struct gdbarch *gdbarch,
|
|||
create_breakpoints_sal (gdbarch, sals, addr_string, cond_string,
|
||||
type_wanted, tempflag ? disp_del : disp_donttouch,
|
||||
thread, task, ignore_count, ops, from_tty,
|
||||
enabled);
|
||||
enabled, internal);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -7688,8 +7719,7 @@ create_breakpoint (struct gdbarch *gdbarch,
|
|||
make_cleanup (xfree, copy_arg);
|
||||
|
||||
b = set_raw_breakpoint_without_location (gdbarch, type_wanted);
|
||||
set_breakpoint_count (breakpoint_count + 1);
|
||||
b->number = breakpoint_count;
|
||||
set_breakpoint_number (internal, b);
|
||||
b->thread = -1;
|
||||
b->addr_string = addr_string[0];
|
||||
b->cond_string = NULL;
|
||||
|
@ -7699,13 +7729,19 @@ create_breakpoint (struct gdbarch *gdbarch,
|
|||
b->ops = ops;
|
||||
b->enable_state = enabled ? bp_enabled : bp_disabled;
|
||||
b->pspace = current_program_space;
|
||||
b->py_bp_object = NULL;
|
||||
|
||||
if (enabled && b->pspace->executing_startup
|
||||
&& (b->type == bp_breakpoint
|
||||
|| b->type == bp_hardware_breakpoint))
|
||||
b->enable_state = bp_startup_disabled;
|
||||
|
||||
mention (b);
|
||||
if (internal)
|
||||
/* Do not mention breakpoints with a negative number,
|
||||
but do notify observers. */
|
||||
observer_notify_breakpoint_created (b->number);
|
||||
else
|
||||
mention (b);
|
||||
}
|
||||
|
||||
if (sals.nelts > 1)
|
||||
|
@ -7750,7 +7786,8 @@ break_command_1 (char *arg, int flag, int from_tty)
|
|||
pending_break_support,
|
||||
NULL /* breakpoint_ops */,
|
||||
from_tty,
|
||||
1 /* enabled */);
|
||||
1 /* enabled */,
|
||||
0 /* internal */);
|
||||
}
|
||||
|
||||
|
||||
|
@ -8017,7 +8054,8 @@ watchpoint_exp_is_const (const struct expression *exp)
|
|||
hw_read: watch read,
|
||||
hw_access: watch access (read or write) */
|
||||
static void
|
||||
watch_command_1 (char *arg, int accessflag, int from_tty, int just_location)
|
||||
watch_command_1 (char *arg, int accessflag, int from_tty,
|
||||
int just_location, int internal)
|
||||
{
|
||||
struct breakpoint *b, *scope_breakpoint = NULL;
|
||||
struct expression *exp;
|
||||
|
@ -8225,8 +8263,7 @@ watch_command_1 (char *arg, int accessflag, int from_tty, int just_location)
|
|||
|
||||
/* Now set up the breakpoint. */
|
||||
b = set_raw_breakpoint_without_location (NULL, bp_type);
|
||||
set_breakpoint_count (breakpoint_count + 1);
|
||||
b->number = breakpoint_count;
|
||||
set_breakpoint_number (internal, b);
|
||||
b->thread = thread;
|
||||
b->disposition = disp_donttouch;
|
||||
b->exp = exp;
|
||||
|
@ -8285,8 +8322,12 @@ watch_command_1 (char *arg, int accessflag, int from_tty, int just_location)
|
|||
/* Finally update the new watchpoint. This creates the locations
|
||||
that should be inserted. */
|
||||
update_watchpoint (b, 1);
|
||||
|
||||
mention (b);
|
||||
if (internal)
|
||||
/* Do not mention breakpoints with a negative number, but do
|
||||
notify observers. */
|
||||
observer_notify_breakpoint_created (b->number);
|
||||
else
|
||||
mention (b);
|
||||
update_global_location_list (1);
|
||||
}
|
||||
|
||||
|
@ -8370,9 +8411,9 @@ can_use_hardware_watchpoint (struct value *v)
|
|||
}
|
||||
|
||||
void
|
||||
watch_command_wrapper (char *arg, int from_tty)
|
||||
watch_command_wrapper (char *arg, int from_tty, int internal)
|
||||
{
|
||||
watch_command_1 (arg, hw_write, from_tty, 0);
|
||||
watch_command_1 (arg, hw_write, from_tty, 0, internal);
|
||||
}
|
||||
|
||||
/* A helper function that looks for an argument at the start of a
|
||||
|
@ -8408,7 +8449,7 @@ watch_maybe_just_location (char *arg, int accessflag, int from_tty)
|
|||
just_location = 1;
|
||||
}
|
||||
|
||||
watch_command_1 (arg, accessflag, from_tty, just_location);
|
||||
watch_command_1 (arg, accessflag, from_tty, just_location, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -8418,9 +8459,9 @@ watch_command (char *arg, int from_tty)
|
|||
}
|
||||
|
||||
void
|
||||
rwatch_command_wrapper (char *arg, int from_tty)
|
||||
rwatch_command_wrapper (char *arg, int from_tty, int internal)
|
||||
{
|
||||
watch_command_1 (arg, hw_read, from_tty, 0);
|
||||
watch_command_1 (arg, hw_read, from_tty, 0, internal);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -8430,9 +8471,9 @@ rwatch_command (char *arg, int from_tty)
|
|||
}
|
||||
|
||||
void
|
||||
awatch_command_wrapper (char *arg, int from_tty)
|
||||
awatch_command_wrapper (char *arg, int from_tty, int internal)
|
||||
{
|
||||
watch_command_1 (arg, hw_access, from_tty, 0);
|
||||
watch_command_1 (arg, hw_access, from_tty, 0, internal);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -8790,7 +8831,8 @@ handle_gnu_v3_exceptions (int tempflag, char *cond_string,
|
|||
0,
|
||||
AUTO_BOOLEAN_TRUE /* pending */,
|
||||
&gnu_v3_exception_catchpoint_ops, from_tty,
|
||||
1 /* enabled */);
|
||||
1 /* enabled */,
|
||||
0 /* internal */);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -11010,7 +11052,8 @@ trace_command (char *arg, int from_tty)
|
|||
pending_break_support,
|
||||
NULL,
|
||||
from_tty,
|
||||
1 /* enabled */))
|
||||
1 /* enabled */,
|
||||
0 /* internal */))
|
||||
set_tracepoint_count (breakpoint_count);
|
||||
}
|
||||
|
||||
|
@ -11026,7 +11069,8 @@ ftrace_command (char *arg, int from_tty)
|
|||
pending_break_support,
|
||||
NULL,
|
||||
from_tty,
|
||||
1 /* enabled */))
|
||||
1 /* enabled */,
|
||||
0 /* internal */))
|
||||
set_tracepoint_count (breakpoint_count);
|
||||
}
|
||||
|
||||
|
@ -11044,7 +11088,8 @@ strace_command (char *arg, int from_tty)
|
|||
pending_break_support,
|
||||
NULL,
|
||||
from_tty,
|
||||
1 /* enabled */))
|
||||
1 /* enabled */,
|
||||
0 /* internal */))
|
||||
set_tracepoint_count (breakpoint_count);
|
||||
}
|
||||
|
||||
|
@ -11106,7 +11151,8 @@ create_tracepoint_from_upload (struct uploaded_tp *utp)
|
|||
pending_break_support,
|
||||
NULL,
|
||||
0 /* from_tty */,
|
||||
utp->enabled /* enabled */))
|
||||
utp->enabled /* enabled */,
|
||||
0 /* internal */))
|
||||
return NULL;
|
||||
|
||||
set_tracepoint_count (breakpoint_count);
|
||||
|
@ -11372,7 +11418,7 @@ save_breakpoints (char *filename, int from_tty,
|
|||
ALL_BREAKPOINTS (tp)
|
||||
{
|
||||
/* Skip internal and momentary breakpoints. */
|
||||
if (!user_settable_breakpoint (tp))
|
||||
if (!user_settable_breakpoint (tp) || tp->number < 0)
|
||||
continue;
|
||||
|
||||
/* If we have a filter, only save the breakpoints it accepts. */
|
||||
|
@ -11410,7 +11456,7 @@ save_breakpoints (char *filename, int from_tty,
|
|||
ALL_BREAKPOINTS (tp)
|
||||
{
|
||||
/* Skip internal and momentary breakpoints. */
|
||||
if (!user_settable_breakpoint (tp))
|
||||
if (!user_settable_breakpoint (tp) || tp->number < 0)
|
||||
continue;
|
||||
|
||||
/* If we have a filter, only save the breakpoints it accepts. */
|
||||
|
@ -11627,6 +11673,21 @@ save_command (char *arg, int from_tty)
|
|||
help_list (save_cmdlist, "save ", -1, gdb_stdout);
|
||||
}
|
||||
|
||||
struct breakpoint *
|
||||
iterate_over_breakpoints (int (*callback) (struct breakpoint *, void *),
|
||||
void *data)
|
||||
{
|
||||
struct breakpoint *b, *temp;
|
||||
|
||||
ALL_BREAKPOINTS_SAFE (b, temp)
|
||||
{
|
||||
if ((*callback) (b, data))
|
||||
return b;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_breakpoint (void)
|
||||
{
|
||||
|
|
|
@ -24,6 +24,11 @@
|
|||
#include "value.h"
|
||||
#include "vec.h"
|
||||
|
||||
#if HAVE_PYTHON
|
||||
#include "python/python.h"
|
||||
#include "python/python-internal.h"
|
||||
#endif
|
||||
|
||||
struct value;
|
||||
struct block;
|
||||
|
||||
|
@ -557,7 +562,14 @@ struct breakpoint
|
|||
breakpoints, we will use this index to try to find the same
|
||||
marker again. */
|
||||
int static_trace_marker_id_idx;
|
||||
};
|
||||
|
||||
/* With a Python scripting enabled GDB, store a reference to the
|
||||
Python object that has been associated with this breakpoint.
|
||||
This is always NULL for a GDB that is not script enabled. It
|
||||
can sometimes be NULL for enabled GDBs as not all breakpoint
|
||||
types are tracked by the Python scripting API. */
|
||||
PyObject *py_bp_object;
|
||||
};
|
||||
|
||||
typedef struct breakpoint *breakpoint_p;
|
||||
DEF_VEC_P(breakpoint_p);
|
||||
|
@ -855,9 +867,9 @@ extern void break_command (char *, int);
|
|||
extern void hbreak_command_wrapper (char *, int);
|
||||
extern void thbreak_command_wrapper (char *, int);
|
||||
extern void rbreak_command_wrapper (char *, int);
|
||||
extern void watch_command_wrapper (char *, int);
|
||||
extern void awatch_command_wrapper (char *, int);
|
||||
extern void rwatch_command_wrapper (char *, int);
|
||||
extern void watch_command_wrapper (char *, int, int);
|
||||
extern void awatch_command_wrapper (char *, int, int);
|
||||
extern void rwatch_command_wrapper (char *, int, int);
|
||||
extern void tbreak_command (char *, int);
|
||||
|
||||
extern int create_breakpoint (struct gdbarch *gdbarch, char *arg,
|
||||
|
@ -868,7 +880,8 @@ extern int create_breakpoint (struct gdbarch *gdbarch, char *arg,
|
|||
enum auto_boolean pending_break_support,
|
||||
struct breakpoint_ops *ops,
|
||||
int from_tty,
|
||||
int enabled);
|
||||
int enabled,
|
||||
int internal);
|
||||
|
||||
extern void insert_breakpoints (void);
|
||||
|
||||
|
@ -1101,4 +1114,15 @@ extern void check_tracepoint_command (char *line, void *closure);
|
|||
extern void start_rbreak_breakpoints (void);
|
||||
extern void end_rbreak_breakpoints (void);
|
||||
|
||||
/* Breakpoint iterator function.
|
||||
|
||||
Calls a callback function once for each breakpoint, so long as the
|
||||
callback function returns false. If the callback function returns
|
||||
true, the iteration will end and the current breakpoint will be
|
||||
returned. This can be useful for implementing a search for a
|
||||
breakpoint with arbitrary attributes, or for applying an operation
|
||||
to every breakpoint. */
|
||||
extern struct breakpoint *iterate_over_breakpoints (int (*) (struct breakpoint *,
|
||||
void *), void *);
|
||||
|
||||
#endif /* !defined (BREAKPOINT_H) */
|
||||
|
|
|
@ -1240,4 +1240,8 @@ void dummy_obstack_deallocate (void *object, void *data);
|
|||
extern void initialize_progspace (void);
|
||||
extern void initialize_inferiors (void);
|
||||
|
||||
#ifndef HAVE_PYTHON
|
||||
typedef int PyObject;
|
||||
#endif
|
||||
|
||||
#endif /* #ifndef DEFS_H */
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2010-11-11 Phil Muldoon <pmuldoon@redhat.com>
|
||||
|
||||
* gdb.texinfo (Breakpoints In Python): Document "internal"
|
||||
parameter, and visible attribute.
|
||||
|
||||
2010-11-05 Doug Evans <dje@google.com>
|
||||
|
||||
* gdb.texinfo (Source Path): Document "set directories".
|
||||
|
|
|
@ -22823,7 +22823,7 @@ Return the symbol table's source absolute file name.
|
|||
Python code can manipulate breakpoints via the @code{gdb.Breakpoint}
|
||||
class.
|
||||
|
||||
@defmethod Breakpoint __init__ spec @r{[}type@r{]} @r{[}wp_class@r{]}
|
||||
@defmethod Breakpoint __init__ spec @r{[}type@r{]} @r{[}wp_class@r{]} @r{[}internal@r{]}
|
||||
Create a new breakpoint. @var{spec} is a string naming the
|
||||
location of the breakpoint, or an expression that defines a
|
||||
watchpoint. The contents can be any location recognized by the
|
||||
|
@ -22831,10 +22831,14 @@ watchpoint. The contents can be any location recognized by the
|
|||
command. The optional @var{type} denotes the breakpoint to create
|
||||
from the types defined later in this chapter. This argument can be
|
||||
either: @code{BP_BREAKPOINT} or @code{BP_WATCHPOINT}. @var{type}
|
||||
defaults to @code{BP_BREAKPOINT}. The optional @var{wp_class}
|
||||
defaults to @code{BP_BREAKPOINT}. The optional @var{internal} argument
|
||||
allows the breakpoint to become invisible to the user. The breakpoint
|
||||
will neither be reported when created, nor will it be listed in the
|
||||
output from @code{info breakpoints} (but will be listed with the
|
||||
@code{maint info breakpoints} command). The optional @var{wp_class}
|
||||
argument defines the class of watchpoint to create, if @var{type} is
|
||||
defined as @code{BP_WATCHPOINT}. If a watchpoint class is not
|
||||
provided, it is assumed to be a @var{WP_WRITE} class.
|
||||
@code{BP_WATCHPOINT}. If a watchpoint class is not provided, it is
|
||||
assumed to be a @var{WP_WRITE} class.
|
||||
@end defmethod
|
||||
|
||||
The available watchpoint types represented by constants are defined in the
|
||||
|
@ -22909,6 +22913,12 @@ determine the actual breakpoint type or use-case. This attribute is not
|
|||
writable.
|
||||
@end defivar
|
||||
|
||||
@defivar Breakpoint visible
|
||||
This attribute tells whether the breakpoint is visible to the user
|
||||
when set, or when the @samp{info breakpoints} command is run. This
|
||||
attribute is not writable.
|
||||
@end defivar
|
||||
|
||||
The available types are represented by constants defined in the @code{gdb}
|
||||
module:
|
||||
|
||||
|
|
|
@ -169,7 +169,7 @@ mi_cmd_break_insert (char *command, char **argv, int argc)
|
|||
temp_p, type_wanted,
|
||||
ignore_count,
|
||||
pending ? AUTO_BOOLEAN_TRUE : AUTO_BOOLEAN_FALSE,
|
||||
NULL, 0, enabled);
|
||||
NULL, 0, enabled, 0);
|
||||
do_cleanups (back_to);
|
||||
|
||||
}
|
||||
|
@ -259,13 +259,13 @@ mi_cmd_break_watch (char *command, char **argv, int argc)
|
|||
switch (type)
|
||||
{
|
||||
case REG_WP:
|
||||
watch_command_wrapper (expr, FROM_TTY);
|
||||
watch_command_wrapper (expr, FROM_TTY, 0);
|
||||
break;
|
||||
case READ_WP:
|
||||
rwatch_command_wrapper (expr, FROM_TTY);
|
||||
rwatch_command_wrapper (expr, FROM_TTY, 0);
|
||||
break;
|
||||
case ACCESS_WP:
|
||||
awatch_command_wrapper (expr, FROM_TTY);
|
||||
awatch_command_wrapper (expr, FROM_TTY, 0);
|
||||
break;
|
||||
default:
|
||||
error (_("mi_cmd_break_watch: Unknown watchpoint type."));
|
||||
|
|
|
@ -34,17 +34,6 @@ typedef struct breakpoint_object breakpoint_object;
|
|||
|
||||
static PyTypeObject breakpoint_object_type;
|
||||
|
||||
/* A dynamically allocated vector of breakpoint objects. Each
|
||||
breakpoint has a number. A breakpoint is valid if its slot in this
|
||||
vector is non-null. When a breakpoint is deleted, we drop our
|
||||
reference to it and zero its slot; this is how we let the Python
|
||||
object have a lifetime which is independent from that of the gdb
|
||||
breakpoint. */
|
||||
static breakpoint_object **bppy_breakpoints;
|
||||
|
||||
/* Number of slots in bppy_breakpoints. */
|
||||
static int bppy_slots;
|
||||
|
||||
/* Number of live breakpoints. */
|
||||
static int bppy_live;
|
||||
|
||||
|
@ -68,7 +57,7 @@ struct breakpoint_object
|
|||
exception if it is invalid. */
|
||||
#define BPPY_REQUIRE_VALID(Breakpoint) \
|
||||
do { \
|
||||
if (! bpnum_is_valid ((Breakpoint)->number)) \
|
||||
if ((Breakpoint)->bp == NULL) \
|
||||
return PyErr_Format (PyExc_RuntimeError, _("Breakpoint %d is invalid."), \
|
||||
(Breakpoint)->number); \
|
||||
} while (0)
|
||||
|
@ -77,7 +66,7 @@ struct breakpoint_object
|
|||
exception if it is invalid. This macro is for use in setter functions. */
|
||||
#define BPPY_SET_REQUIRE_VALID(Breakpoint) \
|
||||
do { \
|
||||
if (! bpnum_is_valid ((Breakpoint)->number)) \
|
||||
if ((Breakpoint)->bp == NULL) \
|
||||
{ \
|
||||
PyErr_Format (PyExc_RuntimeError, _("Breakpoint %d is invalid."), \
|
||||
(Breakpoint)->number); \
|
||||
|
@ -115,18 +104,6 @@ static struct pybp_code pybp_watch_types[] =
|
|||
{NULL} /* Sentinel. */
|
||||
};
|
||||
|
||||
/* Evaluate to true if the breakpoint NUM is valid, false otherwise. */
|
||||
static int
|
||||
bpnum_is_valid (int num)
|
||||
{
|
||||
if (num >=0
|
||||
&& num < bppy_slots
|
||||
&& bppy_breakpoints[num] != NULL)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Python function which checks the validity of a breakpoint object. */
|
||||
static PyObject *
|
||||
bppy_is_valid (PyObject *self, PyObject *args)
|
||||
|
@ -503,6 +480,21 @@ bppy_get_type (PyObject *self, void *closure)
|
|||
return PyInt_FromLong (self_bp->bp->type);
|
||||
}
|
||||
|
||||
/* Python function to get the visibility of the breakpoint. */
|
||||
|
||||
static PyObject *
|
||||
bppy_get_visibility (PyObject *self, void *closure)
|
||||
{
|
||||
breakpoint_object *self_bp = (breakpoint_object *) self;
|
||||
|
||||
BPPY_REQUIRE_VALID (self_bp);
|
||||
|
||||
if (self_bp->bp->number < 0)
|
||||
Py_RETURN_FALSE;
|
||||
|
||||
Py_RETURN_TRUE;
|
||||
}
|
||||
|
||||
/* Python function to get the breakpoint's number. */
|
||||
static PyObject *
|
||||
bppy_get_number (PyObject *self, void *closure)
|
||||
|
@ -569,16 +561,25 @@ static PyObject *
|
|||
bppy_new (PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
PyObject *result;
|
||||
static char *keywords[] = { "spec", "type", "wp_class", NULL };
|
||||
static char *keywords[] = { "spec", "type", "wp_class", "internal", NULL };
|
||||
char *spec;
|
||||
int type = bp_breakpoint;
|
||||
int access_type = hw_write;
|
||||
PyObject *internal = NULL;
|
||||
int internal_bp = 0;
|
||||
volatile struct gdb_exception except;
|
||||
|
||||
if (! PyArg_ParseTupleAndKeywords (args, kwargs, "s|ii", keywords,
|
||||
&spec, &type, &access_type))
|
||||
if (! PyArg_ParseTupleAndKeywords (args, kwargs, "s|iiO", keywords,
|
||||
&spec, &type, &access_type, &internal))
|
||||
return NULL;
|
||||
|
||||
if (internal)
|
||||
{
|
||||
internal_bp = PyObject_IsTrue (internal);
|
||||
if (internal_bp == -1)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = subtype->tp_alloc (subtype, 0);
|
||||
if (! result)
|
||||
return NULL;
|
||||
|
@ -598,17 +599,17 @@ bppy_new (PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
|
|||
0, bp_breakpoint,
|
||||
0,
|
||||
AUTO_BOOLEAN_TRUE,
|
||||
NULL, 0, 1);
|
||||
NULL, 0, 1, internal_bp);
|
||||
break;
|
||||
}
|
||||
case bp_watchpoint:
|
||||
{
|
||||
if (access_type == hw_write)
|
||||
watch_command_wrapper (spec, 0);
|
||||
watch_command_wrapper (spec, 0, internal_bp);
|
||||
else if (access_type == hw_access)
|
||||
awatch_command_wrapper (spec, 0);
|
||||
awatch_command_wrapper (spec, 0, internal_bp);
|
||||
else if (access_type == hw_read)
|
||||
rwatch_command_wrapper (spec, 0);
|
||||
rwatch_command_wrapper (spec, 0, internal_bp);
|
||||
else
|
||||
error(_("Cannot understand watchpoint access type."));
|
||||
break;
|
||||
|
@ -631,31 +632,50 @@ bppy_new (PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
|
|||
|
||||
|
||||
|
||||
static int
|
||||
build_bp_list (struct breakpoint *b, void *arg)
|
||||
{
|
||||
PyObject *list = arg;
|
||||
PyObject *bp = b->py_bp_object;
|
||||
int iserr = 0;
|
||||
|
||||
/* Not all breakpoints will have a companion Python object.
|
||||
Only breakpoints that were created via bppy_new, or
|
||||
breakpoints that were created externally and are tracked by
|
||||
the Python Scripting API. */
|
||||
if (bp)
|
||||
iserr = PyList_Append (list, bp);
|
||||
|
||||
if (iserr == -1)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Static function to return a tuple holding all breakpoints. */
|
||||
|
||||
PyObject *
|
||||
gdbpy_breakpoints (PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *result;
|
||||
PyObject *list;
|
||||
|
||||
if (bppy_live == 0)
|
||||
Py_RETURN_NONE;
|
||||
|
||||
result = PyTuple_New (bppy_live);
|
||||
if (result)
|
||||
{
|
||||
int i, out = 0;
|
||||
list = PyList_New (0);
|
||||
if (!list)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; out < bppy_live; ++i)
|
||||
{
|
||||
if (! bppy_breakpoints[i])
|
||||
continue;
|
||||
Py_INCREF (bppy_breakpoints[i]);
|
||||
PyTuple_SetItem (result, out, (PyObject *) bppy_breakpoints[i]);
|
||||
++out;
|
||||
}
|
||||
/* If iteratre_over_breakpoints returns non NULL it signals an error
|
||||
condition. In that case abandon building the list and return
|
||||
NULL. */
|
||||
if (iterate_over_breakpoints (build_bp_list, list) != NULL)
|
||||
{
|
||||
Py_DECREF (list);
|
||||
return NULL;
|
||||
}
|
||||
return result;
|
||||
|
||||
return PyList_AsTuple (list);
|
||||
}
|
||||
|
||||
|
||||
|
@ -671,13 +691,13 @@ gdbpy_breakpoint_created (int num)
|
|||
struct breakpoint *bp = NULL;
|
||||
PyGILState_STATE state;
|
||||
|
||||
if (num < 0)
|
||||
return;
|
||||
|
||||
bp = get_breakpoint (num);
|
||||
if (! bp)
|
||||
return;
|
||||
|
||||
if (num < 0 && bppy_pending_object == NULL)
|
||||
return;
|
||||
|
||||
if (bp->type != bp_breakpoint
|
||||
&& bp->type != bp_watchpoint
|
||||
&& bp->type != bp_hardware_watchpoint
|
||||
|
@ -685,21 +705,6 @@ gdbpy_breakpoint_created (int num)
|
|||
&& bp->type != bp_access_watchpoint)
|
||||
return;
|
||||
|
||||
if (num >= bppy_slots)
|
||||
{
|
||||
int old = bppy_slots;
|
||||
|
||||
bppy_slots = bppy_slots * 2 + 10;
|
||||
bppy_breakpoints
|
||||
= (breakpoint_object **) xrealloc (bppy_breakpoints,
|
||||
(bppy_slots
|
||||
* sizeof (breakpoint_object *)));
|
||||
memset (&bppy_breakpoints[old], 0,
|
||||
(bppy_slots - old) * sizeof (PyObject *));
|
||||
}
|
||||
|
||||
++bppy_live;
|
||||
|
||||
state = PyGILState_Ensure ();
|
||||
|
||||
if (bppy_pending_object)
|
||||
|
@ -713,12 +718,16 @@ gdbpy_breakpoint_created (int num)
|
|||
{
|
||||
newbp->number = num;
|
||||
newbp->bp = bp;
|
||||
bppy_breakpoints[num] = newbp;
|
||||
newbp->bp->py_bp_object = (PyObject *) newbp;
|
||||
Py_INCREF (newbp);
|
||||
++bppy_live;
|
||||
}
|
||||
else
|
||||
{
|
||||
PyErr_SetString (PyExc_RuntimeError,
|
||||
_("Error while creating breakpoint from GDB."));
|
||||
gdbpy_print_stack ();
|
||||
}
|
||||
|
||||
/* Just ignore errors here. */
|
||||
PyErr_Clear ();
|
||||
|
||||
PyGILState_Release (state);
|
||||
}
|
||||
|
@ -729,14 +738,20 @@ static void
|
|||
gdbpy_breakpoint_deleted (int num)
|
||||
{
|
||||
PyGILState_STATE state;
|
||||
struct breakpoint *bp = NULL;
|
||||
breakpoint_object *bp_obj;
|
||||
|
||||
state = PyGILState_Ensure ();
|
||||
if (bpnum_is_valid (num))
|
||||
bp = get_breakpoint (num);
|
||||
if (! bp)
|
||||
return;
|
||||
|
||||
bp_obj = ((breakpoint_object *) bp->py_bp_object);
|
||||
if (bp_obj)
|
||||
{
|
||||
bppy_breakpoints[num]->bp = NULL;
|
||||
Py_DECREF (bppy_breakpoints[num]);
|
||||
bppy_breakpoints[num] = NULL;
|
||||
bp_obj->bp = NULL;
|
||||
--bppy_live;
|
||||
Py_DECREF (bp_obj);
|
||||
}
|
||||
PyGILState_Release (state);
|
||||
}
|
||||
|
@ -819,6 +834,8 @@ or None if no condition set."},
|
|||
"Commands of the breakpoint, as specified by the user."},
|
||||
{ "type", bppy_get_type, NULL,
|
||||
"Type of breakpoint."},
|
||||
{ "visible", bppy_get_visibility, NULL,
|
||||
"Whether the breakpoint is visible to the user."},
|
||||
{ NULL } /* Sentinel. */
|
||||
};
|
||||
|
||||
|
|
|
@ -1895,7 +1895,8 @@ spu_catch_start (struct objfile *objfile)
|
|||
bp_breakpoint /* type_wanted */,
|
||||
0 /* ignore_count */,
|
||||
AUTO_BOOLEAN_FALSE /* pending_break_support */,
|
||||
NULL /* ops */, 0 /* from_tty */, 1 /* enabled */);
|
||||
NULL /* ops */, 0 /* from_tty */, 1 /* enabled */,
|
||||
0 /* internal */););
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2010-11-11 Phil Muldoon <pmuldoon@redhat.com>
|
||||
|
||||
* gdb.python/py-breakpoint.exp: Add internal watchpoint and
|
||||
breakpoint tests.
|
||||
|
||||
2010-11-09 Pedro Alves <pedro@codesourcery.com>
|
||||
|
||||
* gdb.base/watchpoint.exp: Test "watch -location" with an
|
||||
|
|
|
@ -117,6 +117,33 @@ gdb_test "end"
|
|||
gdb_py_test_silent_cmd "python blist = gdb.breakpoints()" "Get Breakpoint List" 0
|
||||
gdb_test "python print blist\[len(blist)-1\].commands" "print \"Command for breakpoint has been executed.\".*print result"
|
||||
|
||||
# Start with a fresh gdb.
|
||||
clean_restart ${testfile}
|
||||
|
||||
if ![runto_main] then {
|
||||
fail "Cannot run to main."
|
||||
return 0
|
||||
}
|
||||
|
||||
# Test invisible breakpooints.
|
||||
delete_breakpoints
|
||||
set ibp_location [gdb_get_line_number "Break at multiply."]
|
||||
gdb_py_test_silent_cmd "python ibp = gdb.Breakpoint(\"$ibp_location\", internal=False)" "Set invisible breakpoint" 0
|
||||
gdb_py_test_silent_cmd "python ilist = gdb.breakpoints()" "Get Breakpoint List" 0
|
||||
gdb_test "python print ilist\[0\]" "<gdb.Breakpoint object at $hex>" "Check invisible bp obj exists"
|
||||
gdb_test "python print ilist\[0\].location" "py-breakpoint\.c:$ibp_location*" "Check breakpoint location"
|
||||
gdb_test "python print ilist\[0\].visible" "True" "Check breakpoint visibility"
|
||||
gdb_test "info breakpoints" "py-breakpoint\.c:$ibp_location.*" "Check info breakpoints shows visible breakpoints"
|
||||
delete_breakpoints
|
||||
gdb_py_test_silent_cmd "python ibp = gdb.Breakpoint(\"$ibp_location\", internal=True)" "Set invisible breakpoint" 0
|
||||
gdb_py_test_silent_cmd "python ilist = gdb.breakpoints()" "Get Breakpoint List" 0
|
||||
gdb_test "python print ilist\[0\]" "<gdb.Breakpoint object at $hex>" "Check invisible bp obj exists"
|
||||
gdb_test "python print ilist\[0\].location" "py-breakpoint\.c:$ibp_location*" "Check breakpoint location"
|
||||
gdb_test "python print ilist\[0\].visible" "False" "Check breakpoint visibility"
|
||||
gdb_test "info breakpoints" "No breakpoints or watchpoints.*" "Check info breakpoints does not show invisible breakpoints"
|
||||
gdb_test "maint info breakpoints" "py-breakpoint\.c:$ibp_location.*" "Check maint info breakpoints shows invisible breakpoints"
|
||||
|
||||
|
||||
# Watchpoints
|
||||
# Start with a fresh gdb.
|
||||
clean_restart ${testfile}
|
||||
|
@ -134,5 +161,17 @@ if ![runto_main] then {
|
|||
gdb_py_test_silent_cmd "python wp1 = gdb.Breakpoint (\"result\", type=gdb.BP_WATCHPOINT, wp_class=gdb.WP_WRITE )" "Set watchpoint" 0
|
||||
gdb_test "continue" ".*\[Ww\]atchpoint.*result.*Old value = 0.*New value = 25.*main.*" "Test watchpoint write"
|
||||
|
||||
# Internal breakpoints.
|
||||
|
||||
# Start with a fresh gdb.
|
||||
clean_restart ${testfile}
|
||||
|
||||
if ![runto_main] then {
|
||||
fail "Cannot run to main."
|
||||
return 0
|
||||
}
|
||||
delete_breakpoints
|
||||
gdb_py_test_silent_cmd "python wp1 = gdb.Breakpoint (\"result\", type=gdb.BP_WATCHPOINT, wp_class=gdb.WP_WRITE, internal=True )" "Set watchpoint" 0
|
||||
gdb_test "info breakpoints" "No breakpoints or watchpoints.*" "Check info breakpoints does not show invisible breakpoints"
|
||||
gdb_test "maint info breakpoints" ".*hw watchpoint.*result.*" "Check maint info breakpoints shows invisible breakpoints"
|
||||
gdb_test "continue" ".*\[Ww\]atchpoint.*result.*Old value = 0.*New value = 25.*" "Test watchpoint write"
|
||||
|
|
|
@ -39,8 +39,6 @@
|
|||
#if HAVE_PYTHON
|
||||
#include "python/python.h"
|
||||
#include "python/python-internal.h"
|
||||
#else
|
||||
typedef int PyObject;
|
||||
#endif
|
||||
|
||||
/* Non-zero if we want to see trace of varobj level stuff. */
|
||||
|
|
Loading…
Reference in New Issue