From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 16968 invoked by alias); 3 May 2012 16:37:36 -0000 Received: (qmail 16703 invoked by uid 22791); 3 May 2012 16:37:31 -0000 X-SWARE-Spam-Status: No, hits=-3.5 required=5.0 tests=AWL,BAYES_00,KHOP_RCVD_UNTRUST,RCVD_IN_HOSTKARMA_W,RCVD_IN_HOSTKARMA_WL,TW_XZ X-Spam-Check-By: sourceware.org Received: from relay1.mentorg.com (HELO relay1.mentorg.com) (192.94.38.131) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 03 May 2012 16:37:15 +0000 Received: from svr-orw-fem-01.mgc.mentorg.com ([147.34.98.93]) by relay1.mentorg.com with esmtp id 1SPz1m-00006v-I3 from Hui_Zhu@mentor.com ; Thu, 03 May 2012 09:37:14 -0700 Received: from SVR-ORW-FEM-03.mgc.mentorg.com ([147.34.97.39]) by svr-orw-fem-01.mgc.mentorg.com over TLS secured channel with Microsoft SMTPSVC(6.0.3790.4675); Thu, 3 May 2012 09:37:14 -0700 Received: from [127.0.0.1] (147.34.91.1) by svr-orw-fem-03.mgc.mentorg.com (147.34.97.39) with Microsoft SMTP Server id 14.1.289.1; Thu, 3 May 2012 09:37:12 -0700 Message-ID: <4FA2B434.60706@mentor.com> Date: Thu, 03 May 2012 16:37:00 -0000 From: Hui Zhu User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:12.0) Gecko/20120423 Thunderbird/12.0 MIME-Version: 1.0 To: CC: Yao Qi , Stan Shebs , Eli Zaretskii Subject: [PATCH] Autoload-breakpoints without report-async Content-Type: multipart/mixed; boundary="------------030606040108050906010805" X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2012-05/txt/msg00094.txt.bz2 --------------030606040108050906010805 Content-Type: text/plain; charset="ISO-8859-1"; format=flowed Content-Transfer-Encoding: 7bit Content-length: 2472 Hi guys, According to the mail form Yao. I thought make the autoload-breakpoints and report-async function together make it too hard to review. So I move the function that depend on the report-async to be a series of separate patches after report-async. Then the other patches of autoload-breakpoints can be reveiw separate from report-async. Thanks, Hui 2012-05-04 Hui Zhu * breakpoint.c (hex2bin, unpack_varlen_hex): New extern. (autoload_breakpoints_query, autoload_breakpoints_merge, autoload_breakpoints_gdb, autoload_breakpoints_stub, autoload_breakpoints_enums, this_ubpcmd): New variable. (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_reportasync_handler): Add handle for "QBDP". (remote_upload_autoload_breakpoints, remote_download_autoload_breakpoints): New functions. 2012-05-04 Hui Zhu * gdb.texinfo (Setting Breakpoints): Add set breakpoint autoload. (Remote Serial Protocol): Add Autoload-breakpoints Format. --------------030606040108050906010805 Content-Type: text/plain; charset="us-ascii"; name="autoload-breakpoints.txt" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="autoload-breakpoints.txt" Content-length: 19116 --- breakpoint.c | 454 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ breakpoint.h | 49 ++++++ remote.c | 133 +++++++++++++++++ 3 files changed, 635 insertions(+), 1 deletion(-) --- a/breakpoint.c +++ b/breakpoint.c @@ -79,6 +79,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); @@ -470,6 +473,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? */ @@ -1120,6 +1136,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. */ @@ -5837,6 +5862,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 @@ -6554,6 +6587,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 @@ -15074,6 +15109,407 @@ 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; +} + +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, CREATE_BREAKPOINT_FLAGS_INSERTED)) + { + 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) { @@ -15805,6 +16241,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 @@ -709,6 +709,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 @@ -1059,6 +1062,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, @@ -1075,8 +1097,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 *, @@ -1344,6 +1372,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); @@ -1488,4 +1518,21 @@ extern struct gdbarch *get_sal_arch (str extern void handle_solib_event (void); +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); @@ -1284,6 +1288,7 @@ enum { PACKET_qXfer_fdpic, PACKET_QDisableRandomization, PACKET_QAgent, + PACKET_AutoloadBreakpoints, PACKET_MAX }; @@ -3529,6 +3534,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 ()) @@ -3925,6 +3976,8 @@ static struct protocol_feature remote_pr { "QAgent", PACKET_DISABLE, remote_supported_packet, PACKET_QAgent}, { "tracenz", PACKET_DISABLE, remote_string_tracing_feature, -1 }, + { "AutoloadBreakpoints", PACKET_DISABLE, remote_supported_packet, + PACKET_AutoloadBreakpoints }, }; static char *remote_support_xml; @@ -11204,6 +11257,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) { @@ -11537,6 +11667,9 @@ Show the maximum size of the address (in add_packet_config_cmd (&remote_protocol_packets[PACKET_QAgent], "QAgent", "agent", 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 --------------030606040108050906010805 Content-Type: text/plain; charset="us-ascii"; name="autoload-breakpoints-doc.txt" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="autoload-breakpoints-doc.txt" Content-length: 4910 --- doc/gdb.texinfo | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) --- a/doc/gdb.texinfo +++ b/doc/gdb.texinfo @@ -3773,6 +3773,34 @@ not support breakpoint condition evaluat to evaluating all these conditions on the host's side. @end table +Prior to @value{GDBN} connects to remote stub, some breakpoints might +have been already set in target, either by a prior @value{GDBN} session or +by the program itself through some special system API. When @value{GDBN} +connects to target, it should handle these existing breakpoints from +remote stub. We call these breakpoints @dfn{auotload-breakpoints}. + +This feature can be controlled via the following commands: + +@kindex set breakpoint autoload +@kindex show breakpoint autoload +@table @code +@item set breakpoint autoload query +If this option is @samp{query} (the default), @value{GDBN} will query to user +how to handle the autoload-breakpoints when @value{GDBN} connect to the stub. + +@item set breakpoint autoload merge +If this option is @samp{merge}, the autoload-breakpoints of both @value{GDBN} +and of the stub will be kept. + +@item set breakpoint autoload gdb +If this option is @samp{gdb}, the autoload-breakpoints of stub will be removed +when @value{GDBN} connects to stub. + +@item set breakpoint autoload stub +If this option is @samp{stub}, the autoload-breakpoints of GDB will be removed +when @value{GDBN} connects to stub. +@end table + @cindex negative breakpoint numbers @cindex internal @value{GDBN} breakpoints @@ -34333,6 +34361,7 @@ Show the current setting of the target w * Memory Map Format:: * Thread List Format:: * Traceframe Info Format:: +* Autoload-breakpoints Format:: @end menu @node Overview @@ -38936,6 +38965,80 @@ The formal DTD for the traceframe info f length CDATA #REQUIRED> @end smallexample +@node Autoload-breakpoints Format +@section Autoload-breakpoints Format +@cindex autoload-breakpoints format + +@table @samp +@item qBfP +@itemx qBsP +These packets request data in autoload-breakpoints base format +about autoload-breakpoints from the stub. +@value{GDBN} sends @code{qBfP} to get the first piece +of data, and multiple @code{qTsP} to get additional pieces. + +@item @samp{QBDP}@var{autoload-breakpoints base format} +@value{GDBN} and the stub use this packet to control +the autoload-breakpoints in the remote. The stub will translate +this packet through ReportAsync Packets. +@end table + +Autoload-breakpoints base format describes the operation of +the autoload-breakpoints in @value{GDBN} and the stub. + +@table @samp + +@item @var{id}@samp{:}@var{command}@samp{:}@var{addr_string}@samp{:}@var{type}@samp{:}@var{ignore_num} +@table @samp +@item @var{id} +This is the id in hex string format of this command want to control. +this command wants to control. +0 means all autoload-breakpoints. +@item @var{command} +This is the command character, either @samp{E} (for ``enable'') or +@samp{D} (for ``disable''). +If the autoload-breakpoint @var{id} does not exist, create one and +enable or disable it. @value{GDBN} will create this breakpoint as +it have been created in the target. So when the target creates the +breakpoint, it needs to insert this breakpoint by itself. +If the autoload-breakpoint @var{id} does exist, the following items +will be ignored, and the autoload-breakpoint will be enabled or +disabled as specified by @var{command}. +@item @var{addr_string} +This is the address of an autoload-breakpoint to create, encoded +as a hex string. +@item @var{type} +This is the type of the autoload-breakpoint to create, either +@samp{H} (for ``hardware'') or @samp{S} (for ``software''). +@item @var{ignore_num} +This is the ignore count of the autoload-breakpoint to create, +encoded as a hex string. +@end table + +@item @var{id}@samp{:}@samp{R} +This is the remove packet. +@var{id} is the number of the autoload-breakpoint that this command +wants to remove, encoded as a hex string. +0 means all autoload-breakpoints. +When @value{GDBN} get this packet, it will delete this breakpoint +as it have been removed in the target. So when the target send +this packet, it needs to remove these breakpoints in local part by itself. + +@item @var{id}@samp{:}@samp{C}@samp{:}@var{cmd_str} +This packet adds commands in @var{cmd_list} to the command list +of the autoload-breakpoint whose number is @var{id}. +If @var{cmd_str} is empty, the command list will be emptied. +@var{cmd_str} is encoded as hex string. + +@item @var{id}@samp{:}@samp{O}@samp{:}@var{condition_str} +This packet sets the condition of the autoload-breakpoint @var{id} to +be as specified by @var{condition_str}. +If @var{condition_str} is empty, the autoload-breakpoint becomes +unconditional. +@var{condition_str} is encoded as hex string. + +@end table + @include agentexpr.texi @node Target Descriptions --------------030606040108050906010805--