X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fremote.c;h=d47dad7e9e5dcbd57139f5b0ab4b8944ce294cde;hb=c45df9bda811929d3135aebd34d53b44ee45fe15;hp=e5b707a2b34509b531a736f9d8fca640dac1741a;hpb=ad10f812bfdac2cc9e42875246c8fe0ae5224440;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/remote.c b/gdb/remote.c index e5b707a2b3..d47dad7e9e 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -1,6 +1,7 @@ /* Remote target communications for serial-line targets in custom GDB protocol - Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, - 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + + Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, + 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. This file is part of GDB. @@ -85,7 +86,7 @@ static void remote_resume (ptid_t ptid, int step, enum target_signal siggnal); static void remote_async_resume (ptid_t ptid, int step, enum target_signal siggnal); -static int remote_start_remote (PTR); +static int remote_start_remote (struct ui_out *uiout, void *dummy); static void remote_open (char *name, int from_tty); static void remote_async_open (char *name, int from_tty); @@ -93,9 +94,8 @@ static void remote_async_open (char *name, int from_tty); static void extended_remote_open (char *name, int from_tty); static void extended_remote_async_open (char *name, int from_tty); -static void remote_open_1 (char *, int, struct target_ops *, int extended_p); -static void remote_async_open_1 (char *, int, struct target_ops *, - int extended_p); +static void remote_open_1 (char *, int, struct target_ops *, int extended_p, + int async_p); static void remote_close (int quitting); @@ -204,13 +204,9 @@ static void show_packet_config_cmd (struct packet_config *config); static void update_packet_config (struct packet_config *config); -/* Define the target subroutine names */ - -void open_remote_target (char *, int, struct target_ops *, int); - void _initialize_remote (void); -/* Description of the remote protocol. Strictly speeking, when the +/* Description of the remote protocol. Strictly speaking, when the target is open()ed, remote.c should create a per-target description of the remote protocol using that target's architecture. Unfortunatly, the target stack doesn't include local state. For @@ -222,6 +218,7 @@ struct packet_reg long offset; /* Offset into G packet. */ long regnum; /* GDB's internal register number. */ LONGEST pnum; /* Remote protocol register number. */ + int in_g_packet; /* Always part of G packet. */ /* long size in bytes; == REGISTER_RAW_SIZE (regnum); at present. */ /* char *name; == REGISTER_NAME (regnum); at present. */ }; @@ -230,7 +227,10 @@ struct remote_state { /* Description of the remote protocol registers. */ long sizeof_g_packet; - struct packet_reg *g_packet; /* NULL terminated. */ + + /* Description of the remote protocol registers indexed by REGNUM + (making an array of NUM_REGS + NUM_PSEUDO_REGS in size). */ + struct packet_reg *regs; /* This is the size (in chars) of the first response to the ``g'' packet. It is used as a heuristic when determining the maximum @@ -245,13 +245,14 @@ struct remote_state long remote_packet_size; }; + /* Handle for retreving the remote protocol data from gdbarch. */ static struct gdbarch_data *remote_gdbarch_data_handle; static struct remote_state * -get_remote_state () +get_remote_state (void) { - return gdbarch_data (remote_gdbarch_data_handle); + return gdbarch_data (current_gdbarch, remote_gdbarch_data_handle); } static void * @@ -264,16 +265,15 @@ init_remote_state (struct gdbarch *gdbarch) behavour - just copy in the description of the register cache. */ rs->sizeof_g_packet = REGISTER_BYTES; /* OK use. */ - /* Since, for the moment, the regcache is still being direct mapped, - there are exactly NUM_REGS. Zero allocate a buffer adding space - for a sentinal. */ - rs->g_packet = xcalloc (NUM_REGS + 1, sizeof (struct packet_reg)); - rs->g_packet[NUM_REGS].offset = -1; - for (regnum = 0; regnum < NUM_REGS; regnum++) + /* Assume a 1:1 regnum<->pnum table. */ + rs->regs = xcalloc (NUM_REGS + NUM_PSEUDO_REGS, sizeof (struct packet_reg)); + for (regnum = 0; regnum < NUM_REGS + NUM_PSEUDO_REGS; regnum++) { - rs->g_packet[regnum].pnum = regnum; - rs->g_packet[regnum].regnum = regnum; - rs->g_packet[regnum].offset = REGISTER_BYTE (regnum); + struct packet_reg *r = &rs->regs[regnum]; + r->pnum = regnum; + r->regnum = regnum; + r->offset = REGISTER_BYTE (regnum); + r->in_g_packet = (regnum < NUM_REGS); /* ...size = REGISTER_RAW_SIZE (regnum); */ /* ...name = REGISTER_NAME (regnum); */ } @@ -306,35 +306,47 @@ static void free_remote_state (struct gdbarch *gdbarch, void *pointer) { struct remote_state *data = pointer; - xfree (data->g_packet); + xfree (data->regs); xfree (data); } static struct packet_reg * packet_reg_from_regnum (struct remote_state *rs, long regnum) { - struct packet_reg *reg; - for (reg = rs->g_packet; reg->offset >= 0; reg++) + if (regnum < 0 && regnum >= NUM_REGS + NUM_PSEUDO_REGS) + return NULL; + else { - if (reg->regnum == regnum) - return reg; + struct packet_reg *r = &rs->regs[regnum]; + gdb_assert (r->regnum == regnum); + return r; } - return NULL; } static struct packet_reg * packet_reg_from_pnum (struct remote_state *rs, LONGEST pnum) { - struct packet_reg *reg; - for (reg = rs->g_packet; reg->offset >= 0; reg++) + int i; + for (i = 0; i < NUM_REGS + NUM_PSEUDO_REGS; i++) { - if (reg->pnum == pnum) - return reg; + struct packet_reg *r = &rs->regs[i]; + if (r->pnum == pnum) + return r; } return NULL; } -/* */ +/* FIXME: graces/2002-08-08: These variables should eventually be + bound to an instance of the target object (as in gdbarch-tdep()), + when such a thing exists. */ + +/* This is set to the data address of the access causing the target + to stop for a watchpoint. */ +static CORE_ADDR remote_watch_data_address; + +/* This is non-zero if taregt stopped for a watchpoint. */ +static int remote_stopped_by_watchpoint_p; + static struct target_ops remote_ops; @@ -577,7 +589,7 @@ struct packet_config { char *name; char *title; - enum cmd_auto_boolean detect; + enum auto_boolean detect; enum packet_support support; }; @@ -596,13 +608,13 @@ update_packet_config (struct packet_config *config) { switch (config->detect) { - case CMD_AUTO_BOOLEAN_TRUE: + case AUTO_BOOLEAN_TRUE: config->support = PACKET_ENABLE; break; - case CMD_AUTO_BOOLEAN_FALSE: + case AUTO_BOOLEAN_FALSE: config->support = PACKET_DISABLE; break; - case CMD_AUTO_BOOLEAN_AUTO: + case AUTO_BOOLEAN_AUTO: config->support = PACKET_SUPPORT_UNKNOWN; break; } @@ -626,12 +638,12 @@ show_packet_config_cmd (struct packet_config *config) } switch (config->detect) { - case CMD_AUTO_BOOLEAN_AUTO: + case AUTO_BOOLEAN_AUTO: printf_filtered ("Support for remote protocol `%s' (%s) packet is auto-detected, currently %s.\n", config->name, config->title, support); break; - case CMD_AUTO_BOOLEAN_TRUE: - case CMD_AUTO_BOOLEAN_FALSE: + case AUTO_BOOLEAN_TRUE: + case AUTO_BOOLEAN_FALSE: printf_filtered ("Support for remote protocol `%s' (%s) packet is currently %s.\n", config->name, config->title, support); break; @@ -642,11 +654,8 @@ static void add_packet_config_cmd (struct packet_config *config, char *name, char *title, - void (*set_func) (char *args, int from_tty, - struct cmd_list_element * - c), - void (*show_func) (char *name, - int from_tty), + cmd_sfunc_ftype *set_func, + cmd_sfunc_ftype *show_func, struct cmd_list_element **set_remote_list, struct cmd_list_element **show_remote_list, int legacy) @@ -658,7 +667,7 @@ add_packet_config_cmd (struct packet_config *config, char *cmd_name; config->name = name; config->title = title; - config->detect = CMD_AUTO_BOOLEAN_AUTO; + config->detect = AUTO_BOOLEAN_AUTO; config->support = PACKET_SUPPORT_UNKNOWN; xasprintf (&set_doc, "Set use of remote protocol `%s' (%s) packet", name, title); @@ -666,12 +675,10 @@ add_packet_config_cmd (struct packet_config *config, name, title); /* set/show TITLE-packet {auto,on,off} */ xasprintf (&cmd_name, "%s-packet", title); - set_cmd = add_set_auto_boolean_cmd (cmd_name, class_obscure, - &config->detect, set_doc, - set_remote_list); - set_cmd->function.sfunc = set_func; - show_cmd = add_cmd (cmd_name, class_obscure, show_func, show_doc, - show_remote_list); + add_setshow_auto_boolean_cmd (cmd_name, class_obscure, + &config->detect, set_doc, show_doc, + set_func, show_func, + set_remote_list, show_remote_list); /* set/show remote NAME-packet {auto,on,off} -- legacy */ if (legacy) { @@ -724,7 +731,7 @@ packet_ok (const char *buf, struct packet_config *config) switch (config->support) { case PACKET_ENABLE: - if (config->detect == CMD_AUTO_BOOLEAN_AUTO) + if (config->detect == AUTO_BOOLEAN_AUTO) /* If the stub previously indicated that the packet was supported then there is a protocol error.. */ error ("Protocol error: %s (%s) conflicting enabled responses.", @@ -759,7 +766,8 @@ set_remote_protocol_qSymbol_packet_cmd (char *args, int from_tty, } static void -show_remote_protocol_qSymbol_packet_cmd (char *args, int from_tty) +show_remote_protocol_qSymbol_packet_cmd (char *args, int from_tty, + struct cmd_list_element *c) { show_packet_config_cmd (&remote_protocol_qSymbol); } @@ -775,7 +783,8 @@ set_remote_protocol_e_packet_cmd (char *args, int from_tty, } static void -show_remote_protocol_e_packet_cmd (char *args, int from_tty) +show_remote_protocol_e_packet_cmd (char *args, int from_tty, + struct cmd_list_element *c) { show_packet_config_cmd (&remote_protocol_e); } @@ -792,7 +801,8 @@ set_remote_protocol_E_packet_cmd (char *args, int from_tty, } static void -show_remote_protocol_E_packet_cmd (char *args, int from_tty) +show_remote_protocol_E_packet_cmd (char *args, int from_tty, + struct cmd_list_element *c) { show_packet_config_cmd (&remote_protocol_E); } @@ -810,7 +820,8 @@ set_remote_protocol_P_packet_cmd (char *args, int from_tty, } static void -show_remote_protocol_P_packet_cmd (char *args, int from_tty) +show_remote_protocol_P_packet_cmd (char *args, int from_tty, + struct cmd_list_element *c) { show_packet_config_cmd (&remote_protocol_P); } @@ -840,7 +851,8 @@ set_remote_protocol_Z_software_bp_packet_cmd (char *args, int from_tty, } static void -show_remote_protocol_Z_software_bp_packet_cmd (char *args, int from_tty) +show_remote_protocol_Z_software_bp_packet_cmd (char *args, int from_tty, + struct cmd_list_element *c) { show_packet_config_cmd (&remote_protocol_Z[Z_PACKET_SOFTWARE_BP]); } @@ -853,7 +865,8 @@ set_remote_protocol_Z_hardware_bp_packet_cmd (char *args, int from_tty, } static void -show_remote_protocol_Z_hardware_bp_packet_cmd (char *args, int from_tty) +show_remote_protocol_Z_hardware_bp_packet_cmd (char *args, int from_tty, + struct cmd_list_element *c) { show_packet_config_cmd (&remote_protocol_Z[Z_PACKET_HARDWARE_BP]); } @@ -866,7 +879,8 @@ set_remote_protocol_Z_write_wp_packet_cmd (char *args, int from_tty, } static void -show_remote_protocol_Z_write_wp_packet_cmd (char *args, int from_tty) +show_remote_protocol_Z_write_wp_packet_cmd (char *args, int from_tty, + struct cmd_list_element *c) { show_packet_config_cmd (&remote_protocol_Z[Z_PACKET_WRITE_WP]); } @@ -879,7 +893,8 @@ set_remote_protocol_Z_read_wp_packet_cmd (char *args, int from_tty, } static void -show_remote_protocol_Z_read_wp_packet_cmd (char *args, int from_tty) +show_remote_protocol_Z_read_wp_packet_cmd (char *args, int from_tty, + struct cmd_list_element *c) { show_packet_config_cmd (&remote_protocol_Z[Z_PACKET_READ_WP]); } @@ -892,7 +907,8 @@ set_remote_protocol_Z_access_wp_packet_cmd (char *args, int from_tty, } static void -show_remote_protocol_Z_access_wp_packet_cmd (char *args, int from_tty) +show_remote_protocol_Z_access_wp_packet_cmd (char *args, int from_tty, + struct cmd_list_element *c) { show_packet_config_cmd (&remote_protocol_Z[Z_PACKET_ACCESS_WP]); } @@ -900,7 +916,7 @@ show_remote_protocol_Z_access_wp_packet_cmd (char *args, int from_tty) /* For compatibility with older distributions. Provide a ``set remote Z-packet ...'' command that updates all the Z packet types. */ -static enum cmd_auto_boolean remote_Z_packet_detect; +static enum auto_boolean remote_Z_packet_detect; static void set_remote_protocol_Z_packet_cmd (char *args, int from_tty, @@ -915,7 +931,8 @@ set_remote_protocol_Z_packet_cmd (char *args, int from_tty, } static void -show_remote_protocol_Z_packet_cmd (char *args, int from_tty) +show_remote_protocol_Z_packet_cmd (char *args, int from_tty, + struct cmd_list_element *c) { int i; for (i = 0; i < NR_Z_PACKET_TYPES; i++) @@ -956,16 +973,16 @@ set_remote_protocol_binary_download_cmd (char *args, } static void -show_remote_protocol_binary_download_cmd (char *args, - int from_tty) +show_remote_protocol_binary_download_cmd (char *args, int from_tty, + struct cmd_list_element *c) { show_packet_config_cmd (&remote_protocol_binary_download); } /* Tokens for use by the asynchronous signal handlers for SIGINT */ -PTR sigint_remote_twice_token; -PTR sigint_remote_token; +static void *sigint_remote_twice_token; +static void *sigint_remote_token; /* These are pointers to hook functions that may be set in order to modify resume/wait behavior for a particular architecture. */ @@ -996,14 +1013,9 @@ record_currthread (int currthread) if (!in_thread_list (pid_to_ptid (currthread))) { add_thread (pid_to_ptid (currthread)); -#ifdef UI_OUT ui_out_text (uiout, "[New "); ui_out_text (uiout, target_pid_to_str (pid_to_ptid (currthread))); ui_out_text (uiout, "]\n"); -#else - printf_filtered ("[New %s]\n", - target_pid_to_str (pid_to_ptid (currthread))); -#endif } } @@ -1101,7 +1113,7 @@ struct gdb_ext_thread_info #define BUF_THREAD_ID_SIZE (OPAQUETHREADBYTES*2) -char *unpack_varlen_hex (char *buff, int *result); +char *unpack_varlen_hex (char *buff, ULONGEST *result); static char *unpack_nibble (char *buf, int *val); @@ -1222,7 +1234,7 @@ stub_unpack_int (char *buff, int fieldlength) char * unpack_varlen_hex (char *buff, /* packet to parse */ - int *result) + ULONGEST *result) { int nibble; int retval = 0; @@ -2106,14 +2118,16 @@ remote_cisco_objfile_relocate (bfd_signed_vma text_off, bfd_signed_vma data_off, /* Stub for catch_errors. */ static int -remote_start_remote_dummy (void *dummy) +remote_start_remote_dummy (struct ui_out *uiout, void *dummy) { start_remote (); /* Initialize gdb process mechanisms */ + /* NOTE: Return something >=0. A -ve value is reserved for + catch_exceptions. */ return 1; } static int -remote_start_remote (PTR dummy) +remote_start_remote (struct ui_out *uiout, void *dummy) { immediate_quit++; /* Allow user to interrupt it */ @@ -2130,7 +2144,9 @@ remote_start_remote (PTR dummy) putpkt ("?"); /* initiate a query from remote machine */ immediate_quit--; - return remote_start_remote_dummy (dummy); + /* NOTE: See comment above in remote_start_remote_dummy(). This + function returns something >=0. */ + return remote_start_remote_dummy (uiout, dummy); } /* Open a connection to a remote debugger. @@ -2139,14 +2155,14 @@ remote_start_remote (PTR dummy) static void remote_open (char *name, int from_tty) { - remote_open_1 (name, from_tty, &remote_ops, 0); + remote_open_1 (name, from_tty, &remote_ops, 0, 0); } /* Just like remote_open, but with asynchronous support. */ static void remote_async_open (char *name, int from_tty) { - remote_async_open_1 (name, from_tty, &remote_async_ops, 0); + remote_open_1 (name, from_tty, &remote_async_ops, 0, 1); } /* Open a connection to a remote debugger using the extended @@ -2155,14 +2171,16 @@ remote_async_open (char *name, int from_tty) static void extended_remote_open (char *name, int from_tty) { - remote_open_1 (name, from_tty, &extended_remote_ops, 1 /*extended_p */ ); + remote_open_1 (name, from_tty, &extended_remote_ops, 1 /*extended_p */, + 0 /* async_p */); } /* Just like extended_remote_open, but with asynchronous support. */ static void extended_remote_async_open (char *name, int from_tty) { - remote_async_open_1 (name, from_tty, &extended_async_remote_ops, 1 /*extended_p */ ); + remote_open_1 (name, from_tty, &extended_async_remote_ops, + 1 /*extended_p */, 1 /* async_p */); } /* Generic code for opening a connection to a remote target. */ @@ -2221,122 +2239,46 @@ remote_check_symbols (struct objfile *objfile) } } -static void -remote_open_1 (char *name, int from_tty, struct target_ops *target, - int extended_p) +static struct serial * +remote_serial_open (char *name) { - struct remote_state *rs = get_remote_state (); - if (name == 0) - error ("To open a remote debug connection, you need to specify what\n\ -serial device is attached to the remote system\n\ -(e.g. /dev/ttyS0, /dev/ttya, COM1, etc.)."); - - /* See FIXME above */ - wait_forever_enabled_p = 1; - - target_preopen (from_tty); + static int udp_warning = 0; - unpush_target (target); - - remote_desc = serial_open (name); - if (!remote_desc) - perror_with_name (name); - - if (baud_rate != -1) + /* FIXME: Parsing NAME here is a hack. But we want to warn here instead + of in ser-tcp.c, because it is the remote protocol assuming that the + serial connection is reliable and not the serial connection promising + to be. */ + if (!udp_warning && strncmp (name, "udp:", 4) == 0) { - if (serial_setbaudrate (remote_desc, baud_rate)) - { - serial_close (remote_desc); - perror_with_name (name); - } + warning ("The remote protocol may be unreliable over UDP."); + warning ("Some events may be lost, rendering further debugging " + "impossible."); + udp_warning = 1; } - serial_raw (remote_desc); - - /* If there is something sitting in the buffer we might take it as a - response to a command, which would be bad. */ - serial_flush_input (remote_desc); - - if (from_tty) - { - puts_filtered ("Remote debugging using "); - puts_filtered (name); - puts_filtered ("\n"); - } - push_target (target); /* Switch to using remote target now */ - - init_all_packet_configs (); - - general_thread = -2; - continue_thread = -2; - - /* Probe for ability to use "ThreadInfo" query, as required. */ - use_threadinfo_query = 1; - use_threadextra_query = 1; - - /* Without this, some commands which require an active target (such - as kill) won't work. This variable serves (at least) double duty - as both the pid of the target process (if it has such), and as a - flag indicating that a target is active. These functions should - be split out into seperate variables, especially since GDB will - someday have a notion of debugging several processes. */ - - inferior_ptid = pid_to_ptid (MAGIC_NULL_PID); -#ifdef SOLIB_CREATE_INFERIOR_HOOK - /* First delete any symbols previously loaded from shared libraries. */ - no_shared_libraries (NULL, 0); -#endif - - /* Start the remote connection; if error (0), discard this target. - In particular, if the user quits, be sure to discard it - (we'd be in an inconsistent state otherwise). */ - if (!catch_errors (remote_start_remote, NULL, - "Couldn't establish connection to remote target\n", - RETURN_MASK_ALL)) - { - pop_target (); - return; - } - - if (extended_p) - { - /* Tell the remote that we are using the extended protocol. */ - char *buf = alloca (rs->remote_packet_size); - putpkt ("!"); - getpkt (buf, (rs->remote_packet_size), 0); - } -#ifdef SOLIB_CREATE_INFERIOR_HOOK - /* FIXME: need a master target_open vector from which all - remote_opens can be called, so that stuff like this can - go there. Failing that, the following code must be copied - to the open function for any remote target that wants to - support svr4 shared libraries. */ - - /* Set up to detect and load shared libraries. */ - if (exec_bfd) /* No use without an exec file. */ - { - SOLIB_CREATE_INFERIOR_HOOK (PIDGET (inferior_ptid)); - remote_check_symbols (symfile_objfile); - } -#endif + return serial_open (name); } -/* Just like remote_open but with asynchronous support. */ static void -remote_async_open_1 (char *name, int from_tty, struct target_ops *target, - int extended_p) +remote_open_1 (char *name, int from_tty, struct target_ops *target, + int extended_p, int async_p) { + int ex; struct remote_state *rs = get_remote_state (); if (name == 0) - error ("To open a remote debug connection, you need to specify what\n\ -serial device is attached to the remote system\n\ -(e.g. /dev/ttyS0, /dev/ttya, COM1, etc.)."); + error ("To open a remote debug connection, you need to specify what\n" + "serial device is attached to the remote system\n" + "(e.g. /dev/ttyS0, /dev/ttya, COM1, etc.)."); + + /* See FIXME above */ + if (!async_p) + wait_forever_enabled_p = 1; target_preopen (from_tty); unpush_target (target); - remote_desc = serial_open (name); + remote_desc = remote_serial_open (name); if (!remote_desc) perror_with_name (name); @@ -2361,11 +2303,10 @@ serial device is attached to the remote system\n\ puts_filtered (name); puts_filtered ("\n"); } - push_target (target); /* Switch to using remote target now */ init_all_packet_configs (); - + general_thread = -2; continue_thread = -2; @@ -2379,38 +2320,59 @@ serial device is attached to the remote system\n\ flag indicating that a target is active. These functions should be split out into seperate variables, especially since GDB will someday have a notion of debugging several processes. */ - inferior_ptid = pid_to_ptid (MAGIC_NULL_PID); - /* With this target we start out by owning the terminal. */ - remote_async_terminal_ours_p = 1; + inferior_ptid = pid_to_ptid (MAGIC_NULL_PID); - /* FIXME: cagney/1999-09-23: During the initial connection it is - assumed that the target is already ready and able to respond to - requests. Unfortunately remote_start_remote() eventually calls - wait_for_inferior() with no timeout. wait_forever_enabled_p gets - around this. Eventually a mechanism that allows - wait_for_inferior() to expect/get timeouts will be - implemented. */ - wait_forever_enabled_p = 0; + if (async_p) + { + /* With this target we start out by owning the terminal. */ + remote_async_terminal_ours_p = 1; + + /* FIXME: cagney/1999-09-23: During the initial connection it is + assumed that the target is already ready and able to respond to + requests. Unfortunately remote_start_remote() eventually calls + wait_for_inferior() with no timeout. wait_forever_enabled_p gets + around this. Eventually a mechanism that allows + wait_for_inferior() to expect/get timeouts will be + implemented. */ + wait_forever_enabled_p = 0; + } #ifdef SOLIB_CREATE_INFERIOR_HOOK /* First delete any symbols previously loaded from shared libraries. */ no_shared_libraries (NULL, 0); #endif - /* Start the remote connection; if error (0), discard this target. - In particular, if the user quits, be sure to discard it - (we'd be in an inconsistent state otherwise). */ - if (!catch_errors (remote_start_remote, NULL, - "Couldn't establish connection to remote target\n", - RETURN_MASK_ALL)) + /* Start the remote connection. If error() or QUIT, discard this + target (we'd otherwise be in an inconsistent state) and then + propogate the error on up the exception chain. This ensures that + the caller doesn't stumble along blindly assuming that the + function succeeded. The CLI doesn't have this problem but other + UI's, such as MI do. + + FIXME: cagney/2002-05-19: Instead of re-throwing the exception, + this function should return an error indication letting the + caller restore the previous state. Unfortunatly the command + ``target remote'' is directly wired to this function making that + impossible. On a positive note, the CLI side of this problem has + been fixed - the function set_cmd_context() makes it possible for + all the ``target ....'' commands to share a common callback + function. See cli-dump.c. */ + ex = catch_exceptions (uiout, + remote_start_remote, NULL, + "Couldn't establish connection to remote" + " target\n", + RETURN_MASK_ALL); + if (ex < 0) { pop_target (); - wait_forever_enabled_p = 1; - return; + if (async_p) + wait_forever_enabled_p = 1; + throw_exception (ex); } - wait_forever_enabled_p = 1; + if (async_p) + wait_forever_enabled_p = 1; if (extended_p) { @@ -2876,7 +2838,7 @@ interrupt_query (void) Give up (and stop debugging it)? ")) { target_mourn_inferior (); - return_to_top_level (RETURN_QUIT); + throw_exception (RETURN_QUIT); } target_terminal_inferior (); @@ -2957,7 +2919,8 @@ remote_wait (ptid_t ptid, struct target_waitstatus *status) { struct remote_state *rs = get_remote_state (); unsigned char *buf = alloca (rs->remote_packet_size); - int thread_num = -1; + ULONGEST thread_num = -1; + ULONGEST addr; status->kind = TARGET_WAITKIND_EXITED; status->value.integer = 0; @@ -2975,6 +2938,8 @@ remote_wait (ptid_t ptid, struct target_waitstatus *status) if (target_wait_loop_hook) (*target_wait_loop_hook) (); + remote_stopped_by_watchpoint_p = 0; + switch (buf[0]) { case 'E': /* Error of some sort */ @@ -2998,24 +2963,52 @@ remote_wait (ptid_t ptid, struct target_waitstatus *status) unsigned char *p1; char *p_temp; int fieldsize; + LONGEST pnum = 0; - /* Read the ``P'' register number. */ - LONGEST pnum = strtol ((const char *) p, &p_temp, 16); - p1 = (unsigned char *) p_temp; + /* If the packet contains a register number save it in pnum + and set p1 to point to the character following it. + Otherwise p1 points to p. */ + + /* If this packet is an awatch packet, don't parse the 'a' + as a register number. */ + + if (strncmp (p, "awatch", strlen("awatch")) != 0) + { + /* Read the ``P'' register number. */ + pnum = strtol (p, &p_temp, 16); + p1 = (unsigned char *) p_temp; + } + else + p1 = p; if (p1 == p) /* No register number present here */ { - p1 = (unsigned char *) strchr ((const char *) p, ':'); + p1 = (unsigned char *) strchr (p, ':'); if (p1 == NULL) warning ("Malformed packet(a) (missing colon): %s\n\ Packet: '%s'\n", p, buf); - if (strncmp ((const char *) p, "thread", p1 - p) == 0) + if (strncmp (p, "thread", p1 - p) == 0) { p_temp = unpack_varlen_hex (++p1, &thread_num); record_currthread (thread_num); p = (unsigned char *) p_temp; } + else if ((strncmp (p, "watch", p1 - p) == 0) + || (strncmp (p, "rwatch", p1 - p) == 0) + || (strncmp (p, "awatch", p1 - p) == 0)) + { + remote_stopped_by_watchpoint_p = 1; + p = unpack_varlen_hex (++p1, &addr); + remote_watch_data_address = (CORE_ADDR)addr; + } + else + { + /* Silently skip unknown optional info. */ + p_temp = strchr (p1 + 1, ';'); + if (p_temp) + p = (unsigned char *) p_temp; + } } else { @@ -3171,11 +3164,14 @@ remote_async_wait (ptid_t ptid, struct target_waitstatus *status) { struct remote_state *rs = get_remote_state (); unsigned char *buf = alloca (rs->remote_packet_size); - int thread_num = -1; + ULONGEST thread_num = -1; + ULONGEST addr; status->kind = TARGET_WAITKIND_EXITED; status->value.integer = 0; + remote_stopped_by_watchpoint_p = 0; + while (1) { unsigned char *p; @@ -3218,25 +3214,54 @@ remote_async_wait (ptid_t ptid, struct target_waitstatus *status) unsigned char *p1; char *p_temp; int fieldsize; + long pnum = 0; - /* Read the register number */ - long pnum = strtol ((const char *) p, &p_temp, 16); - p1 = (unsigned char *) p_temp; + /* If the packet contains a register number, save it in pnum + and set p1 to point to the character following it. + Otherwise p1 points to p. */ + + /* If this packet is an awatch packet, don't parse the 'a' + as a register number. */ + + if (!strncmp (p, "awatch", strlen ("awatch")) != 0) + { + /* Read the register number. */ + pnum = strtol (p, &p_temp, 16); + p1 = (unsigned char *) p_temp; + } + else + p1 = p; if (p1 == p) /* No register number present here */ { - p1 = (unsigned char *) strchr ((const char *) p, ':'); + p1 = (unsigned char *) strchr (p, ':'); if (p1 == NULL) warning ("Malformed packet(a) (missing colon): %s\n\ Packet: '%s'\n", p, buf); - if (strncmp ((const char *) p, "thread", p1 - p) == 0) + if (strncmp (p, "thread", p1 - p) == 0) { p_temp = unpack_varlen_hex (++p1, &thread_num); record_currthread (thread_num); p = (unsigned char *) p_temp; } + else if ((strncmp (p, "watch", p1 - p) == 0) + || (strncmp (p, "rwatch", p1 - p) == 0) + || (strncmp (p, "awatch", p1 - p) == 0)) + { + remote_stopped_by_watchpoint_p = 1; + p = unpack_varlen_hex (++p1, &addr); + remote_watch_data_address = (CORE_ADDR)addr; + } + else + { + /* Silently skip unknown optional info. */ + p_temp = (unsigned char *) strchr (p1 + 1, ';'); + if (p_temp) + p = p_temp; + } } + else { struct packet_reg *reg = packet_reg_from_pnum (rs, pnum); @@ -3406,6 +3431,16 @@ remote_fetch_registers (int regnum) set_thread (PIDGET (inferior_ptid), 1); + if (regnum >= 0) + { + struct packet_reg *reg = packet_reg_from_regnum (rs, regnum); + gdb_assert (reg != NULL); + if (!reg->in_g_packet) + internal_error (__FILE__, __LINE__, + "Attempt to fetch a non G-packet register when this " + "remote.c does not support the p-packet."); + } + sprintf (buf, "g"); remote_send (buf, (rs->remote_packet_size)); @@ -3462,14 +3497,18 @@ remote_fetch_registers (int regnum) warning ("Remote reply is too short: %s", buf); } -supply_them: + supply_them: { - struct packet_reg *g; - for (g = rs->g_packet; g->offset >= 0; g++) + int i; + for (i = 0; i < NUM_REGS + NUM_PSEUDO_REGS; i++) { - supply_register (g->regnum, regs + g->offset); - if (buf[g->offset * 2] == 'x') - set_register_cached (i, -1); + struct packet_reg *r = &rs->regs[i]; + if (r->in_g_packet) + { + supply_register (r->regnum, regs + r->offset); + if (buf[r->offset * 2] == 'x') + set_register_cached (i, -1); + } } } } @@ -3489,7 +3528,8 @@ remote_prepare_to_store (void) /* NOTE: This isn't rs->sizeof_g_packet because here, we are forcing the register cache to read its and not the target registers. */ - read_register_bytes (0, (char *) NULL, REGISTER_BYTES); /* OK use. */ + deprecated_read_register_bytes (0, (char *) NULL, + REGISTER_BYTES); /* OK use. */ break; case PACKET_ENABLE: break; @@ -3566,12 +3606,14 @@ remote_store_registers (int regnum) /* Extract all the registers in the regcache copying them into a local buffer. */ { - struct packet_reg *g; + int i; regs = alloca (rs->sizeof_g_packet); memset (regs, rs->sizeof_g_packet, 0); - for (g = rs->g_packet; g->offset >= 0; g++) + for (i = 0; i < NUM_REGS + NUM_PSEUDO_REGS; i++) { - regcache_collect (g->regnum, regs + g->offset); + struct packet_reg *r = &rs->regs[i]; + if (r->in_g_packet) + regcache_collect (r->regnum, regs + r->offset); } } @@ -3887,7 +3929,9 @@ remote_read_bytes (CORE_ADDR memaddr, char *myaddr, int len) putpkt (buf); getpkt (buf, sizeof_buf, 0); - if (buf[0] == 'E') + if (buf[0] == 'E' + && isxdigit (buf[1]) && isxdigit (buf[2]) + && buf[3] == '\0') { /* There is no correspondance between what the remote protocol uses for errors and errno codes. We would like a cleaner way of @@ -3922,8 +3966,7 @@ remote_read_bytes (CORE_ADDR memaddr, char *myaddr, int len) /* ARGSUSED */ static int remote_xfer_memory (CORE_ADDR mem_addr, char *buffer, int mem_len, - int should_write, - struct mem_attrib *attrib ATTRIBUTE_UNUSED, + int should_write, struct mem_attrib *attrib, struct target_ops *target) { CORE_ADDR targ_addr; @@ -4660,7 +4703,7 @@ remote_insert_breakpoint (CORE_ADDR addr, char *contents_cache) if (val == 0) { - if (TARGET_BYTE_ORDER == BIG_ENDIAN) + if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) val = target_write_memory (addr, (char *) big_break_insn, sizeof big_break_insn); else @@ -4727,10 +4770,7 @@ watchpoint_to_Z_packet (int type) } } -/* FIXME: This function should be static and a member of the remote - target vector. */ - -int +static int remote_insert_watchpoint (CORE_ADDR addr, int len, int type) { struct remote_state *rs = get_remote_state (); @@ -4764,10 +4804,8 @@ remote_insert_watchpoint (CORE_ADDR addr, int len, int type) "remote_insert_watchpoint: reached end of function"); } -/* FIXME: This function should be static and a member of the remote - target vector. */ -int +static int remote_remove_watchpoint (CORE_ADDR addr, int len, int type) { struct remote_state *rs = get_remote_state (); @@ -4800,16 +4838,60 @@ remote_remove_watchpoint (CORE_ADDR addr, int len, int type) "remote_remove_watchpoint: reached end of function"); } -/* FIXME: This function should be static and a member of the remote - target vector. */ + +int remote_hw_watchpoint_limit = 0; +int remote_hw_breakpoint_limit = 0; + +int +remote_check_watch_resources (int type, int cnt, int ot) +{ + if (type == bp_hardware_breakpoint) + { + if (remote_hw_breakpoint_limit == 0) + return 0; + else if (cnt <= remote_hw_breakpoint_limit) + return 1; + } + else + { + if (remote_hw_watchpoint_limit == 0) + return 0; + else if (ot) + return -1; + else if (cnt <= remote_hw_watchpoint_limit) + return 1; + } + return -1; +} int -remote_insert_hw_breakpoint (CORE_ADDR addr, int len) +remote_stopped_by_watchpoint (void) +{ + return remote_stopped_by_watchpoint_p; +} + +CORE_ADDR +remote_stopped_data_address (void) +{ + if (remote_stopped_by_watchpoint ()) + return remote_watch_data_address; + return (CORE_ADDR)0; +} + + +static int +remote_insert_hw_breakpoint (CORE_ADDR addr, char *shadow) { + int len = 0; struct remote_state *rs = get_remote_state (); char *buf = alloca (rs->remote_packet_size); char *p = buf; + /* The length field should be set to the size of a breakpoint + instruction. */ + + BREAKPOINT_FROM_PC (&addr, &len); + if (remote_protocol_Z[Z_PACKET_HARDWARE_BP].support == PACKET_DISABLE) error ("Can't set hardware breakpoint without the '%s' (%s) packet\n", remote_protocol_Z[Z_PACKET_HARDWARE_BP].name, @@ -4835,19 +4917,23 @@ remote_insert_hw_breakpoint (CORE_ADDR addr, int len) return 0; } internal_error (__FILE__, __LINE__, - "remote_remove_watchpoint: reached end of function"); + "remote_insert_hw_breakpoint: reached end of function"); } -/* FIXME: This function should be static and a member of the remote - target vector. */ -int -remote_remove_hw_breakpoint (CORE_ADDR addr, int len) +static int +remote_remove_hw_breakpoint (CORE_ADDR addr, char *shadow) { + int len; struct remote_state *rs = get_remote_state (); char *buf = alloca (rs->remote_packet_size); char *p = buf; - + + /* The length field should be set to the size of a breakpoint + instruction. */ + + BREAKPOINT_FROM_PC (&addr, &len); + if (remote_protocol_Z[Z_PACKET_HARDWARE_BP].support == PACKET_DISABLE) error ("Can't clear hardware breakpoint without the '%s' (%s) packet\n", remote_protocol_Z[Z_PACKET_HARDWARE_BP].name, @@ -4873,7 +4959,7 @@ remote_remove_hw_breakpoint (CORE_ADDR addr, int len) return 0; } internal_error (__FILE__, __LINE__, - "remote_remove_watchpoint: reached end of function"); + "remote_remove_hw_breakpoint: reached end of function"); } /* Some targets are only capable of doing downloads, and afterwards @@ -4893,18 +4979,6 @@ push_remote_target (char *name, int from_tty) remote_open (name, from_tty); } -/* Other targets want to use the entire remote serial module but with - certain remote_ops overridden. */ - -void -open_remote_target (char *name, int from_tty, struct target_ops *target, - int extended_p) -{ - printf_filtered ("Selecting the %sremote protocol\n", - (extended_p ? "extended-" : "")); - remote_open_1 (name, from_tty, target, extended_p); -} - /* Table used by the crc32 function to calcuate the checksum. */ static unsigned long crc32_table[256] = @@ -4997,8 +5071,8 @@ compare_sections_command (char *args, int from_tty) getpkt (buf, (rs->remote_packet_size), 0); if (buf[0] == 'E') - error ("target memory fault, section %s, range 0x%08x -- 0x%08x", - sectname, lma, lma + size); + error ("target memory fault, section %s, range 0x%s -- 0x%s", + sectname, paddr (lma), paddr (lma + size)); if (buf[0] != 'C') error ("remote target does not support this operation"); @@ -5350,6 +5424,13 @@ Specify the serial device it is connected to\n\ remote_ops.to_files_info = remote_files_info; remote_ops.to_insert_breakpoint = remote_insert_breakpoint; remote_ops.to_remove_breakpoint = remote_remove_breakpoint; + remote_ops.to_stopped_by_watchpoint = remote_stopped_by_watchpoint; + remote_ops.to_stopped_data_address = remote_stopped_data_address; + remote_ops.to_can_use_hw_breakpoint = remote_check_watch_resources; + remote_ops.to_insert_hw_breakpoint = remote_insert_hw_breakpoint; + remote_ops.to_remove_hw_breakpoint = remote_remove_hw_breakpoint; + remote_ops.to_insert_watchpoint = remote_insert_watchpoint; + remote_ops.to_remove_watchpoint = remote_remove_watchpoint; remote_ops.to_kill = remote_kill; remote_ops.to_load = generic_load; remote_ops.to_mourn_inferior = remote_mourn; @@ -5436,10 +5517,10 @@ remote_info_process (char *args, int from_tty) static void remote_cisco_open (char *name, int from_tty) { + int ex; if (name == 0) - error ( - "To open a remote debug connection, you need to specify what \n\ -device is attached to the remote system (e.g. host:port)."); + error ("To open a remote debug connection, you need to specify what \n" + "device is attached to the remote system (e.g. host:port)."); /* See FIXME above */ wait_forever_enabled_p = 1; @@ -5448,7 +5529,7 @@ device is attached to the remote system (e.g. host:port)."); unpush_target (&remote_cisco_ops); - remote_desc = serial_open (name); + remote_desc = remote_serial_open (name); if (!remote_desc) perror_with_name (name); @@ -5499,14 +5580,18 @@ device is attached to the remote system (e.g. host:port)."); someday have a notion of debugging several processes. */ inferior_ptid = pid_to_ptid (MAGIC_NULL_PID); - /* Start the remote connection; if error (0), discard this target. */ - - if (!catch_errors (remote_start_remote_dummy, (char *) 0, - "Couldn't establish connection to remote target\n", - RETURN_MASK_ALL)) + /* Start the remote connection; if error, discard this target. See + the comments in remote_open_1() for further details such as the + need to re-throw the exception. */ + ex = catch_exceptions (uiout, + remote_start_remote_dummy, NULL, + "Couldn't establish connection to remote" + " target\n", + RETURN_MASK_ALL); + if (ex < 0) { pop_target (); - return; + throw_exception (ex); } } @@ -5702,7 +5787,7 @@ minitelnet (void) if (query ("Interrupt GDB? ")) { printf_filtered ("Interrupted by user.\n"); - return_to_top_level (RETURN_QUIT); + throw_exception (RETURN_QUIT); } quit_count = 0; } @@ -5761,7 +5846,14 @@ Specify the serial device it is connected to (e.g. host:2020)."; remote_cisco_ops.to_xfer_memory = remote_xfer_memory; remote_cisco_ops.to_files_info = remote_files_info; remote_cisco_ops.to_insert_breakpoint = remote_insert_breakpoint; - remote_cisco_ops.to_remove_breakpoint = remote_remove_breakpoint; + remote_cisco_ops.to_remove_breakpoint = remote_remove_breakpoint; + remote_cisco_ops.to_remove_hw_breakpoint = remote_remove_hw_breakpoint; + remote_cisco_ops.to_insert_hw_breakpoint = remote_insert_hw_breakpoint; + remote_cisco_ops.to_insert_watchpoint = remote_insert_watchpoint; + remote_cisco_ops.to_remove_watchpoint = remote_remove_watchpoint; + remote_cisco_ops.to_stopped_by_watchpoint = remote_stopped_by_watchpoint; + remote_cisco_ops.to_stopped_data_address = remote_stopped_data_address; + remote_cisco_ops.to_can_use_hw_breakpoint = remote_check_watch_resources; remote_cisco_ops.to_kill = remote_kill; remote_cisco_ops.to_load = generic_load; remote_cisco_ops.to_mourn_inferior = remote_cisco_mourn; @@ -5851,6 +5943,13 @@ Specify the serial device it is connected to (e.g. /dev/ttya)."; remote_async_ops.to_files_info = remote_files_info; remote_async_ops.to_insert_breakpoint = remote_insert_breakpoint; remote_async_ops.to_remove_breakpoint = remote_remove_breakpoint; + remote_async_ops.to_can_use_hw_breakpoint = remote_check_watch_resources; + remote_async_ops.to_insert_hw_breakpoint = remote_insert_hw_breakpoint; + remote_async_ops.to_remove_hw_breakpoint = remote_remove_hw_breakpoint; + remote_async_ops.to_insert_watchpoint = remote_insert_watchpoint; + remote_async_ops.to_remove_watchpoint = remote_remove_watchpoint; + remote_async_ops.to_stopped_by_watchpoint = remote_stopped_by_watchpoint; + remote_async_ops.to_stopped_data_address = remote_stopped_data_address; remote_async_ops.to_terminal_inferior = remote_async_terminal_inferior; remote_async_ops.to_terminal_ours = remote_async_terminal_ours; remote_async_ops.to_kill = remote_async_kill; @@ -5904,13 +6003,14 @@ set_remote_cmd (char *args, int from_tty) static void show_remote_cmd (char *args, int from_tty) { - - show_remote_protocol_Z_packet_cmd (args, from_tty); - show_remote_protocol_e_packet_cmd (args, from_tty); - show_remote_protocol_E_packet_cmd (args, from_tty); - show_remote_protocol_P_packet_cmd (args, from_tty); - show_remote_protocol_qSymbol_packet_cmd (args, from_tty); - show_remote_protocol_binary_download_cmd (args, from_tty); + /* FIXME: cagney/2002-06-15: This function should iterate over + remote_show_cmdlist for a list of sub commands to show. */ + show_remote_protocol_Z_packet_cmd (args, from_tty, NULL); + show_remote_protocol_e_packet_cmd (args, from_tty, NULL); + show_remote_protocol_E_packet_cmd (args, from_tty, NULL); + show_remote_protocol_P_packet_cmd (args, from_tty, NULL); + show_remote_protocol_qSymbol_packet_cmd (args, from_tty, NULL); + show_remote_protocol_binary_download_cmd (args, from_tty, NULL); } static void @@ -6005,11 +6105,11 @@ response packet. GDB supplies the initial `$' character, and the\n\ terminating `#' character and checksum.", &maintenancelist); - add_show_from_set - (add_set_boolean_cmd ("remotebreak", no_class, &remote_break, - "Set whether to send break if interrupted.\n", - &setlist), - &showlist); + add_setshow_boolean_cmd ("remotebreak", no_class, &remote_break, + "Set whether to send break if interrupted.\n", + "Show whether to send break if interrupted.\n", + NULL, NULL, + &setlist, &showlist); /* Install commands for configuring memory read/write packets. */ @@ -6084,6 +6184,10 @@ in a memory packet.\n", show_remote_protocol_e_packet_cmd, &remote_set_cmdlist, &remote_show_cmdlist, 0); + /* Disable by default. The ``e'' packet has nasty interactions with + the threading code - it relies on global state. */ + remote_protocol_e.detect = AUTO_BOOLEAN_FALSE; + update_packet_config (&remote_protocol_e); add_packet_config_cmd (&remote_protocol_E, "E", "step-over-range-w-signal", @@ -6091,6 +6195,10 @@ in a memory packet.\n", show_remote_protocol_E_packet_cmd, &remote_set_cmdlist, &remote_show_cmdlist, 0); + /* Disable by default. The ``e'' packet has nasty interactions with + the threading code - it relies on global state. */ + remote_protocol_E.detect = AUTO_BOOLEAN_FALSE; + update_packet_config (&remote_protocol_E); add_packet_config_cmd (&remote_protocol_P, "P", "set-register", @@ -6135,12 +6243,11 @@ in a memory packet.\n", 0); /* Keep the old ``set remote Z-packet ...'' working. */ - tmpcmd = add_set_auto_boolean_cmd ("Z-packet", class_obscure, - &remote_Z_packet_detect, - "\ -Set use of remote protocol `Z' packets", &remote_set_cmdlist); - tmpcmd->function.sfunc = set_remote_protocol_Z_packet_cmd; - add_cmd ("Z-packet", class_obscure, show_remote_protocol_Z_packet_cmd, - "Show use of remote protocol `Z' packets ", - &remote_show_cmdlist); + add_setshow_auto_boolean_cmd ("Z-packet", class_obscure, + &remote_Z_packet_detect, "\ +Set use of remote protocol `Z' packets", + "Show use of remote protocol `Z' packets ", + set_remote_protocol_Z_packet_cmd, + show_remote_protocol_Z_packet_cmd, + &remote_set_cmdlist, &remote_show_cmdlist); }