/* Remote target communications for serial-line targets in custom GDB protocol
- Copyright 1988, 1991-2000 Free Software Foundation, Inc.
+ Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+ 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of GDB.
#include "gdb_string.h"
#include <ctype.h>
#include <fcntl.h>
-#include "frame.h"
#include "inferior.h"
#include "bfd.h"
#include "symfile.h"
#include "target.h"
-#include "gdb_wait.h"
/*#include "terminal.h" */
#include "gdbcmd.h"
#include "objfiles.h"
#include "gdb-stabs.h"
#include "gdbthread.h"
#include "remote.h"
-
-#include "dcache.h"
+#include "regcache.h"
#include <ctype.h>
#include <sys/time.h>
#include <signal.h>
#include "serial.h"
+#include "gdbcore.h" /* for exec_bfd */
+
/* Prototypes for local functions */
static void cleanup_sigint_signal_handler (void *dummy);
static void initialize_sigint_signal_handler (void);
static int remote_xfer_memory (CORE_ADDR memaddr, char *myaddr,
int len, int should_write,
+ struct mem_attrib *attrib,
struct target_ops *target);
static void remote_prepare_to_store (void);
config->title = title;
config->detect = CMD_AUTO_BOOLEAN_AUTO;
config->support = PACKET_SUPPORT_UNKNOWN;
- asprintf (&set_doc, "Set use of remote protocol `%s' (%s) packet",
- name, title);
- asprintf (&show_doc, "Show current use of remote protocol `%s' (%s) packet",
- name, title);
+ xasprintf (&set_doc, "Set use of remote protocol `%s' (%s) packet",
+ name, title);
+ xasprintf (&show_doc, "Show current use of remote protocol `%s' (%s) packet",
+ name, title);
/* set/show TITLE-packet {auto,on,off} */
- asprintf (&cmd_name, "%s-packet", title);
+ xasprintf (&cmd_name, "%s-packet", title);
set_cmd = add_set_auto_boolean_cmd (cmd_name, class_obscure,
&config->detect, set_doc,
set_remote_list);
if (legacy)
{
char *legacy_name;
- asprintf (&legacy_name, "%s-packet", name);
+ xasprintf (&legacy_name, "%s-packet", name);
add_alias_cmd (legacy_name, cmd_name, class_obscure, 0,
set_remote_list);
add_alias_cmd (legacy_name, cmd_name, class_obscure, 0,
config->support = PACKET_ENABLE;
break;
case PACKET_DISABLE:
- internal_error ("packet_ok: attempt to use a disabled packet");
+ internal_error (__FILE__, __LINE__,
+ "packet_ok: attempt to use a disabled packet");
break;
case PACKET_ENABLE:
break;
}
}
+/* Should we try the 'e' (step over range) request? */
+static struct packet_config remote_protocol_e;
+
+static void
+set_remote_protocol_e_packet_cmd (char *args, int from_tty,
+ struct cmd_list_element *c)
+{
+ update_packet_config (&remote_protocol_e);
+}
+
+static void
+show_remote_protocol_e_packet_cmd (char *args, int from_tty)
+{
+ show_packet_config_cmd (&remote_protocol_e);
+}
+
+
+/* Should we try the 'E' (step over range / w signal #) request? */
+static struct packet_config remote_protocol_E;
+
+static void
+set_remote_protocol_E_packet_cmd (char *args, int from_tty,
+ struct cmd_list_element *c)
+{
+ update_packet_config (&remote_protocol_E);
+}
+
+static void
+show_remote_protocol_E_packet_cmd (char *args, int from_tty)
+{
+ show_packet_config_cmd (&remote_protocol_E);
+}
+
+
/* Should we try the 'P' (set register) request? */
static struct packet_config remote_protocol_P;
int n = 0; /* position in display_buf */
if (remote_desc == 0) /* paranoia */
- internal_error ("remote_threads_extra_info");
+ internal_error (__FILE__, __LINE__,
+ "remote_threads_extra_info");
if (use_threadextra_query)
{
asection *sect;
bfd *abfd;
int len;
- char *p;
if (symfile_objfile == NULL)
return -1; /* no can do nothin' */
sect != 0;
sect = sect->next)
{
- p = (unsigned char *) bfd_get_section_name (abfd, sect);
+ const char *p = bfd_get_section_name (abfd, sect);
len = strlen (p);
if (strcmp (p + len - 4, "data") == 0) /* ends in "data" */
if (data_base == 0 ||
/* Generic code for opening a connection to a remote target. */
-static DCACHE *remote_dcache;
-
static void
init_all_packet_configs (void)
{
int i;
+ update_packet_config (&remote_protocol_e);
+ update_packet_config (&remote_protocol_E);
update_packet_config (&remote_protocol_P);
for (i = 0; i < NR_Z_PACKET_TYPES; i++)
update_packet_config (&remote_protocol_Z[i]);
unpush_target (target);
- if (!remote_dcache)
- remote_dcache = dcache_init (remote_read_bytes, remote_write_bytes);
- else
- dcache_invd (remote_dcache);
-
remote_desc = SERIAL_OPEN (name);
if (!remote_desc)
perror_with_name (name);
if (extended_p)
{
- /* tell the remote that we're using the extended protocol. */
+ /* Tell the remote that we are using the extended protocol. */
char *buf = alloca (PBUFSIZ);
putpkt ("!");
getpkt (buf, PBUFSIZ, 0);
}
+ /* 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. */
+#ifdef SOLIB_CREATE_INFERIOR_HOOK
+ if (exec_bfd) /* No use without an exec file. */
+ SOLIB_CREATE_INFERIOR_HOOK (inferior_pid);
+#endif
}
/* Just like remote_open but with asynchronous support. */
unpush_target (target);
- remote_dcache = dcache_init (remote_read_bytes, remote_write_bytes);
-
remote_desc = SERIAL_OPEN (name);
if (!remote_desc)
perror_with_name (name);
/* FIXME: cagney/1999-09-23: During the initial connection it is
assumed that the target is already ready and able to respond to
- requests. Unfortunatly remote_start_remote() eventually calls
+ 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
if (extended_p)
{
- /* tell the remote that we're using the extended protocol. */
+ /* Tell the remote that we are using the extended protocol. */
char *buf = alloca (PBUFSIZ);
putpkt ("!");
getpkt (buf, PBUFSIZ, 0);
}
+ /* 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. */
+#ifdef SOLIB_CREATE_INFERIOR_HOOK
+ if (exec_bfd) /* No use without an exec file. */
+ SOLIB_CREATE_INFERIOR_HOOK (inferior_pid);
+#endif
}
/* This takes a program previously attached to and detaches it. After
remote_resume (int pid, int step, enum target_signal siggnal)
{
char *buf = alloca (PBUFSIZ);
+ char *p;
if (pid == -1)
set_thread (0, 0); /* run any thread */
else
set_thread (pid, 0); /* run this thread */
- dcache_invd (remote_dcache);
-
last_sent_signal = siggnal;
last_sent_step = step;
if (target_resume_hook)
(*target_resume_hook) ();
+
+ /* The s/S/c/C packets do not return status. So if the target does
+ not support the S or C packets, the debug agent returns an empty
+ string which is detected in remote_wait(). This protocol defect
+ is fixed in the e/E packets. */
+
+ if (step && step_range_end)
+ {
+ /* If the target does not support the 'E' packet, we try the 'S'
+ packet. Ideally we would fall back to the 'e' packet if that
+ too is not supported. But that would require another copy of
+ the code to issue the 'e' packet (and fall back to 's' if not
+ supported) in remote_wait(). */
+
+ if (siggnal != TARGET_SIGNAL_0)
+ {
+ if (remote_protocol_E.support != PACKET_DISABLE)
+ {
+ p = buf;
+ *p++ = 'E';
+ *p++ = tohex (((int) siggnal >> 4) & 0xf);
+ *p++ = tohex (((int) siggnal) & 0xf);
+ *p++ = ',';
+ p += hexnumstr (p, (ULONGEST) step_range_start);
+ *p++ = ',';
+ p += hexnumstr (p, (ULONGEST) step_range_end);
+ *p++ = 0;
+
+ putpkt (buf);
+ getpkt (buf, PBUFSIZ, 0);
+
+ if (packet_ok(buf, &remote_protocol_E) == PACKET_OK)
+ return;
+ }
+ }
+ else
+ {
+ if (remote_protocol_e.support != PACKET_DISABLE)
+ {
+ p = buf;
+ *p++ = 'e';
+ p += hexnumstr (p, (ULONGEST) step_range_start);
+ *p++ = ',';
+ p += hexnumstr (p, (ULONGEST) step_range_end);
+ *p++ = 0;
+
+ putpkt (buf);
+ getpkt (buf, PBUFSIZ, 0);
+
+ if (packet_ok(buf, &remote_protocol_e) == PACKET_OK)
+ return;
+ }
+ }
+ }
+
if (siggnal != TARGET_SIGNAL_0)
{
buf[0] = step ? 'S' : 'C';
buf[1] = tohex (((int) siggnal >> 4) & 0xf);
- buf[2] = tohex ((int) siggnal & 0xf);
+ buf[2] = tohex (((int) siggnal) & 0xf);
buf[3] = '\0';
}
else
remote_async_resume (int pid, int step, enum target_signal siggnal)
{
char *buf = alloca (PBUFSIZ);
+ char *p;
if (pid == -1)
set_thread (0, 0); /* run any thread */
else
set_thread (pid, 0); /* run this thread */
- dcache_invd (remote_dcache);
-
last_sent_signal = siggnal;
last_sent_step = step;
if (target_resume_hook)
(*target_resume_hook) ();
+ /* The s/S/c/C packets do not return status. So if the target does
+ not support the S or C packets, the debug agent returns an empty
+ string which is detected in remote_wait(). This protocol defect
+ is fixed in the e/E packets. */
+
+ if (step && step_range_end)
+ {
+ /* If the target does not support the 'E' packet, we try the 'S'
+ packet. Ideally we would fall back to the 'e' packet if that
+ too is not supported. But that would require another copy of
+ the code to issue the 'e' packet (and fall back to 's' if not
+ supported) in remote_wait(). */
+
+ if (siggnal != TARGET_SIGNAL_0)
+ {
+ if (remote_protocol_E.support != PACKET_DISABLE)
+ {
+ p = buf;
+ *p++ = 'E';
+ *p++ = tohex (((int) siggnal >> 4) & 0xf);
+ *p++ = tohex (((int) siggnal) & 0xf);
+ *p++ = ',';
+ p += hexnumstr (p, (ULONGEST) step_range_start);
+ *p++ = ',';
+ p += hexnumstr (p, (ULONGEST) step_range_end);
+ *p++ = 0;
+
+ putpkt (buf);
+ getpkt (buf, PBUFSIZ, 0);
+
+ if (packet_ok(buf, &remote_protocol_E) == PACKET_OK)
+ goto register_event_loop;
+ }
+ }
+ else
+ {
+ if (remote_protocol_e.support != PACKET_DISABLE)
+ {
+ p = buf;
+ *p++ = 'e';
+ p += hexnumstr (p, (ULONGEST) step_range_start);
+ *p++ = ',';
+ p += hexnumstr (p, (ULONGEST) step_range_end);
+ *p++ = 0;
+
+ putpkt (buf);
+ getpkt (buf, PBUFSIZ, 0);
+
+ if (packet_ok(buf, &remote_protocol_e) == PACKET_OK)
+ goto register_event_loop;
+ }
+ }
+ }
+
if (siggnal != TARGET_SIGNAL_0)
{
buf[0] = step ? 'S' : 'C';
}
else
strcpy (buf, step ? "s" : "c");
+
+ putpkt (buf);
+register_event_loop:
/* We are about to start executing the inferior, let's register it
with the event loop. NOTE: this is the one place where all the
execution commands end up. We could alternatively do this in each
this information already found in the continuation block? */
if (target_is_async_p ())
target_executing = 1;
- putpkt (buf);
}
\f
{
int i;
long regno;
- char regs[MAX_REGISTER_RAW_SIZE];
+ char* regs = (char*) alloca (MAX_REGISTER_RAW_SIZE);
/* Expedited reply, containing Signal, {regno, reg} repeat */
/* format is: 'Tssn...:r...;n...:r...;n...:r...;#cc', where
{
int i;
long regno;
- char regs[MAX_REGISTER_RAW_SIZE];
+ char* regs = (char*) alloca (MAX_REGISTER_RAW_SIZE);
/* Expedited reply, containing Signal, {regno, reg} repeat */
/* format is: 'Tssn...:r...;n...:r...;n...:r...;#cc', where
char *buf = alloca (PBUFSIZ);
int i;
char *p;
- char regs[REGISTER_BYTES];
+ char *regs = alloca (REGISTER_BYTES);
set_thread (inferior_pid, 1);
if (i != register_bytes_found)
{
register_bytes_found = i;
-#ifdef REGISTER_BYTES_OK
- if (!REGISTER_BYTES_OK (i))
+ if (REGISTER_BYTES_OK_P ()
+ && !REGISTER_BYTES_OK (i))
warning ("Remote reply is too short: %s", buf);
-#endif
}
supply_them:
{
supply_register (i, ®s[REGISTER_BYTE (i)]);
if (buf[REGISTER_BYTE (i) * 2] == 'x')
- register_valid[i] = -1; /* register value not available */
+ set_register_cached (i, -1);
}
}
sprintf (buf, "P%x=", regno);
p = buf + strlen (buf);
- regp = ®isters[REGISTER_BYTE (regno)];
+ regp = register_buffer (regno);
for (i = 0; i < REGISTER_RAW_SIZE (regno); ++i)
{
*p++ = tohex ((regp[i] >> 4) & 0xf);
/* Store register REGNO, or all registers if REGNO == -1, from the contents
- of REGISTERS. FIXME: ignores errors. */
+ of the register cache buffer. FIXME: ignores errors. */
static void
remote_store_registers (int regno)
char *buf = alloca (PBUFSIZ);
int i;
char *p;
+ char *regs;
set_thread (inferior_pid, 1);
/* Command describes registers byte by byte,
each byte encoded as two hex characters. */
+ regs = register_buffer (-1);
p = buf + 1;
/* remote_prepare_to_store insures that register_bytes_found gets set. */
for (i = 0; i < register_bytes_found; i++)
{
- *p++ = tohex ((registers[i] >> 4) & 0xf);
- *p++ = tohex (registers[i] & 0xf);
+ *p++ = tohex ((regs[i] >> 4) & 0xf);
+ *p++ = tohex (regs[i] & 0xf);
}
*p = '\0';
todo = min (len, max_buf_size / 2);
break;
case PACKET_SUPPORT_UNKNOWN:
- internal_error ("remote_write_bytes: bad switch");
+ internal_error (__FILE__, __LINE__,
+ "remote_write_bytes: bad internal state");
+ default:
+ internal_error (__FILE__, __LINE__, "bad switch");
}
/* Append <memaddr> */
*p = '\0';
break;
case PACKET_SUPPORT_UNKNOWN:
- internal_error ("remote_write_bytes: bad switch");
+ internal_error (__FILE__, __LINE__,
+ "remote_write_bytes: bad internal state");
+ default:
+ internal_error (__FILE__, __LINE__, "bad switch");
}
putpkt_binary (buf, (int) (p - buf));
/* Read or write LEN bytes from inferior memory at MEMADDR,
transferring to or from debugger address BUFFER. Write to inferior if
SHOULD_WRITE is nonzero. Returns length of data written or read; 0
- for error. */
+ for error. TARGET is unused. */
/* ARGSUSED */
static int
-remote_xfer_memory (mem_addr, buffer, mem_len, should_write, target)
- CORE_ADDR mem_addr;
- char *buffer;
- int mem_len;
- int should_write;
- struct target_ops *target; /* ignored */
+remote_xfer_memory (CORE_ADDR mem_addr, char *buffer, int mem_len,
+ int should_write,
+ struct mem_attrib *attrib ATTRIBUTE_UNUSED,
+ struct target_ops *target)
{
CORE_ADDR targ_addr;
int targ_len;
+ int res;
+
REMOTE_TRANSLATE_XFER_ADDRESS (mem_addr, mem_len, &targ_addr, &targ_len);
if (targ_len <= 0)
return 0;
- return dcache_xfer_memory (remote_dcache, targ_addr, buffer,
- targ_len, should_write);
+ if (should_write)
+ res = remote_write_bytes (targ_addr, buffer, targ_len);
+ else
+ res = remote_read_bytes (targ_addr, buffer, targ_len);
+
+ return res;
}
/* Enable after 4.12. */
void
-remote_search (len, data, mask, startaddr, increment, lorange, hirange
- addr_found, data_found)
- int len;
- char *data;
- char *mask;
- CORE_ADDR startaddr;
- int increment;
- CORE_ADDR lorange;
- CORE_ADDR hirange;
- CORE_ADDR *addr_found;
- char *data_found;
+remote_search (int len, char *data, char *mask, CORE_ADDR startaddr,
+ int increment, CORE_ADDR lorange, CORE_ADDR hirange,
+ CORE_ADDR *addr_found, char *data_found)
{
if (increment == -4 && len == 4)
{
executing user code to stop. If FOREVER == 0, this function is
allowed to time out gracefully and return an indication of this to
the caller. */
-int
+static int
getpkt_sane (char *buf,
long sizeof_buf,
int forever)
return 4;
break;
default:
- internal_error ("hw_bp_to_z: bad watchpoint type %d", type);
+ internal_error (__FILE__, __LINE__,
+ "hw_bp_to_z: bad watchpoint type %d", type);
}
}
case PACKET_OK:
return 0;
}
- internal_error ("remote_insert_watchpoint: reached end of function");
+ internal_error (__FILE__, __LINE__,
+ "remote_insert_watchpoint: reached end of function");
}
/* FIXME: This function should be static and a member of the remote
case PACKET_OK:
return 0;
}
- internal_error ("remote_remove_watchpoint: reached end of function");
+ internal_error (__FILE__, __LINE__,
+ "remote_remove_watchpoint: reached end of function");
}
/* FIXME: This function should be static and a member of the remote
addr = remote_address_masked (addr);
p += hexnumstr (p, (ULONGEST) addr);
- *p = '\0';
+ sprintf (p, ",%x", len);
putpkt (buf);
getpkt (buf, PBUFSIZ, 0);
case PACKET_OK:
return 0;
}
- internal_error ("remote_remove_watchpoint: reached end of function");
+ internal_error (__FILE__, __LINE__,
+ "remote_remove_watchpoint: reached end of function");
}
/* FIXME: This function should be static and a member of the remote
addr = remote_address_masked (addr);
p += hexnumstr (p, (ULONGEST) addr);
- *p = '\0';
+ sprintf (p, ",%x", len);
putpkt(buf);
getpkt (buf, PBUFSIZ, 0);
case PACKET_OK:
return 0;
}
- internal_error ("remote_remove_watchpoint: reached end of function");
+ internal_error (__FILE__, __LINE__,
+ "remote_remove_watchpoint: reached end of function");
}
/* Some targets are only capable of doing downloads, and afterwards
struct cleanup *old_chain;
char *tmp;
char *sectdata;
- char *sectname;
+ const char *sectname;
char *buf = alloca (PBUFSIZ);
bfd_size_type size;
bfd_vma lma;
if (size == 0)
continue; /* skip zero-length section */
- sectname = (char *) bfd_get_section_name (exec_bfd, s);
+ sectname = bfd_get_section_name (exec_bfd, s);
if (args && strcmp (args, sectname) != 0)
continue; /* not the section selected by user */
/* be clever; compute the host_crc before waiting for target reply */
sectdata = xmalloc (size);
- old_chain = make_cleanup (free, sectdata);
+ old_chain = make_cleanup (xfree, sectdata);
bfd_get_section_contents (exec_bfd, s, sectdata, 0, size);
host_crc = crc32 ((unsigned char *) sectdata, size, 0xffffffff);
#endif /* 0 */
+/* Convert a thread ID to a string. Returns the string in a static
+ buffer. */
+
+static char *
+remote_pid_to_str (int pid)
+{
+ static char buf[30];
+
+ sprintf (buf, "Thread %d", pid);
+ return buf;
+}
+
static void
init_remote_ops (void)
{
remote_ops.to_thread_alive = remote_thread_alive;
remote_ops.to_find_new_threads = remote_threads_info;
remote_ops.to_extra_thread_info = remote_threads_extra_info;
+ remote_ops.to_pid_to_str = remote_pid_to_str;
remote_ops.to_stop = remote_stop;
remote_ops.to_query = remote_query;
remote_ops.to_rcmd = remote_rcmd;
unpush_target (&remote_cisco_ops);
- if (!remote_dcache)
- remote_dcache = dcache_init (remote_read_bytes, remote_write_bytes);
- else
- dcache_invd (remote_dcache);
-
remote_desc = SERIAL_OPEN (name);
if (!remote_desc)
perror_with_name (name);
remote_async (void (*callback) (enum inferior_event_type event_type, void *context), void *context)
{
if (current_target.to_async_mask_value == 0)
- internal_error ("Calling remote_async when async is masked");
+ internal_error (__FILE__, __LINE__,
+ "Calling remote_async when async is masked");
if (callback != NULL)
{
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_binary_download_cmd (args, from_tty);
}
/* Cisco stuff */
tty_input = xmalloc (PBUFSIZ);
- remote_address_size = TARGET_PTR_BIT;
+ remote_address_size = TARGET_ADDR_BIT;
}
void
add_cmd ("remotewritesize", no_class, set_memory_write_packet_size,
"Set the maximum number of bytes per memory write packet (deprecated).\n",
&setlist);
- add_cmd ("remotewritesize", no_class, set_memory_write_packet_size,
+ add_cmd ("remotewritesize", no_class, show_memory_write_packet_size,
"Show the maximum number of bytes per memory write packet (deprecated).\n",
&showlist);
add_cmd ("memory-write-packet-size", no_class,
add_info ("remote-process", remote_info_process,
"Query the remote system for process info.");
+ add_packet_config_cmd (&remote_protocol_e,
+ "e", "step-over-range",
+ set_remote_protocol_e_packet_cmd,
+ show_remote_protocol_e_packet_cmd,
+ &remote_set_cmdlist, &remote_show_cmdlist,
+ 0);
+
+ add_packet_config_cmd (&remote_protocol_E,
+ "E", "step-over-range-w-signal",
+ set_remote_protocol_E_packet_cmd,
+ show_remote_protocol_E_packet_cmd,
+ &remote_set_cmdlist, &remote_show_cmdlist,
+ 0);
+
add_packet_config_cmd (&remote_protocol_P,
"P", "set-register",
set_remote_protocol_P_packet_cmd,