/* Remote target communications for serial-line targets in custom GDB protocol
Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
- 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* See the GDB User Guide for details of the GDB remote protocol. */
#include "gdbcore.h" /* for exec_bfd */
#include "remote-fileio.h"
+#include "gdb/fileio.h"
#include "memory-map.h"
static void async_remote_interrupt (gdb_client_data);
void async_remote_interrupt_twice (gdb_client_data);
-static void build_remote_gdbarch_data (void);
-
static void remote_files_info (struct target_ops *ignore);
-static void remote_prepare_to_store (void);
+static void remote_prepare_to_store (struct regcache *regcache);
-static void remote_fetch_registers (int regno);
+static void remote_fetch_registers (struct regcache *regcache, int regno);
static void remote_resume (ptid_t ptid, int step,
enum target_signal siggnal);
static void remote_close (int quitting);
-static void remote_store_registers (int regno);
+static void remote_store_registers (struct regcache *regcache, int regno);
static void remote_mourn (void);
static void remote_async_mourn (void);
void _initialize_remote (void);
+/* For "remote". */
+
+static struct cmd_list_element *remote_cmdlist;
+
/* For "set remote" and "show remote". */
static struct cmd_list_element *remote_set_cmdlist;
a buffer in the stub), this will be set to that packet size.
Otherwise zero, meaning to use the guessed size. */
long explicit_packet_size;
+
+ /* remote_wait is normally called when the target is running and
+ waits for a stop reply packet. But sometimes we need to call it
+ when the target is already stopped. We can send a "?" packet
+ and have remote_wait read the response. Or, if we already have
+ the response, we can stash it in BUF and tell remote_wait to
+ skip calling getpkt. This flag is set when BUF contains a
+ stop reply packet and the target is not waiting. */
+ int cached_wait_status;
};
/* This data could be associated with a target, but we do not always
int in_g_packet; /* Always part of G packet. */
/* long size in bytes; == register_size (current_gdbarch, regnum);
at present. */
- /* char *name; == REGISTER_NAME (regnum); at present. */
+ /* char *name; == gdbarch_register_name (current_gdbarch, regnum);
+ at present. */
};
struct remote_arch_state
long sizeof_g_packet;
/* Description of the remote protocol registers indexed by REGNUM
- (making an array NUM_REGS in size). */
+ (making an array gdbarch_num_regs in size). */
struct packet_reg *regs;
/* This is the size (in chars) of the first response to the ``g''
/* Use the architecture to build a regnum<->pnum table, which will be
1:1 unless a feature set specifies otherwise. */
- rsa->regs = GDBARCH_OBSTACK_CALLOC (gdbarch, NUM_REGS, struct packet_reg);
- for (regnum = 0; regnum < NUM_REGS; regnum++)
+ rsa->regs = GDBARCH_OBSTACK_CALLOC (gdbarch,
+ gdbarch_num_regs (gdbarch),
+ struct packet_reg);
+ for (regnum = 0; regnum < gdbarch_num_regs (gdbarch); regnum++)
{
struct packet_reg *r = &rsa->regs[regnum];
- r->pnum = gdbarch_remote_register_number (gdbarch, regnum);
+
+ if (register_size (gdbarch, regnum) == 0)
+ /* Do not try to fetch zero-sized (placeholder) registers. */
+ r->pnum = -1;
+ else
+ r->pnum = gdbarch_remote_register_number (gdbarch, regnum);
+
r->regnum = regnum;
}
with a remote protocol number, in order of ascending protocol
number. */
- remote_regs = alloca (NUM_REGS * sizeof (struct packet_reg *));
- for (num_remote_regs = 0, regnum = 0; regnum < NUM_REGS; regnum++)
+ remote_regs = alloca (gdbarch_num_regs (gdbarch)
+ * sizeof (struct packet_reg *));
+ for (num_remote_regs = 0, regnum = 0;
+ regnum < gdbarch_num_regs (gdbarch);
+ regnum++)
if (rsa->regs[regnum].pnum != -1)
remote_regs[num_remote_regs++] = &rsa->regs[regnum];
{
remote_regs[regnum]->in_g_packet = 1;
remote_regs[regnum]->offset = offset;
- offset += register_size (current_gdbarch, remote_regs[regnum]->regnum);
+ offset += register_size (gdbarch, remote_regs[regnum]->regnum);
}
/* Record the maximum possible size of the g packet - it may turn out
static struct packet_reg *
packet_reg_from_regnum (struct remote_arch_state *rsa, long regnum)
{
- if (regnum < 0 && regnum >= NUM_REGS)
+ if (regnum < 0 && regnum >= gdbarch_num_regs (current_gdbarch))
return NULL;
else
{
packet_reg_from_pnum (struct remote_arch_state *rsa, LONGEST pnum)
{
int i;
- for (i = 0; i < NUM_REGS; i++)
+ for (i = 0; i < gdbarch_num_regs (current_gdbarch); i++)
{
struct packet_reg *r = &rsa->regs[i];
if (r->pnum == pnum)
extended_remote_ops, but with asynchronous support. */
static struct target_ops remote_async_ops;
+static int remote_async_mask_value = 1;
+
static struct target_ops extended_async_remote_ops;
/* FIXME: cagney/1999-09-23: Even though getpkt was called with
static int remote_async_terminal_ours_p;
+/* The executable file to use for "run" on the remote side. */
+
+static char *remote_exec_file = "";
+
\f
/* User configurable variables for the number of characters in a
memory read/write packet. MIN (rsa->remote_packet_size,
PACKET_Z2,
PACKET_Z3,
PACKET_Z4,
+ PACKET_vFile_open,
+ PACKET_vFile_pread,
+ PACKET_vFile_pwrite,
+ PACKET_vFile_close,
+ PACKET_vFile_unlink,
PACKET_qXfer_auxv,
PACKET_qXfer_features,
+ PACKET_qXfer_libraries,
PACKET_qXfer_memory_map,
+ PACKET_qXfer_spu_read,
+ PACKET_qXfer_spu_write,
PACKET_qGetTLSAddr,
PACKET_qSupported,
PACKET_QPassSignals,
+ PACKET_qSearch_memory,
+ PACKET_vAttach,
+ PACKET_vRun,
PACKET_MAX
};
static struct async_signal_handler *sigint_remote_twice_token;
static struct async_signal_handler *sigint_remote_token;
-/* These are pointers to hook functions that may be set in order to
- modify resume/wait behavior for a particular architecture. */
-
-void (*deprecated_target_resume_hook) (void);
-void (*deprecated_target_wait_loop_hook) (void);
\f
/* If this is a new thread, add it to GDB's thread list.
If we leave it up to WFI to do this, bad things will happen. */
if (!in_thread_list (pid_to_ptid (currthread)))
- {
- add_thread (pid_to_ptid (currthread));
- ui_out_text (uiout, "[New ");
- ui_out_text (uiout, target_pid_to_str (pid_to_ptid (currthread)));
- ui_out_text (uiout, "]\n");
- }
+ add_thread (pid_to_ptid (currthread));
}
static char *last_pass_packet;
static char *
unpack_nibble (char *buf, int *val)
{
- ishex (*buf++, val);
+ *val = fromhex (*buf++);
return buf;
}
putpkt (rs->buf);
getpkt (&rs->buf, &rs->buf_size, 0);
- *result_count =
- parse_threadlist_response (rs->buf + 2, result_limit, &echo_nextthread,
- threadlist, done);
+ if (*rs->buf == '\0')
+ *result_count = 0;
+ else
+ *result_count =
+ parse_threadlist_response (rs->buf + 2, result_limit, &echo_nextthread,
+ threadlist, done);
if (!threadmatch (&echo_nextthread, nextthread))
{
putpkt (rs->buf);
remote_fileio_reset ();
-
- /* Now query for status so this looks just like we restarted
- gdbserver from scratch. */
- putpkt ("?");
- getpkt (&rs->buf, &rs->buf_size, 0);
}
\f
/* Clean up connection to a remote debugger. */
struct remote_state *rs = get_remote_state ();
char *buf;
char *ptr;
- int lose;
- CORE_ADDR text_addr, data_addr, bss_addr;
+ int lose, num_segments = 0, do_sections, do_segments;
+ CORE_ADDR text_addr, data_addr, bss_addr, segments[2];
struct section_offsets *offs;
+ struct symfile_segment_data *data;
+
+ if (symfile_objfile == NULL)
+ return;
putpkt ("qOffsets");
getpkt (&rs->buf, &rs->buf_size, 0);
/* Don't use strtol, could lose on big values. */
while (*ptr && *ptr != ';')
text_addr = (text_addr << 4) + fromhex (*ptr++);
- }
- else
- lose = 1;
- if (!lose && strncmp (ptr, ";Data=", 6) == 0)
- {
- ptr += 6;
- while (*ptr && *ptr != ';')
- data_addr = (data_addr << 4) + fromhex (*ptr++);
- }
- else
- lose = 1;
+ if (strncmp (ptr, ";Data=", 6) == 0)
+ {
+ ptr += 6;
+ while (*ptr && *ptr != ';')
+ data_addr = (data_addr << 4) + fromhex (*ptr++);
+ }
+ else
+ lose = 1;
- if (!lose && strncmp (ptr, ";Bss=", 5) == 0)
+ if (!lose && strncmp (ptr, ";Bss=", 5) == 0)
+ {
+ ptr += 5;
+ while (*ptr && *ptr != ';')
+ bss_addr = (bss_addr << 4) + fromhex (*ptr++);
+
+ if (bss_addr != data_addr)
+ warning (_("Target reported unsupported offsets: %s"), buf);
+ }
+ else
+ lose = 1;
+ }
+ else if (strncmp (ptr, "TextSeg=", 8) == 0)
{
- ptr += 5;
+ ptr += 8;
+ /* Don't use strtol, could lose on big values. */
while (*ptr && *ptr != ';')
- bss_addr = (bss_addr << 4) + fromhex (*ptr++);
+ text_addr = (text_addr << 4) + fromhex (*ptr++);
+ num_segments = 1;
+
+ if (strncmp (ptr, ";DataSeg=", 9) == 0)
+ {
+ ptr += 9;
+ while (*ptr && *ptr != ';')
+ data_addr = (data_addr << 4) + fromhex (*ptr++);
+ num_segments++;
+ }
}
else
lose = 1;
if (lose)
error (_("Malformed response to offset query, %s"), buf);
-
- if (symfile_objfile == NULL)
- return;
+ else if (*ptr != '\0')
+ warning (_("Target reported unsupported offsets: %s"), buf);
offs = ((struct section_offsets *)
alloca (SIZEOF_N_SECTION_OFFSETS (symfile_objfile->num_sections)));
memcpy (offs, symfile_objfile->section_offsets,
SIZEOF_N_SECTION_OFFSETS (symfile_objfile->num_sections));
- offs->offsets[SECT_OFF_TEXT (symfile_objfile)] = text_addr;
+ data = get_symfile_segment_data (symfile_objfile->obfd);
+ do_segments = (data != NULL);
+ do_sections = num_segments == 0;
+
+ if (num_segments > 0)
+ {
+ segments[0] = text_addr;
+ segments[1] = data_addr;
+ }
+ /* If we have two segments, we can still try to relocate everything
+ by assuming that the .text and .data offsets apply to the whole
+ text and data segments. Convert the offsets given in the packet
+ to base addresses for symfile_map_offsets_to_segments. */
+ else if (data && data->num_segments == 2)
+ {
+ segments[0] = data->segment_bases[0] + text_addr;
+ segments[1] = data->segment_bases[1] + data_addr;
+ num_segments = 2;
+ }
+ /* There's no way to relocate by segment. */
+ else
+ do_segments = 0;
+
+ if (do_segments)
+ {
+ int ret = symfile_map_offsets_to_segments (symfile_objfile->obfd, data,
+ offs, num_segments, segments);
+
+ if (ret == 0 && !do_sections)
+ error (_("Can not handle qOffsets TextSeg response with this symbol file"));
+
+ if (ret > 0)
+ do_sections = 0;
+ }
+
+ if (data)
+ free_symfile_segment_data (data);
+
+ if (do_sections)
+ {
+ offs->offsets[SECT_OFF_TEXT (symfile_objfile)] = text_addr;
- /* This is a temporary kludge to force data and bss to use the same offsets
- because that's what nlmconv does now. The real solution requires changes
- to the stub and remote.c that I don't have time to do right now. */
+ /* This is a temporary kludge to force data and bss to use the same offsets
+ because that's what nlmconv does now. The real solution requires changes
+ to the stub and remote.c that I don't have time to do right now. */
- offs->offsets[SECT_OFF_DATA (symfile_objfile)] = data_addr;
- offs->offsets[SECT_OFF_BSS (symfile_objfile)] = data_addr;
+ offs->offsets[SECT_OFF_DATA (symfile_objfile)] = data_addr;
+ offs->offsets[SECT_OFF_BSS (symfile_objfile)] = data_addr;
+ }
objfile_relocate (symfile_objfile, offs);
}
/* Stub for catch_exception. */
+struct start_remote_args
+{
+ int from_tty;
+
+ /* The current target. */
+ struct target_ops *target;
+
+ /* Non-zero if this is an extended-remote target. */
+ int extended_p;
+};
+
static void
-remote_start_remote (struct ui_out *uiout, void *from_tty_p)
+remote_start_remote (struct ui_out *uiout, void *opaque)
{
- int from_tty = * (int *) from_tty_p;
+ struct remote_state *rs = get_remote_state ();
+ struct start_remote_args *args = opaque;
+ char *wait_status = NULL;
immediate_quit++; /* Allow user to interrupt it. */
/* Ack any packet which the remote side has already sent. */
serial_write (remote_desc, "+", 1);
+ /* Check whether the target is running now. */
+ putpkt ("?");
+ getpkt (&rs->buf, &rs->buf_size, 0);
+
+ if (rs->buf[0] == 'W' || rs->buf[0] == 'X')
+ {
+ if (args->extended_p)
+ {
+ /* We're connected, but not running. Drop out before we
+ call start_remote. */
+ target_mark_exited (args->target);
+ return;
+ }
+ else
+ error (_("The target is not running (try extended-remote?)"));
+ }
+ else
+ {
+ if (args->extended_p)
+ target_mark_running (args->target);
+
+ /* Save the reply for later. */
+ wait_status = alloca (strlen (rs->buf) + 1);
+ strcpy (wait_status, rs->buf);
+ }
+
/* Let the stub know that we want it to return the thread. */
set_thread (-1, 0);
+ /* 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);
+
+ /* Now, if we have thread information, update inferior_ptid. */
inferior_ptid = remote_current_thread (inferior_ptid);
get_offsets (); /* Get text, data & bss offsets. */
- putpkt ("?"); /* Initiate a query from remote machine. */
- immediate_quit--;
+ /* Use the previously fetched status. */
+ gdb_assert (wait_status != NULL);
+ strcpy (rs->buf, wait_status);
+ rs->cached_wait_status = 1;
- start_remote (from_tty); /* Initialize gdb process mechanisms. */
+ immediate_quit--;
+ start_remote (args->from_tty); /* Initialize gdb process mechanisms. */
}
/* Open a connection to a remote debugger.
if (sym == NULL)
xsnprintf (msg, get_remote_packet_size (), "qSymbol::%s", &reply[8]);
else
- xsnprintf (msg, get_remote_packet_size (), "qSymbol:%s:%s",
- paddr_nz (SYMBOL_VALUE_ADDRESS (sym)),
- &reply[8]);
+ {
+ CORE_ADDR sym_addr = SYMBOL_VALUE_ADDRESS (sym);
+
+ /* If this is a function address, return the start of code
+ instead of any data function descriptor. */
+ sym_addr = gdbarch_convert_from_func_ptr_addr (current_gdbarch,
+ sym_addr,
+ ¤t_target);
+
+ xsnprintf (msg, get_remote_packet_size (), "qSymbol:%s:%s",
+ paddr_nz (sym_addr), &reply[8]);
+ }
+
putpkt (msg);
getpkt (&rs->buf, &rs->buf_size, 0);
reply = rs->buf;
PACKET_qXfer_auxv },
{ "qXfer:features:read", PACKET_DISABLE, remote_supported_packet,
PACKET_qXfer_features },
+ { "qXfer:libraries:read", PACKET_DISABLE, remote_supported_packet,
+ PACKET_qXfer_libraries },
{ "qXfer:memory-map:read", PACKET_DISABLE, remote_supported_packet,
PACKET_qXfer_memory_map },
+ { "qXfer:spu:read", PACKET_DISABLE, remote_supported_packet,
+ PACKET_qXfer_spu_read },
+ { "qXfer:spu:write", PACKET_DISABLE, remote_supported_packet,
+ PACKET_qXfer_spu_write },
{ "QPassSignals", PACKET_DISABLE, remote_supported_packet,
PACKET_QPassSignals },
};
if (!async_p)
wait_forever_enabled_p = 1;
+ /* If we're connected to a running target, target_preopen will kill it.
+ But if we're connected to a target system with no running process,
+ then we will still be connected when it returns. Ask this question
+ first, before target_preopen has a chance to kill anything. */
+ if (remote_desc != NULL && !target_has_execution)
+ {
+ if (!from_tty
+ || query (_("Already connected to a remote target. Disconnect? ")))
+ pop_target ();
+ else
+ error (_("Still connected."));
+ }
+
target_preopen (from_tty);
unpush_target (target);
+ /* This time without a query. If we were connected to an
+ extended-remote target and target_preopen killed the running
+ process, we may still be connected. If we are starting "target
+ remote" now, the extended-remote target will not have been
+ removed by unpush_target. */
+ if (remote_desc != NULL && !target_has_execution)
+ pop_target ();
+
/* Make sure we send the passed signals list the next time we resume. */
xfree (last_pass_packet);
last_pass_packet = NULL;
}
push_target (target); /* Switch to using remote target now. */
+ /* Assume that the target is running, unless we learn otherwise. */
+ target_mark_running (target);
+
/* Reset the target state; these things will be queried either by
remote_query_supported or as they are needed. */
init_all_packet_configs ();
this before anything involving memory or registers. */
target_find_description ();
- /* 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);
-
if (async_p)
{
/* With this target we start out by owning the terminal. */
all the ``target ....'' commands to share a common callback
function. See cli-dump.c. */
{
- struct gdb_exception ex
- = catch_exception (uiout, remote_start_remote, &from_tty,
- RETURN_MASK_ALL);
+ struct gdb_exception ex;
+ struct start_remote_args args;
+
+ args.from_tty = from_tty;
+ args.target = target;
+ args.extended_p = extended_p;
+
+ ex = catch_exception (uiout, remote_start_remote, &args, RETURN_MASK_ALL);
if (ex.reason < 0)
{
pop_target ();
getpkt (&rs->buf, &rs->buf_size, 0);
}
- if (exec_bfd) /* No use without an exec file. */
- remote_check_symbols (symfile_objfile);
+ /* If we connected to a live target, do some additional setup. */
+ if (target_has_execution)
+ {
+ if (exec_bfd) /* No use without an exec file. */
+ remote_check_symbols (symfile_objfile);
+ }
}
/* This takes a program previously attached to and detaches it. After
die when it hits one. */
static void
-remote_detach (char *args, int from_tty)
+remote_detach_1 (char *args, int from_tty, int extended)
{
struct remote_state *rs = get_remote_state ();
if (args)
error (_("Argument given to \"detach\" when remotely debugging."));
+ if (!target_has_execution)
+ error (_("No process to detach from."));
+
/* Tell the remote target to detach. */
strcpy (rs->buf, "D");
- remote_send (&rs->buf, &rs->buf_size);
+ putpkt (rs->buf);
+ getpkt (&rs->buf, &rs->buf_size, 0);
+
+ if (rs->buf[0] == 'E')
+ error (_("Can't detach process."));
/* Unregister the file descriptor from the event loop. */
if (target_is_async_p ())
target_mourn_inferior ();
if (from_tty)
- puts_filtered ("Ending remote debugging.\n");
+ {
+ if (extended)
+ puts_filtered ("Detached from remote process.\n");
+ else
+ puts_filtered ("Ending remote debugging.\n");
+ }
+}
+
+static void
+remote_detach (char *args, int from_tty)
+{
+ remote_detach_1 (args, from_tty, 0);
+}
+
+static void
+extended_remote_detach (char *args, int from_tty)
+{
+ remote_detach_1 (args, from_tty, 1);
}
/* Same as remote_detach, but don't send the "D" packet; just disconnect. */
remote_disconnect (struct target_ops *target, char *args, int from_tty)
{
if (args)
- error (_("Argument given to \"detach\" when remotely debugging."));
+ error (_("Argument given to \"disconnect\" when remotely debugging."));
/* Unregister the file descriptor from the event loop. */
if (target_is_async_p ())
serial_async (remote_desc, NULL, 0);
- target_mourn_inferior ();
+ /* Make sure we unpush even the extended remote targets; mourn
+ won't do it. So call remote_mourn_1 directly instead of
+ target_mourn_inferior. */
+ remote_mourn_1 (target);
+
if (from_tty)
puts_filtered ("Ending remote debugging.\n");
}
+/* Attach to the process specified by ARGS. If FROM_TTY is non-zero,
+ be chatty about it. */
+
+static void
+extended_remote_attach_1 (struct target_ops *target, char *args, int from_tty)
+{
+ struct remote_state *rs = get_remote_state ();
+ int pid;
+ char *dummy;
+ char *wait_status = NULL;
+
+ if (!args)
+ error_no_arg (_("process-id to attach"));
+
+ dummy = args;
+ pid = strtol (args, &dummy, 0);
+ /* Some targets don't set errno on errors, grrr! */
+ if (pid == 0 && args == dummy)
+ error (_("Illegal process-id: %s."), args);
+
+ if (remote_protocol_packets[PACKET_vAttach].support == PACKET_DISABLE)
+ error (_("This target does not support attaching to a process"));
+
+ sprintf (rs->buf, "vAttach;%x", pid);
+ putpkt (rs->buf);
+ getpkt (&rs->buf, &rs->buf_size, 0);
+
+ if (packet_ok (rs->buf, &remote_protocol_packets[PACKET_vAttach]) == PACKET_OK)
+ {
+ if (from_tty)
+ printf_unfiltered (_("Attached to %s\n"),
+ target_pid_to_str (pid_to_ptid (pid)));
+
+ /* Save the reply for later. */
+ wait_status = alloca (strlen (rs->buf) + 1);
+ strcpy (wait_status, rs->buf);
+ }
+ else if (remote_protocol_packets[PACKET_vAttach].support == PACKET_DISABLE)
+ error (_("This target does not support attaching to a process"));
+ else
+ error (_("Attaching to %s failed"),
+ target_pid_to_str (pid_to_ptid (pid)));
+
+ target_mark_running (target);
+ inferior_ptid = pid_to_ptid (pid);
+ attach_flag = 1;
+
+ /* Next, if the target can specify a description, read it. We do
+ this before anything involving memory or registers. */
+ target_find_description ();
+
+ /* Use the previously fetched status. */
+ gdb_assert (wait_status != NULL);
+ strcpy (rs->buf, wait_status);
+ rs->cached_wait_status = 1;
+}
+
+static void
+extended_remote_attach (char *args, int from_tty)
+{
+ extended_remote_attach_1 (&extended_remote_ops, args, from_tty);
+}
+
+static void
+extended_async_remote_attach (char *args, int from_tty)
+{
+ extended_remote_attach_1 (&extended_async_remote_ops, args, from_tty);
+}
+
/* Convert hex digit A to a number. */
static int
{
struct remote_state *rs = get_remote_state ();
int pid = PIDGET (ptid);
- char *buf = NULL, *outbuf;
+ char *outbuf;
struct cleanup *old_cleanup;
if (remote_protocol_packets[PACKET_vCont].support == PACKET_SUPPORT_UNKNOWN)
last_sent_signal = siggnal;
last_sent_step = step;
- /* A hook for when we need to do something at the last moment before
- resumption. */
- if (deprecated_target_resume_hook)
- (*deprecated_target_resume_hook) ();
-
/* Update the inferior on signals to silently pass, if they've changed. */
remote_pass_signals ();
static void
initialize_sigint_signal_handler (void)
{
- sigint_remote_token =
- create_async_signal_handler (async_remote_interrupt, NULL);
signal (SIGINT, handle_remote_sigint);
}
handle_remote_sigint (int sig)
{
signal (sig, handle_remote_sigint_twice);
- sigint_remote_twice_token =
- create_async_signal_handler (async_remote_interrupt_twice, NULL);
mark_async_signal_handler_wrapper (sigint_remote_token);
}
static void
handle_remote_sigint_twice (int sig)
{
- signal (sig, handle_sigint);
- sigint_remote_twice_token =
- create_async_signal_handler (inferior_event_handler_wrapper, NULL);
+ signal (sig, handle_remote_sigint);
mark_async_signal_handler_wrapper (sigint_remote_twice_token);
}
{
if (remote_debug)
fprintf_unfiltered (gdb_stdlog, "remote_interrupt_twice called\n");
- /* Do something only if the target was not killed by the previous
- cntl-C. */
- if (target_executing)
- {
- interrupt_query ();
- signal (SIGINT, handle_remote_sigint);
- }
+
+ interrupt_query ();
}
/* Reinstall the usual SIGINT handlers, after the target has
cleanup_sigint_signal_handler (void *dummy)
{
signal (SIGINT, handle_sigint);
- if (sigint_remote_twice_token)
- delete_async_signal_handler (&sigint_remote_twice_token);
- if (sigint_remote_token)
- delete_async_signal_handler (&sigint_remote_token);
}
/* Send ^C to target to halt it. Target will respond, and send us a
/* If this doesn't work, try more severe steps. */
signal (signo, remote_interrupt_twice);
- if (remote_debug)
- fprintf_unfiltered (gdb_stdlog, "remote_interrupt called\n");
-
- target_stop ();
+ gdb_call_async_signal_handler (sigint_remote_token, 1);
}
/* The user typed ^C twice. */
remote_interrupt_twice (int signo)
{
signal (signo, ofunc);
- interrupt_query ();
+ gdb_call_async_signal_handler (sigint_remote_twice_token, 1);
signal (signo, remote_interrupt);
}
Give up (and stop debugging it)? "))
{
target_mourn_inferior ();
+ signal (SIGINT, handle_sigint);
deprecated_throw_reason (RETURN_QUIT);
}
struct remote_arch_state *rsa = get_remote_arch_state ();
ULONGEST thread_num = -1;
ULONGEST addr;
+ int solibs_changed = 0;
status->kind = TARGET_WAITKIND_EXITED;
status->value.integer = 0;
{
char *buf, *p;
- ofunc = signal (SIGINT, remote_interrupt);
- getpkt (&rs->buf, &rs->buf_size, 1);
- signal (SIGINT, ofunc);
+ if (rs->cached_wait_status)
+ /* Use the cached wait status, but only once. */
+ rs->cached_wait_status = 0;
+ else
+ {
+ ofunc = signal (SIGINT, remote_interrupt);
+ /* If the user hit C-c before this packet, or between packets,
+ pretend that it was hit right here. */
+ if (quit_flag)
+ {
+ quit_flag = 0;
+ remote_interrupt (SIGINT);
+ }
+ getpkt (&rs->buf, &rs->buf_size, 1);
+ signal (SIGINT, ofunc);
+ }
buf = rs->buf;
- /* This is a hook for when we need to do something (perhaps the
- collection of trace data) every time the target stops. */
- if (deprecated_target_wait_loop_hook)
- (*deprecated_target_wait_loop_hook) ();
-
remote_stopped_by_watchpoint_p = 0;
switch (buf[0])
{
case 'E': /* Error of some sort. */
+ /* We're out of sync with the target now. Did it continue or not?
+ Not is more likely, so report a stop. */
warning (_("Remote failure reply: %s"), buf);
- continue;
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_0;
+ goto got_status;
case 'F': /* File-I/O request. */
remote_fileio_request (buf);
continue;
p = unpack_varlen_hex (++p1, &addr);
remote_watch_data_address = (CORE_ADDR)addr;
}
+ else if (strncmp (p, "library", p1 - p) == 0)
+ {
+ p1++;
+ p_temp = p1;
+ while (*p_temp && *p_temp != ';')
+ p_temp++;
+
+ solibs_changed = 1;
+ p = p_temp;
+ }
else
{
/* Silently skip unknown optional info. */
if (fieldsize < register_size (current_gdbarch,
reg->regnum))
warning (_("Remote reply is too short: %s"), buf);
- regcache_raw_supply (current_regcache,
+ regcache_raw_supply (get_current_regcache (),
reg->regnum, regs);
}
}
/* fall through */
case 'S': /* Old style status, just signal only. */
- status->kind = TARGET_WAITKIND_STOPPED;
- status->value.sig = (enum target_signal)
- (((fromhex (buf[1])) << 4) + (fromhex (buf[2])));
+ if (solibs_changed)
+ status->kind = TARGET_WAITKIND_LOADED;
+ else
+ {
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = (enum target_signal)
+ (((fromhex (buf[1])) << 4) + (fromhex (buf[2])));
+ }
if (buf[3] == 'p')
{
struct remote_arch_state *rsa = get_remote_arch_state ();
ULONGEST thread_num = -1;
ULONGEST addr;
+ int solibs_changed = 0;
status->kind = TARGET_WAITKIND_EXITED;
status->value.integer = 0;
{
char *buf, *p;
- if (!target_is_async_p ())
- ofunc = signal (SIGINT, remote_interrupt);
- /* FIXME: cagney/1999-09-27: If we're in async mode we should
- _never_ wait for ever -> test on target_is_async_p().
- However, before we do that we need to ensure that the caller
- knows how to take the target into/out of async mode. */
- getpkt (&rs->buf, &rs->buf_size, wait_forever_enabled_p);
- if (!target_is_async_p ())
- signal (SIGINT, ofunc);
+ if (rs->cached_wait_status)
+ /* Use the cached wait status, but only once. */
+ rs->cached_wait_status = 0;
+ else
+ {
+ if (!target_is_async_p ())
+ {
+ ofunc = signal (SIGINT, remote_interrupt);
+ /* If the user hit C-c before this packet, or between packets,
+ pretend that it was hit right here. */
+ if (quit_flag)
+ {
+ quit_flag = 0;
+ remote_interrupt (SIGINT);
+ }
+ }
+ /* FIXME: cagney/1999-09-27: If we're in async mode we should
+ _never_ wait for ever -> test on target_is_async_p().
+ However, before we do that we need to ensure that the caller
+ knows how to take the target into/out of async mode. */
+ getpkt (&rs->buf, &rs->buf_size, wait_forever_enabled_p);
+ if (!target_is_async_p ())
+ signal (SIGINT, ofunc);
+ }
buf = rs->buf;
- /* This is a hook for when we need to do something (perhaps the
- collection of trace data) every time the target stops. */
- if (deprecated_target_wait_loop_hook)
- (*deprecated_target_wait_loop_hook) ();
-
switch (buf[0])
{
case 'E': /* Error of some sort. */
+ /* We're out of sync with the target now. Did it continue or not?
+ Not is more likely, so report a stop. */
warning (_("Remote failure reply: %s"), buf);
- continue;
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_0;
+ goto got_status;
case 'F': /* File-I/O request. */
remote_fileio_request (buf);
continue;
/* If this packet is an awatch packet, don't parse the 'a'
as a register number. */
- if (!strncmp (p, "awatch", strlen ("awatch")) != 0)
+ if (strncmp (p, "awatch", strlen("awatch")) != 0)
{
/* Read the register number. */
pnum = strtol (p, &p_temp, 16);
p = unpack_varlen_hex (++p1, &addr);
remote_watch_data_address = (CORE_ADDR)addr;
}
+ else if (strncmp (p, "library", p1 - p) == 0)
+ {
+ p1++;
+ p_temp = p1;
+ while (*p_temp && *p_temp != ';')
+ p_temp++;
+
+ solibs_changed = 1;
+ p = p_temp;
+ }
else
{
/* Silently skip unknown optional info. */
if (fieldsize < register_size (current_gdbarch,
reg->regnum))
warning (_("Remote reply is too short: %s"), buf);
- regcache_raw_supply (current_regcache, reg->regnum, regs);
+ regcache_raw_supply (get_current_regcache (),
+ reg->regnum, regs);
}
if (*p++ != ';')
}
/* fall through */
case 'S': /* Old style status, just signal only. */
- status->kind = TARGET_WAITKIND_STOPPED;
- status->value.sig = (enum target_signal)
- (((fromhex (buf[1])) << 4) + (fromhex (buf[2])));
+ if (solibs_changed)
+ status->kind = TARGET_WAITKIND_LOADED;
+ else
+ {
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = (enum target_signal)
+ (((fromhex (buf[1])) << 4) + (fromhex (buf[2])));
+ }
if (buf[3] == 'p')
{
/* Fetch a single register using a 'p' packet. */
static int
-fetch_register_using_p (struct packet_reg *reg)
+fetch_register_using_p (struct regcache *regcache, struct packet_reg *reg)
{
struct remote_state *rs = get_remote_state ();
char *buf, *p;
return 0;
case PACKET_ERROR:
error (_("Could not fetch register \"%s\""),
- gdbarch_register_name (current_gdbarch, reg->regnum));
+ gdbarch_register_name (get_regcache_arch (regcache), reg->regnum));
}
/* If this register is unfetchable, tell the regcache. */
if (buf[0] == 'x')
{
- regcache_raw_supply (current_regcache, reg->regnum, NULL);
- set_register_cached (reg->regnum, -1);
+ regcache_raw_supply (regcache, reg->regnum, NULL);
return 1;
}
regp[i++] = fromhex (p[0]) * 16 + fromhex (p[1]);
p += 2;
}
- regcache_raw_supply (current_regcache, reg->regnum, regp);
+ regcache_raw_supply (regcache, reg->regnum, regp);
return 1;
}
}
static void
-process_g_packet (void)
+process_g_packet (struct regcache *regcache)
{
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
struct remote_state *rs = get_remote_state ();
struct remote_arch_state *rsa = get_remote_arch_state ();
int i, buf_len;
buf_len = strlen (rs->buf);
/* Further sanity checks, with knowledge of the architecture. */
- if (REGISTER_BYTES_OK_P () && !REGISTER_BYTES_OK (buf_len / 2))
- error (_("Remote 'g' packet reply is wrong length: %s"), rs->buf);
if (buf_len > 2 * rsa->sizeof_g_packet)
error (_("Remote 'g' packet reply is too long: %s"), rs->buf);
{
rsa->sizeof_g_packet = buf_len / 2;
- for (i = 0; i < NUM_REGS; i++)
+ for (i = 0; i < gdbarch_num_regs (gdbarch); i++)
{
if (rsa->regs[i].pnum == -1)
continue;
{
int i;
- for (i = 0; i < NUM_REGS; i++)
+ for (i = 0; i < gdbarch_num_regs (gdbarch); i++)
{
struct packet_reg *r = &rsa->regs[i];
if (r->in_g_packet)
gdb_assert (r->offset * 2 < strlen (rs->buf));
/* The register isn't available, mark it as such (at
the same time setting the value to zero). */
- regcache_raw_supply (current_regcache, r->regnum, NULL);
- set_register_cached (i, -1);
+ regcache_raw_supply (regcache, r->regnum, NULL);
}
else
- regcache_raw_supply (current_regcache, r->regnum,
+ regcache_raw_supply (regcache, r->regnum,
regs + r->offset);
}
}
}
static void
-fetch_registers_using_g (void)
+fetch_registers_using_g (struct regcache *regcache)
{
send_g_packet ();
- process_g_packet ();
+ process_g_packet (regcache);
}
static void
-remote_fetch_registers (int regnum)
+remote_fetch_registers (struct regcache *regcache, int regnum)
{
struct remote_state *rs = get_remote_state ();
struct remote_arch_state *rsa = get_remote_arch_state ();
contents, so fall back to 'p'. */
if (reg->in_g_packet)
{
- fetch_registers_using_g ();
+ fetch_registers_using_g (regcache);
if (reg->in_g_packet)
return;
}
- if (fetch_register_using_p (reg))
+ if (fetch_register_using_p (regcache, reg))
return;
/* This register is not available. */
- regcache_raw_supply (current_regcache, reg->regnum, NULL);
- set_register_cached (reg->regnum, -1);
+ regcache_raw_supply (regcache, reg->regnum, NULL);
return;
}
- fetch_registers_using_g ();
+ fetch_registers_using_g (regcache);
- for (i = 0; i < NUM_REGS; i++)
+ for (i = 0; i < gdbarch_num_regs (get_regcache_arch (regcache)); i++)
if (!rsa->regs[i].in_g_packet)
- if (!fetch_register_using_p (&rsa->regs[i]))
+ if (!fetch_register_using_p (regcache, &rsa->regs[i]))
{
/* This register is not available. */
- regcache_raw_supply (current_regcache, i, NULL);
- set_register_cached (i, -1);
+ regcache_raw_supply (regcache, i, NULL);
}
}
first. */
static void
-remote_prepare_to_store (void)
+remote_prepare_to_store (struct regcache *regcache)
{
struct remote_arch_state *rsa = get_remote_arch_state ();
int i;
case PACKET_DISABLE:
case PACKET_SUPPORT_UNKNOWN:
/* Make sure all the necessary registers are cached. */
- for (i = 0; i < NUM_REGS; i++)
+ for (i = 0; i < gdbarch_num_regs (get_regcache_arch (regcache)); i++)
if (rsa->regs[i].in_g_packet)
- regcache_raw_read (current_regcache, rsa->regs[i].regnum, buf);
+ regcache_raw_read (regcache, rsa->regs[i].regnum, buf);
break;
case PACKET_ENABLE:
break;
packet was not recognized. */
static int
-store_register_using_P (struct packet_reg *reg)
+store_register_using_P (const struct regcache *regcache, struct packet_reg *reg)
{
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
struct remote_state *rs = get_remote_state ();
struct remote_arch_state *rsa = get_remote_arch_state ();
/* Try storing a single register. */
xsnprintf (buf, get_remote_packet_size (), "P%s=", phex_nz (reg->pnum, 0));
p = buf + strlen (buf);
- regcache_raw_collect (current_regcache, reg->regnum, regp);
- bin2hex (regp, p, register_size (current_gdbarch, reg->regnum));
+ regcache_raw_collect (regcache, reg->regnum, regp);
+ bin2hex (regp, p, register_size (gdbarch, reg->regnum));
remote_send (&rs->buf, &rs->buf_size);
switch (packet_ok (rs->buf, &remote_protocol_packets[PACKET_P]))
return 1;
case PACKET_ERROR:
error (_("Could not write register \"%s\""),
- gdbarch_register_name (current_gdbarch, reg->regnum));
+ gdbarch_register_name (gdbarch, reg->regnum));
case PACKET_UNKNOWN:
return 0;
default:
contents of the register cache buffer. FIXME: ignores errors. */
static void
-store_registers_using_G (void)
+store_registers_using_G (const struct regcache *regcache)
{
struct remote_state *rs = get_remote_state ();
struct remote_arch_state *rsa = get_remote_arch_state ();
int i;
regs = alloca (rsa->sizeof_g_packet);
memset (regs, 0, rsa->sizeof_g_packet);
- for (i = 0; i < NUM_REGS; i++)
+ for (i = 0; i < gdbarch_num_regs (get_regcache_arch (regcache)); i++)
{
struct packet_reg *r = &rsa->regs[i];
if (r->in_g_packet)
- regcache_raw_collect (current_regcache, r->regnum, regs + r->offset);
+ regcache_raw_collect (regcache, r->regnum, regs + r->offset);
}
}
of the register cache buffer. FIXME: ignores errors. */
static void
-remote_store_registers (int regnum)
+remote_store_registers (struct regcache *regcache, int regnum)
{
struct remote_state *rs = get_remote_state ();
struct remote_arch_state *rsa = get_remote_arch_state ();
possible; we often change only a small number of registers.
Sometimes we change a larger number; we'd need help from a
higher layer to know to use 'G'. */
- if (store_register_using_P (reg))
+ if (store_register_using_P (regcache, reg))
return;
/* For now, don't complain if we have no way to write the
if (!reg->in_g_packet)
return;
- store_registers_using_G ();
+ store_registers_using_G (regcache);
return;
}
- store_registers_using_G ();
+ store_registers_using_G (regcache);
- for (i = 0; i < NUM_REGS; i++)
+ for (i = 0; i < gdbarch_num_regs (get_regcache_arch (regcache)); i++)
if (!rsa->regs[i].in_g_packet)
- if (!store_register_using_P (&rsa->regs[i]))
+ if (!store_register_using_P (regcache, &rsa->regs[i]))
/* See above for why we do not issue an error here. */
continue;
}
static CORE_ADDR
remote_address_masked (CORE_ADDR addr)
{
- if (remote_address_size > 0
- && remote_address_size < (sizeof (ULONGEST) * 8))
+ int address_size = remote_address_size;
+ /* If "remoteaddresssize" was not set, default to target address size. */
+ if (!address_size)
+ address_size = gdbarch_addr_bit (current_gdbarch);
+
+ if (address_size > 0
+ && address_size < (sizeof (ULONGEST) * 8))
{
/* Only create a mask when that mask can safely be constructed
in a ULONGEST variable. */
ULONGEST mask = 1;
- mask = (mask << remote_address_size) - 1;
+ mask = (mask << address_size) - 1;
addr &= mask;
}
return addr;
internal_error (__FILE__, __LINE__,
"remote_write_bytes_aux: bad packet format");
- /* Should this be the selected frame? */
- gdbarch_remote_translate_xfer_address (current_gdbarch,
- current_regcache,
- memaddr, len,
- &memaddr, &len);
-
if (len <= 0)
return 0;
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;
static int
putpkt_binary (char *buf, int cnt)
{
+ struct remote_state *rs = get_remote_state ();
int i;
unsigned char csum = 0;
char *buf2 = alloca (cnt + 6);
int tcount = 0;
char *p;
+ /* We're sending out a new packet. Make sure we don't look at a
+ stale cached response. */
+ rs->cached_wait_status = 0;
+
/* Copy the packet into buffer BUF2, encapsulating it
and giving it a checksum. */
static int
getpkt_sane (char **buf, long *sizeof_buf, int forever)
{
+ struct remote_state *rs = get_remote_state ();
int c;
int tries;
int timeout;
int val;
+ /* We're reading a new response. Make sure we don't look at a
+ previously cached response. */
+ rs->cached_wait_status = 0;
+
strcpy (*buf, "timeout");
if (forever)
{
QUIT;
target_mourn_inferior ();
- error (_("Watchdog has expired. Target detached."));
+ error (_("Watchdog timeout has expired. Target detached."));
}
if (remote_debug)
fputs_filtered ("Timed out.\n", gdb_stdlog);
remote_mourn_1 (&remote_async_ops);
}
-static void
-extended_remote_mourn (void)
-{
- /* We do _not_ want to mourn the target like this; this will
- remove the extended remote target from the target stack,
- and the next time the user says "run" it'll fail.
-
- FIXME: What is the right thing to do here? */
-#if 0
- remote_mourn_1 (&extended_remote_ops);
-#endif
-}
-
/* Worker function for remote_mourn. */
static void
remote_mourn_1 (struct target_ops *target)
generic_mourn_inferior ();
}
-/* In the extended protocol we want to be able to do things like
- "run" and have them basically work as expected. So we need
- a special create_inferior function.
-
- FIXME: One day add support for changing the exec file
- we're debugging, arguments and an environment. */
-
static void
-extended_remote_create_inferior (char *exec_file, char *args,
- char **env, int from_tty)
+extended_remote_mourn_1 (struct target_ops *target)
{
- /* Rip out the breakpoints; we'll reinsert them after restarting
- the remote server. */
- remove_breakpoints ();
+ struct remote_state *rs = get_remote_state ();
- /* Now restart the remote server. */
- extended_remote_restart ();
+ /* Unlike "target remote", we do not want to unpush the target; then
+ the next time the user says "run", we won't be connected. */
- /* NOTE: We don't need to recheck for a target description here; but
- if we gain the ability to switch the remote executable we may
- need to, if for instance we are running a process which requested
- different emulated hardware from the operating system. A
- concrete example of this is ARM GNU/Linux, where some binaries
- will have a legacy FPA coprocessor emulated and others may have
- access to a hardware VFP unit. */
+ /* Call common code to mark the inferior as not running. */
+ generic_mourn_inferior ();
- /* Now put the breakpoints back in. This way we're safe if the
- restart function works via a unix fork on the remote side. */
- insert_breakpoints ();
+ /* Check whether the target is running now - some remote stubs
+ automatically restart after kill. */
+ putpkt ("?");
+ getpkt (&rs->buf, &rs->buf_size, 0);
- /* Clean up from the last time we were running. */
- clear_proceed_status ();
+ if (rs->buf[0] == 'S' || rs->buf[0] == 'T')
+ {
+ /* Assume that the target has been restarted. Set inferior_ptid
+ so that bits of core GDB realizes there's something here, e.g.,
+ so that the user can say "kill" again. */
+ inferior_ptid = pid_to_ptid (MAGIC_NULL_PID);
+ }
+ else
+ {
+ /* Mark this (still pushed) target as not executable until we
+ restart it. */
+ target_mark_exited (target);
+ }
}
-/* Async version of extended_remote_create_inferior. */
static void
-extended_remote_async_create_inferior (char *exec_file, char *args,
- char **env, int from_tty)
+extended_remote_mourn (void)
{
- /* Rip out the breakpoints; we'll reinsert them after restarting
- the remote server. */
- remove_breakpoints ();
-
- /* If running asynchronously, register the target file descriptor
- with the event loop. */
- if (target_can_async_p ())
- target_async (inferior_event_handler, 0);
+ extended_remote_mourn_1 (&extended_remote_ops);
+}
- /* Now restart the remote server. */
- extended_remote_restart ();
+static void
+extended_async_remote_mourn (void)
+{
+ extended_remote_mourn_1 (&extended_async_remote_ops);
+}
+
+static int
+extended_remote_run (char *args)
+{
+ struct remote_state *rs = get_remote_state ();
+ char *p;
+ int len;
+
+ /* If the user has disabled vRun support, or we have detected that
+ support is not available, do not try it. */
+ if (remote_protocol_packets[PACKET_vRun].support == PACKET_DISABLE)
+ return -1;
- /* NOTE: We don't need to recheck for a target description here; but
- if we gain the ability to switch the remote executable we may
- need to, if for instance we are running a process which requested
- different emulated hardware from the operating system. A
- concrete example of this is ARM GNU/Linux, where some binaries
- will have a legacy FPA coprocessor emulated and others may have
- access to a hardware VFP unit. */
+ strcpy (rs->buf, "vRun;");
+ len = strlen (rs->buf);
- /* Now put the breakpoints back in. This way we're safe if the
- restart function works via a unix fork on the remote side. */
- insert_breakpoints ();
+ 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);
+
+ if (*args)
+ {
+ struct cleanup *back_to;
+ int i;
+ char **argv;
- /* Clean up from the last time we were running. */
- clear_proceed_status ();
+ argv = buildargv (args);
+ back_to = make_cleanup ((void (*) (void *)) freeargv, argv);
+ for (i = 0; argv[i] != NULL; i++)
+ {
+ 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);
+ }
+ do_cleanups (back_to);
+ }
+
+ rs->buf[len++] = '\0';
+
+ putpkt (rs->buf);
+ getpkt (&rs->buf, &rs->buf_size, 0);
+
+ if (packet_ok (rs->buf, &remote_protocol_packets[PACKET_vRun]) == PACKET_OK)
+ {
+ /* We have a wait response; we don't need it, though. All is well. */
+ return 0;
+ }
+ else if (remote_protocol_packets[PACKET_vRun].support == PACKET_DISABLE)
+ /* It wasn't disabled before, but it is now. */
+ return -1;
+ else
+ {
+ if (remote_exec_file[0] == '\0')
+ error (_("Running the default executable on the remote target failed; "
+ "try \"set remote exec-file\"?"));
+ else
+ error (_("Running \"%s\" on the remote target failed"),
+ remote_exec_file);
+ }
}
-\f
-/* On some machines, e.g. 68k, we may use a different breakpoint
- instruction than other targets; in those use
- DEPRECATED_REMOTE_BREAKPOINT instead of just BREAKPOINT_FROM_PC.
- Also, bi-endian targets may define
- DEPRECATED_LITTLE_REMOTE_BREAKPOINT and
- DEPRECATED_BIG_REMOTE_BREAKPOINT. If none of these are defined, we
- just call the standard routines that are in mem-break.c. */
+/* In the extended protocol we want to be able to do things like
+ "run" and have them basically work as expected. So we need
+ a special create_inferior function. We support changing the
+ executable file and the command line arguments, but not the
+ environment. */
-/* NOTE: cagney/2003-06-08: This is silly. A remote and simulator
- target should use an identical BREAKPOINT_FROM_PC. As for native,
- the ARCH-OS-tdep.c code can override the default. */
+static void
+extended_remote_create_inferior_1 (char *exec_file, char *args,
+ char **env, int from_tty,
+ int async_p)
+{
+ /* If running asynchronously, register the target file descriptor
+ with the event loop. */
+ if (async_p && target_can_async_p ())
+ target_async (inferior_event_handler, 0);
-#if defined (DEPRECATED_LITTLE_REMOTE_BREAKPOINT) && defined (DEPRECATED_BIG_REMOTE_BREAKPOINT) && !defined(DEPRECATED_REMOTE_BREAKPOINT)
-#define DEPRECATED_REMOTE_BREAKPOINT
-#endif
+ /* Now restart the remote server. */
+ if (extended_remote_run (args) == -1)
+ {
+ /* vRun was not supported. Fail if we need it to do what the
+ user requested. */
+ if (remote_exec_file[0])
+ error (_("Remote target does not support \"set remote exec-file\""));
+ if (args[0])
+ error (_("Remote target does not support \"set args\" or run <ARGS>"));
+
+ /* Fall back to "R". */
+ extended_remote_restart ();
+ }
-#ifdef DEPRECATED_REMOTE_BREAKPOINT
+ /* Clean up from the last time we ran, before we mark the target
+ running again. This will mark breakpoints uninserted, and
+ get_offsets may insert breakpoints. */
+ init_thread_list ();
+ init_wait_for_inferior ();
-/* If the target isn't bi-endian, just pretend it is. */
-#if !defined (DEPRECATED_LITTLE_REMOTE_BREAKPOINT) && !defined (DEPRECATED_BIG_REMOTE_BREAKPOINT)
-#define DEPRECATED_LITTLE_REMOTE_BREAKPOINT DEPRECATED_REMOTE_BREAKPOINT
-#define DEPRECATED_BIG_REMOTE_BREAKPOINT DEPRECATED_REMOTE_BREAKPOINT
-#endif
+ /* Now mark the inferior as running before we do anything else. */
+ attach_flag = 0;
+ inferior_ptid = pid_to_ptid (MAGIC_NULL_PID);
+ if (async_p)
+ target_mark_running (&extended_async_remote_ops);
+ else
+ target_mark_running (&extended_remote_ops);
-static unsigned char big_break_insn[] = DEPRECATED_BIG_REMOTE_BREAKPOINT;
-static unsigned char little_break_insn[] = DEPRECATED_LITTLE_REMOTE_BREAKPOINT;
+ /* Get updated offsets, if the stub uses qOffsets. */
+ get_offsets ();
+}
+
+static void
+extended_remote_create_inferior (char *exec_file, char *args,
+ char **env, int from_tty)
+{
+ extended_remote_create_inferior_1 (exec_file, args, env, from_tty, 0);
+}
-#endif /* DEPRECATED_REMOTE_BREAKPOINT */
+static void
+extended_remote_async_create_inferior (char *exec_file, char *args,
+ char **env, int from_tty)
+{
+ extended_remote_create_inferior_1 (exec_file, args, env, from_tty, 1);
+}
+\f
/* Insert a breakpoint. On targets that have software breakpoint
support, we ask the remote target to do the work; on targets
static int
remote_insert_breakpoint (struct bp_target_info *bp_tgt)
{
- CORE_ADDR addr = bp_tgt->placed_address;
- struct remote_state *rs = get_remote_state ();
-#ifdef DEPRECATED_REMOTE_BREAKPOINT
- int val;
-#endif
-
/* Try the "Z" s/w breakpoint packet if it is not already disabled.
If it succeeds, then set the support to PACKET_ENABLE. If it
fails, and the user has explicitly requested the Z support then
if (remote_protocol_packets[PACKET_Z0].support != PACKET_DISABLE)
{
- char *p = rs->buf;
+ CORE_ADDR addr;
+ struct remote_state *rs;
+ char *p;
+
+ gdbarch_breakpoint_from_pc
+ (current_gdbarch, &bp_tgt->placed_address, &bp_tgt->placed_size);
+
+ rs = get_remote_state ();
+ p = rs->buf;
*(p++) = 'Z';
*(p++) = '0';
*(p++) = ',';
- BREAKPOINT_FROM_PC (&bp_tgt->placed_address, &bp_tgt->placed_size);
addr = (ULONGEST) remote_address_masked (bp_tgt->placed_address);
p += hexnumstr (p, addr);
sprintf (p, ",%d", bp_tgt->placed_size);
}
}
-#ifdef DEPRECATED_REMOTE_BREAKPOINT
- bp_tgt->placed_size = bp_tgt->shadow_len = sizeof big_break_insn;
- val = target_read_memory (addr, bp_tgt->shadow_contents, bp_tgt->shadow_len);
-
- if (val == 0)
- {
- if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
- val = target_write_memory (addr, (char *) big_break_insn,
- sizeof big_break_insn);
- else
- val = target_write_memory (addr, (char *) little_break_insn,
- sizeof little_break_insn);
- }
-
- return val;
-#else
return memory_insert_breakpoint (bp_tgt);
-#endif /* DEPRECATED_REMOTE_BREAKPOINT */
}
static int
return (rs->buf[0] == 'E');
}
-#ifdef DEPRECATED_REMOTE_BREAKPOINT
- return target_write_memory (bp_tgt->placed_address, bp_tgt->shadow_contents,
- bp_tgt->shadow_len);
-#else
return memory_remove_breakpoint (bp_tgt);
-#endif /* DEPRECATED_REMOTE_BREAKPOINT */
}
static int
return remote_stopped_by_watchpoint_p;
}
-extern int stepped_after_stopped_by_watchpoint;
-
static int
remote_stopped_data_address (struct target_ops *target, CORE_ADDR *addr_p)
{
int rc = 0;
- if (remote_stopped_by_watchpoint ()
- || stepped_after_stopped_by_watchpoint)
+ if (remote_stopped_by_watchpoint ())
{
*addr_p = remote_watch_data_address;
rc = 1;
remote_insert_hw_breakpoint (struct bp_target_info *bp_tgt)
{
CORE_ADDR addr;
- struct remote_state *rs = get_remote_state ();
- char *p = rs->buf;
+ struct remote_state *rs;
+ char *p;
/* The length field should be set to the size of a breakpoint
instruction, even though we aren't inserting one ourselves. */
- BREAKPOINT_FROM_PC (&bp_tgt->placed_address, &bp_tgt->placed_size);
+ gdbarch_breakpoint_from_pc
+ (current_gdbarch, &bp_tgt->placed_address, &bp_tgt->placed_size);
if (remote_protocol_packets[PACKET_Z1].support == PACKET_DISABLE)
return -1;
+ rs = get_remote_state ();
+ p = rs->buf;
+
*(p++) = 'Z';
*(p++) = '1';
*(p++) = ',';
printf_filtered (_("No loaded section named '%s'.\n"), args);
}
+/* Write LEN bytes from WRITEBUF into OBJECT_NAME/ANNEX at OFFSET
+ into remote target. The number of bytes written to the remote
+ target is returned, or -1 for error. */
+
+static LONGEST
+remote_write_qxfer (struct target_ops *ops, const char *object_name,
+ const char *annex, const gdb_byte *writebuf,
+ ULONGEST offset, LONGEST len,
+ struct packet_config *packet)
+{
+ int i, buf_len;
+ ULONGEST n;
+ gdb_byte *wbuf;
+ struct remote_state *rs = get_remote_state ();
+ int max_size = get_memory_write_packet_size ();
+
+ if (packet->support == PACKET_DISABLE)
+ return -1;
+
+ /* Insert header. */
+ i = snprintf (rs->buf, max_size,
+ "qXfer:%s:write:%s:%s:",
+ object_name, annex ? annex : "",
+ phex_nz (offset, sizeof offset));
+ max_size -= (i + 1);
+
+ /* Escape as much data as fits into rs->buf. */
+ buf_len = remote_escape_output
+ (writebuf, len, (rs->buf + i), &max_size, 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;
+
+ unpack_varlen_hex (rs->buf, &n);
+ return n;
+}
+
/* Read OBJECT_NAME/ANNEX from the remote target using a qXfer packet.
Data at OFFSET, of up to LEN bytes, is read into READBUF; the
number of bytes read is returned, or 0 for EOF, or -1 for error.
i = remote_unescape_input (rs->buf + 1, packet_len - 1, readbuf, n);
/* 'l' is an EOF marker, possibly including a final block of data,
- or possibly empty. Record it to bypass the next read, if one is
- issued. */
- if (rs->buf[0] == 'l')
+ or possibly empty. If we have the final block of a non-empty
+ object, record this fact to bypass a subsequent partial read. */
+ if (rs->buf[0] == 'l' && offset + i > 0)
{
finished_object = xstrdup (object_name);
finished_annex = xstrdup (annex ? annex : "");
int xfered;
errno = 0;
+ /* 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;
+
if (writebuf != NULL)
xfered = remote_write_bytes (offset, writebuf, len);
else
return -1;
}
+ /* Handle SPU memory using qxfer packets. */
+ if (object == TARGET_OBJECT_SPU)
+ {
+ if (readbuf)
+ return remote_read_qxfer (ops, "spu", annex, readbuf, offset, 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]);
+ }
+
/* Only handle flash writes. */
if (writebuf != NULL)
{
(ops, "features", annex, readbuf, offset, len,
&remote_protocol_packets[PACKET_qXfer_features]);
+ case TARGET_OBJECT_LIBRARIES:
+ return remote_read_qxfer
+ (ops, "libraries", annex, readbuf, offset, len,
+ &remote_protocol_packets[PACKET_qXfer_libraries]);
+
case TARGET_OBJECT_MEMORY_MAP:
gdb_assert (annex == NULL);
return remote_read_qxfer (ops, "memory-map", annex, readbuf, offset, len,
return strlen ((char *) readbuf);
}
+static int
+remote_search_memory (struct target_ops* ops,
+ CORE_ADDR start_addr, ULONGEST search_space_len,
+ const gdb_byte *pattern, ULONGEST pattern_len,
+ CORE_ADDR *found_addrp)
+{
+ struct remote_state *rs = get_remote_state ();
+ int max_size = get_memory_write_packet_size ();
+ struct packet_config *packet =
+ &remote_protocol_packets[PACKET_qSearch_memory];
+ /* number of packet bytes used to encode the pattern,
+ this could be more than PATTERN_LEN due to escape characters */
+ int escaped_pattern_len;
+ /* amount of pattern that was encodable in the packet */
+ int used_pattern_len;
+ int i;
+ int found;
+ ULONGEST found_addr;
+
+ /* Don't go to the target if we don't have to.
+ This is done before checking packet->support to avoid the possibility that
+ a success for this edge case means the facility works in general. */
+ if (pattern_len > search_space_len)
+ return 0;
+ if (pattern_len == 0)
+ {
+ *found_addrp = start_addr;
+ return 1;
+ }
+
+ /* If we already know the packet isn't supported, fall back to the simple
+ way of searching memory. */
+
+ if (packet->support == PACKET_DISABLE)
+ {
+ /* Target doesn't provided special support, fall back and use the
+ standard support (copy memory and do the search here). */
+ return simple_search_memory (ops, start_addr, search_space_len,
+ pattern, pattern_len, found_addrp);
+ }
+
+ /* Insert header. */
+ i = snprintf (rs->buf, max_size,
+ "qSearch:memory:%s;%s;",
+ paddr_nz (start_addr),
+ phex_nz (search_space_len, sizeof (search_space_len)));
+ max_size -= (i + 1);
+
+ /* Escape as much data as fits into rs->buf. */
+ escaped_pattern_len =
+ remote_escape_output (pattern, pattern_len, (rs->buf + i),
+ &used_pattern_len, max_size);
+
+ /* Bail if the pattern is too large. */
+ if (used_pattern_len != pattern_len)
+ error ("pattern is too large to transmit to remote target");
+
+ if (putpkt_binary (rs->buf, i + escaped_pattern_len) < 0
+ || getpkt_sane (&rs->buf, &rs->buf_size, 0) < 0
+ || packet_ok (rs->buf, packet) != PACKET_OK)
+ {
+ /* The request may not have worked because the command is not
+ supported. If so, fall back to the simple way. */
+ if (packet->support == PACKET_DISABLE)
+ {
+ return simple_search_memory (ops, start_addr, search_space_len,
+ pattern, pattern_len, found_addrp);
+ }
+ return -1;
+ }
+
+ if (rs->buf[0] == '0')
+ found = 0;
+ else if (rs->buf[0] == '1')
+ {
+ found = 1;
+ if (rs->buf[1] != ',')
+ error (_("unknown qSearch:memory reply: %s"), rs->buf);
+ unpack_varlen_hex (rs->buf + 2, &found_addr);
+ *found_addrp = found_addr;
+ }
+ else
+ error (_("unknown qSearch:memory reply: %s"), rs->buf);
+
+ return found;
+}
+
static void
remote_rcmd (char *command,
struct ui_file *outbuf)
return NULL;
}
+/* Remote file transfer support. This is host-initiated I/O, not
+ target-initiated; for target-initiated, see remote-fileio.c. */
+
+/* If *LEFT is at least the length of STRING, copy STRING to
+ *BUFFER, update *BUFFER to point to the new end of the buffer, and
+ decrease *LEFT. Otherwise raise an error. */
+
+static void
+remote_buffer_add_string (char **buffer, int *left, char *string)
+{
+ int len = strlen (string);
+
+ if (len > *left)
+ error (_("Packet too long for target."));
+
+ memcpy (*buffer, string, len);
+ *buffer += len;
+ *left -= len;
+
+ /* NUL-terminate the buffer as a convenience, if there is
+ room. */
+ if (*left)
+ **buffer = '\0';
+}
+
+/* If *LEFT is large enough, hex encode LEN bytes from BYTES into
+ *BUFFER, update *BUFFER to point to the new end of the buffer, and
+ decrease *LEFT. Otherwise raise an error. */
+
+static void
+remote_buffer_add_bytes (char **buffer, int *left, const gdb_byte *bytes,
+ int len)
+{
+ if (2 * len > *left)
+ error (_("Packet too long for target."));
+
+ bin2hex (bytes, *buffer, len);
+ *buffer += 2 * len;
+ *left -= 2 * len;
+
+ /* NUL-terminate the buffer as a convenience, if there is
+ room. */
+ if (*left)
+ **buffer = '\0';
+}
+
+/* If *LEFT is large enough, convert VALUE to hex and add it to
+ *BUFFER, update *BUFFER to point to the new end of the buffer, and
+ decrease *LEFT. Otherwise raise an error. */
+
+static void
+remote_buffer_add_int (char **buffer, int *left, ULONGEST value)
+{
+ int len = hexnumlen (value);
+
+ if (len > *left)
+ error (_("Packet too long for target."));
+
+ hexnumstr (*buffer, value);
+ *buffer += len;
+ *left -= len;
+
+ /* NUL-terminate the buffer as a convenience, if there is
+ room. */
+ if (*left)
+ **buffer = '\0';
+}
+
+/* Parse an I/O result packet from BUFFER. Set RETCODE to the return
+ value, *REMOTE_ERRNO to the remote error number or zero if none
+ was included, and *ATTACHMENT to point to the start of the annex
+ if any. The length of the packet isn't needed here; there may
+ be NUL bytes in BUFFER, but they will be after *ATTACHMENT.
+
+ Return 0 if the packet could be parsed, -1 if it could not. If
+ -1 is returned, the other variables may not be initialized. */
+
+static int
+remote_hostio_parse_result (char *buffer, int *retcode,
+ int *remote_errno, char **attachment)
+{
+ char *p, *p2;
+
+ *remote_errno = 0;
+ *attachment = NULL;
+
+ if (buffer[0] != 'F')
+ return -1;
+
+ errno = 0;
+ *retcode = strtol (&buffer[1], &p, 16);
+ if (errno != 0 || p == &buffer[1])
+ return -1;
+
+ /* Check for ",errno". */
+ if (*p == ',')
+ {
+ errno = 0;
+ *remote_errno = strtol (p + 1, &p2, 16);
+ if (errno != 0 || p + 1 == p2)
+ return -1;
+ p = p2;
+ }
+
+ /* Check for ";attachment". If there is no attachment, the
+ packet should end here. */
+ if (*p == ';')
+ {
+ *attachment = p + 1;
+ return 0;
+ }
+ else if (*p == '\0')
+ return 0;
+ else
+ return -1;
+}
+
+/* Send a prepared I/O packet to the target and read its response.
+ The prepared packet is in the global RS->BUF before this function
+ is called, and the answer is there when we return.
+
+ COMMAND_BYTES is the length of the request to send, which may include
+ binary data. WHICH_PACKET is the packet configuration to check
+ before attempting a packet. If an error occurs, *REMOTE_ERRNO
+ is set to the error number and -1 is returned. Otherwise the value
+ returned by the function is returned.
+
+ ATTACHMENT and ATTACHMENT_LEN should be non-NULL if and only if an
+ attachment is expected; an error will be reported if there's a
+ mismatch. If one is found, *ATTACHMENT will be set to point into
+ the packet buffer and *ATTACHMENT_LEN will be set to the
+ attachment's length. */
+
+static int
+remote_hostio_send_command (int command_bytes, int which_packet,
+ int *remote_errno, char **attachment,
+ int *attachment_len)
+{
+ struct remote_state *rs = get_remote_state ();
+ int ret, bytes_read;
+ char *attachment_tmp;
+
+ if (remote_protocol_packets[which_packet].support == PACKET_DISABLE)
+ {
+ *remote_errno = FILEIO_ENOSYS;
+ return -1;
+ }
+
+ putpkt_binary (rs->buf, command_bytes);
+ bytes_read = getpkt_sane (&rs->buf, &rs->buf_size, 0);
+
+ /* If it timed out, something is wrong. Don't try to parse the
+ buffer. */
+ if (bytes_read < 0)
+ {
+ *remote_errno = FILEIO_EINVAL;
+ return -1;
+ }
+
+ switch (packet_ok (rs->buf, &remote_protocol_packets[which_packet]))
+ {
+ case PACKET_ERROR:
+ *remote_errno = FILEIO_EINVAL;
+ return -1;
+ case PACKET_UNKNOWN:
+ *remote_errno = FILEIO_ENOSYS;
+ return -1;
+ case PACKET_OK:
+ break;
+ }
+
+ if (remote_hostio_parse_result (rs->buf, &ret, remote_errno,
+ &attachment_tmp))
+ {
+ *remote_errno = FILEIO_EINVAL;
+ return -1;
+ }
+
+ /* Make sure we saw an attachment if and only if we expected one. */
+ if ((attachment_tmp == NULL && attachment != NULL)
+ || (attachment_tmp != NULL && attachment == NULL))
+ {
+ *remote_errno = FILEIO_EINVAL;
+ return -1;
+ }
+
+ /* If an attachment was found, it must point into the packet buffer;
+ work out how many bytes there were. */
+ if (attachment_tmp != NULL)
+ {
+ *attachment = attachment_tmp;
+ *attachment_len = bytes_read - (*attachment - rs->buf);
+ }
+
+ return ret;
+}
+
+/* Open FILENAME on the remote target, using FLAGS and MODE. Return a
+ remote file descriptor, or -1 if an error occurs (and set
+ *REMOTE_ERRNO). */
+
+static int
+remote_hostio_open (const char *filename, int flags, int mode,
+ int *remote_errno)
+{
+ struct remote_state *rs = get_remote_state ();
+ char *p = rs->buf;
+ int left = get_remote_packet_size () - 1;
+
+ remote_buffer_add_string (&p, &left, "vFile:open:");
+
+ remote_buffer_add_bytes (&p, &left, (const gdb_byte *) filename,
+ strlen (filename));
+ remote_buffer_add_string (&p, &left, ",");
+
+ remote_buffer_add_int (&p, &left, flags);
+ remote_buffer_add_string (&p, &left, ",");
+
+ remote_buffer_add_int (&p, &left, mode);
+
+ return remote_hostio_send_command (p - rs->buf, PACKET_vFile_open,
+ remote_errno, NULL, NULL);
+}
+
+/* Write up to LEN bytes from WRITE_BUF to FD on the remote target.
+ Return the number of bytes written, or -1 if an error occurs (and
+ set *REMOTE_ERRNO). */
+
+static int
+remote_hostio_pwrite (int fd, const gdb_byte *write_buf, int len,
+ ULONGEST offset, int *remote_errno)
+{
+ struct remote_state *rs = get_remote_state ();
+ char *p = rs->buf;
+ int left = get_remote_packet_size ();
+ int out_len;
+
+ remote_buffer_add_string (&p, &left, "vFile:pwrite:");
+
+ remote_buffer_add_int (&p, &left, fd);
+ remote_buffer_add_string (&p, &left, ",");
+
+ remote_buffer_add_int (&p, &left, offset);
+ remote_buffer_add_string (&p, &left, ",");
+
+ p += remote_escape_output (write_buf, len, p, &out_len,
+ get_remote_packet_size () - (p - rs->buf));
+
+ return remote_hostio_send_command (p - rs->buf, PACKET_vFile_pwrite,
+ remote_errno, NULL, NULL);
+}
+
+/* Read up to LEN bytes FD on the remote target into READ_BUF
+ Return the number of bytes read, or -1 if an error occurs (and
+ set *REMOTE_ERRNO). */
+
+static int
+remote_hostio_pread (int fd, gdb_byte *read_buf, int len,
+ ULONGEST offset, int *remote_errno)
+{
+ struct remote_state *rs = get_remote_state ();
+ char *p = rs->buf;
+ char *attachment;
+ int left = get_remote_packet_size ();
+ int ret, attachment_len;
+ int read_len;
+
+ remote_buffer_add_string (&p, &left, "vFile:pread:");
+
+ remote_buffer_add_int (&p, &left, fd);
+ remote_buffer_add_string (&p, &left, ",");
+
+ remote_buffer_add_int (&p, &left, len);
+ remote_buffer_add_string (&p, &left, ",");
+
+ remote_buffer_add_int (&p, &left, offset);
+
+ ret = remote_hostio_send_command (p - rs->buf, PACKET_vFile_pread,
+ remote_errno, &attachment,
+ &attachment_len);
+
+ if (ret < 0)
+ return ret;
+
+ read_len = remote_unescape_input (attachment, attachment_len,
+ read_buf, len);
+ if (read_len != ret)
+ error (_("Read returned %d, but %d bytes."), ret, (int) read_len);
+
+ return ret;
+}
+
+/* Close FD on the remote target. Return 0, or -1 if an error occurs
+ (and set *REMOTE_ERRNO). */
+
+static int
+remote_hostio_close (int fd, int *remote_errno)
+{
+ struct remote_state *rs = get_remote_state ();
+ char *p = rs->buf;
+ int left = get_remote_packet_size () - 1;
+
+ remote_buffer_add_string (&p, &left, "vFile:close:");
+
+ remote_buffer_add_int (&p, &left, fd);
+
+ return remote_hostio_send_command (p - rs->buf, PACKET_vFile_close,
+ remote_errno, NULL, NULL);
+}
+
+/* Unlink FILENAME on the remote target. Return 0, or -1 if an error
+ occurs (and set *REMOTE_ERRNO). */
+
+static int
+remote_hostio_unlink (const char *filename, int *remote_errno)
+{
+ struct remote_state *rs = get_remote_state ();
+ char *p = rs->buf;
+ int left = get_remote_packet_size () - 1;
+
+ remote_buffer_add_string (&p, &left, "vFile:unlink:");
+
+ remote_buffer_add_bytes (&p, &left, (const gdb_byte *) filename,
+ strlen (filename));
+
+ return remote_hostio_send_command (p - rs->buf, PACKET_vFile_unlink,
+ remote_errno, NULL, NULL);
+}
+
+static int
+remote_fileio_errno_to_host (int errnum)
+{
+ switch (errnum)
+ {
+ case FILEIO_EPERM:
+ return EPERM;
+ case FILEIO_ENOENT:
+ return ENOENT;
+ case FILEIO_EINTR:
+ return EINTR;
+ case FILEIO_EIO:
+ return EIO;
+ case FILEIO_EBADF:
+ return EBADF;
+ case FILEIO_EACCES:
+ return EACCES;
+ case FILEIO_EFAULT:
+ return EFAULT;
+ case FILEIO_EBUSY:
+ return EBUSY;
+ case FILEIO_EEXIST:
+ return EEXIST;
+ case FILEIO_ENODEV:
+ return ENODEV;
+ case FILEIO_ENOTDIR:
+ return ENOTDIR;
+ case FILEIO_EISDIR:
+ return EISDIR;
+ case FILEIO_EINVAL:
+ return EINVAL;
+ case FILEIO_ENFILE:
+ return ENFILE;
+ case FILEIO_EMFILE:
+ return EMFILE;
+ case FILEIO_EFBIG:
+ return EFBIG;
+ case FILEIO_ENOSPC:
+ return ENOSPC;
+ case FILEIO_ESPIPE:
+ return ESPIPE;
+ case FILEIO_EROFS:
+ return EROFS;
+ case FILEIO_ENOSYS:
+ return ENOSYS;
+ case FILEIO_ENAMETOOLONG:
+ return ENAMETOOLONG;
+ }
+ return -1;
+}
+
+static char *
+remote_hostio_error (int errnum)
+{
+ int host_error = remote_fileio_errno_to_host (errnum);
+
+ if (host_error == -1)
+ error (_("Unknown remote I/O error %d"), errnum);
+ else
+ error (_("Remote I/O error: %s"), safe_strerror (host_error));
+}
+
+static void
+fclose_cleanup (void *file)
+{
+ fclose (file);
+}
+
+static void
+remote_hostio_close_cleanup (void *opaque)
+{
+ int fd = *(int *) opaque;
+ int remote_errno;
+
+ remote_hostio_close (fd, &remote_errno);
+}
+
+void
+remote_file_put (const char *local_file, const char *remote_file, int from_tty)
+{
+ struct cleanup *back_to, *close_cleanup;
+ int retcode, fd, remote_errno, bytes, io_size;
+ FILE *file;
+ gdb_byte *buffer;
+ int bytes_in_buffer;
+ int saw_eof;
+ ULONGEST offset;
+
+ if (!remote_desc)
+ error (_("command can only be used with remote target"));
+
+ file = fopen (local_file, "rb");
+ if (file == NULL)
+ perror_with_name (local_file);
+ back_to = make_cleanup (fclose_cleanup, file);
+
+ fd = remote_hostio_open (remote_file, (FILEIO_O_WRONLY | FILEIO_O_CREAT
+ | FILEIO_O_TRUNC),
+ 0700, &remote_errno);
+ if (fd == -1)
+ remote_hostio_error (remote_errno);
+
+ /* Send up to this many bytes at once. They won't all fit in the
+ remote packet limit, so we'll transfer slightly fewer. */
+ io_size = get_remote_packet_size ();
+ buffer = xmalloc (io_size);
+ make_cleanup (xfree, buffer);
+
+ close_cleanup = make_cleanup (remote_hostio_close_cleanup, &fd);
+
+ bytes_in_buffer = 0;
+ saw_eof = 0;
+ offset = 0;
+ while (bytes_in_buffer || !saw_eof)
+ {
+ if (!saw_eof)
+ {
+ bytes = fread (buffer + bytes_in_buffer, 1, io_size - bytes_in_buffer,
+ file);
+ if (bytes == 0)
+ {
+ if (ferror (file))
+ error (_("Error reading %s."), local_file);
+ else
+ {
+ /* EOF. Unless there is something still in the
+ buffer from the last iteration, we are done. */
+ saw_eof = 1;
+ if (bytes_in_buffer == 0)
+ break;
+ }
+ }
+ }
+ else
+ bytes = 0;
+
+ bytes += bytes_in_buffer;
+ bytes_in_buffer = 0;
+
+ retcode = remote_hostio_pwrite (fd, buffer, bytes, offset, &remote_errno);
+
+ if (retcode < 0)
+ remote_hostio_error (remote_errno);
+ else if (retcode == 0)
+ error (_("Remote write of %d bytes returned 0!"), bytes);
+ else if (retcode < bytes)
+ {
+ /* Short write. Save the rest of the read data for the next
+ write. */
+ bytes_in_buffer = bytes - retcode;
+ memmove (buffer, buffer + retcode, bytes_in_buffer);
+ }
+
+ offset += retcode;
+ }
+
+ discard_cleanups (close_cleanup);
+ if (remote_hostio_close (fd, &remote_errno))
+ remote_hostio_error (remote_errno);
+
+ if (from_tty)
+ printf_filtered (_("Successfully sent file \"%s\".\n"), local_file);
+ do_cleanups (back_to);
+}
+
+void
+remote_file_get (const char *remote_file, const char *local_file, int from_tty)
+{
+ struct cleanup *back_to, *close_cleanup;
+ int retcode, fd, remote_errno, bytes, io_size;
+ FILE *file;
+ gdb_byte *buffer;
+ ULONGEST offset;
+
+ if (!remote_desc)
+ error (_("command can only be used with remote target"));
+
+ fd = remote_hostio_open (remote_file, FILEIO_O_RDONLY, 0, &remote_errno);
+ if (fd == -1)
+ remote_hostio_error (remote_errno);
+
+ file = fopen (local_file, "wb");
+ if (file == NULL)
+ perror_with_name (local_file);
+ back_to = make_cleanup (fclose_cleanup, file);
+
+ /* Send up to this many bytes at once. They won't all fit in the
+ remote packet limit, so we'll transfer slightly fewer. */
+ io_size = get_remote_packet_size ();
+ buffer = xmalloc (io_size);
+ make_cleanup (xfree, buffer);
+
+ close_cleanup = make_cleanup (remote_hostio_close_cleanup, &fd);
+
+ offset = 0;
+ while (1)
+ {
+ bytes = remote_hostio_pread (fd, buffer, io_size, offset, &remote_errno);
+ if (bytes == 0)
+ /* Success, but no bytes, means end-of-file. */
+ break;
+ if (bytes == -1)
+ remote_hostio_error (remote_errno);
+
+ offset += bytes;
+
+ bytes = fwrite (buffer, 1, bytes, file);
+ if (bytes == 0)
+ perror_with_name (local_file);
+ }
+
+ discard_cleanups (close_cleanup);
+ if (remote_hostio_close (fd, &remote_errno))
+ remote_hostio_error (remote_errno);
+
+ if (from_tty)
+ printf_filtered (_("Successfully fetched file \"%s\".\n"), remote_file);
+ do_cleanups (back_to);
+}
+
+void
+remote_file_delete (const char *remote_file, int from_tty)
+{
+ int retcode, remote_errno;
+
+ if (!remote_desc)
+ error (_("command can only be used with remote target"));
+
+ retcode = remote_hostio_unlink (remote_file, &remote_errno);
+ if (retcode == -1)
+ remote_hostio_error (remote_errno);
+
+ if (from_tty)
+ printf_filtered (_("Successfully deleted file \"%s\".\n"), remote_file);
+}
+
+static void
+remote_put_command (char *args, int from_tty)
+{
+ struct cleanup *back_to;
+ char **argv;
+
+ argv = buildargv (args);
+ if (argv == NULL)
+ nomem (0);
+ back_to = make_cleanup_freeargv (argv);
+ if (argv[0] == NULL || argv[1] == NULL || argv[2] != NULL)
+ error (_("Invalid parameters to remote put"));
+
+ remote_file_put (argv[0], argv[1], from_tty);
+
+ do_cleanups (back_to);
+}
+
+static void
+remote_get_command (char *args, int from_tty)
+{
+ struct cleanup *back_to;
+ char **argv;
+
+ argv = buildargv (args);
+ if (argv == NULL)
+ nomem (0);
+ back_to = make_cleanup_freeargv (argv);
+ if (argv[0] == NULL || argv[1] == NULL || argv[2] != NULL)
+ error (_("Invalid parameters to remote get"));
+
+ remote_file_get (argv[0], argv[1], from_tty);
+
+ do_cleanups (back_to);
+}
+
+static void
+remote_delete_command (char *args, int from_tty)
+{
+ struct cleanup *back_to;
+ char **argv;
+
+ argv = buildargv (args);
+ if (argv == NULL)
+ nomem (0);
+ back_to = make_cleanup_freeargv (argv);
+ if (argv[0] == NULL || argv[1] != NULL)
+ error (_("Invalid parameters to remote delete"));
+
+ remote_file_delete (argv[0], from_tty);
+
+ do_cleanups (back_to);
+}
+
+static void
+remote_command (char *args, int from_tty)
+{
+ help_list (remote_cmdlist, "remote ", -1, gdb_stdout);
+}
+
+static int
+remote_return_zero (void)
+{
+ return 0;
+}
+
static void
init_remote_ops (void)
{
remote_ops.to_stop = remote_stop;
remote_ops.to_xfer_partial = remote_xfer_partial;
remote_ops.to_rcmd = remote_rcmd;
+ remote_ops.to_log_command = serial_log_command;
remote_ops.to_get_thread_local_address = remote_get_thread_local_address;
remote_ops.to_stratum = process_stratum;
remote_ops.to_has_all_memory = 1;
remote_ops.to_flash_erase = remote_flash_erase;
remote_ops.to_flash_done = remote_flash_done;
remote_ops.to_read_description = remote_read_description;
+ remote_ops.to_search_memory = remote_search_memory;
+ remote_ops.to_can_async_p = remote_return_zero;
+ remote_ops.to_is_async_p = remote_return_zero;
}
/* Set up the extended remote vector by making a copy of the standard
extended_remote_ops.to_open = extended_remote_open;
extended_remote_ops.to_create_inferior = extended_remote_create_inferior;
extended_remote_ops.to_mourn_inferior = extended_remote_mourn;
+ extended_remote_ops.to_detach = extended_remote_detach;
+ extended_remote_ops.to_attach = extended_remote_attach;
}
static int
remote_can_async_p (void)
{
/* We're async whenever the serial device is. */
- return (current_target.to_async_mask_value) && serial_can_async_p (remote_desc);
+ return remote_async_mask_value && serial_can_async_p (remote_desc);
}
static int
remote_is_async_p (void)
{
/* We're async whenever the serial device is. */
- return (current_target.to_async_mask_value) && serial_is_async_p (remote_desc);
+ return remote_async_mask_value && serial_is_async_p (remote_desc);
}
/* Pass the SERIAL event on and up to the client. One day this code
remote_async (void (*callback) (enum inferior_event_type event_type,
void *context), void *context)
{
- if (current_target.to_async_mask_value == 0)
+ if (remote_async_mask_value == 0)
internal_error (__FILE__, __LINE__,
_("Calling remote_async when async is masked"));
serial_async (remote_desc, NULL, NULL);
}
+static int
+remote_async_mask (int new_mask)
+{
+ int curr_mask = remote_async_mask_value;
+ remote_async_mask_value = new_mask;
+ return curr_mask;
+}
+
/* Target async and target extended-async.
This are temporary targets, until it is all tested. Eventually
remote_async_ops.to_stop = remote_stop;
remote_async_ops.to_xfer_partial = remote_xfer_partial;
remote_async_ops.to_rcmd = remote_rcmd;
+ remote_async_ops.to_get_thread_local_address
+ = remote_get_thread_local_address;
remote_async_ops.to_stratum = process_stratum;
remote_async_ops.to_has_all_memory = 1;
remote_async_ops.to_has_memory = 1;
remote_async_ops.to_can_async_p = remote_can_async_p;
remote_async_ops.to_is_async_p = remote_is_async_p;
remote_async_ops.to_async = remote_async;
- remote_async_ops.to_async_mask_value = 1;
+ remote_async_ops.to_async_mask = remote_async_mask;
remote_async_ops.to_magic = OPS_MAGIC;
remote_async_ops.to_memory_map = remote_memory_map;
remote_async_ops.to_flash_erase = remote_flash_erase;
remote_async_ops.to_flash_done = remote_flash_done;
- remote_ops.to_read_description = remote_read_description;
+ remote_async_ops.to_read_description = remote_read_description;
+ remote_async_ops.to_search_memory = remote_search_memory;
}
/* Set up the async extended remote vector by making a copy of the standard
Specify the serial device it is connected to (e.g. /dev/ttya).",
extended_async_remote_ops.to_open = extended_remote_async_open;
extended_async_remote_ops.to_create_inferior = extended_remote_async_create_inferior;
- extended_async_remote_ops.to_mourn_inferior = extended_remote_mourn;
+ extended_async_remote_ops.to_mourn_inferior = extended_async_remote_mourn;
+ extended_async_remote_ops.to_detach = extended_remote_detach;
+ extended_async_remote_ops.to_attach = extended_async_remote_attach;
}
static void
do_cleanups (showlist_chain);
}
-static void
-build_remote_gdbarch_data (void)
-{
- remote_address_size = TARGET_ADDR_BIT;
-}
-
-/* Saved pointer to previous owner of the new_objfile event. */
-static void (*remote_new_objfile_chain) (struct objfile *);
/* Function to be called whenever a new objfile (shlib) is detected. */
static void
remote_new_objfile (struct objfile *objfile)
{
if (remote_desc != 0) /* Have a remote connection. */
- {
- remote_check_symbols (objfile);
- }
- /* Call predecessor on chain, if any. */
- if (remote_new_objfile_chain)
- remote_new_objfile_chain (objfile);
+ remote_check_symbols (objfile);
}
void
remote_g_packet_data_handle =
gdbarch_data_register_pre_init (remote_g_packet_data_init);
- /* Old tacky stuff. NOTE: This comes after the remote protocol so
- that the remote protocol has been initialized. */
- DEPRECATED_REGISTER_GDBARCH_SWAP (remote_address_size);
- deprecated_register_gdbarch_swap (NULL, 0, build_remote_gdbarch_data);
-
/* Initialize the per-target state. At the moment there is only one
of these, not one per target. Only one target is active at a
time. The default buffer size is unimportant; it will be expanded
add_target (&extended_async_remote_ops);
/* Hook into new objfile notification. */
- remote_new_objfile_chain = deprecated_target_new_objfile_hook;
- deprecated_target_new_objfile_hook = remote_new_objfile;
+ observer_attach_new_objfile (remote_new_objfile);
+
+ /* Set up signal handlers. */
+ sigint_remote_token =
+ create_async_signal_handler (async_remote_interrupt, NULL);
+ sigint_remote_twice_token =
+ create_async_signal_handler (inferior_event_handler_wrapper, NULL);
#if 0
init_remote_threadtests ();
add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_features],
"qXfer:features:read", "target-features", 0);
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_libraries],
+ "qXfer:libraries:read", "library-info", 0);
+
add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_memory_map],
"qXfer:memory-map:read", "memory-map", 0);
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_spu_read],
+ "qXfer:spu:read", "read-spu-object", 0);
+
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_spu_write],
+ "qXfer:spu:write", "write-spu-object", 0);
+
add_packet_config_cmd (&remote_protocol_packets[PACKET_qGetTLSAddr],
"qGetTLSAddr", "get-thread-local-storage-address",
0);
add_packet_config_cmd (&remote_protocol_packets[PACKET_qSupported],
"qSupported", "supported-packets", 0);
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_qSearch_memory],
+ "qSearch:memory", "search-memory", 0);
+
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_vFile_open],
+ "vFile:open", "hostio-open", 0);
+
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_vFile_pread],
+ "vFile:pread", "hostio-pread", 0);
+
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_vFile_pwrite],
+ "vFile:pwrite", "hostio-pwrite", 0);
+
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_vFile_close],
+ "vFile:close", "hostio-close", 0);
+
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_vFile_unlink],
+ "vFile:unlink", "hostio-unlink", 0);
+
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_vAttach],
+ "vAttach", "attach", 0);
+
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_vRun],
+ "vRun", "run", 0);
+
/* Keep the old ``set remote Z-packet ...'' working. Each individual
Z sub-packet has its own set and show commands, but users may
have sets to this variable in their .gdbinit files (or in their
show_remote_protocol_Z_packet_cmd, /* FIXME: i18n: Use of remote protocol `Z' packets is %s. */
&remote_set_cmdlist, &remote_show_cmdlist);
+ add_prefix_cmd ("remote", class_files, remote_command, _("\
+Manipulate files on the remote system\n\
+Transfer files to and from the remote target system."),
+ &remote_cmdlist, "remote ",
+ 0 /* allow-unknown */, &cmdlist);
+
+ add_cmd ("put", class_files, remote_put_command,
+ _("Copy a local file to the remote system."),
+ &remote_cmdlist);
+
+ add_cmd ("get", class_files, remote_get_command,
+ _("Copy a remote file to the local system."),
+ &remote_cmdlist);
+
+ add_cmd ("delete", class_files, remote_delete_command,
+ _("Delete a remote file."),
+ &remote_cmdlist);
+
+ remote_exec_file = xstrdup ("");
+ add_setshow_string_noescape_cmd ("exec-file", class_files,
+ &remote_exec_file, _("\
+Set the remote pathname for \"run\""), _("\
+Show the remote pathname for \"run\""), NULL, NULL, NULL,
+ &remote_set_cmdlist, &remote_show_cmdlist);
+
/* Eventually initialize fileio. See fileio.c */
initialize_remote_fileio (remote_set_cmdlist, remote_show_cmdlist);
}