/* Remote target communications for serial-line targets in custom GDB protocol
- Copyright (C) 1988-2013 Free Software Foundation, Inc.
+ Copyright (C) 1988-2014 Free Software Foundation, Inc.
This file is part of GDB.
/* See the GDB User Guide for details of the GDB remote protocol. */
#include "defs.h"
-#include "gdb_string.h"
+#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include "inferior.h"
#include "target-descriptions.h"
#include "gdb_bfd.h"
#include "filestuff.h"
+#include "rsp-low.h"
-#include <ctype.h>
#include <sys/time.h>
#include "event-loop.h"
#include "remote-fileio.h"
#include "gdb/fileio.h"
-#include "gdb_stat.h"
+#include <sys/stat.h>
#include "xml-support.h"
#include "memory-map.h"
static void remote_files_info (struct target_ops *ignore);
-static void remote_prepare_to_store (struct regcache *regcache);
+static void remote_prepare_to_store (struct target_ops *self,
+ struct regcache *regcache);
static void remote_open (char *name, int from_tty);
static void remote_open_1 (char *, int, struct target_ops *, int extended_p);
-static void remote_close (void);
+static void remote_close (struct target_ops *self);
static void remote_mourn (struct target_ops *ops);
static void remote_kill (struct target_ops *ops);
-static int tohex (int nib);
-
-static int remote_can_async_p (void);
+static int remote_can_async_p (struct target_ops *);
-static int remote_is_async_p (void);
+static int remote_is_async_p (struct target_ops *);
-static void remote_async (void (*callback) (enum inferior_event_type event_type,
- void *context), void *context);
-
-static void remote_detach (struct target_ops *ops, char *args, int from_tty);
+static void remote_async (struct target_ops *ops,
+ void (*callback) (enum inferior_event_type event_type,
+ void *context),
+ void *context);
static void sync_remote_interrupt_twice (int signo);
static void init_extended_remote_ops (void);
-static void remote_stop (ptid_t);
-
-static int ishex (int ch, int *val);
+static void remote_stop (struct target_ops *self, ptid_t);
static int stubhex (int ch);
static void remote_find_new_threads (void);
-static int fromhex (int a);
-
static int putpkt_binary (char *buf, int cnt);
static void check_binary_download (CORE_ADDR addr);
static void stop_reply_xfree (struct stop_reply *);
static void remote_parse_stop_reply (char *, struct stop_reply *);
static void push_stop_reply (struct stop_reply *);
-static void discard_pending_stop_replies_in_queue (void);
+static void discard_pending_stop_replies_in_queue (struct remote_state *);
static int peek_stop_reply (ptid_t ptid);
static void remote_async_inferior_event_handler (gdb_client_data);
-static void remote_terminal_ours (void);
+static void remote_terminal_ours (struct target_ops *self);
static int remote_read_description_p (struct target_ops *target);
static void remote_console_output (char *msg);
-static int remote_supports_cond_breakpoints (void);
+static int remote_supports_cond_breakpoints (struct target_ops *self);
-static int remote_can_run_breakpoint_commands (void);
+static int remote_can_run_breakpoint_commands (struct target_ops *self);
/* For "remote". */
static void
remote_add_thread (ptid_t ptid, int running)
{
- add_thread (ptid);
+ struct remote_state *rs = get_remote_state ();
+
+ /* GDB historically didn't pull threads in the initial connection
+ setup. If the remote target doesn't even have a concept of
+ threads (e.g., a bare-metal target), even if internally we
+ consider that a single-threaded target, mentioning a new thread
+ might be confusing to the user. Be silent then, preserving the
+ age old behavior. */
+ if (rs->starting_up)
+ add_thread_silent (ptid);
+ else
+ add_thread (ptid);
set_executing (ptid, running);
set_running (ptid, running);
/* If we found a new inferior, let the common code do whatever
it needs to with it (e.g., read shared libraries, insert
- breakpoints). */
+ breakpoints), unless we're just setting up an all-stop
+ connection. */
if (inf != NULL)
- notice_new_inferior (currthread, running, 0);
+ {
+ struct remote_state *rs = get_remote_state ();
+
+ if (non_stop || !rs->starting_up)
+ notice_new_inferior (currthread, running, 0);
+ }
}
}
it can simply pass through to the inferior without reporting. */
static void
-remote_pass_signals (int numsigs, unsigned char *pass_signals)
+remote_pass_signals (struct target_ops *self,
+ int numsigs, unsigned char *pass_signals)
{
if (remote_protocol_packets[PACKET_QPassSignals].support != PACKET_DISABLE)
{
*p = 0;
if (!rs->last_pass_packet || strcmp (rs->last_pass_packet, pass_packet))
{
- char *buf = rs->buf;
-
putpkt (pass_packet);
getpkt (&rs->buf, &rs->buf_size, 0);
- packet_ok (buf, &remote_protocol_packets[PACKET_QPassSignals]);
+ packet_ok (rs->buf, &remote_protocol_packets[PACKET_QPassSignals]);
if (rs->last_pass_packet)
xfree (rs->last_pass_packet);
rs->last_pass_packet = pass_packet;
signals it should pass through to the inferior when detaching. */
static void
-remote_program_signals (int numsigs, unsigned char *signals)
+remote_program_signals (struct target_ops *self,
+ int numsigs, unsigned char *signals)
{
if (remote_protocol_packets[PACKET_QProgramSignals].support != PACKET_DISABLE)
{
if (!rs->last_program_signals_packet
|| strcmp (rs->last_program_signals_packet, packet) != 0)
{
- char *buf = rs->buf;
-
putpkt (packet);
getpkt (&rs->buf, &rs->buf_size, 0);
- packet_ok (buf, &remote_protocol_packets[PACKET_QProgramSignals]);
+ packet_ok (rs->buf, &remote_protocol_packets[PACKET_QProgramSignals]);
xfree (rs->last_program_signals_packet);
rs->last_program_signals_packet = packet;
}
#define BUF_THREAD_ID_SIZE (OPAQUETHREADBYTES * 2)
-char *unpack_varlen_hex (char *buff, ULONGEST *result);
-
static char *unpack_nibble (char *buf, int *val);
-static char *pack_nibble (char *buf, int nibble);
-
-static char *pack_hex_byte (char *pkt, int /* unsigned char */ byte);
-
static char *unpack_byte (char *buf, int *value);
static char *pack_int (char *buf, int value);
return ptid_build (pid, 0, tid);
}
-/* Encode 64 bits in 16 chars of hex. */
-
-static const char hexchars[] = "0123456789abcdef";
-
-static int
-ishex (int ch, int *val)
-{
- if ((ch >= 'a') && (ch <= 'f'))
- {
- *val = ch - 'a' + 10;
- return 1;
- }
- if ((ch >= 'A') && (ch <= 'F'))
- {
- *val = ch - 'A' + 10;
- return 1;
- }
- if ((ch >= '0') && (ch <= '9'))
- {
- *val = ch - '0';
- return 1;
- }
- return 0;
-}
-
static int
stubhex (int ch)
{
return retval;
}
-char *
-unpack_varlen_hex (char *buff, /* packet to parse */
- ULONGEST *result)
-{
- int nibble;
- ULONGEST retval = 0;
-
- while (ishex (*buff, &nibble))
- {
- buff++;
- retval = retval << 4;
- retval |= nibble & 0x0f;
- }
- *result = retval;
- return buff;
-}
-
static char *
unpack_nibble (char *buf, int *val)
{
return buf;
}
-static char *
-pack_nibble (char *buf, int nibble)
-{
- *buf++ = hexchars[(nibble & 0x0f)];
- return buf;
-}
-
-static char *
-pack_hex_byte (char *pkt, int byte)
-{
- *pkt++ = hexchars[(byte >> 4) & 0xf];
- *pkt++ = hexchars[(byte & 0xf)];
- return pkt;
-}
-
static char *
unpack_byte (char *buf, int *value)
{
*/
static char *
-remote_threads_extra_info (struct thread_info *tp)
+remote_threads_extra_info (struct target_ops *self, struct thread_info *tp)
{
struct remote_state *rs = get_remote_state ();
int result;
/* Implement the to_get_ada_task_ptid function for the remote targets. */
static ptid_t
-remote_get_ada_task_ptid (long lwp, long thread)
+remote_get_ada_task_ptid (struct target_ops *self, long lwp, long thread)
{
return ptid_build (ptid_get_pid (inferior_ptid), 0, lwp);
}
/* Clean up connection to a remote debugger. */
static void
-remote_close (void)
+remote_close (struct target_ops *self)
{
struct remote_state *rs = get_remote_state ();
/* Make sure we leave stdin registered in the event loop, and we
don't leave the async SIGINT signal handler installed. */
- remote_terminal_ours ();
+ remote_terminal_ours (self);
serial_close (rs->remote_desc);
rs->remote_desc = NULL;
/* We are closing the remote target, so we should discard
everything of this target. */
- discard_pending_stop_replies_in_queue ();
+ discard_pending_stop_replies_in_queue (rs);
if (remote_async_inferior_event_token)
delete_async_event_handler (&remote_async_inferior_event_token);
return null_ptid;
}
+/* Determine the remote side's current thread. If we have a stop
+ reply handy (in WAIT_STATUS), maybe it's a T stop reply with a
+ "thread" register we can extract the current thread from. If not,
+ ask the remote which is the current thread with qC. The former
+ method avoids a roundtrip. */
+
+static ptid_t
+get_current_thread (char *wait_status)
+{
+ ptid_t ptid;
+
+ /* Note we don't use remote_parse_stop_reply as that makes use of
+ the target architecture, which we haven't yet fully determined at
+ this point. */
+ if (wait_status != NULL)
+ ptid = stop_reply_extract_thread (wait_status);
+ if (ptid_equal (ptid, null_ptid))
+ ptid = remote_current_thread (inferior_ptid);
+
+ return ptid;
+}
+
/* Query the remote target for which is the current thread/process,
add it to our tables, and update INFERIOR_PTID. The caller is
responsible for setting the state such that the remote end is ready
inferior_ptid = null_ptid;
- /* Now, if we have thread information, update inferior_ptid. First
- if we have a stop reply handy, maybe it's a T stop reply with a
- "thread" register we can extract the current thread from. If
- not, ask the remote which is the current thread, with qC. The
- former method avoids a roundtrip. Note we don't use
- remote_parse_stop_reply as that makes use of the target
- architecture, which we haven't yet fully determined at this
- point. */
- if (wait_status != NULL)
- ptid = stop_reply_extract_thread (wait_status);
- if (ptid_equal (ptid, null_ptid))
- ptid = remote_current_thread (inferior_ptid);
+ /* Now, if we have thread information, update inferior_ptid. */
+ ptid = get_current_thread (wait_status);
if (!ptid_equal (ptid, null_ptid))
{
strcpy (wait_status, rs->buf);
}
+ /* Fetch thread list. */
+ target_find_new_threads ();
+
/* Let the stub know that we want it to return the thread. */
set_continue_thread (minus_one_ptid);
- add_current_inferior_and_thread (wait_status);
+ if (thread_count () == 0)
+ {
+ /* Target has no concept of threads at all. GDB treats
+ non-threaded target as single-threaded; add a main
+ thread. */
+ add_current_inferior_and_thread (wait_status);
+ }
+ else
+ {
+ /* We have thread information; select the thread the target
+ says should be current. If we're reconnecting to a
+ multi-threaded program, this will ideally be the thread
+ that last reported an event before GDB disconnected. */
+ inferior_ptid = get_current_thread (wait_status);
+ if (ptid_equal (inferior_ptid, null_ptid))
+ {
+ /* Odd... The target was able to list threads, but not
+ tell us which thread was current (no "thread"
+ register in T stop reply?). Just pick the first
+ thread in the thread list then. */
+ inferior_ptid = thread_list->ptid;
+ }
+ }
/* init_wait_for_inferior should be called before get_offsets in order
to manage `inserted' flag in bp loc in a correct state.
gdb_assert (wait_status == NULL);
/* Report all signals during attach/startup. */
- remote_pass_signals (0, NULL);
+ remote_pass_signals (target, 0, NULL);
}
/* If we connected to a live target, do some additional setup. */
if (target_has_execution)
{
- if (exec_bfd) /* No use without an exec file. */
+ if (symfile_objfile) /* No use without a symbol-file. */
remote_check_symbols ();
}
die when it hits one. */
static void
-remote_detach_1 (char *args, int from_tty, int extended)
+remote_detach_1 (const char *args, int from_tty, int extended)
{
int pid = ptid_get_pid (inferior_ptid);
struct remote_state *rs = get_remote_state ();
}
static void
-remote_detach (struct target_ops *ops, char *args, int from_tty)
+remote_detach (struct target_ops *ops, const char *args, int from_tty)
{
remote_detach_1 (args, from_tty, 0);
}
static void
-extended_remote_detach (struct target_ops *ops, char *args, int from_tty)
+extended_remote_detach (struct target_ops *ops, const char *args, int from_tty)
{
remote_detach_1 (args, from_tty, 1);
}
extended_remote_attach_1 (ops, args, from_tty);
}
-/* Convert hex digit A to a number. */
-
-static int
-fromhex (int a)
-{
- if (a >= '0' && a <= '9')
- return a - '0';
- else if (a >= 'a' && a <= 'f')
- return a - 'a' + 10;
- else if (a >= 'A' && a <= 'F')
- return a - 'A' + 10;
- else
- error (_("Reply contains invalid hex digit %d"), a);
-}
-
-int
-hex2bin (const char *hex, gdb_byte *bin, int count)
-{
- int i;
-
- for (i = 0; i < count; i++)
- {
- if (hex[0] == 0 || hex[1] == 0)
- {
- /* Hex string is short, or of uneven length.
- Return the count that has been converted so far. */
- return i;
- }
- *bin++ = fromhex (hex[0]) * 16 + fromhex (hex[1]);
- hex += 2;
- }
- return i;
-}
-
-/* Convert number NIB to a hex digit. */
-
-static int
-tohex (int nib)
-{
- if (nib < 10)
- return '0' + nib;
- else
- return 'a' + nib - 10;
-}
-
-int
-bin2hex (const gdb_byte *bin, char *hex, int count)
-{
- int i;
-
- /* May use a length, or a nul-terminated string as input. */
- if (count == 0)
- count = strlen ((char *) bin);
-
- for (i = 0; i < count; i++)
- {
- *hex++ = tohex ((*bin >> 4) & 0xf);
- *hex++ = tohex (*bin++ & 0xf);
- }
- *hex = 0;
- return i;
-}
\f
/* Check for the availability of vCont. This function should also check
the response. */
will eventually end up here. */
static void
-remote_stop (ptid_t ptid)
+remote_stop (struct target_ops *self, ptid_t ptid)
{
if (remote_debug)
fprintf_unfiltered (gdb_stdlog, "remote_stop called\n");
is required. */
static void
-remote_terminal_inferior (void)
+remote_terminal_inferior (struct target_ops *self)
{
if (!target_async_permitted)
/* Nothing to do. */
}
static void
-remote_terminal_ours (void)
+remote_terminal_ours (struct target_ops *self)
{
if (!target_async_permitted)
/* Nothing to do. */
/* The identifier of the thread about this event */
ptid_t ptid;
+ /* The remote state this event is associated with. When the remote
+ connection, represented by a remote_state object, is closed,
+ all the associated stop_reply events should be released. */
+ struct remote_state *rs;
+
struct target_waitstatus ws;
/* Expedited registers. This makes remote debugging a bit more
remote_notif_stop_alloc_reply (void)
{
struct notif_event *r
- = (struct notif_event *) XMALLOC (struct stop_reply);
+ = (struct notif_event *) XNEW (struct stop_reply);
r->dtr = stop_reply_dtr;
remove_stop_reply_for_inferior, ¶m);
}
-/* Discard the stop replies in stop_reply_queue. */
+/* If its remote state is equal to the given remote state,
+ remove EVENT from the stop reply queue. */
+
+static int
+remove_stop_reply_of_remote_state (QUEUE (stop_reply_p) *q,
+ QUEUE_ITER (stop_reply_p) *iter,
+ stop_reply_p event,
+ void *data)
+{
+ struct queue_iter_param *param = data;
+ struct remote_state *rs = param->input;
+
+ if (event->rs == rs)
+ {
+ stop_reply_xfree (event);
+ QUEUE_remove_elem (stop_reply_p, q, iter);
+ }
+
+ return 1;
+}
+
+/* Discard the stop replies for RS in stop_reply_queue. */
static void
-discard_pending_stop_replies_in_queue (void)
+discard_pending_stop_replies_in_queue (struct remote_state *rs)
{
struct queue_iter_param param;
- param.input = NULL;
+ param.input = rs;
param.output = NULL;
/* Discard the stop replies we have already pulled with
vStopped. */
QUEUE_iterate (stop_reply_p, stop_reply_queue,
- remove_stop_reply_for_inferior, ¶m);
+ remove_stop_reply_of_remote_state, ¶m);
}
/* A parameter to pass data in and out. */
char *p;
event->ptid = null_ptid;
+ event->rs = get_remote_state ();
event->ws.kind = TARGET_WAITKIND_IGNORE;
event->ws.value.integer = 0;
event->stopped_by_watchpoint_p = 0;
/* fall through */
case 'S': /* Old style status, just signal only. */
- event->ws.kind = TARGET_WAITKIND_STOPPED;
- event->ws.value.sig = (enum gdb_signal)
- (((fromhex (buf[1])) << 4) + (fromhex (buf[2])));
+ {
+ int sig;
+
+ event->ws.kind = TARGET_WAITKIND_STOPPED;
+ sig = (fromhex (buf[1]) << 4) + fromhex (buf[2]);
+ if (GDB_SIGNAL_FIRST <= sig && sig < GDB_SIGNAL_LAST)
+ event->ws.value.sig = (enum gdb_signal) sig;
+ else
+ event->ws.value.sig = GDB_SIGNAL_UNKNOWN;
+ }
break;
case 'W': /* Target exited. */
case 'X':
{
/* The remote process exited with a signal. */
event->ws.kind = TARGET_WAITKIND_SIGNALLED;
- event->ws.value.sig = (enum gdb_signal) value;
+ if (GDB_SIGNAL_FIRST <= value && value < GDB_SIGNAL_LAST)
+ event->ws.value.sig = (enum gdb_signal) value;
+ else
+ event->ws.value.sig = GDB_SIGNAL_UNKNOWN;
}
/* If no process is specified, assume inferior_ptid. */
first. */
static void
-remote_prepare_to_store (struct regcache *regcache)
+remote_prepare_to_store (struct target_ops *self, struct regcache *regcache)
{
struct remote_arch_state *rsa = get_remote_arch_state ();
int i;
return addr;
}
-/* Convert BUFFER, binary data at least LEN bytes long, into escaped
- binary data in OUT_BUF. Set *OUT_LEN to the length of the data
- encoded in OUT_BUF, and return the number of bytes in OUT_BUF
- (which may be more than *OUT_LEN due to escape characters). The
- total number of bytes in the output buffer will be at most
- OUT_MAXLEN. */
-
-static int
-remote_escape_output (const gdb_byte *buffer, int len,
- gdb_byte *out_buf, int *out_len,
- int out_maxlen)
-{
- int input_index, output_index;
-
- output_index = 0;
- for (input_index = 0; input_index < len; input_index++)
- {
- gdb_byte b = buffer[input_index];
-
- if (b == '$' || b == '#' || b == '}')
- {
- /* These must be escaped. */
- if (output_index + 2 > out_maxlen)
- break;
- out_buf[output_index++] = '}';
- out_buf[output_index++] = b ^ 0x20;
- }
- else
- {
- if (output_index + 1 > out_maxlen)
- break;
- out_buf[output_index++] = b;
- }
- }
-
- *out_len = input_index;
- return output_index;
-}
-
-/* Convert BUFFER, escaped data LEN bytes long, into binary data
- in OUT_BUF. Return the number of bytes written to OUT_BUF.
- Raise an error if the total number of bytes exceeds OUT_MAXLEN.
-
- This function reverses remote_escape_output. It allows more
- escaped characters than that function does, in particular because
- '*' must be escaped to avoid the run-length encoding processing
- in reading packets. */
-
-static int
-remote_unescape_input (const gdb_byte *buffer, int len,
- gdb_byte *out_buf, int out_maxlen)
-{
- int input_index, output_index;
- int escaped;
-
- output_index = 0;
- escaped = 0;
- for (input_index = 0; input_index < len; input_index++)
- {
- gdb_byte b = buffer[input_index];
-
- if (output_index + 1 > out_maxlen)
- {
- warning (_("Received too much data from remote target;"
- " ignoring overflow."));
- return output_index;
- }
-
- if (escaped)
- {
- out_buf[output_index++] = b ^ 0x20;
- escaped = 0;
- }
- else if (b == '}')
- escaped = 1;
- else
- out_buf[output_index++] = b;
- }
-
- if (escaped)
- error (_("Unmatched escape character in target response."));
-
- return output_index;
-}
-
/* Determine whether the remote target supports binary downloading.
This is accomplished by sending a no-op memory write of zero length
to the target at the specified address. It does not suffice to send
If USE_LENGTH is 0, then the <LENGTH> field and the preceding comma
are omitted.
- Returns the number of bytes transferred, or a negative value (an
- 'enum target_xfer_error' value) for error. Only transfer a single
- packet. */
+ Return the transferred status, error or OK (an
+ 'enum target_xfer_status' value). Save the number of bytes
+ transferred in *XFERED_LEN. Only transfer a single packet. */
-static LONGEST
+static enum target_xfer_status
remote_write_bytes_aux (const char *header, CORE_ADDR memaddr,
- const gdb_byte *myaddr, ssize_t len,
- char packet_format, int use_length)
+ const gdb_byte *myaddr, ULONGEST len,
+ ULONGEST *xfered_len, char packet_format,
+ int use_length)
{
struct remote_state *rs = get_remote_state ();
char *p;
internal_error (__FILE__, __LINE__,
_("remote_write_bytes_aux: bad packet format"));
- if (len <= 0)
- return 0;
+ if (len == 0)
+ return TARGET_XFER_EOF;
payload_size = get_memory_write_packet_size ();
/* Return NR_BYTES, not TODO, in case escape chars caused us to send
fewer bytes than we'd planned. */
- return nr_bytes;
+ *xfered_len = (ULONGEST) nr_bytes;
+ return TARGET_XFER_OK;
}
/* Write memory data directly to the remote machine.
MYADDR is the address of the buffer in our space.
LEN is the number of bytes.
- Returns number of bytes transferred, or a negative value (an 'enum
- target_xfer_error' value) for error. Only transfer a single
- packet. */
+ Return the transferred status, error or OK (an
+ 'enum target_xfer_status' value). Save the number of bytes
+ transferred in *XFERED_LEN. Only transfer a single packet. */
-static LONGEST
-remote_write_bytes (CORE_ADDR memaddr, const gdb_byte *myaddr, ssize_t len)
+static enum target_xfer_status
+remote_write_bytes (CORE_ADDR memaddr, const gdb_byte *myaddr, ULONGEST len,
+ ULONGEST *xfered_len)
{
char *packet_format = 0;
}
return remote_write_bytes_aux (packet_format,
- memaddr, myaddr, len, packet_format[0], 1);
+ memaddr, myaddr, len, xfered_len,
+ packet_format[0], 1);
}
/* Read memory data directly from the remote machine.
MYADDR is the address of the buffer in our space.
LEN is the number of bytes.
- Returns number of bytes transferred, or a negative value (an 'enum
- target_xfer_error' value) for error. */
+ Return the transferred status, error or OK (an
+ 'enum target_xfer_status' value). Save the number of bytes
+ transferred in *XFERED_LEN. */
-static LONGEST
-remote_read_bytes (CORE_ADDR memaddr, gdb_byte *myaddr, int len)
+static enum target_xfer_status
+remote_read_bytes (CORE_ADDR memaddr, gdb_byte *myaddr, ULONGEST len,
+ ULONGEST *xfered_len)
{
struct remote_state *rs = get_remote_state ();
int max_buf_size; /* Max size of packet output buffer. */
int todo;
int i;
- if (len <= 0)
+ if (len == 0)
return 0;
max_buf_size = get_memory_read_packet_size ();
p = rs->buf;
i = hex2bin (p, myaddr, todo);
/* Return what we have. Let higher layers handle partial reads. */
- return i;
+ *xfered_len = (ULONGEST) i;
+ return TARGET_XFER_OK;
}
\f
do_cleanups (back_to);
}
-static LONGEST
-remote_flash_write (struct target_ops *ops,
- ULONGEST address, LONGEST length,
- const gdb_byte *data)
+static enum target_xfer_status
+remote_flash_write (struct target_ops *ops, ULONGEST address,
+ ULONGEST length, ULONGEST *xfered_len,
+ const gdb_byte *data)
{
int saved_remote_timeout = remote_timeout;
- LONGEST ret;
+ enum target_xfer_status ret;
struct cleanup *back_to = make_cleanup (restore_remote_timeout,
- &saved_remote_timeout);
+ &saved_remote_timeout);
remote_timeout = remote_flash_timeout;
- ret = remote_write_bytes_aux ("vFlashWrite:", address, data, length, 'X', 0);
+ ret = remote_write_bytes_aux ("vFlashWrite:", address, data, length,
+ xfered_len,'X', 0);
do_cleanups (back_to);
return ret;
we get a packet. */
for (;;)
{
- /* If we get a timeout or bad checksm, retry up to MAX_TRIES
+ /* If we get a timeout or bad checksum, retry up to MAX_TRIES
times. */
for (tries = 1; tries <= MAX_TRIES; tries++)
{
}
\f
-/* A helper function that just calls putpkt; for type correctness. */
-
-static int
-putpkt_for_catch_errors (void *arg)
-{
- return putpkt (arg);
-}
-
static void
remote_kill (struct target_ops *ops)
{
- /* Use catch_errors so the user can quit from gdb even when we
+ volatile struct gdb_exception ex;
+
+ /* Catch errors so the user can quit from gdb even when we
aren't on speaking terms with the remote system. */
- catch_errors (putpkt_for_catch_errors, "k", "", RETURN_MASK_ERROR);
+ TRY_CATCH (ex, RETURN_MASK_ERROR)
+ {
+ putpkt ("k");
+ }
+ if (ex.reason < 0)
+ {
+ if (ex.error == TARGET_CLOSE_ERROR)
+ {
+ /* If we got an (EOF) error that caused the target
+ to go away, then we're done, that's what we wanted.
+ "k" is susceptible to cause a premature EOF, given
+ that the remote server isn't actually required to
+ reply to "k", and it can happen that it doesn't
+ even get to reply ACK to the "k". */
+ return;
+ }
+
+ /* Otherwise, something went wrong. We didn't actually kill
+ the target. Just propagate the exception, and let the
+ user or higher layers decide what to do. */
+ throw_exception (ex);
+ }
- /* Don't wait for it to die. I'm not really sure it matters whether
- we do or not. For the existing stubs, kill is a noop. */
+ /* We've killed the remote end, we get to mourn it. Since this is
+ target remote, single-process, mourning the inferior also
+ unpushes remote_ops. */
target_mourn_inferior ();
}
}
static int
-extended_remote_supports_disable_randomization (void)
+extended_remote_supports_disable_randomization (struct target_ops *self)
{
return (remote_protocol_packets[PACKET_QDisableRandomization].support
== PACKET_ENABLE);
if (strlen (remote_exec_file) * 2 + len >= get_remote_packet_size ())
error (_("Remote file name too long for run packet"));
- len += 2 * bin2hex ((gdb_byte *) remote_exec_file, rs->buf + len, 0);
+ len += 2 * bin2hex ((gdb_byte *) remote_exec_file, rs->buf + len,
+ strlen (remote_exec_file));
gdb_assert (args != NULL);
if (*args)
if (strlen (argv[i]) * 2 + 1 + len >= get_remote_packet_size ())
error (_("Argument list too long for run packet"));
rs->buf[len++] = ';';
- len += 2 * bin2hex ((gdb_byte *) argv[i], rs->buf + len, 0);
+ len += 2 * bin2hex ((gdb_byte *) argv[i], rs->buf + len,
+ strlen (argv[i]));
}
do_cleanups (back_to);
}
environment. */
static void
-extended_remote_create_inferior_1 (char *exec_file, char *args,
- char **env, int from_tty)
+extended_remote_create_inferior (struct target_ops *ops,
+ char *exec_file, char *args,
+ char **env, int from_tty)
{
int run_worked;
char *stop_reply;
target_async (inferior_event_handler, 0);
/* Disable address space randomization if requested (and supported). */
- if (extended_remote_supports_disable_randomization ())
+ if (extended_remote_supports_disable_randomization (ops))
extended_remote_disable_randomization (disable_randomization);
/* Now restart the remote server. */
/* Get updated offsets, if the stub uses qOffsets. */
get_offsets ();
}
-
-static void
-extended_remote_create_inferior (struct target_ops *ops,
- char *exec_file, char *args,
- char **env, int from_tty)
-{
- extended_remote_create_inferior_1 (exec_file, args, env, from_tty);
-}
\f
/* Given a location's target info BP_TGT and the packet buffer BUF, output
buf = pack_hex_byte (buf, aexpr->buf[i]);
*buf = '\0';
}
-
- VEC_free (agent_expr_p, bp_tgt->conditions);
return 0;
}
buf = pack_hex_byte (buf, aexpr->buf[i]);
*buf = '\0';
}
-
- VEC_free (agent_expr_p, bp_tgt->tcommands);
}
/* Insert a breakpoint. On targets that have software breakpoint
which don't, we insert a traditional memory breakpoint. */
static int
-remote_insert_breakpoint (struct gdbarch *gdbarch,
+remote_insert_breakpoint (struct target_ops *ops,
+ struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
/* Try the "Z" s/w breakpoint packet if it is not already disabled.
p += hexnumstr (p, addr);
xsnprintf (p, endbuf - p, ",%d", bpsize);
- if (remote_supports_cond_breakpoints ())
+ if (remote_supports_cond_breakpoints (ops))
remote_add_target_side_condition (gdbarch, bp_tgt, p, endbuf);
- if (remote_can_run_breakpoint_commands ())
+ if (remote_can_run_breakpoint_commands (ops))
remote_add_target_side_commands (gdbarch, bp_tgt, p);
putpkt (rs->buf);
}
}
- return memory_insert_breakpoint (gdbarch, bp_tgt);
+ /* If this breakpoint has target-side commands but this stub doesn't
+ support Z0 packets, throw error. */
+ if (!VEC_empty (agent_expr_p, bp_tgt->tcommands))
+ throw_error (NOT_SUPPORTED_ERROR, _("\
+Target doesn't support breakpoints that have target side commands."));
+
+ return memory_insert_breakpoint (ops, gdbarch, bp_tgt);
}
static int
-remote_remove_breakpoint (struct gdbarch *gdbarch,
+remote_remove_breakpoint (struct target_ops *ops,
+ struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
CORE_ADDR addr = bp_tgt->placed_address;
return (rs->buf[0] == 'E');
}
- return memory_remove_breakpoint (gdbarch, bp_tgt);
+ return memory_remove_breakpoint (ops, gdbarch, bp_tgt);
}
static int
}
static int
-remote_insert_watchpoint (CORE_ADDR addr, int len, int type,
+remote_insert_watchpoint (struct target_ops *self,
+ CORE_ADDR addr, int len, int type,
struct expression *cond)
{
struct remote_state *rs = get_remote_state ();
static int
-remote_remove_watchpoint (CORE_ADDR addr, int len, int type,
+remote_remove_watchpoint (struct target_ops *self,
+ CORE_ADDR addr, int len, int type,
struct expression *cond)
{
struct remote_state *rs = get_remote_state ();
int remote_hw_breakpoint_limit = -1;
static int
-remote_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
+remote_region_ok_for_hw_watchpoint (struct target_ops *self,
+ CORE_ADDR addr, int len)
{
if (remote_hw_watchpoint_length_limit == 0)
return 0;
}
static int
-remote_check_watch_resources (int type, int cnt, int ot)
+remote_check_watch_resources (struct target_ops *self,
+ int type, int cnt, int ot)
{
if (type == bp_hardware_breakpoint)
{
}
static int
-remote_stopped_by_watchpoint (void)
+remote_stopped_by_watchpoint (struct target_ops *ops)
{
struct remote_state *rs = get_remote_state ();
struct remote_state *rs = get_remote_state ();
int rc = 0;
- if (remote_stopped_by_watchpoint ())
+ if (remote_stopped_by_watchpoint (target))
{
*addr_p = rs->remote_watch_data_address;
rc = 1;
static int
-remote_insert_hw_breakpoint (struct gdbarch *gdbarch,
+remote_insert_hw_breakpoint (struct target_ops *self, struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
CORE_ADDR addr;
p += hexnumstr (p, (ULONGEST) addr);
xsnprintf (p, endbuf - p, ",%x", bp_tgt->placed_size);
- if (remote_supports_cond_breakpoints ())
+ if (remote_supports_cond_breakpoints (self))
remote_add_target_side_condition (gdbarch, bp_tgt, p, endbuf);
- if (remote_can_run_breakpoint_commands ())
+ if (remote_can_run_breakpoint_commands (self))
remote_add_target_side_commands (gdbarch, bp_tgt, p);
putpkt (rs->buf);
static int
-remote_remove_hw_breakpoint (struct gdbarch *gdbarch,
+remote_remove_hw_breakpoint (struct target_ops *self, struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
CORE_ADDR addr;
into remote target. The number of bytes written to the remote
target is returned, or -1 for error. */
-static LONGEST
+static enum target_xfer_status
remote_write_qxfer (struct target_ops *ops, const char *object_name,
const char *annex, const gdb_byte *writebuf,
- ULONGEST offset, LONGEST len,
+ ULONGEST offset, LONGEST len, ULONGEST *xfered_len,
struct packet_config *packet)
{
int i, buf_len;
int max_size = get_memory_write_packet_size ();
if (packet->support == PACKET_DISABLE)
- return -1;
+ return TARGET_XFER_E_IO;
/* Insert header. */
i = snprintf (rs->buf, max_size,
if (putpkt_binary (rs->buf, i + buf_len) < 0
|| getpkt_sane (&rs->buf, &rs->buf_size, 0) < 0
|| packet_ok (rs->buf, packet) != PACKET_OK)
- return -1;
+ return TARGET_XFER_E_IO;
unpack_varlen_hex (rs->buf, &n);
- return n;
+
+ *xfered_len = n;
+ return TARGET_XFER_OK;
}
/* Read OBJECT_NAME/ANNEX from the remote target using a qXfer packet.
EOF. PACKET is checked and updated to indicate whether the remote
target supports this object. */
-static LONGEST
+static enum target_xfer_status
remote_read_qxfer (struct target_ops *ops, const char *object_name,
const char *annex,
gdb_byte *readbuf, ULONGEST offset, LONGEST len,
+ ULONGEST *xfered_len,
struct packet_config *packet)
{
struct remote_state *rs = get_remote_state ();
LONGEST i, n, packet_len;
if (packet->support == PACKET_DISABLE)
- return -1;
+ return TARGET_XFER_E_IO;
/* Check whether we've cached an end-of-object packet that matches
this request. */
if (strcmp (object_name, rs->finished_object) == 0
&& strcmp (annex ? annex : "", rs->finished_annex) == 0
&& offset == rs->finished_offset)
- return 0;
+ return TARGET_XFER_EOF;
+
/* Otherwise, we're now reading something different. Discard
the cache. */
phex_nz (n, sizeof n));
i = putpkt (rs->buf);
if (i < 0)
- return -1;
+ return TARGET_XFER_E_IO;
rs->buf[0] = '\0';
packet_len = getpkt_sane (&rs->buf, &rs->buf_size, 0);
if (packet_len < 0 || packet_ok (rs->buf, packet) != PACKET_OK)
- return -1;
+ return TARGET_XFER_E_IO;
if (rs->buf[0] != 'l' && rs->buf[0] != 'm')
error (_("Unknown remote qXfer reply: %s"), rs->buf);
rs->finished_offset = offset + i;
}
- return i;
+ if (i == 0)
+ return TARGET_XFER_EOF;
+ else
+ {
+ *xfered_len = i;
+ return TARGET_XFER_OK;
+ }
}
-static LONGEST
+static enum target_xfer_status
remote_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
- const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
+ const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len)
{
struct remote_state *rs;
int i;
/* Handle memory using the standard memory routines. */
if (object == TARGET_OBJECT_MEMORY)
{
- LONGEST xfered;
-
/* If the remote target is connected but not running, we should
pass this request down to a lower stratum (e.g. the executable
file). */
if (!target_has_execution)
- return 0;
+ return TARGET_XFER_EOF;
if (writebuf != NULL)
- xfered = remote_write_bytes (offset, writebuf, len);
+ return remote_write_bytes (offset, writebuf, len, xfered_len);
else
- xfered = remote_read_bytes (offset, readbuf, len);
-
- return xfered;
+ return remote_read_bytes (offset, readbuf, len, xfered_len);
}
/* Handle SPU memory using qxfer packets. */
{
if (readbuf)
return remote_read_qxfer (ops, "spu", annex, readbuf, offset, len,
- &remote_protocol_packets
- [PACKET_qXfer_spu_read]);
+ xfered_len, &remote_protocol_packets
+ [PACKET_qXfer_spu_read]);
else
return remote_write_qxfer (ops, "spu", annex, writebuf, offset, len,
- &remote_protocol_packets
- [PACKET_qXfer_spu_write]);
+ xfered_len, &remote_protocol_packets
+ [PACKET_qXfer_spu_write]);
}
/* Handle extra signal info using qxfer packets. */
{
if (readbuf)
return remote_read_qxfer (ops, "siginfo", annex, readbuf, offset, len,
- &remote_protocol_packets
+ xfered_len, &remote_protocol_packets
[PACKET_qXfer_siginfo_read]);
else
return remote_write_qxfer (ops, "siginfo", annex,
- writebuf, offset, len,
+ writebuf, offset, len, xfered_len,
&remote_protocol_packets
[PACKET_qXfer_siginfo_write]);
}
{
if (readbuf)
return remote_read_qxfer (ops, "statictrace", annex,
- readbuf, offset, len,
+ readbuf, offset, len, xfered_len,
&remote_protocol_packets
[PACKET_qXfer_statictrace_read]);
else
- return -1;
+ return TARGET_XFER_E_IO;
}
/* Only handle flash writes. */
switch (object)
{
case TARGET_OBJECT_FLASH:
- return remote_flash_write (ops, offset, len, writebuf);
+ return remote_flash_write (ops, offset, len, xfered_len,
+ writebuf);
default:
- return -1;
+ return TARGET_XFER_E_IO;
}
}
case TARGET_OBJECT_AUXV:
gdb_assert (annex == NULL);
return remote_read_qxfer (ops, "auxv", annex, readbuf, offset, len,
+ xfered_len,
&remote_protocol_packets[PACKET_qXfer_auxv]);
case TARGET_OBJECT_AVAILABLE_FEATURES:
return remote_read_qxfer
- (ops, "features", annex, readbuf, offset, len,
+ (ops, "features", annex, readbuf, offset, len, xfered_len,
&remote_protocol_packets[PACKET_qXfer_features]);
case TARGET_OBJECT_LIBRARIES:
return remote_read_qxfer
- (ops, "libraries", annex, readbuf, offset, len,
+ (ops, "libraries", annex, readbuf, offset, len, xfered_len,
&remote_protocol_packets[PACKET_qXfer_libraries]);
case TARGET_OBJECT_LIBRARIES_SVR4:
return remote_read_qxfer
- (ops, "libraries-svr4", annex, readbuf, offset, len,
+ (ops, "libraries-svr4", annex, readbuf, offset, len, xfered_len,
&remote_protocol_packets[PACKET_qXfer_libraries_svr4]);
case TARGET_OBJECT_MEMORY_MAP:
gdb_assert (annex == NULL);
return remote_read_qxfer (ops, "memory-map", annex, readbuf, offset, len,
+ xfered_len,
&remote_protocol_packets[PACKET_qXfer_memory_map]);
case TARGET_OBJECT_OSDATA:
/* Should only get here if we're connected. */
gdb_assert (rs->remote_desc);
return remote_read_qxfer
- (ops, "osdata", annex, readbuf, offset, len,
+ (ops, "osdata", annex, readbuf, offset, len, xfered_len,
&remote_protocol_packets[PACKET_qXfer_osdata]);
case TARGET_OBJECT_THREADS:
gdb_assert (annex == NULL);
return remote_read_qxfer (ops, "threads", annex, readbuf, offset, len,
+ xfered_len,
&remote_protocol_packets[PACKET_qXfer_threads]);
case TARGET_OBJECT_TRACEFRAME_INFO:
gdb_assert (annex == NULL);
return remote_read_qxfer
- (ops, "traceframe-info", annex, readbuf, offset, len,
+ (ops, "traceframe-info", annex, readbuf, offset, len, xfered_len,
&remote_protocol_packets[PACKET_qXfer_traceframe_info]);
case TARGET_OBJECT_FDPIC:
return remote_read_qxfer (ops, "fdpic", annex, readbuf, offset, len,
+ xfered_len,
&remote_protocol_packets[PACKET_qXfer_fdpic]);
case TARGET_OBJECT_OPENVMS_UIB:
return remote_read_qxfer (ops, "uib", annex, readbuf, offset, len,
+ xfered_len,
&remote_protocol_packets[PACKET_qXfer_uib]);
case TARGET_OBJECT_BTRACE:
return remote_read_qxfer (ops, "btrace", annex, readbuf, offset, len,
+ xfered_len,
&remote_protocol_packets[PACKET_qXfer_btrace]);
default:
- return -1;
+ return TARGET_XFER_E_IO;
}
/* Note: a zero OFFSET and LEN can be used to query the minimum
/* Minimum outbuf size is get_remote_packet_size (). If LEN is not
large enough let the caller deal with it. */
if (len < get_remote_packet_size ())
- return -1;
+ return TARGET_XFER_E_IO;
len = get_remote_packet_size ();
/* Except for querying the minimum buffer size, target must be open. */
i = putpkt (rs->buf);
if (i < 0)
- return i;
+ return TARGET_XFER_E_IO;
getpkt (&rs->buf, &rs->buf_size, 0);
strcpy ((char *) readbuf, rs->buf);
- return strlen ((char *) readbuf);
+ *xfered_len = strlen ((char *) readbuf);
+ return TARGET_XFER_OK;
}
static int
}
static void
-remote_rcmd (char *command,
+remote_rcmd (struct target_ops *self, char *command,
struct ui_file *outbuf)
{
struct remote_state *rs = get_remote_state ();
error (_("\"monitor\" command ``%s'' is too long."), command);
/* Encode the actual command. */
- bin2hex ((gdb_byte *) command, p, 0);
+ bin2hex ((gdb_byte *) command, p, strlen (command));
if (putpkt (rs->buf) < 0)
error (_("Communication problem with target."));
*REMOTE_ERRNO). */
static int
-remote_hostio_open (const char *filename, int flags, int mode,
+remote_hostio_open (struct target_ops *self,
+ const char *filename, int flags, int mode,
int *remote_errno)
{
struct remote_state *rs = get_remote_state ();
set *REMOTE_ERRNO). */
static int
-remote_hostio_pwrite (int fd, const gdb_byte *write_buf, int len,
+remote_hostio_pwrite (struct target_ops *self,
+ int fd, const gdb_byte *write_buf, int len,
ULONGEST offset, int *remote_errno)
{
struct remote_state *rs = get_remote_state ();
gdb_assert (remote_filename_p (filename));
- fd = remote_hostio_open (filename + 7, FILEIO_O_RDONLY, 0, &remote_errno);
+ fd = remote_hostio_open (find_target_at (process_stratum),
+ filename + 7, FILEIO_O_RDONLY, 0, &remote_errno);
if (fd == -1)
{
errno = remote_fileio_errno_to_host (remote_errno);
perror_with_name (local_file);
back_to = make_cleanup_fclose (file);
- fd = remote_hostio_open (remote_file, (FILEIO_O_WRONLY | FILEIO_O_CREAT
+ fd = remote_hostio_open (find_target_at (process_stratum),
+ remote_file, (FILEIO_O_WRONLY | FILEIO_O_CREAT
| FILEIO_O_TRUNC),
0700, &remote_errno);
if (fd == -1)
bytes += bytes_in_buffer;
bytes_in_buffer = 0;
- retcode = remote_hostio_pwrite (fd, buffer, bytes,
+ retcode = remote_hostio_pwrite (find_target_at (process_stratum),
+ fd, buffer, bytes,
offset, &remote_errno);
if (retcode < 0)
if (!rs->remote_desc)
error (_("command can only be used with remote target"));
- fd = remote_hostio_open (remote_file, FILEIO_O_RDONLY, 0, &remote_errno);
+ fd = remote_hostio_open (find_target_at (process_stratum),
+ remote_file, FILEIO_O_RDONLY, 0, &remote_errno);
if (fd == -1)
remote_hostio_error (remote_errno);
}
static int
-remote_can_execute_reverse (void)
+remote_can_execute_reverse (struct target_ops *self)
{
if (remote_protocol_packets[PACKET_bs].support == PACKET_ENABLE
|| remote_protocol_packets[PACKET_bc].support == PACKET_ENABLE)
}
static int
-remote_supports_non_stop (void)
+remote_supports_non_stop (struct target_ops *self)
{
return 1;
}
static int
-remote_supports_disable_randomization (void)
+remote_supports_disable_randomization (struct target_ops *self)
{
/* Only supported in extended mode. */
return 0;
}
static int
-remote_supports_multi_process (void)
+remote_supports_multi_process (struct target_ops *self)
{
struct remote_state *rs = get_remote_state ();
}
static int
-remote_supports_cond_breakpoints (void)
+remote_supports_cond_breakpoints (struct target_ops *self)
{
struct remote_state *rs = get_remote_state ();
}
static int
-remote_supports_enable_disable_tracepoint (void)
+remote_supports_enable_disable_tracepoint (struct target_ops *self)
{
struct remote_state *rs = get_remote_state ();
}
static int
-remote_supports_string_tracing (void)
+remote_supports_string_tracing (struct target_ops *self)
{
struct remote_state *rs = get_remote_state ();
}
static int
-remote_can_run_breakpoint_commands (void)
+remote_can_run_breakpoint_commands (struct target_ops *self)
{
struct remote_state *rs = get_remote_state ();
p = rs->buf + strlen (rs->buf);
if ((p - rs->buf) + strlen (tsv->name) * 2 >= get_remote_packet_size ())
error (_("Trace state variable name too long for tsv definition packet"));
- p += 2 * bin2hex ((gdb_byte *) (tsv->name), p, 0);
+ p += 2 * bin2hex ((gdb_byte *) (tsv->name), p, strlen (tsv->name));
*p++ = '\0';
putpkt (rs->buf);
remote_get_noisy_reply (&target_buf, &target_buf_size);
p += strlen (p);
if ((p - rs->buf) + strlen (filename) * 2 >= get_remote_packet_size ())
error (_("Remote file name too long for trace save packet"));
- p += 2 * bin2hex ((gdb_byte *) filename, p, 0);
+ p += 2 * bin2hex ((gdb_byte *) filename, p, strlen (filename));
*p++ = '\0';
putpkt (rs->buf);
reply = remote_get_noisy_reply (&target_buf, &target_buf_size);
{
char *text;
+ /* If current traceframe is not selected, don't bother the remote
+ stub. */
+ if (get_traceframe_number () < 0)
+ return NULL;
+
text = target_read_stralloc (¤t_target,
TARGET_OBJECT_TRACEFRAME_INFO, NULL);
if (text != NULL)
if (user)
{
buf += xsnprintf (buf, endbuf - buf, "user:");
- nbytes = bin2hex ((gdb_byte *) user, buf, 0);
+ nbytes = bin2hex ((gdb_byte *) user, buf, strlen (user));
buf += 2 * nbytes;
*buf++ = ';';
}
if (notes)
{
buf += xsnprintf (buf, endbuf - buf, "notes:");
- nbytes = bin2hex ((gdb_byte *) notes, buf, 0);
+ nbytes = bin2hex ((gdb_byte *) notes, buf, strlen (notes));
buf += 2 * nbytes;
*buf++ = ';';
}
if (stop_notes)
{
buf += xsnprintf (buf, endbuf - buf, "tstop:");
- nbytes = bin2hex ((gdb_byte *) stop_notes, buf, 0);
+ nbytes = bin2hex ((gdb_byte *) stop_notes, buf, strlen (stop_notes));
buf += 2 * nbytes;
*buf++ = ';';
}
/* Check whether the target supports branch tracing. */
static int
-remote_supports_btrace (void)
+remote_supports_btrace (struct target_ops *self)
{
if (remote_protocol_packets[PACKET_Qbtrace_off].support != PACKET_ENABLE)
return 0;
/* Read the branch trace. */
-static VEC (btrace_block_s) *
-remote_read_btrace (struct btrace_target_info *tinfo,
+static enum btrace_error
+remote_read_btrace (VEC (btrace_block_s) **btrace,
+ struct btrace_target_info *tinfo,
enum btrace_read_type type)
{
struct packet_config *packet = &remote_protocol_packets[PACKET_qXfer_btrace];
struct remote_state *rs = get_remote_state ();
- VEC (btrace_block_s) *btrace = NULL;
+ struct cleanup *cleanup;
const char *annex;
char *xml;
switch (type)
{
- case btrace_read_all:
+ case BTRACE_READ_ALL:
annex = "all";
break;
- case btrace_read_new:
+ case BTRACE_READ_NEW:
annex = "new";
break;
+ case BTRACE_READ_DELTA:
+ annex = "delta";
+ break;
default:
internal_error (__FILE__, __LINE__,
_("Bad branch tracing read type: %u."),
xml = target_read_stralloc (¤t_target,
TARGET_OBJECT_BTRACE, annex);
- if (xml != NULL)
- {
- struct cleanup *cleanup = make_cleanup (xfree, xml);
+ if (xml == NULL)
+ return BTRACE_ERR_UNKNOWN;
- btrace = parse_xml_btrace (xml);
- do_cleanups (cleanup);
- }
+ cleanup = make_cleanup (xfree, xml);
+ *btrace = parse_xml_btrace (xml);
+ do_cleanups (cleanup);
- return btrace;
+ return BTRACE_ERR_NONE;
}
static int
return rs->augmented_libraries_svr4_read;
}
+/* Implementation of to_load. */
+
+static void
+remote_load (struct target_ops *self, char *name, int from_tty)
+{
+ generic_load (name, from_tty);
+}
+
static void
init_remote_ops (void)
{
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_load = remote_load;
remote_ops.to_mourn_inferior = remote_mourn;
remote_ops.to_pass_signals = remote_pass_signals;
remote_ops.to_program_signals = remote_program_signals;
}
static int
-remote_can_async_p (void)
+remote_can_async_p (struct target_ops *ops)
{
struct remote_state *rs = get_remote_state ();
}
static int
-remote_is_async_p (void)
+remote_is_async_p (struct target_ops *ops)
{
struct remote_state *rs = get_remote_state ();
}
static void
-remote_async (void (*callback) (enum inferior_event_type event_type,
- void *context), void *context)
+remote_async (struct target_ops *ops,
+ void (*callback) (enum inferior_event_type event_type,
+ void *context),
+ void *context)
{
struct remote_state *rs = get_remote_state ();