[PATCH] Add autoload-breakpoints [5/7] autoload-breakpoints
Hui Zhu
hui_zhu@mentor.com
Sat Mar 17 08:53:00 GMT 2012
Hi,
This is the patch to add autoload-breakpints.
It try to sync the autoload-breakpoints in the stub when GDB connec to
stub. And the stub can use the ReportAsync interface control the
breakpoint in it.
If autoload-breakpoints control the breakpoint when inferior is running,
I still not sure about the stub can handle this breakpoint or something.
What I thougt is, if the stub think it need, send back a ReportAsync
packet let GDB contol the stub reload the breakpoint (interrupt and
continue the inferior). How do you think about it?
Thanks,
Hui
2012-03-17 Hui Zhu <hui_zhu@mentor.com>
* breakpoint.c (hex2bin, unpack_varlen_hex): New extern.
(autoload_breakpoints_query, autoload_breakpoints_merge,
autoload_breakpoints_gdb, autoload_breakpoints_stub,
autoload_breakpoints_enums,
breakpoint_add_command_line_next, this_ubpcmd): New variable.
(breakpoint_add_command_line, breakpoint_add_command,
breakpoint_get_commands): New function.
(print_one_breakpoint): Add out for b->autoload_id.
(init_raw_breakpoint_without_location): Add init for autoload_id
and autoload_inserted.
(autoload_breakpoints_get_id, uploaded_bp_commands_clean,
uploaded_bp_commands_add, handle_autoload_breakpoint_cmd,
parse_autoload_breakpoint_definition,
handle_autoload_breakpoint_cmd_to_breakpoints,
parse_autoload_breakpoint_definition_to_breakpoints,
clean_upload_autoload_breakpoints,
show_upload_autoload_breakpoints,
read_autoload_breakpoints_action,
merge_uploaded_autoload_breakpoints, autoload_breakpoints_reset,
autoload_breakpoints_clean,
autoload_breakpoints_number): New function.
(initialize_breakpoint_ops): add command "autoload".
* breakpoint.h (breakpoint): Add autoload_id and autoload_inserted.
(uploaded_bpcmd, uploaded_bp): New struct.
(autoload_breakpoints_query, autoload_breakpoints_merge,
autoload_breakpoints_gdb, autoload_breakpoints_stub,
autoload_breakpoints_mode, breakpoint_get_commands,
autoload_breakpoints_reset, autoload_breakpoints_clean,
autoload_breakpoints_number, parse_autoload_breakpoint_definition,
parse_autoload_breakpoint_definition_to_breakpoints,
clean_upload_autoload_breakpoints, show_upload_autoload_breakpoints,
merge_uploaded_autoload_breakpoints): New extern.
* remote.c (PACKET_AutoloadBreakpoints): New enum.
(remote_start_remote): Check PACKET_AutoloadBreakpoints,
if need call autoload-breakpoints functions.
(remote_pr): Add PACKET_AutoloadBreakpoints.
(remote_insert_breakpoint): Check inside_reportasync_handler.
(remote_remove_breakpoint): Ditto.
(remote_insert_hw_breakpoint): Ditto.
(remote_remove_hw_breakpoint): Ditto.
(remote_reportasync_handler): Add handle for "QBDP".
(remote_upload_autoload_breakpoints,
remote_download_autoload_breakpoints): New functions.
-------------- next part --------------
---
breakpoint.c | 663 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
breakpoint.h | 49 ++++
remote.c | 156 +++++++++++++
3 files changed, 866 insertions(+), 2 deletions(-)
--- a/breakpoint.c
+++ b/breakpoint.c
@@ -78,6 +78,9 @@
#include "mi/mi-common.h"
#include "python/python.h"
+extern int hex2bin (const char *hex, gdb_byte *bin, int count);
+extern char *unpack_varlen_hex (char *buff, ULONGEST *result);
+
/* Prototypes for local functions. */
static void enable_delete_command (char *, int);
@@ -467,6 +470,19 @@ gdb_evaluates_breakpoint_condition_p (vo
return (mode == condition_evaluation_host);
}
+const char autoload_breakpoints_query[] = "query";
+const char autoload_breakpoints_merge[] = "merge";
+const char autoload_breakpoints_gdb[] = "gdb";
+const char autoload_breakpoints_stub[] = "stub";
+const char *const autoload_breakpoints_enums[] = {
+ autoload_breakpoints_query,
+ autoload_breakpoints_merge,
+ autoload_breakpoints_gdb,
+ autoload_breakpoints_stub,
+ NULL
+};
+const char *autoload_breakpoints_mode = autoload_breakpoints_query;
+
void _initialize_breakpoint (void);
/* Are we executing breakpoint commands? */
@@ -1196,6 +1212,34 @@ static_tracepoints_here (CORE_ADDR addr)
return found;
}
+static char *breakpoint_add_command_line_next = NULL;
+
+static char *
+breakpoint_add_command_line (void)
+{
+ char *ret = breakpoint_add_command_line_next;
+ breakpoint_add_command_line_next = NULL;
+
+ return ret;
+}
+
+static void
+breakpoint_add_command (struct breakpoint *b, char *cmd)
+{
+ struct command_line *newline, *last;
+
+ breakpoint_add_command_line_next = cmd;
+ newline = read_command_lines_1 (breakpoint_add_command_line, 1, NULL, NULL);
+ if (b->commands && b->commands->commands)
+ {
+ for (last = b->commands->commands; last->next; last = last->next)
+ ;
+ last->next = newline;
+ }
+ else
+ breakpoint_set_commands (b, newline);
+}
+
/* Set the command list of B to COMMANDS. If breakpoint is tracepoint,
validate that only allowed commands are included. */
@@ -1211,6 +1255,15 @@ breakpoint_set_commands (struct breakpoi
observer_notify_breakpoint_modified (b);
}
+struct command_line *
+breakpoint_get_commands (struct breakpoint *b)
+{
+ if (b->commands && b->commands->commands)
+ return b->commands->commands;
+
+ return NULL;
+}
+
/* Set the internal `silent' flag on the breakpoint. Note that this
is not the same as the "silent" that may appear in the breakpoint's
commands. */
@@ -5846,6 +5899,14 @@ print_one_breakpoint (struct breakpoint
}
}
}
+
+ if (b->autoload_id)
+ {
+ annotate_field (7);
+ ui_out_text (uiout, "\tautoload-breakpoint ");
+ ui_out_field_int (uiout, "id", b->autoload_id);
+ ui_out_text (uiout, "\n");
+ }
}
static int
@@ -6563,6 +6624,8 @@ init_raw_breakpoint_without_location (st
b->condition_not_parsed = 0;
b->py_bp_object = NULL;
b->related_breakpoint = b;
+ b->autoload_id = 0;
+ b->autoload_inserted = 0;
}
/* Helper to set_raw_breakpoint below. Creates a breakpoint
@@ -14997,6 +15060,588 @@ pc_at_non_inline_function (struct addres
return 0;
}
+static int
+autoload_breakpoints_get_id (void)
+{
+ struct breakpoint *b;
+ int id = 1;
+
+ while (1)
+ {
+ ALL_BREAKPOINTS (b)
+ {
+ if (b->autoload_id == id)
+ break;
+ }
+ if (b)
+ id ++;
+ else
+ break;
+ }
+
+ return id;
+}
+
+static void
+uploaded_bp_commands_clean (struct uploaded_bp *ubp)
+{
+ struct uploaded_bpcmd *cmd, *cmd_tmp;
+
+ for (cmd = ubp->commands; cmd ? (cmd_tmp = cmd->next, 1): 0; cmd = cmd_tmp)
+ xfree (cmd);
+ ubp->commands = NULL;
+}
+
+static void
+uploaded_bp_commands_add (struct uploaded_bp *ubp, char *buf)
+{
+ struct uploaded_bpcmd *new_cmd, *cmd;
+
+ new_cmd = xzalloc (sizeof (struct uploaded_bpcmd));
+ new_cmd->str = xstrdup (buf);
+
+ for (cmd = ubp->commands; cmd && cmd->next; cmd = cmd->next)
+ ;
+ if (cmd)
+ cmd->next = new_cmd;
+ else
+ ubp->commands = new_cmd;
+}
+
+static void
+handle_autoload_breakpoint_cmd (char cmd, struct uploaded_bp *ubp)
+{
+ switch (cmd)
+ {
+ case 'E':
+ ubp->enable = 1;
+ break;
+ case 'D':
+ ubp->enable = 0;
+ break;
+ case 'R':
+ ubp->removed = 1;
+ break;
+ }
+}
+
+int
+parse_autoload_breakpoint_definition (char *line, struct uploaded_bp **ubpp)
+{
+ ULONGEST id;
+ char cmd;
+ struct uploaded_bp *ubp, *ubp_tmp;
+
+ /* Get id. */
+ line = unpack_varlen_hex (line, &id);
+ if (line[0] != ':')
+ return -1;
+ if (strlen (line) < 2)
+ return -1;
+ line += 1;
+
+ cmd = line[0];
+ if (line[1] == ':')
+ line += 2;
+ else
+ line += 1;
+
+ if ((cmd == 'C' || cmd == 'O') && id == 0)
+ return -1;
+
+ for (ubp = *ubpp; ubp ? (ubp_tmp = ubp->next, 1): 0; ubp = ubp_tmp)
+ {
+ int loop_stop = 0;
+
+ if (ubp->removed)
+ continue;
+
+ switch (cmd)
+ {
+ case 'E':
+ case 'D':
+ case 'R':
+ if (id == 0)
+ handle_autoload_breakpoint_cmd (cmd, ubp);
+ else if (ubp->id == (int)id)
+ {
+ if (line[0] != '\0' && cmd != 'R')
+ {
+ /* Get the ubp that same with the id,
+ change it to new value. */
+ loop_stop = 1;
+ }
+ else
+ {
+ handle_autoload_breakpoint_cmd (cmd, ubp);
+ return 0;
+ }
+ }
+ break;
+ case 'C':
+ case 'O':
+ if (ubp->id == (int)id)
+ loop_stop = 1;
+ break;
+ default:
+ return -1;
+ break;
+ }
+
+ if (loop_stop)
+ break;
+ }
+
+ if (id == 0)
+ return 0;
+
+ switch (cmd)
+ {
+ case 'E':
+ case 'D':
+ {
+ char *b_addr_hex;
+ char *b_addr;
+ enum bptype b_type;
+ ULONGEST ignore_num;
+ int end;
+
+ b_addr_hex = line;
+ line = strchr (line, ':');
+ if (!line)
+ return -1;
+ line[0] = '\0';
+ line += 1;
+ b_addr = alloca (strlen (b_addr_hex) / 2);
+ end = hex2bin (b_addr_hex, (gdb_byte *) b_addr,
+ strlen (b_addr_hex) / 2);
+ b_addr[end] = '\0';
+
+ if (line[0] == 'S')
+ b_type = bp_breakpoint;
+ else if (line[0] == 'H')
+ b_type = bp_hardware_breakpoint;
+ else
+ return -1;
+ if (line[1] != ':' || line[2] == '\0')
+ return -1;
+ line += 2;
+
+ unpack_varlen_hex (line, &ignore_num);
+
+ if (ubp)
+ ubp->removed = 1;
+ ubp = xzalloc (sizeof (struct uploaded_bp));
+
+ ubp->id = (int) id;
+ ubp->enable = (cmd == 'E') ? 1 : 0;
+ ubp->addr_string = xstrdup (b_addr);
+ ubp->type = b_type;
+ ubp->ignore_count = (int) ignore_num;
+
+ for (ubp_tmp = *ubpp; ubp_tmp && ubp_tmp->next;
+ ubp_tmp = ubp_tmp->next)
+ ;
+ if (ubp_tmp)
+ ubp_tmp->next = ubp;
+ else
+ *ubpp = ubp;
+ }
+ break;
+ case 'R':
+ return -1;
+ break;
+ case 'C':
+ case 'O':
+ if (!ubp)
+ return -1;
+ {
+ char buf[strlen(line)/2 + 1];
+ int end;
+
+ end = hex2bin (line, (gdb_byte *) buf, strlen (line) / 2);
+ buf[end] = '\0';
+ if (cmd == 'O')
+ {
+ if (ubp->condition)
+ {
+ xfree (ubp->condition);
+ ubp->condition = NULL;
+ }
+ if (end)
+ ubp->condition = xstrdup (buf);
+ }
+ else
+ {
+ if (end == 0)
+ uploaded_bp_commands_clean (ubp);
+ else
+ uploaded_bp_commands_add (ubp, buf);
+ }
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static void
+handle_autoload_breakpoint_cmd_to_breakpoints (char cmd, struct breakpoint *b)
+{
+ switch (cmd)
+ {
+ case 'E':
+ enable_breakpoint (b);
+ break;
+ case 'D':
+ disable_breakpoint (b);
+ break;
+ case 'R':
+ delete_breakpoint (b);
+ break;
+ }
+}
+
+/* Get autoload breakpoints cmd from LINE. */
+
+int
+parse_autoload_breakpoint_definition_to_breakpoints (char *line)
+{
+ ULONGEST id;
+ char cmd;
+ struct breakpoint *b, *btmp;
+
+ /* Get id. */
+ line = unpack_varlen_hex (line, &id);
+ if (line[0] != ':')
+ return -1;
+ if (strlen (line) < 2)
+ return -1;
+ line += 1;
+
+ cmd = line[0];
+ if (line[1] == ':')
+ line += 2;
+ else
+ line += 1;
+
+ if ((cmd == 'C' || cmd == 'O') && id == 0)
+ return -1;
+
+ ALL_BREAKPOINTS_SAFE (b, btmp)
+ {
+ int loop_stop = 0;
+
+ if (b->autoload_id == 0)
+ continue;
+
+ switch (cmd)
+ {
+ case 'E':
+ case 'D':
+ case 'R':
+ if (id == 0)
+ handle_autoload_breakpoint_cmd_to_breakpoints (cmd, b);
+ else if (b->autoload_id == (int)id)
+ {
+ if (line[0] != '\0' && cmd != 'R')
+ loop_stop = 1;
+ else
+ {
+ handle_autoload_breakpoint_cmd_to_breakpoints (cmd, b);
+ return 0;
+ }
+ }
+ break;
+ case 'C':
+ case 'O':
+ if (b->autoload_id == (int)id)
+ loop_stop = 1;
+ break;
+ default:
+ return -1;
+ break;
+ }
+
+ if (loop_stop)
+ break;
+ }
+
+ if (id == 0)
+ return 0;
+
+ switch (cmd)
+ {
+ case 'E':
+ case 'D':
+ {
+ char *b_addr_hex;
+ char *b_addr;
+ enum bptype b_type;
+ ULONGEST ignore_num;
+ int end;
+
+ b_addr_hex = line;
+ line = strchr (line, ':');
+ if (!line)
+ return -1;
+ line[0] = '\0';
+ line += 1;
+ b_addr = alloca (strlen (b_addr_hex) / 2);
+ end = hex2bin (b_addr_hex, (gdb_byte *) b_addr,
+ strlen (b_addr_hex) / 2);
+ b_addr[end] = '\0';
+
+ if (line[0] == 'S')
+ b_type = bp_breakpoint;
+ else if (line[0] == 'H')
+ b_type = bp_hardware_breakpoint;
+ else
+ return -1;
+ if (line[1] != ':' || line[2] == '\0')
+ return -1;
+ line += 2;
+
+ unpack_varlen_hex (line, &ignore_num);
+
+ if (b)
+ {
+ if (b->type == b_type && strcmp (b->addr_string, b_addr) == 0)
+ {
+ /* b is same with the breakpoint from stub. */
+ handle_autoload_breakpoint_cmd_to_breakpoints (cmd, b);
+ b->autoload_inserted = 1;
+ return 0;
+ }
+ else
+ {
+ /* Set b to other autoload_id. */
+ b->autoload_id = autoload_breakpoints_get_id ();
+ b->autoload_inserted = 0;
+ }
+ }
+
+ /* Create new breakpoint. */
+ create_breakpoint (get_current_arch (),
+ b_addr,
+ NULL, -1, 0,
+ 0, b_type,
+ (int) ignore_num,
+ AUTO_BOOLEAN_TRUE,
+ &bkpt_breakpoint_ops,
+ 0,
+ (cmd == 'E') ? 1 : 0,
+ 0, 0);
+ b = get_breakpoint (breakpoint_count);
+ b->autoload_id = (int)id;
+ b->autoload_inserted = 1;
+ }
+ break;
+ case 'R':
+ return -1;
+ break;
+ case 'C':
+ case 'O':
+ if (!b)
+ return -1;
+ {
+ char buf[strlen(line)/2 + 1];
+ int end;
+
+ end = hex2bin (line, (gdb_byte *) buf, strlen (line) / 2);
+ buf[end] = '\0';
+ if (cmd == 'O')
+ set_breakpoint_condition (b, buf, 0);
+ else
+ {
+ if (end == 0)
+ breakpoint_set_commands (b, NULL);
+ else
+ breakpoint_add_command (b, buf);
+ }
+ }
+ break;
+ }
+
+ return 0;
+}
+
+void
+clean_upload_autoload_breakpoints (void *p)
+{
+ struct uploaded_bp **ubpp = p;
+ struct uploaded_bp *ubp, *ubp_tmp;
+
+ for (ubp = *ubpp; ubp ? (ubp_tmp = ubp->next, 1): 0; ubp = ubp_tmp)
+ {
+ uploaded_bp_commands_clean (ubp);
+ xfree (ubp);
+ }
+ *ubpp = NULL;
+}
+
+void
+show_upload_autoload_breakpoints (struct uploaded_bp *ubp)
+{
+ struct uploaded_bp *tmp;
+ int number = 0;
+
+ for (tmp = ubp; tmp; tmp = tmp->next)
+ {
+ if (!tmp->removed)
+ number ++;
+ }
+ if (number)
+ printf_filtered (_("Got %d autoload-breakpoints from target\n"), number);
+ else
+ return;
+
+ for (tmp = ubp; tmp; tmp = tmp->next)
+ {
+ if (tmp->removed)
+ continue;
+ printf_filtered (_("Id %d in %s"), tmp->id, tmp->addr_string);
+ if (tmp->condition)
+ printf_filtered (_(" stop only if %s"), tmp->condition);
+ if (tmp->ignore_count)
+ printf_filtered (_(" ignore next %d hits"), tmp->ignore_count);
+ printf_filtered (_("\n"));
+ if (tmp->commands)
+ {
+ struct uploaded_bpcmd *cmd;
+
+ for (cmd = ubp->commands; cmd; cmd = cmd->next)
+ printf_filtered (_(" %s\n"), cmd->str);
+ }
+ }
+}
+
+struct uploaded_bpcmd *this_ubpcmd = NULL;
+
+static char *
+read_autoload_breakpoints_action (void)
+{
+ char *ret = NULL;
+
+ if (this_ubpcmd)
+ {
+ ret = this_ubpcmd->str;
+ this_ubpcmd = this_ubpcmd->next;
+ }
+
+ return ret;
+}
+
+void
+merge_uploaded_autoload_breakpoints (struct uploaded_bp *ubp)
+{
+ for (; ubp; ubp = ubp->next)
+ {
+ struct breakpoint *b;
+
+ if (ubp->removed)
+ continue;
+
+ ALL_BREAKPOINTS(b)
+ {
+ if (b->autoload_inserted)
+ continue;
+
+ if (b->autoload_id == ubp->id)
+ {
+ if (strcmp (b->addr_string, ubp->addr_string) == 0)
+ {
+ printf_filtered (_("\
+Assuming autoload-breakpoints %d in GDB is same as target's\n\
+autoload-breakpoints %d at %s.\n"),
+ b->number, ubp->id, ubp->addr_string);
+ b->autoload_inserted = 1;
+ break;
+ }
+ else
+ {
+ b->autoload_id = autoload_breakpoints_get_id ();
+ printf_filtered (_("\
+Change breakpoint %d's autoload-breakpoints id to %d.\n"),
+ b->number, b->autoload_id);
+ }
+ }
+ }
+
+ if (!b)
+ {
+ /* Create new breakpoint. */
+ if (!create_breakpoint (get_current_arch (),
+ ubp->addr_string,
+ ubp->condition, -1, 0,
+ 0, ubp->type,
+ ubp->ignore_count,
+ AUTO_BOOLEAN_TRUE,
+ &bkpt_breakpoint_ops,
+ 0,
+ ubp->enable,
+ 0, 0))
+ {
+ printf_filtered (_("\
+Create breakpoint for autoload-breakpoint %d got error.\n"),
+ ubp->id);
+ continue;
+ }
+ b = get_breakpoint (breakpoint_count);
+ b->autoload_id = ubp->id;
+ b->autoload_inserted = 1;
+ if (ubp->commands)
+ {
+ struct command_line *cmd_list;
+
+ this_ubpcmd = ubp->commands;
+ cmd_list = read_command_lines_1 (read_autoload_breakpoints_action,
+ 1, NULL, NULL);
+ breakpoint_set_commands (b, cmd_list);
+ }
+ printf_filtered (_("\
+Create breakpoint %d for autoload-breakpoint %d.\n"),
+ b->number, b->autoload_id);
+ }
+ }
+}
+
+void
+autoload_breakpoints_reset (void)
+{
+ struct breakpoint *b;
+
+ ALL_BREAKPOINTS(b)
+ b->autoload_inserted = 0;
+}
+
+void
+autoload_breakpoints_clean (void)
+{
+ struct breakpoint *b, *btmp;
+
+ ALL_BREAKPOINTS_SAFE (b, btmp)
+ {
+ if (b->autoload_id)
+ delete_breakpoint (b);
+ }
+}
+
+int
+autoload_breakpoints_number (void)
+{
+ int ret = 0;
+ struct breakpoint *b;
+
+ ALL_BREAKPOINTS(b)
+ {
+ if (b->autoload_id)
+ ret ++;
+ }
+
+ return ret;
+}
+
void
initialize_breakpoint_ops (void)
{
@@ -15713,6 +16358,24 @@ In this case, if gdb is controlling the
behaves as if always-inserted mode is on; if gdb is controlling the\n\
inferior in all-stop mode, gdb behaves as if always-inserted mode is off."),
NULL,
+ NULL,
+ &breakpoint_set_cmdlist,
+ &breakpoint_show_cmdlist);
+
+ add_setshow_enum_cmd ("autoload", class_support,
+ autoload_breakpoints_enums, &autoload_breakpoints_mode,
+ _("\
+Set mode for autoload-breakpoints."), _("\
+Show mode for autoload-breakpoints."), _("\
+When this mode is \"query\" (the default mode), will query when got the\n\
+autoload-breakpoints.\n\
+When this mode is \"merge\", the autoload-breakpoints\n\
+of GDB and stub will merge together when GDB connect to stub.\n\
+When this mode is \"gdb\", the autoload-breakpoints of stub will be removed\n\
+when GDB connect to stub.\n\
+When this mode is \"stub\", the autoload-breakpoints of GDB will be removed\n\
+when GDB connect to stub."),
+ NULL,
&show_always_inserted_mode,
&breakpoint_set_cmdlist,
&breakpoint_show_cmdlist);
--- a/breakpoint.h
+++ b/breakpoint.h
@@ -705,6 +705,9 @@ struct breakpoint
can sometimes be NULL for enabled GDBs as not all breakpoint
types are tracked by the Python scripting API. */
struct breakpoint_object *py_bp_object;
+
+ int autoload_id;
+ int autoload_inserted;
};
/* An instance of this type is used to represent a watchpoint. It
@@ -1055,6 +1058,25 @@ struct bpstats
enum bp_print_how print_it;
};
+struct uploaded_bpcmd
+ {
+ struct uploaded_bpcmd *next;
+ char *str;
+ };
+
+struct uploaded_bp
+ {
+ int removed;
+ struct uploaded_bp *next;
+ int id;
+ int enable;
+ char *addr_string;
+ enum bptype type;
+ int ignore_count;
+ char *condition;
+ struct uploaded_bpcmd *commands;
+ };
+
enum inf_context
{
inf_starting,
@@ -1071,8 +1093,14 @@ enum breakpoint_here
ordinary_breakpoint_here,
permanent_breakpoint_here
};
-
+extern const char autoload_breakpoints_query[];
+extern const char autoload_breakpoints_merge[];
+extern const char autoload_breakpoints_gdb[];
+extern const char autoload_breakpoints_stub[];
+extern const char *autoload_breakpoints_mode;
+
+
/* Prototypes for breakpoint-related functions. */
extern enum breakpoint_here breakpoint_here_p (struct address_space *,
@@ -1336,6 +1364,8 @@ extern void enable_breakpoint (struct br
extern void breakpoint_set_commands (struct breakpoint *b,
struct command_line *commands);
+extern struct command_line * breakpoint_get_commands (struct breakpoint *b);
+
extern void breakpoint_set_silent (struct breakpoint *b, int silent);
extern void breakpoint_set_thread (struct breakpoint *b, int thread);
@@ -1482,4 +1512,21 @@ extern void handle_solib_event (void);
extern void bp_location_remove_fail_chain_remove (struct bp_location *bl);
+extern void autoload_breakpoints_reset (void);
+
+extern void autoload_breakpoints_clean (void);
+
+extern int autoload_breakpoints_number (void);
+
+extern int parse_autoload_breakpoint_definition (char *line,
+ struct uploaded_bp **ubpp);
+
+extern int parse_autoload_breakpoint_definition_to_breakpoints (char *line);
+
+extern void clean_upload_autoload_breakpoints (void *p);
+
+extern void show_upload_autoload_breakpoints (struct uploaded_bp *ubp);
+
+extern void merge_uploaded_autoload_breakpoints (struct uploaded_bp *ubp);
+
#endif /* !defined (BREAKPOINT_H) */
--- a/remote.c
+++ b/remote.c
@@ -214,6 +214,10 @@ static int remote_get_trace_status (stru
static int remote_upload_tracepoints (struct uploaded_tp **utpp);
static int remote_upload_trace_state_variables (struct uploaded_tsv **utsvp);
+
+static int remote_upload_autoload_breakpoints (struct uploaded_bp **ubpp);
+
+static void remote_download_autoload_breakpoints (void);
static void remote_query_supported (void);
@@ -1297,6 +1301,7 @@ enum {
PACKET_QDisableRandomization,
PACKET_QAgent,
PACKET_ReportAsync,
+ PACKET_AutoloadBreakpoints,
PACKET_MAX
};
@@ -3540,6 +3545,52 @@ remote_start_remote (int from_tty, struc
up. */
rs->starting_up = 0;
+ /* Get autoload-breakpoints from stub. */
+ if (remote_protocol_packets[PACKET_AutoloadBreakpoints].support
+ != PACKET_DISABLE)
+ {
+ static struct uploaded_bp *uploaded_bps = NULL;
+ struct cleanup *old_chain = make_cleanup
+ (clean_upload_autoload_breakpoints,
+ &uploaded_bps);
+ int num;
+
+ if ((autoload_breakpoints_mode == autoload_breakpoints_stub)
+ || (autoload_breakpoints_mode == autoload_breakpoints_query
+ && (num = autoload_breakpoints_number ())
+ && query (_("Remove %d autoload-breakpoints in GDB?"), num)))
+ autoload_breakpoints_clean ();
+ else
+ autoload_breakpoints_reset ();
+
+ if (autoload_breakpoints_mode != autoload_breakpoints_gdb)
+ {
+ remote_upload_autoload_breakpoints (&uploaded_bps);
+ show_upload_autoload_breakpoints (uploaded_bps);
+ }
+ else
+ {
+ /* Remove all the autoload-breakpoints in stub part. */
+ snprintf (rs->buf, rs->buf_size, "QBDP0:R");
+ remote_send (&rs->buf, &rs->buf_size);
+ }
+
+ if (autoload_breakpoints_mode == autoload_breakpoints_query)
+ {
+ if (uploaded_bps)
+ {
+ if (!query (_("Add to GDB?")))
+ clean_upload_autoload_breakpoints (&uploaded_bps);
+ }
+ }
+
+ merge_uploaded_autoload_breakpoints (uploaded_bps);
+
+ do_cleanups (old_chain);
+
+ remote_download_autoload_breakpoints ();
+ }
+
/* If breakpoints are global, insert them now. */
if (gdbarch_has_global_breakpoints (target_gdbarch)
&& breakpoints_always_inserted_mode ())
@@ -3938,6 +3989,8 @@ static struct protocol_feature remote_pr
remote_string_tracing_feature, -1 },
{ "ReportAsync", PACKET_DISABLE, remote_supported_packet,
PACKET_ReportAsync },
+ { "AutoloadBreakpoints", PACKET_DISABLE, remote_supported_packet,
+ PACKET_AutoloadBreakpoints },
};
static char *remote_support_xml;
@@ -7919,6 +7972,9 @@ static int
remote_insert_breakpoint (struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
+ if (inside_reportasync_handler)
+ return -1;
+
/* Try the "Z" s/w breakpoint packet if it is not already disabled.
If it succeeds, then set the support to PACKET_ENABLE. If it
fails, and the user has explicitly requested the Z support then
@@ -7974,6 +8030,9 @@ remote_remove_breakpoint (struct gdbarch
CORE_ADDR addr = bp_tgt->placed_address;
struct remote_state *rs = get_remote_state ();
+ if (inside_reportasync_handler)
+ return -1;
+
if (remote_protocol_packets[PACKET_Z0].support != PACKET_DISABLE)
{
char *p = rs->buf;
@@ -8165,6 +8224,9 @@ remote_insert_hw_breakpoint (struct gdba
struct remote_state *rs;
char *p, *endbuf;
+ if (inside_reportasync_handler)
+ return -1;
+
/* The length field should be set to the size of a breakpoint
instruction, even though we aren't inserting one ourselves. */
@@ -8214,6 +8276,9 @@ remote_remove_hw_breakpoint (struct gdba
char *p = rs->buf;
char *endbuf = rs->buf + get_remote_packet_size ();
+ if (inside_reportasync_handler)
+ return -1;
+
if (remote_protocol_packets[PACKET_Z1].support == PACKET_DISABLE)
return -1;
@@ -11165,7 +11230,16 @@ remote_reportasync_handler (struct remot
if (remote_debug)
fprintf_unfiltered (gdb_stdlog, "ReportAsync: %s\n", rs->buf);
- putpkt ("");
+ if (strncmp (rs->buf, "QBDP", strlen ("QBDP")) == 0)
+ {
+ if (parse_autoload_breakpoint_definition_to_breakpoints
+ (rs->buf + strlen ("QBDP")) == 0)
+ putpkt ("OK");
+ else
+ putpkt ("E01");
+ }
+ else
+ putpkt ("");
do_cleanups (old_chain);
}
@@ -11317,6 +11391,83 @@ remote_upload_trace_state_variables (str
return 0;
}
+static int
+remote_upload_autoload_breakpoints (struct uploaded_bp **ubpp)
+{
+ struct remote_state *rs = get_remote_state ();
+ char *p;
+
+ /* Ask for a first packet of autoload-breakpoints definition. */
+ putpkt ("qBfP");
+ getpkt (&rs->buf, &rs->buf_size, 0);
+ p = rs->buf;
+ while (*p && *p != 'l')
+ {
+ parse_autoload_breakpoint_definition (p, ubpp);
+ /* Ask for another packet of autoload-breakpoints definition. */
+ putpkt ("qBsP");
+ getpkt (&rs->buf, &rs->buf_size, 0);
+ p = rs->buf;
+ }
+ return 0;
+}
+
+static void
+remote_download_autoload_breakpoints (void)
+{
+ struct remote_state *rs = get_remote_state ();
+ struct breakpoint *b;
+ extern struct breakpoint *breakpoint_chain;
+
+ for (b = breakpoint_chain; b; b = b->next)
+ {
+ if (b->autoload_id && !b->autoload_inserted)
+ {
+ struct command_line *cmd;
+ char *hex = alloca (strlen (b->addr_string) * 2);
+ int end = bin2hex (b->addr_string, hex, 0);
+
+ hex[end * 2] = '\0';
+ snprintf (rs->buf, rs->buf_size, "QBDP%x:%c:%s:%c:%x",
+ b->autoload_id, (b->enable_state == bp_enabled) ? 'E' : 'D',
+ hex,
+ (b->type == bp_hardware_breakpoint) ? 'H' : 'S',
+ b->ignore_count);
+ remote_send (&rs->buf, &rs->buf_size);
+
+ if (b->cond_string)
+ {
+ char *p = rs->buf;
+ int end;
+
+ snprintf (rs->buf, rs->buf_size, "QBDP%x:O:", b->autoload_id);
+ p += strlen (p);
+ end = bin2hex (b->cond_string, p, strlen (b->cond_string));
+ p[end] = '\0';
+ remote_send (&rs->buf, &rs->buf_size);
+ }
+
+ for (cmd = breakpoint_get_commands (b); cmd; cmd = cmd->next)
+ {
+ char *p = rs->buf;
+ int end;
+
+ snprintf (rs->buf, rs->buf_size, "QBDP%x:C:", b->autoload_id);
+ p += strlen (p);
+ end = bin2hex (cmd->line, p, strlen (cmd->line));
+ p[end] = '\0';
+ remote_send (&rs->buf, &rs->buf_size);
+ }
+
+ b->autoload_inserted = 1;
+
+ printf_filtered (_("\
+Download breakpoint %d to target as autoload-breakpoint %d.\n"),
+ b->number, b->autoload_id);
+ }
+ }
+}
+
void
_initialize_remote (void)
{
@@ -11653,6 +11804,9 @@ Show the maximum size of the address (in
add_packet_config_cmd (&remote_protocol_packets[PACKET_ReportAsync],
"ReportAsync", "report-async", 0);
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_AutoloadBreakpoints],
+ "AutoloadBreakpoints", "autoload-breakpoints", 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
More information about the Gdb-patches
mailing list