aboutsummaryrefslogtreecommitdiff
path: root/gdb/gdbserver/mem-break.c
diff options
context:
space:
mode:
authorStan Shebs <shebs@codesourcery.com>2012-07-02 15:29:39 +0000
committerStan Shebs <shebs@codesourcery.com>2012-07-02 15:29:39 +0000
commitd3ce09f5bf7a7e8f97c3f1c9888e886ee267c2f2 (patch)
tree782811ca1df7a4f775823d1918d0b571fdac9b5a /gdb/gdbserver/mem-break.c
parenta47edf2745dd6414d635e4b372d416035c7b8c12 (diff)
downloadgdb-d3ce09f5bf7a7e8f97c3f1c9888e886ee267c2f2.zip
gdb-d3ce09f5bf7a7e8f97c3f1c9888e886ee267c2f2.tar.gz
gdb-d3ce09f5bf7a7e8f97c3f1c9888e886ee267c2f2.tar.bz2
Add target-side support for dynamic printf.
* NEWS: Mention the additional style. * breakpoint.h (struct bp_target_info): New fields tcommands, persist. (struct bp_location): New field cmd_bytecode. * breakpoint.c: Include format.h. (disconnected_dprintf): New global. (parse_cmd_to_aexpr): New function. (build_target_command_list): New function. (insert_bp_location): Call it. (remove_breakpoints_pid): Skip dprintf breakpoints. (print_one_breakpoint_location): Ditto. (dprintf_style_agent): New global. (dprintf_style_enums): Add dprintf_style_agent. (update_dprintf_command_list): Add agent case. (agent_printf_command): New function. (_initialize_breakpoint): Add new commands. * common/ax.def (printf): New bytecode. * ax.h (ax_string): Declare. * ax-gdb.h (gen_printf): Declare. * ax-gdb.c: Include cli-utils.h, format.h. (gen_printf): New function. (maint_agent_print_command): New function. (_initialize_ax_gdb): Add maint agent-printf command. * ax-general.c (ax_string): New function. (ax_print): Add printf disassembly. * Makefile.in (SFILES): Add format.c (COMMON_OBS): Add format.o. * common/format.h: New file. * common/format.c: New file. * printcmd.c: Include format.h. (ui_printf): Call parse_format_string. * remote.c (remote_state): New field breakpoint_commands. (PACKET_BreakpointCommands): New enum. (remote_breakpoint_commands_feature): New function. (remote_protocol_features): Add new BreakpointCommands entry. (remote_can_run_breakpoint_commands): New function. (remote_add_target_side_commands): New function. (remote_insert_breakpoint): Call it. (remote_insert_hw_breakpoint): Ditto. (_initialize_remote): Add new packet configuration for target-side breakpoint commands. * target.h (struct target_ops): New field to_can_run_breakpoint_commands. (target_can_run_breakpoint_commands): New macro. * target.c (update_current_target): Handle to_can_run_breakpoint_commands. [gdbserver] * Makefile.in (WARN_CFLAGS_NO_FORMAT): Define. (ax.o): Add it to build rule. (ax-ipa.o): Ditto. (OBS): Add format.o. (IPA_OBS): Add format.o. * server.c (handle_query): Claim support for breakpoint commands. (process_point_options): Add command case. (process_serial_event): Leave running if there are printfs in effect. * mem-break.h (any_persistent_commands): Declare. (add_breakpoint_commands): Declare. (gdb_no_commands_at_breakpoint): Declare. (run_breakpoint_commands): Declare. * mem-break.c (struct point_command_list): New struct. (struct breakpoint): New field command_list. (any_persistent_commands): New function. (add_commands_to_breakpoint): New function. (add_breakpoint_commands): New function. (gdb_no_commands_at_breakpoint): New function. (run_breakpoint_commands): New function. * linux-low.c (linux_wait_1): Test for and run breakpoint commands locally. * ax.c: Include format.h. (ax_printf): New function. (gdb_eval_agent_expr): Add printf opcode. [doc] * gdb.texinfo (Dynamic Printf): Mention agent style and disconnected dprintf. (Maintenance Commands): Describe maint agent-printf. (General Query Packets): Mention BreakpointCommands feature. (Packets): Document commands extension to Z0 packet. * agentexpr.texi (Bytecode Descriptions): Document printf bytecode. [testsuite] * gdb.base/dprintf.exp: Add agent style tests.
Diffstat (limited to 'gdb/gdbserver/mem-break.c')
-rw-r--r--gdb/gdbserver/mem-break.c125
1 files changed, 125 insertions, 0 deletions
diff --git a/gdb/gdbserver/mem-break.c b/gdb/gdbserver/mem-break.c
index 6b6b25c..aec09ba 100644
--- a/gdb/gdbserver/mem-break.c
+++ b/gdb/gdbserver/mem-break.c
@@ -97,6 +97,20 @@ struct point_cond_list
struct point_cond_list *next;
};
+struct point_command_list
+{
+ /* Pointer to the agent expression that is the breakpoint's
+ commands. */
+ struct agent_expr *cmd;
+
+ /* Flag that is true if this command should run even while GDB is
+ disconnected. */
+ int persistence;
+
+ /* Pointer to the next command. */
+ struct point_command_list *next;
+};
+
/* A high level (in gdbserver's perspective) breakpoint. */
struct breakpoint
{
@@ -111,6 +125,9 @@ struct breakpoint
target's side. */
struct point_cond_list *cond_list;
+ /* Point to the list of commands to run when this is hit. */
+ struct point_command_list *command_list;
+
/* Link to this breakpoint's raw breakpoint. This is always
non-NULL. */
struct raw_breakpoint *raw;
@@ -121,6 +138,23 @@ struct breakpoint
int (*handler) (CORE_ADDR);
};
+int
+any_persistent_commands ()
+{
+ struct process_info *proc = current_process ();
+ struct breakpoint *bp;
+ struct point_command_list *cl;
+
+ for (bp = proc->breakpoints; bp != NULL; bp = bp->next)
+ {
+ for (cl = bp->command_list; cl != NULL; cl = cl->next)
+ if (cl->persistence)
+ return 1;
+ }
+
+ return 0;
+}
+
static struct raw_breakpoint *
find_raw_breakpoint_at (CORE_ADDR where)
{
@@ -835,6 +869,97 @@ gdb_condition_true_at_breakpoint (CORE_ADDR where)
return (value != 0);
}
+/* Add commands COMMANDS to GDBserver's breakpoint BP. */
+
+void
+add_commands_to_breakpoint (struct breakpoint *bp,
+ struct agent_expr *commands, int persist)
+{
+ struct point_command_list *new_cmd;
+
+ /* Create new command. */
+ new_cmd = xcalloc (1, sizeof (*new_cmd));
+ new_cmd->cmd = commands;
+ new_cmd->persistence = persist;
+
+ /* Add commands to the list. */
+ new_cmd->next = bp->command_list;
+ bp->command_list = new_cmd;
+}
+
+/* Add a target-side command COMMAND to the breakpoint at ADDR. */
+
+int
+add_breakpoint_commands (CORE_ADDR addr, char **command, int persist)
+{
+ struct breakpoint *bp = find_gdb_breakpoint_at (addr);
+ char *actparm = *command;
+ struct agent_expr *cmd;
+
+ if (bp == NULL)
+ return 1;
+
+ if (command == NULL)
+ return 1;
+
+ cmd = gdb_parse_agent_expr (&actparm);
+
+ if (cmd == NULL)
+ {
+ fprintf (stderr, "Command evaluation failed. "
+ "Disabling.\n");
+ return 0;
+ }
+
+ add_commands_to_breakpoint (bp, cmd, persist);
+
+ *command = actparm;
+
+ return 0;
+}
+
+/* Return true if there are no commands to run at this location,
+ which likely means we want to report back to GDB. */
+int
+gdb_no_commands_at_breakpoint (CORE_ADDR where)
+{
+ struct breakpoint *bp = find_gdb_breakpoint_at (where);
+
+ if (bp == NULL)
+ return 0;
+
+ if (debug_threads)
+ fprintf (stderr, "at 0x%s, bp command_list is 0x%x\n",
+ paddress (where), (int) bp->command_list);
+ return (bp->command_list == NULL);
+}
+
+void
+run_breakpoint_commands (CORE_ADDR where)
+{
+ /* Fetch registers for the current inferior. */
+ struct breakpoint *bp = find_gdb_breakpoint_at (where);
+ ULONGEST value = 0;
+ struct point_command_list *cl;
+ int err = 0;
+
+ struct regcache *regcache = get_thread_regcache (current_inferior, 1);
+
+ if (bp == NULL)
+ return;
+
+ for (cl = bp->command_list;
+ cl && !value && !err; cl = cl->next)
+ {
+ /* Run the command. */
+ err = gdb_eval_agent_expr (regcache, NULL, cl->cmd, &value);
+
+ /* If one command has a problem, stop digging the hole deeper. */
+ if (err)
+ break;
+ }
+}
+
/* Return 1 if there is a breakpoint inserted in address WHERE
and if its condition, if it exists, is true. */