#include "remote-fileio.h"
+/* The size to align memory write packets, when practical. The protocol
+ does not guarantee any alignment, and gdb will generate short
+ writes and unaligned writes, but even as a best-effort attempt this
+ can improve bulk transfers. For instance, if a write is misaligned
+ relative to the target's data bus, the stub may need to make an extra
+ round trip fetching data from the target. This doesn't make a
+ huge difference, but it's easy to do, so we try to be helpful.
+
+ The alignment chosen is arbitrary; usually data bus width is
+ important here, not the possibly larger cache line size. */
+enum { REMOTE_ALIGN_WRITES = 16 };
+
/* Prototypes for local functions. */
static void cleanup_sigint_signal_handler (void *dummy);
static void initialize_sigint_signal_handler (void);
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_size (current_gdbarch, regnum);
+ /* long size in bytes; == register_size (current_gdbarch, regnum);
at present. */
/* char *name; == REGISTER_NAME (regnum); at present. */
};
struct gdb_ext_thread_info
{
threadref threadid; /* External form of thread reference. */
- int active; /* Has state interesting to GDB?
+ int active; /* Has state interesting to GDB?
regs, stack. */
- char display[256]; /* Brief state display, name,
+ char display[256]; /* Brief state display, name,
blocked/suspended. */
char shortname[32]; /* To be used to name threads. */
- char more_display[256]; /* Long info, statistics, queue depth,
+ char more_display[256]; /* Long info, statistics, queue depth,
whatever. */
};
static int threadmatch (threadref *dest, threadref *src);
-static char *pack_threadinfo_request (char *pkt, int mode,
+static char *pack_threadinfo_request (char *pkt, int mode,
threadref *id);
static int remote_unpack_thread_info_response (char *pkt,
*info);
-static int remote_get_threadinfo (threadref *threadid,
+static int remote_get_threadinfo (threadref *threadid,
int fieldset, /*TAG mask */
struct gdb_ext_thread_info *info);
static int parse_threadlist_response (char *pkt,
int result_limit,
threadref *original_echo,
- threadref *resultlist,
+ threadref *resultlist,
int *doneflag);
static int remote_get_threadlist (int startflag,
threadref *nextthread,
int result_limit,
int *done,
- int *result_count,
+ int *result_count,
threadref *threadlist);
typedef int (*rmt_thread_action) (threadref *ref, void *context);
ULONGEST *result)
{
int nibble;
- int retval = 0;
+ ULONGEST retval = 0;
while (ishex (*buff, &nibble))
{
if (threadinfo.active)
{
if (*threadinfo.shortname)
- n += xsnprintf (&display_buf[0], sizeof (display_buf) - n,
+ n += xsnprintf (&display_buf[0], sizeof (display_buf) - n,
" Name: %s,", threadinfo.shortname);
if (*threadinfo.display)
- n += xsnprintf (&display_buf[n], sizeof (display_buf) - n,
+ n += xsnprintf (&display_buf[n], sizeof (display_buf) - n,
" State: %s,", threadinfo.display);
if (*threadinfo.more_display)
- n += xsnprintf (&display_buf[n], sizeof (display_buf) - n,
+ n += xsnprintf (&display_buf[n], sizeof (display_buf) - n,
" Priority: %s", threadinfo.more_display);
if (n > 0)
putpkt (rs->buf);
remote_fileio_reset ();
-
+
/* Now query for status so this looks just like we restarted
gdbserver from scratch. */
putpkt ("?");
static struct protocol_feature remote_protocol_features[] = {
{ "PacketSize", PACKET_DISABLE, remote_packet_size, -1 },
- { "qPart:auxv:read", PACKET_DISABLE, remote_supported_packet,
+ { "qXfer:auxv:read", PACKET_DISABLE, remote_supported_packet,
PACKET_qXfer_auxv }
};
{
signal (SIGINT, handle_sigint);
if (sigint_remote_twice_token)
- delete_async_signal_handler ((struct async_signal_handler **)
+ delete_async_signal_handler ((struct async_signal_handler **)
&sigint_remote_twice_token);
if (sigint_remote_token)
- delete_async_signal_handler ((struct async_signal_handler **)
+ delete_async_signal_handler ((struct async_signal_handler **)
&sigint_remote_token);
}
phex_nz (pnum, 0), p, buf);
fieldsize = hex2bin (p, regs,
- register_size (current_gdbarch,
+ register_size (current_gdbarch,
reg->regnum));
p += 2 * fieldsize;
- if (fieldsize < register_size (current_gdbarch,
+ if (fieldsize < register_size (current_gdbarch,
reg->regnum))
warning (_("Remote reply is too short: %s"), buf);
- regcache_raw_supply (current_regcache,
+ regcache_raw_supply (current_regcache,
reg->regnum, regs);
}
if (*p++ != ';')
- error (_("Remote register badly formatted: %s\nhere: %s"),
+ error (_("Remote register badly formatted: %s\nhere: %s"),
buf, p);
}
}
pnum, p, buf);
fieldsize = hex2bin (p, regs,
- register_size (current_gdbarch,
+ register_size (current_gdbarch,
reg->regnum));
p += 2 * fieldsize;
- if (fieldsize < register_size (current_gdbarch,
+ if (fieldsize < register_size (current_gdbarch,
reg->regnum))
warning (_("Remote reply is too short: %s"), buf);
regcache_raw_supply (current_regcache, reg->regnum, regs);
error. Only transfer a single packet. */
int
-remote_write_bytes (CORE_ADDR memaddr, gdb_byte *myaddr, int len)
+remote_write_bytes (CORE_ADDR memaddr, const gdb_byte *myaddr, int len)
{
struct remote_state *rs = get_remote_state ();
char *buf;
int todo;
int nr_bytes;
int payload_size;
- char *payload_start;
+ int payload_length;
+
+ /* Should this be the selected frame? */
+ gdbarch_remote_translate_xfer_address (current_gdbarch,
+ current_regcache,
+ memaddr, len,
+ &memaddr, &len);
+
+ if (len <= 0)
+ return 0;
/* Verify that the target can support a binary download. */
check_binary_download (memaddr);
payload_size = get_memory_write_packet_size ();
-
+
/* The packet buffer will be large enough for the payload;
get_memory_packet_size ensures this. */
buf = rs->buf;
internal_error (__FILE__, __LINE__,
_("minumum packet size too small to write data"));
+ /* If we already need another packet, then try to align the end
+ of this packet to a useful boundary. */
+ if (todo > 2 * REMOTE_ALIGN_WRITES && todo < len)
+ todo = ((memaddr + todo) & ~(REMOTE_ALIGN_WRITES - 1)) - memaddr;
+
/* Append "<memaddr>". */
memaddr = remote_address_masked (memaddr);
p += hexnumstr (p, (ULONGEST) memaddr);
*p = '\0';
/* Append the packet body. */
- payload_start = p;
switch (remote_protocol_packets[PACKET_X].support)
{
case PACKET_ENABLE:
/* Binary mode. Send target system values byte by byte, in
increasing byte addresses. Only escape certain critical
characters. */
- p += remote_escape_output (myaddr, todo, p, &nr_bytes, payload_size);
+ payload_length = remote_escape_output (myaddr, todo, p, &nr_bytes,
+ payload_size);
+
+ /* If not all TODO bytes fit, then we'll need another packet. Make
+ a second try to keep the end of the packet aligned. */
+ if (nr_bytes < todo)
+ {
+ int new_nr_bytes;
+
+ new_nr_bytes = (((memaddr + nr_bytes) & ~(REMOTE_ALIGN_WRITES - 1))
+ - memaddr);
+ if (new_nr_bytes != nr_bytes)
+ payload_length = remote_escape_output (myaddr, new_nr_bytes,
+ p, &nr_bytes,
+ payload_size);
+ }
+
+ p += payload_length;
if (nr_bytes < todo)
{
/* Escape chars have filled up the buffer prematurely,
int max_buf_size; /* Max size of packet output buffer. */
int origlen;
+ /* Should this be the selected frame? */
+ gdbarch_remote_translate_xfer_address (current_gdbarch,
+ current_regcache,
+ memaddr, len,
+ &memaddr, &len);
+
+ if (len <= 0)
+ return 0;
+
max_buf_size = get_memory_read_packet_size ();
/* The packet buffer will be large enough for the payload;
get_memory_packet_size ensures this. */
int should_write, struct mem_attrib *attrib,
struct target_ops *target)
{
- CORE_ADDR targ_addr;
- int targ_len;
int res;
- /* Should this be the selected frame? */
- gdbarch_remote_translate_xfer_address (current_gdbarch,
- current_regcache,
- mem_addr, mem_len,
- &targ_addr, &targ_len);
- if (targ_len <= 0)
- return 0;
-
if (should_write)
- res = remote_write_bytes (targ_addr, buffer, targ_len);
+ res = remote_write_bytes (mem_addr, buffer, mem_len);
else
- res = remote_read_bytes (targ_addr, buffer, targ_len);
+ res = remote_read_bytes (mem_addr, buffer, mem_len);
return res;
}
case '$':
{
if (remote_debug)
- fprintf_unfiltered (gdb_stdlog,
+ fprintf_unfiltered (gdb_stdlog,
"Packet instead of Ack, ignoring it\n");
/* It's probably an old response sent because an ACK
was lost. Gobble up the packet and ack it so it
if (check_0 == SERIAL_TIMEOUT || check_1 == SERIAL_TIMEOUT)
{
if (remote_debug)
- fputs_filtered ("Timeout in checksum, retrying\n",
+ fputs_filtered ("Timeout in checksum, retrying\n",
gdb_stdlog);
return -1;
}
else if (check_0 < 0 || check_1 < 0)
{
if (remote_debug)
- fputs_filtered ("Communication error in checksum\n",
+ fputs_filtered ("Communication error in checksum\n",
gdb_stdlog);
return -1;
}
serial_write (remote_desc, "-", 1);
}
- /* We have tried hard enough, and just can't receive the packet.
+ /* We have tried hard enough, and just can't receive the packet.
Give up. */
printf_unfiltered (_("Ignoring packet error, continuing...\n"));
if (remote_protocol_packets[PACKET_Z1].support == PACKET_DISABLE)
return -1;
-
+
*(p++) = 'Z';
*(p++) = '1';
*(p++) = ',';
char *p2;
char query_type;
- /* Handle memory using remote_xfer_memory. */
+ /* Handle memory using the standard memory routines. */
if (object == TARGET_OBJECT_MEMORY)
{
int xfered;
errno = 0;
if (writebuf != NULL)
- {
- void *buffer = xmalloc (len);
- struct cleanup *cleanup = make_cleanup (xfree, buffer);
- memcpy (buffer, writebuf, len);
- xfered = remote_xfer_memory (offset, buffer, len, 1, NULL, ops);
- do_cleanups (cleanup);
- }
+ xfered = remote_write_bytes (offset, writebuf, len);
else
- xfered = remote_xfer_memory (offset, readbuf, len, 0, NULL, ops);
+ xfered = remote_read_bytes (offset, readbuf, len);
if (xfered > 0)
return xfered;
will be able to delay notifying the client of an event until the
point where an entire packet has been received. */
-static void (*async_client_callback) (enum inferior_event_type event_type,
+static void (*async_client_callback) (enum inferior_event_type event_type,
void *context);
static void *async_client_context;
static serial_event_ftype remote_async_serial_handler;
}
static void
-remote_async (void (*callback) (enum inferior_event_type event_type,
+remote_async (void (*callback) (enum inferior_event_type event_type,
void *context), void *context)
{
if (current_target.to_async_mask_value == 0)
init_remote_async_ops (void)
{
remote_async_ops.to_shortname = "async";
- remote_async_ops.to_longname =
+ remote_async_ops.to_longname =
"Remote serial target in async version of the gdb-specific protocol";
remote_async_ops.to_doc =
"Use a remote computer via a serial line, using a gdb-specific protocol.\n\
struct remote_state *rs;
/* architecture specific data */
- remote_gdbarch_data_handle =
+ remote_gdbarch_data_handle =
gdbarch_data_register_post_init (init_remote_state);
/* Old tacky stuff. NOTE: This comes after the remote protocol so