diff options
author | Stan Shebs <shebs@codesourcery.com> | 2012-07-02 15:29:39 +0000 |
---|---|---|
committer | Stan Shebs <shebs@codesourcery.com> | 2012-07-02 15:29:39 +0000 |
commit | d3ce09f5bf7a7e8f97c3f1c9888e886ee267c2f2 (patch) | |
tree | 782811ca1df7a4f775823d1918d0b571fdac9b5a /gdb/gdbserver/mem-break.c | |
parent | a47edf2745dd6414d635e4b372d416035c7b8c12 (diff) | |
download | gdb-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.c | 125 |
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. */ |