2010-06-11 Stan Shebs <stan@codesourcery.com>
Add per-operation permission flags. * target.h (struct target_ops): New method to_set_permissions. (target_set_permissions): New macro. (target_insert_breakpoint): Change macro to function. (target_remove_breakpoint): Ditto. (target_stop): Ditto. (may_write_registers): Declare. (may_write_memory): Declare. (may_insert_breakpoints): Declare. (may_insert_tracepoints): Declare. (may_insert_fast_tracepoints): Declare. (may_stop): Declare. * target.c (may_write_registers, may_write_registers_1): New globals. (may_write_memory, may_write_memory_1): New globals. (may_insert_breakpoints, may_insert_breakpoints_1): New globals. (may_insert_tracepoints, may_insert_tracepoints_1): New globals. (may_insert_fast_tracepoints, may_insert_fast_tracepoints_1): New globals. (may_stop, may_stop_1): New global. (target_xfer_partial): Test for write permission. (target_store_registers): Ditto. (target_insert_breakpoint): New function. (target_remove_breakpoint): New function. (target_stop): New function. (_initialize_targets): Add new set/show variables. (set_write_memory_permission): New function. (update_target_permissions): New function. (set_target_permissions): New function. (update_current_target): Default to_set_permissions. (_initialize_targets): Use new globals and setter function. * tracepoint.c (start_tracing): Test for permission. * inferior.h (update_observer_mode): Declare. * infrun.c (non_stop_1): Define earlier. (observer_mode, observer_mode_1): New globals. (set_observer_mode, show_observer_mode): New functions. (update_observer_mode): New function. (_initialize_infrun): Define "set observer" command. * remote.c (PACKET_QAllow): New optional packet. (remote_protocol_features): Add QAllow. (remote_set_permissions): New function. (remote_start_remote): Call it. (init_remote_ops): Add it to target vector. (_initialize_remote): Add config command for QAllow. * gdb.texinfo (Observer Mode): New section. (General Query Packets): Document QAllow. * gdb.base/permissions.exp: New file.
This commit is contained in:
parent
139f2ac873
commit
d914c394a9
11 changed files with 634 additions and 12 deletions
|
@ -1,3 +1,50 @@
|
|||
2010-06-11 Stan Shebs <stan@codesourcery.com>
|
||||
|
||||
Add per-operation permission flags.
|
||||
|
||||
* target.h (struct target_ops): New method to_set_permissions.
|
||||
(target_set_permissions): New macro.
|
||||
(target_insert_breakpoint): Change macro to function.
|
||||
(target_remove_breakpoint): Ditto.
|
||||
(target_stop): Ditto.
|
||||
(may_write_registers): Declare.
|
||||
(may_write_memory): Declare.
|
||||
(may_insert_breakpoints): Declare.
|
||||
(may_insert_tracepoints): Declare.
|
||||
(may_insert_fast_tracepoints): Declare.
|
||||
(may_stop): Declare.
|
||||
* target.c (may_write_registers, may_write_registers_1): New globals.
|
||||
(may_write_memory, may_write_memory_1): New globals.
|
||||
(may_insert_breakpoints, may_insert_breakpoints_1): New globals.
|
||||
(may_insert_tracepoints, may_insert_tracepoints_1): New globals.
|
||||
(may_insert_fast_tracepoints, may_insert_fast_tracepoints_1): New
|
||||
globals.
|
||||
(may_stop, may_stop_1): New global.
|
||||
(target_xfer_partial): Test for write permission.
|
||||
(target_store_registers): Ditto.
|
||||
(target_insert_breakpoint): New function.
|
||||
(target_remove_breakpoint): New function.
|
||||
(target_stop): New function.
|
||||
(_initialize_targets): Add new set/show variables.
|
||||
(set_write_memory_permission): New function.
|
||||
(update_target_permissions): New function.
|
||||
(set_target_permissions): New function.
|
||||
(update_current_target): Default to_set_permissions.
|
||||
(_initialize_targets): Use new globals and setter function.
|
||||
* tracepoint.c (start_tracing): Test for permission.
|
||||
* inferior.h (update_observer_mode): Declare.
|
||||
* infrun.c (non_stop_1): Define earlier.
|
||||
(observer_mode, observer_mode_1): New globals.
|
||||
(set_observer_mode, show_observer_mode): New functions.
|
||||
(update_observer_mode): New function.
|
||||
(_initialize_infrun): Define "set observer" command.
|
||||
* remote.c (PACKET_QAllow): New optional packet.
|
||||
(remote_protocol_features): Add QAllow.
|
||||
(remote_set_permissions): New function.
|
||||
(remote_start_remote): Call it.
|
||||
(init_remote_ops): Add it to target vector.
|
||||
(_initialize_remote): Add config command for QAllow.
|
||||
|
||||
2010-06-11 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
* dwarf2read.c (dwarf2_add_member_fn): Handle correct form of
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2010-06-11 Stan Shebs <stan@codesourcery.com>
|
||||
|
||||
* gdb.texinfo (Observer Mode): New section.
|
||||
(General Query Packets): Document QAllow.
|
||||
|
||||
2010-06-04 Doug Evans <dje@google.com>
|
||||
|
||||
* gdb.texinfo (Python API): New node `Disabling Pretty-Printers'.
|
||||
|
|
|
@ -4958,6 +4958,7 @@ you examine the stopped thread in the debugger.
|
|||
* Background Execution:: Running your program asynchronously
|
||||
* Thread-Specific Breakpoints:: Controlling breakpoints
|
||||
* Interrupted System Calls:: GDB may interfere with system calls
|
||||
* Observer Mode:: GDB does not alter program behavior
|
||||
@end menu
|
||||
|
||||
@node All-Stop Mode
|
||||
|
@ -5318,6 +5319,103 @@ monitor certain events such as thread creation and thread destruction.
|
|||
When such an event happens, a system call in another thread may return
|
||||
prematurely, even though your program does not appear to stop.
|
||||
|
||||
@node Observer Mode
|
||||
@subsection Observer Mode
|
||||
|
||||
If you want to build on non-stop mode and observe program behavior
|
||||
without any chance of disruption by @value{GDBN}, you can set
|
||||
variables to disable all of the debugger's attempts to modify state,
|
||||
whether by writing memory, inserting breakpoints, etc. These operate
|
||||
at a low level, intercepting operations from all commands.
|
||||
|
||||
When all of these are set to @code{off}, then @value{GDBN} is said to
|
||||
be @dfn{observer mode}. As a convenience, the variable
|
||||
@code{observer} can be set to disable these, plus enable non-stop
|
||||
mode.
|
||||
|
||||
Note that @value{GDBN} will not prevent you from making nonsensical
|
||||
combinations of these settings. For instance, if you have enabled
|
||||
@code{may-insert-breakpoints} but disabled @code{may-write-memory},
|
||||
then breakpoints that work by writing trap instructions into the code
|
||||
stream will still not be able to be placed.
|
||||
|
||||
@table @code
|
||||
|
||||
@kindex observer
|
||||
@item set observer on
|
||||
@itemx set observer off
|
||||
When set to @code{on}, this disables all the permission variables
|
||||
below (except for @code{insert-fast-tracepoints}), plus enables
|
||||
non-stop debugging. Setting this to @code{off} switches back to
|
||||
normal debugging, though remaining in non-stop mode.
|
||||
|
||||
@item show observer
|
||||
Show whether observer mode is on or off.
|
||||
|
||||
@kindex may-write-registers
|
||||
@item set may-write-registers on
|
||||
@itemx set may-write-registers off
|
||||
This controls whether @value{GDBN} will attempt to alter the values of
|
||||
registers, such as with assignment expressions in @code{print}, or the
|
||||
@code{jump} command. It defaults to @code{on}.
|
||||
|
||||
@item show may-write-registers
|
||||
Show the current permission to write registers.
|
||||
|
||||
@kindex may-write-memory
|
||||
@item set may-write-memory on
|
||||
@itemx set may-write-memory off
|
||||
This controls whether @value{GDBN} will attempt to alter the contents
|
||||
of memory, such as with assignment expressions in @code{print}. It
|
||||
defaults to @code{on}.
|
||||
|
||||
@item show may-write-memory
|
||||
Show the current permission to write memory.
|
||||
|
||||
@kindex may-insert-breakpoints
|
||||
@item set may-insert-breakpoints on
|
||||
@itemx set may-insert-breakpoints off
|
||||
This controls whether @value{GDBN} will attempt to insert breakpoints.
|
||||
This affects all breakpoints, including internal breakpoints defined
|
||||
by @value{GDBN}. It defaults to @code{on}.
|
||||
|
||||
@item show may-insert-breakpoints
|
||||
Show the current permission to insert breakpoints.
|
||||
|
||||
@kindex may-insert-tracepoints
|
||||
@item set may-insert-tracepoints on
|
||||
@itemx set may-insert-tracepoints off
|
||||
This controls whether @value{GDBN} will attempt to insert (regular)
|
||||
tracepoints at the beginning of a tracing experiment. It affects only
|
||||
non-fast tracepoints, fast tracepoints being under the control of
|
||||
@code{may-insert-fast-tracepoints}. It defaults to @code{on}.
|
||||
|
||||
@item show may-insert-tracepoints
|
||||
Show the current permission to insert tracepoints.
|
||||
|
||||
@kindex may-insert-fast-tracepoints
|
||||
@item set may-insert-fast-tracepoints on
|
||||
@itemx set may-insert-fast-tracepoints off
|
||||
This controls whether @value{GDBN} will attempt to insert fast
|
||||
tracepoints at the beginning of a tracing experiment. It affects only
|
||||
fast tracepoints, regular (non-fast) tracepoints being under the
|
||||
control of @code{may-insert-tracepoints}. It defaults to @code{on}.
|
||||
|
||||
@item show may-insert-fast-tracepoints
|
||||
Show the current permission to insert fast tracepoints.
|
||||
|
||||
@kindex may-interrupt
|
||||
@item set may-interrupt on
|
||||
@itemx set may-interrupt off
|
||||
This controls whether @value{GDBN} will attempt to interrupt or stop
|
||||
program execution. When this variable is @code{off}, the
|
||||
@code{interrupt} command will have no effect, nor will
|
||||
@kbd{Ctrl-c}. It defaults to @code{on}.
|
||||
|
||||
@item show may-interrupt
|
||||
Show the current permission to interrupt or stop the program.
|
||||
|
||||
@end table
|
||||
|
||||
@node Reverse Execution
|
||||
@chapter Running programs backward
|
||||
|
@ -31190,6 +31288,18 @@ Here are the currently defined query and set packets:
|
|||
|
||||
@table @samp
|
||||
|
||||
@item QAllow:@var{op}:@var{val}@dots{}
|
||||
@cindex @samp{QAllow} packet
|
||||
Specify which operations @value{GDBN} expects to request of the
|
||||
target, as a semicolon-separated list of operation name and value
|
||||
pairs. Possible values for @var{op} include @samp{WriteReg},
|
||||
@samp{WriteMem}, @samp{InsertBreak}, @samp{InsertTrace},
|
||||
@samp{InsertFastTrace}, and @samp{Stop}. @var{val} is either 0,
|
||||
indicating that @value{GDBN} will not request the operation, or 1,
|
||||
indicating that it may. (The target can then use this to set up its
|
||||
own internals optimally, for instance if the debugger never expects to
|
||||
insert breakpoints, it may not need to install its own trap handler.)
|
||||
|
||||
@item qC
|
||||
@cindex current thread, remote request
|
||||
@cindex @samp{qC} packet
|
||||
|
@ -31711,6 +31821,11 @@ These are the currently defined stub features and their properties:
|
|||
@tab @samp{-}
|
||||
@tab No
|
||||
|
||||
@item @samp{QAllow}
|
||||
@tab No
|
||||
@tab @samp{-}
|
||||
@tab No
|
||||
|
||||
@end multitable
|
||||
|
||||
These are the currently defined stub features, in more detail:
|
||||
|
@ -31808,6 +31923,9 @@ The remote stub accepts and implements the reverse step packet
|
|||
The remote stub understands the @samp{QTDPsrc} packet that supplies
|
||||
the source form of tracepoint definitions.
|
||||
|
||||
@item QAllow
|
||||
The remote stub understands the @samp{QAllow} packet.
|
||||
|
||||
@end table
|
||||
|
||||
@item qSymbol::
|
||||
|
|
|
@ -628,4 +628,6 @@ extern int number_of_inferiors (void);
|
|||
|
||||
extern struct inferior *add_inferior_with_spaces (void);
|
||||
|
||||
extern void update_observer_mode (void);
|
||||
|
||||
#endif /* !defined (INFERIOR_H) */
|
||||
|
|
93
gdb/infrun.c
93
gdb/infrun.c
|
@ -178,6 +178,85 @@ show_debug_infrun (struct ui_file *file, int from_tty,
|
|||
#define SOLIB_IN_DYNAMIC_LINKER(pid,pc) 0
|
||||
#endif
|
||||
|
||||
/* "Observer mode" is somewhat like a more extreme version of
|
||||
non-stop, in which all GDB operations that might affect the
|
||||
target's execution have been disabled. */
|
||||
|
||||
static int non_stop_1 = 0;
|
||||
|
||||
int observer_mode = 0;
|
||||
static int observer_mode_1 = 0;
|
||||
|
||||
static void
|
||||
set_observer_mode (char *args, int from_tty,
|
||||
struct cmd_list_element *c)
|
||||
{
|
||||
extern int pagination_enabled;
|
||||
|
||||
if (target_has_execution)
|
||||
{
|
||||
observer_mode_1 = observer_mode;
|
||||
error (_("Cannot change this setting while the inferior is running."));
|
||||
}
|
||||
|
||||
observer_mode = observer_mode_1;
|
||||
|
||||
may_write_registers = !observer_mode;
|
||||
may_write_memory = !observer_mode;
|
||||
may_insert_breakpoints = !observer_mode;
|
||||
may_insert_tracepoints = !observer_mode;
|
||||
/* We can insert fast tracepoints in or out of observer mode,
|
||||
but enable them if we're going into this mode. */
|
||||
if (observer_mode)
|
||||
may_insert_fast_tracepoints = 1;
|
||||
may_stop = !observer_mode;
|
||||
update_target_permissions ();
|
||||
|
||||
/* Going *into* observer mode we must force non-stop, then
|
||||
going out we leave it that way. */
|
||||
if (observer_mode)
|
||||
{
|
||||
target_async_permitted = 1;
|
||||
pagination_enabled = 0;
|
||||
non_stop = non_stop_1 = 1;
|
||||
}
|
||||
|
||||
if (from_tty)
|
||||
printf_filtered (_("Observer mode is now %s.\n"),
|
||||
(observer_mode ? "on" : "off"));
|
||||
}
|
||||
|
||||
static void
|
||||
show_observer_mode (struct ui_file *file, int from_tty,
|
||||
struct cmd_list_element *c, const char *value)
|
||||
{
|
||||
fprintf_filtered (file, _("Observer mode is %s.\n"), value);
|
||||
}
|
||||
|
||||
/* This updates the value of observer mode based on changes in
|
||||
permissions. Note that we are deliberately ignoring the values of
|
||||
may-write-registers and may-write-memory, since the user may have
|
||||
reason to enable these during a session, for instance to turn on a
|
||||
debugging-related global. */
|
||||
|
||||
void
|
||||
update_observer_mode (void)
|
||||
{
|
||||
int newval;
|
||||
|
||||
newval = (!may_insert_breakpoints
|
||||
&& !may_insert_tracepoints
|
||||
&& may_insert_fast_tracepoints
|
||||
&& !may_stop
|
||||
&& non_stop);
|
||||
|
||||
/* Let the user know if things change. */
|
||||
if (newval != observer_mode)
|
||||
printf_filtered (_("Observer mode is now %s.\n"),
|
||||
(newval ? "on" : "off"));
|
||||
|
||||
observer_mode = observer_mode_1 = newval;
|
||||
}
|
||||
|
||||
/* Tables of how to react to signals; the user sets them. */
|
||||
|
||||
|
@ -6423,7 +6502,6 @@ show_exec_direction_func (struct ui_file *out, int from_tty,
|
|||
/* User interface for non-stop mode. */
|
||||
|
||||
int non_stop = 0;
|
||||
static int non_stop_1 = 0;
|
||||
|
||||
static void
|
||||
set_non_stop (char *args, int from_tty,
|
||||
|
@ -6725,4 +6803,17 @@ Tells gdb whether to detach the child of a fork."),
|
|||
isn't initialized yet. At this point, we're quite sure there
|
||||
isn't another convenience variable of the same name. */
|
||||
create_internalvar_type_lazy ("_siginfo", siginfo_make_value);
|
||||
|
||||
add_setshow_boolean_cmd ("observer", no_class,
|
||||
&observer_mode_1, _("\
|
||||
Set whether gdb controls the inferior in observer mode."), _("\
|
||||
Show whether gdb controls the inferior in observer mode."), _("\
|
||||
In observer mode, GDB can get data from the inferior, but not\n\
|
||||
affect its execution. Registers and memory may not be changed,\n\
|
||||
breakpoints may not be set, and the program cannot be interrupted\n\
|
||||
or signalled."),
|
||||
set_observer_mode,
|
||||
show_observer_mode,
|
||||
&setlist,
|
||||
&showlist);
|
||||
}
|
||||
|
|
43
gdb/remote.c
43
gdb/remote.c
|
@ -212,6 +212,8 @@ static void show_remote_protocol_packet_cmd (struct ui_file *file,
|
|||
static char *write_ptid (char *buf, const char *endbuf, ptid_t ptid);
|
||||
static ptid_t read_ptid (char *buf, char **obuf);
|
||||
|
||||
static void remote_set_permissions (void);
|
||||
|
||||
struct remote_state;
|
||||
static int remote_get_trace_status (struct trace_status *ts);
|
||||
|
||||
|
@ -1213,6 +1215,7 @@ enum {
|
|||
PACKET_bc,
|
||||
PACKET_bs,
|
||||
PACKET_TracepointSource,
|
||||
PACKET_QAllow,
|
||||
PACKET_MAX
|
||||
};
|
||||
|
||||
|
@ -3047,6 +3050,10 @@ remote_start_remote (struct ui_out *uiout, void *opaque)
|
|||
which later probes to skip. */
|
||||
remote_query_supported ();
|
||||
|
||||
/* If the stub wants to get a QAllow, compose one and send it. */
|
||||
if (remote_protocol_packets[PACKET_QAllow].support != PACKET_DISABLE)
|
||||
remote_set_permissions ();
|
||||
|
||||
/* Next, we possibly activate noack mode.
|
||||
|
||||
If the QStartNoAckMode packet configuration is set to AUTO,
|
||||
|
@ -3393,6 +3400,36 @@ Some events may be lost, rendering further debugging impossible."));
|
|||
return serial_open (name);
|
||||
}
|
||||
|
||||
/* Inform the target of our permission settings. The permission flags
|
||||
work without this, but if the target knows the settings, it can do
|
||||
a couple things. First, it can add its own check, to catch cases
|
||||
that somehow manage to get by the permissions checks in target
|
||||
methods. Second, if the target is wired to disallow particular
|
||||
settings (for instance, a system in the field that is not set up to
|
||||
be able to stop at a breakpoint), it can object to any unavailable
|
||||
permissions. */
|
||||
|
||||
void
|
||||
remote_set_permissions (void)
|
||||
{
|
||||
struct remote_state *rs = get_remote_state ();
|
||||
|
||||
sprintf (rs->buf, "QAllow:"
|
||||
"WriteReg:%x;WriteMem:%x;"
|
||||
"InsertBreak:%x;InsertTrace:%x;"
|
||||
"InsertFastTrace:%x;Stop:%x",
|
||||
may_write_registers, may_write_memory,
|
||||
may_insert_breakpoints, may_insert_tracepoints,
|
||||
may_insert_fast_tracepoints, may_stop);
|
||||
putpkt (rs->buf);
|
||||
getpkt (&rs->buf, &rs->buf_size, 0);
|
||||
|
||||
/* If the target didn't like the packet, warn the user. Do not try
|
||||
to undo the user's settings, that would just be maddening. */
|
||||
if (strcmp (rs->buf, "OK") != 0)
|
||||
warning ("Remote refused setting permissions with: %s", rs->buf);
|
||||
}
|
||||
|
||||
/* This type describes each known response to the qSupported
|
||||
packet. */
|
||||
struct protocol_feature
|
||||
|
@ -3564,6 +3601,8 @@ static struct protocol_feature remote_protocol_features[] = {
|
|||
PACKET_bs },
|
||||
{ "TracepointSource", PACKET_DISABLE, remote_supported_packet,
|
||||
PACKET_TracepointSource },
|
||||
{ "QAllow", PACKET_DISABLE, remote_supported_packet,
|
||||
PACKET_QAllow },
|
||||
};
|
||||
|
||||
static char *remote_support_xml;
|
||||
|
@ -10061,6 +10100,7 @@ Specify the serial device it is connected to\n\
|
|||
remote_ops.to_core_of_thread = remote_core_of_thread;
|
||||
remote_ops.to_verify_memory = remote_verify_memory;
|
||||
remote_ops.to_get_tib_address = remote_get_tib_address;
|
||||
remote_ops.to_set_permissions = remote_set_permissions;
|
||||
}
|
||||
|
||||
/* Set up the extended remote vector by making a copy of the standard
|
||||
|
@ -10536,6 +10576,9 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
|
|||
add_packet_config_cmd (&remote_protocol_packets[PACKET_TracepointSource],
|
||||
"TracepointSource", "TracepointSource", 0);
|
||||
|
||||
add_packet_config_cmd (&remote_protocol_packets[PACKET_QAllow],
|
||||
"QAllow", "allow", 0);
|
||||
|
||||
/* Keep the old ``set remote Z-packet ...'' working. Each individual
|
||||
Z sub-packet has its own set and show commands, but users may
|
||||
have sets to this variable in their .gdbinit files (or in their
|
||||
|
|
180
gdb/target.c
180
gdb/target.c
|
@ -195,6 +195,22 @@ static int trust_readonly = 0;
|
|||
|
||||
static int show_memory_breakpoints = 0;
|
||||
|
||||
/* These globals control whether GDB attempts to perform these
|
||||
operations; they are useful for targets that need to prevent
|
||||
inadvertant disruption, such as in non-stop mode. */
|
||||
|
||||
int may_write_registers = 1;
|
||||
|
||||
int may_write_memory = 1;
|
||||
|
||||
int may_insert_breakpoints = 1;
|
||||
|
||||
int may_insert_tracepoints = 1;
|
||||
|
||||
int may_insert_fast_tracepoints = 1;
|
||||
|
||||
int may_stop = 1;
|
||||
|
||||
/* Non-zero if we want to see trace of target level stuff. */
|
||||
|
||||
static int targetdebug = 0;
|
||||
|
@ -662,6 +678,7 @@ update_current_target (void)
|
|||
INHERIT (to_set_disconnected_tracing, t);
|
||||
INHERIT (to_set_circular_trace_buffer, t);
|
||||
INHERIT (to_get_tib_address, t);
|
||||
INHERIT (to_set_permissions, t);
|
||||
INHERIT (to_magic, t);
|
||||
/* Do not inherit to_memory_map. */
|
||||
/* Do not inherit to_flash_erase. */
|
||||
|
@ -858,6 +875,9 @@ update_current_target (void)
|
|||
de_fault (to_get_tib_address,
|
||||
(int (*) (ptid_t, CORE_ADDR *))
|
||||
tcomplain);
|
||||
de_fault (to_set_permissions,
|
||||
(void (*) (void))
|
||||
target_ignore);
|
||||
#undef de_fault
|
||||
|
||||
/* Finally, position the target-stack beneath the squashed
|
||||
|
@ -1404,6 +1424,10 @@ target_xfer_partial (struct target_ops *ops,
|
|||
|
||||
gdb_assert (ops->to_xfer_partial != NULL);
|
||||
|
||||
if (writebuf && !may_write_memory)
|
||||
error (_("Writing to memory is not allowed (addr %s, len %s)"),
|
||||
core_addr_to_string_nz (offset), plongest (len));
|
||||
|
||||
/* If this is a memory transfer, let the memory-specific code
|
||||
have a look at it instead. Memory transfers are more
|
||||
complicated. */
|
||||
|
@ -1967,6 +1991,36 @@ get_target_memory_unsigned (struct target_ops *ops, CORE_ADDR addr,
|
|||
return extract_unsigned_integer (buf, len, byte_order);
|
||||
}
|
||||
|
||||
int
|
||||
target_insert_breakpoint (struct gdbarch *gdbarch,
|
||||
struct bp_target_info *bp_tgt)
|
||||
{
|
||||
if (!may_insert_breakpoints)
|
||||
{
|
||||
warning (_("May not insert breakpoints"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return (*current_target.to_insert_breakpoint) (gdbarch, bp_tgt);
|
||||
}
|
||||
|
||||
int
|
||||
target_remove_breakpoint (struct gdbarch *gdbarch,
|
||||
struct bp_target_info *bp_tgt)
|
||||
{
|
||||
/* This is kind of a weird case to handle, but the permission might
|
||||
have been changed after breakpoints were inserted - in which case
|
||||
we should just take the user literally and assume that any
|
||||
breakpoints should be left in place. */
|
||||
if (!may_insert_breakpoints)
|
||||
{
|
||||
warning (_("May not remove breakpoints"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return (*current_target.to_remove_breakpoint) (gdbarch, bp_tgt);
|
||||
}
|
||||
|
||||
static void
|
||||
target_info (char *args, int from_tty)
|
||||
{
|
||||
|
@ -2949,6 +3003,18 @@ target_find_new_threads (void)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
target_stop (ptid_t ptid)
|
||||
{
|
||||
if (!may_stop)
|
||||
{
|
||||
warning (_("May not interrupt or stop the target, ignoring attempt"));
|
||||
return;
|
||||
}
|
||||
|
||||
(*current_target.to_stop) (ptid);
|
||||
}
|
||||
|
||||
static void
|
||||
debug_to_post_attach (int pid)
|
||||
{
|
||||
|
@ -3058,6 +3124,9 @@ target_store_registers (struct regcache *regcache, int regno)
|
|||
{
|
||||
struct target_ops *t;
|
||||
|
||||
if (!may_write_registers)
|
||||
error (_("Writing to registers is not allowed (regno %d)"), regno);
|
||||
|
||||
for (t = current_target.beneath; t != NULL; t = t->beneath)
|
||||
{
|
||||
if (t->to_store_registers != NULL)
|
||||
|
@ -3675,6 +3744,62 @@ show_maintenance_target_async_permitted (struct ui_file *file, int from_tty,
|
|||
Controlling the inferior in asynchronous mode is %s.\n"), value);
|
||||
}
|
||||
|
||||
/* Temporary copies of permission settings. */
|
||||
|
||||
static int may_write_registers_1 = 1;
|
||||
static int may_write_memory_1 = 1;
|
||||
static int may_insert_breakpoints_1 = 1;
|
||||
static int may_insert_tracepoints_1 = 1;
|
||||
static int may_insert_fast_tracepoints_1 = 1;
|
||||
static int may_stop_1 = 1;
|
||||
|
||||
/* Make the user-set values match the real values again. */
|
||||
|
||||
void
|
||||
update_target_permissions (void)
|
||||
{
|
||||
may_write_registers_1 = may_write_registers;
|
||||
may_write_memory_1 = may_write_memory;
|
||||
may_insert_breakpoints_1 = may_insert_breakpoints;
|
||||
may_insert_tracepoints_1 = may_insert_tracepoints;
|
||||
may_insert_fast_tracepoints_1 = may_insert_fast_tracepoints;
|
||||
may_stop_1 = may_stop;
|
||||
}
|
||||
|
||||
/* The one function handles (most of) the permission flags in the same
|
||||
way. */
|
||||
|
||||
static void
|
||||
set_target_permissions (char *args, int from_tty,
|
||||
struct cmd_list_element *c)
|
||||
{
|
||||
if (target_has_execution)
|
||||
{
|
||||
update_target_permissions ();
|
||||
error (_("Cannot change this setting while the inferior is running."));
|
||||
}
|
||||
|
||||
/* Make the real values match the user-changed values. */
|
||||
may_write_registers = may_write_registers_1;
|
||||
may_insert_breakpoints = may_insert_breakpoints_1;
|
||||
may_insert_tracepoints = may_insert_tracepoints_1;
|
||||
may_insert_fast_tracepoints = may_insert_fast_tracepoints_1;
|
||||
may_stop = may_stop_1;
|
||||
update_observer_mode ();
|
||||
}
|
||||
|
||||
/* Set memory write permission independently of observer mode. */
|
||||
|
||||
static void
|
||||
set_write_memory_permission (char *args, int from_tty,
|
||||
struct cmd_list_element *c)
|
||||
{
|
||||
/* Make the real values match the user-changed values. */
|
||||
may_write_memory = may_write_memory_1;
|
||||
update_observer_mode ();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
initialize_targets (void)
|
||||
{
|
||||
|
@ -3733,5 +3858,60 @@ By default, caching for stack access is on."),
|
|||
show_stack_cache_enabled_p,
|
||||
&setlist, &showlist);
|
||||
|
||||
add_setshow_boolean_cmd ("may-write-registers", class_support,
|
||||
&may_write_registers_1, _("\
|
||||
Set permission to write into registers."), _("\
|
||||
Show permission to write into registers."), _("\
|
||||
When this permission is on, GDB may write into the target's registers.\n\
|
||||
Otherwise, any sort of write attempt will result in an error."),
|
||||
set_target_permissions, NULL,
|
||||
&setlist, &showlist);
|
||||
|
||||
add_setshow_boolean_cmd ("may-write-memory", class_support,
|
||||
&may_write_memory_1, _("\
|
||||
Set permission to write into target memory."), _("\
|
||||
Show permission to write into target memory."), _("\
|
||||
When this permission is on, GDB may write into the target's memory.\n\
|
||||
Otherwise, any sort of write attempt will result in an error."),
|
||||
set_write_memory_permission, NULL,
|
||||
&setlist, &showlist);
|
||||
|
||||
add_setshow_boolean_cmd ("may-insert-breakpoints", class_support,
|
||||
&may_insert_breakpoints_1, _("\
|
||||
Set permission to insert breakpoints in the target."), _("\
|
||||
Show permission to insert breakpoints in the target."), _("\
|
||||
When this permission is on, GDB may insert breakpoints in the program.\n\
|
||||
Otherwise, any sort of insertion attempt will result in an error."),
|
||||
set_target_permissions, NULL,
|
||||
&setlist, &showlist);
|
||||
|
||||
add_setshow_boolean_cmd ("may-insert-tracepoints", class_support,
|
||||
&may_insert_tracepoints_1, _("\
|
||||
Set permission to insert tracepoints in the target."), _("\
|
||||
Show permission to insert tracepoints in the target."), _("\
|
||||
When this permission is on, GDB may insert tracepoints in the program.\n\
|
||||
Otherwise, any sort of insertion attempt will result in an error."),
|
||||
set_target_permissions, NULL,
|
||||
&setlist, &showlist);
|
||||
|
||||
add_setshow_boolean_cmd ("may-insert-fast-tracepoints", class_support,
|
||||
&may_insert_fast_tracepoints_1, _("\
|
||||
Set permission to insert fast tracepoints in the target."), _("\
|
||||
Show permission to insert fast tracepoints in the target."), _("\
|
||||
When this permission is on, GDB may insert fast tracepoints.\n\
|
||||
Otherwise, any sort of insertion attempt will result in an error."),
|
||||
set_target_permissions, NULL,
|
||||
&setlist, &showlist);
|
||||
|
||||
add_setshow_boolean_cmd ("may-interrupt", class_support,
|
||||
&may_stop_1, _("\
|
||||
Set permission to interrupt or signal the target."), _("\
|
||||
Show permission to interrupt or signal the target."), _("\
|
||||
When this permission is on, GDB may interrupt/stop the target's execution.\n\
|
||||
Otherwise, any attempt to interrupt or stop will be ignored."),
|
||||
set_target_permissions, NULL,
|
||||
&setlist, &showlist);
|
||||
|
||||
|
||||
target_dcache = dcache_init ();
|
||||
}
|
||||
|
|
25
gdb/target.h
25
gdb/target.h
|
@ -686,6 +686,9 @@ struct target_ops
|
|||
a Windows OS specific feature. */
|
||||
int (*to_get_tib_address) (ptid_t ptid, CORE_ADDR *addr);
|
||||
|
||||
/* Send the new settings of write permission variables. */
|
||||
void (*to_set_permissions) (void);
|
||||
|
||||
int to_magic;
|
||||
/* Need sub-structure for target machine related rather than comm related?
|
||||
*/
|
||||
|
@ -889,14 +892,14 @@ extern int inferior_has_called_syscall (ptid_t pid, int *syscall_number);
|
|||
/* Insert a breakpoint at address BP_TGT->placed_address in the target
|
||||
machine. Result is 0 for success, or an errno value. */
|
||||
|
||||
#define target_insert_breakpoint(gdbarch, bp_tgt) \
|
||||
(*current_target.to_insert_breakpoint) (gdbarch, bp_tgt)
|
||||
extern int target_insert_breakpoint (struct gdbarch *gdbarch,
|
||||
struct bp_target_info *bp_tgt);
|
||||
|
||||
/* Remove a breakpoint at address BP_TGT->placed_address in the target
|
||||
machine. Result is 0 for success, or an errno value. */
|
||||
|
||||
#define target_remove_breakpoint(gdbarch, bp_tgt) \
|
||||
(*current_target.to_remove_breakpoint) (gdbarch, bp_tgt)
|
||||
extern int target_remove_breakpoint (struct gdbarch *gdbarch,
|
||||
struct bp_target_info *bp_tgt);
|
||||
|
||||
/* Initialize the terminal settings we record for the inferior,
|
||||
before we actually run the inferior. */
|
||||
|
@ -1091,7 +1094,7 @@ extern void target_find_new_threads (void);
|
|||
Unix, this should act like SIGSTOP). This function is normally
|
||||
used by GUIs to implement a stop button. */
|
||||
|
||||
#define target_stop(ptid) (*current_target.to_stop) (ptid)
|
||||
extern void target_stop (ptid_t ptid);
|
||||
|
||||
/* Send the specified COMMAND to the target's monitor
|
||||
(shell,interpreter) for execution. The result of the query is
|
||||
|
@ -1378,6 +1381,9 @@ extern int target_search_memory (CORE_ADDR start_addr,
|
|||
#define target_get_tib_address(ptid, addr) \
|
||||
(*current_target.to_get_tib_address) ((ptid), (addr))
|
||||
|
||||
#define target_set_permissions() \
|
||||
(*current_target.to_set_permissions) ()
|
||||
|
||||
/* Command logging facility. */
|
||||
|
||||
#define target_log_command(p) \
|
||||
|
@ -1540,6 +1546,15 @@ extern enum target_signal target_signal_from_command (int);
|
|||
to restore it back to the current value. */
|
||||
extern struct cleanup *make_show_memory_breakpoints_cleanup (int show);
|
||||
|
||||
extern int may_write_registers;
|
||||
extern int may_write_memory;
|
||||
extern int may_insert_breakpoints;
|
||||
extern int may_insert_tracepoints;
|
||||
extern int may_insert_fast_tracepoints;
|
||||
extern int may_stop;
|
||||
|
||||
extern void update_target_permissions (void);
|
||||
|
||||
|
||||
/* Imported from machine dependent code */
|
||||
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
:010-06-11 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
|
||||
2010-06-11 Stan Shebs <stan@codesourcery.com>
|
||||
|
||||
* gdb.base/permissions.exp: New file.
|
||||
|
||||
2010-06-11 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
|
||||
|
||||
* gdb.base/valgrind-db-attach.exp: Fail gracefully if valgrind
|
||||
does not support ELF executable class.
|
||||
|
|
101
gdb/testsuite/gdb.base/permissions.exp
Normal file
101
gdb/testsuite/gdb.base/permissions.exp
Normal file
|
@ -0,0 +1,101 @@
|
|||
# Copyright 2010 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Tests for permissions and observer mode.
|
||||
|
||||
# The permissions flags are only fully functional with stubs or targets
|
||||
# that can run asynchronously.
|
||||
|
||||
set testfile permission
|
||||
set srcfile start.c
|
||||
set binfile ${objdir}/${subdir}/${testfile}
|
||||
|
||||
if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug nowarnings}] != "" } {
|
||||
untested permissions.exp
|
||||
return -1
|
||||
}
|
||||
|
||||
if [get_compiler_info $binfile] {
|
||||
return -1
|
||||
}
|
||||
|
||||
gdb_exit
|
||||
gdb_start
|
||||
gdb_reinitialize_dir $srcdir/$subdir
|
||||
|
||||
gdb_test "show may-write-registers" \
|
||||
"Permission to write into registers is on."
|
||||
|
||||
gdb_test "show may-write-memory" \
|
||||
"Permission to write into target memory is on."
|
||||
|
||||
gdb_test "show may-insert-breakpoints" \
|
||||
"Permission to insert breakpoints in the target is on."
|
||||
|
||||
gdb_test "show may-insert-tracepoints" \
|
||||
"Permission to insert tracepoints in the target is on."
|
||||
|
||||
gdb_test "show may-insert-fast-tracepoints" \
|
||||
"Permission to insert fast tracepoints in the target is on."
|
||||
|
||||
gdb_test "show may-interrupt" \
|
||||
"Permission to interrupt or signal the target is on."
|
||||
|
||||
gdb_test "set observer on" "Observer mode is now on." "enable observer mode"
|
||||
|
||||
gdb_test "show may-write-memory" \
|
||||
"Permission to write into target memory is off."
|
||||
|
||||
gdb_test "show may-write-registers" \
|
||||
"Permission to write into registers is off."
|
||||
|
||||
gdb_test "show may-insert-breakpoints" \
|
||||
"Permission to insert breakpoints in the target is off."
|
||||
|
||||
gdb_test "show may-insert-tracepoints" \
|
||||
"Permission to insert tracepoints in the target is off."
|
||||
|
||||
gdb_test "show may-insert-fast-tracepoints" \
|
||||
"Permission to insert fast tracepoints in the target is on."
|
||||
|
||||
gdb_test "show may-interrupt" \
|
||||
"Permission to interrupt or signal the target is off."
|
||||
|
||||
gdb_test "set observer off" "Observer mode is now off." "disable observer mode"
|
||||
|
||||
# Go back to all-stop mode.
|
||||
|
||||
gdb_test_no_output "set non-stop off"
|
||||
|
||||
gdb_load ${binfile}
|
||||
|
||||
if ![runto_main] then {
|
||||
perror "couldn't run to breakpoint"
|
||||
continue
|
||||
}
|
||||
|
||||
gdb_test "print x = 45" "$decimal = 45" "set a global"
|
||||
|
||||
gdb_test "print x" "$decimal = 45"
|
||||
|
||||
gdb_test "set may-write-memory off"
|
||||
|
||||
gdb_test "print x = 92" "Writing to memory is not allowed.*" \
|
||||
"try to set a global"
|
||||
|
||||
gdb_test "print x" "$decimal = 45"
|
||||
|
||||
# FIXME Add tests for other flags when a testsuite-able target becomes
|
||||
# available.
|
|
@ -1490,7 +1490,7 @@ start_tracing (void)
|
|||
int ix;
|
||||
struct breakpoint *t;
|
||||
struct trace_state_variable *tsv;
|
||||
int any_enabled = 0;
|
||||
int any_enabled = 0, num_to_download = 0;
|
||||
|
||||
tp_vec = all_tracepoints ();
|
||||
|
||||
|
@ -1504,10 +1504,15 @@ start_tracing (void)
|
|||
for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, t); ix++)
|
||||
{
|
||||
if (t->enable_state == bp_enabled)
|
||||
{
|
||||
any_enabled = 1;
|
||||
break;
|
||||
}
|
||||
any_enabled = 1;
|
||||
|
||||
if ((t->type == bp_fast_tracepoint
|
||||
? may_insert_fast_tracepoints
|
||||
: may_insert_tracepoints))
|
||||
++num_to_download;
|
||||
else
|
||||
warning (_("May not insert %stracepoints, skipping tracepoint %d"),
|
||||
(t->type == bp_fast_tracepoint ? "fast " : ""), t->number);
|
||||
}
|
||||
|
||||
/* No point in tracing with only disabled tracepoints. */
|
||||
|
@ -1517,10 +1522,21 @@ start_tracing (void)
|
|||
error (_("No tracepoints enabled, not starting trace"));
|
||||
}
|
||||
|
||||
if (num_to_download <= 0)
|
||||
{
|
||||
VEC_free (breakpoint_p, tp_vec);
|
||||
error (_("No tracepoints that may be downloaded, not starting trace"));
|
||||
}
|
||||
|
||||
target_trace_init ();
|
||||
|
||||
for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, t); ix++)
|
||||
{
|
||||
if ((t->type == bp_fast_tracepoint
|
||||
? !may_insert_fast_tracepoints
|
||||
: !may_insert_tracepoints))
|
||||
continue;
|
||||
|
||||
t->number_on_target = 0;
|
||||
target_download_tracepoint (t);
|
||||
t->number_on_target = t->number;
|
||||
|
|
Loading…
Reference in a new issue