static void remote_store_registers (struct regcache *regcache, int regno);
-static void remote_mourn (void);
+static void remote_mourn (struct target_ops *ops);
static void extended_remote_restart (void);
-static void extended_remote_mourn (void);
+static void extended_remote_mourn (struct target_ops *);
static void remote_mourn_1 (struct target_ops *);
static int remote_async_mask (int new_mask);
-static void remote_detach (char *args, int from_tty);
+static void remote_detach (struct target_ops *ops, char *args, int from_tty);
static void remote_interrupt (int signo);
static void remote_async_inferior_event_handler (gdb_client_data);
static void remote_async_get_pending_events_handler (gdb_client_data);
+static void remote_terminal_ours (void);
+
+static int remote_read_description_p (struct target_ops *target);
+
/* The non-stop remote protocol provisions for one pending stop reply.
This is where we keep it until it is acknowledged. */
PACKET_qXfer_memory_map,
PACKET_qXfer_spu_read,
PACKET_qXfer_spu_write,
+ PACKET_qXfer_osdata,
PACKET_qGetTLSAddr,
PACKET_qSupported,
PACKET_QPassSignals,
static void
notice_new_inferiors (ptid_t currthread)
{
- /* When connecting to a target remote, or to a target
- extended-remote which already was debugging an inferior, we may
- not know about it yet. Add it before adding its child thread, so
- notifications are emitted in a sensible order. */
- if (!in_inferior_list (ptid_get_pid (currthread)))
- add_inferior (ptid_get_pid (currthread));
-
/* 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. */
return;
}
+ /* When connecting to a target remote, or to a target
+ extended-remote which already was debugging an inferior, we
+ may not know about it yet. Add it before adding its child
+ thread, so notifications are emitted in a sensible order. */
+ if (!in_inferior_list (ptid_get_pid (currthread)))
+ add_inferior (ptid_get_pid (currthread));
+
/* This is really a new thread. Add it. */
add_thread (currthread);
}
static void
remote_close (int quitting)
{
- if (remote_desc)
- {
- /* Unregister the file descriptor from the event loop. */
- if (target_is_async_p ())
- target_async (NULL, 0);
- serial_close (remote_desc);
- remote_desc = NULL;
- }
+ if (remote_desc == NULL)
+ return; /* already closed */
- /* Make sure we don't leave the async SIGINT signal handler
- installed. */
- signal (SIGINT, handle_sigint);
+ /* Make sure we leave stdin registered in the event loop, and we
+ don't leave the async SIGINT signal handler installed. */
+ remote_terminal_ours ();
+
+ serial_close (remote_desc);
+ remote_desc = NULL;
/* We don't have a connection to the remote stub anymore. Get rid
of all the inferiors and their threads we were controlling. */
this before anything involving memory or registers. */
target_find_description ();
+ /* On OSs where the list of libraries is global to all
+ processes, we fetch them early. */
+ if (gdbarch_has_global_solist (target_gdbarch))
+ solib_add (NULL, args->from_tty, args->target, auto_solib_add);
+
if (non_stop)
{
if (!rs->non_stop_aware)
get_offsets (); /* Get text, data & bss offsets. */
+ /* If we could not find a description using qXfer, and we know
+ how to do it some other way, try again. This is not
+ supported for non-stop; it could be, but it is tricky if
+ there are no stopped threads when we connect. */
+ if (remote_read_description_p (args->target)
+ && gdbarch_target_desc (target_gdbarch) == NULL)
+ {
+ target_clear_description ();
+ target_find_description ();
+ }
+
/* Use the previously fetched status. */
gdb_assert (wait_status != NULL);
strcpy (rs->buf, wait_status);
if (exec_bfd) /* No use without an exec file. */
remote_check_symbols (symfile_objfile);
}
+
+ /* If code is shared between processes, then breakpoints are global
+ too; Insert them now. */
+ if (gdbarch_has_global_solist (target_gdbarch)
+ && breakpoints_always_inserted_mode ())
+ insert_breakpoints ();
}
/* Open a connection to a remote debugger.
PACKET_qXfer_spu_read },
{ "qXfer:spu:write", PACKET_DISABLE, remote_supported_packet,
PACKET_qXfer_spu_write },
+ { "qXfer:osdata:read", PACKET_DISABLE, remote_supported_packet,
+ PACKET_qXfer_osdata },
{ "QPassSignals", PACKET_DISABLE, remote_supported_packet,
PACKET_QPassSignals },
{ "QStartNoAckMode", PACKET_DISABLE, remote_supported_packet,
}
push_target (target); /* Switch to using remote target now. */
- /* Assume that the target is running, unless we learn otherwise. */
- target_mark_running (target);
+ /* Assume that the target is not running, until we learn otherwise. */
+ if (extended_p)
+ target_mark_exited (target);
/* Register extra event sources in the event loop. */
remote_async_inferior_event_token
}
static void
-remote_detach (char *args, int from_tty)
+remote_detach (struct target_ops *ops, char *args, int from_tty)
{
remote_detach_1 (args, from_tty, 0);
}
static void
-extended_remote_detach (char *args, int from_tty)
+extended_remote_detach (struct target_ops *ops, char *args, int from_tty)
{
remote_detach_1 (args, from_tty, 1);
}
}
static void
-extended_remote_attach (char *args, int from_tty)
+extended_remote_attach (struct target_ops *ops, char *args, int from_tty)
{
- extended_remote_attach_1 (&extended_remote_ops, args, from_tty);
+ extended_remote_attach_1 (ops, args, from_tty);
}
/* Convert hex digit A to a number. */
error (_("Remote failure reply: %s"), *buf);
}
+/* Return a pointer to an xmalloc'ed string representing an escaped
+ version of BUF, of len N. E.g. \n is converted to \\n, \t to \\t,
+ etc. The caller is responsible for releasing the returned
+ memory. */
+
+static char *
+escape_buffer (const char *buf, int n)
+{
+ struct cleanup *old_chain;
+ struct ui_file *stb;
+ char *str;
+ long length;
+
+ stb = mem_fileopen ();
+ old_chain = make_cleanup_ui_file_delete (stb);
+
+ fputstrn_unfiltered (buf, n, 0, stb);
+ str = ui_file_xstrdup (stb, &length);
+ do_cleanups (old_chain);
+ return str;
+}
+
/* Display a null-terminated packet on stdout, for debugging, using C
string notation. */
if (remote_debug)
{
+ struct cleanup *old_chain;
+ char *str;
+
*p = '\0';
- fprintf_unfiltered (gdb_stdlog, "Sending packet: ");
- fputstrn_unfiltered (buf2, p - buf2, 0, gdb_stdlog);
- fprintf_unfiltered (gdb_stdlog, "...");
+ str = escape_buffer (buf2, p - buf2);
+ old_chain = make_cleanup (xfree, str);
+ fprintf_unfiltered (gdb_stdlog, "Sending packet: %s...", str);
gdb_flush (gdb_stdlog);
+ do_cleanups (old_chain);
}
if (serial_write (remote_desc, buf2, p - buf2))
perror_with_name (_("putpkt: write failed"));
{
if (remote_debug)
{
- fprintf_unfiltered (gdb_stdlog, " Notification received: ");
- fputstrn_unfiltered (rs->buf, val, 0, gdb_stdlog);
- fprintf_unfiltered (gdb_stdlog, "\n");
+ struct cleanup *old_chain;
+ char *str;
+
+ str = escape_buffer (rs->buf, val);
+ old_chain = make_cleanup (xfree, str);
+ fprintf_unfiltered (gdb_stdlog,
+ " Notification received: %s\n",
+ str);
+ do_cleanups (old_chain);
}
handle_notification (rs->buf, val);
/* We're in sync now, rewait for the ack. */
if (remote_debug)
{
- fprintf_filtered (gdb_stdlog,
- "Bad checksum, sentsum=0x%x, csum=0x%x, buf=",
- pktcsum, csum);
- fputstrn_filtered (buf, bc, 0, gdb_stdlog);
- fputs_filtered ("\n", gdb_stdlog);
+ struct cleanup *old_chain;
+ char *str;
+
+ str = escape_buffer (buf, bc);
+ old_chain = make_cleanup (xfree, str);
+ fprintf_unfiltered (gdb_stdlog,
+ "\
+Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n",
+ pktcsum, csum, str);
+ do_cleanups (old_chain);
}
/* Number of characters in buffer ignoring trailing
NULL. */
{
if (remote_debug)
{
- fprintf_unfiltered (gdb_stdlog, "Packet received: ");
- fputstrn_unfiltered (*buf, val, 0, gdb_stdlog);
- fprintf_unfiltered (gdb_stdlog, "\n");
+ struct cleanup *old_chain;
+ char *str;
+
+ str = escape_buffer (*buf, val);
+ old_chain = make_cleanup (xfree, str);
+ fprintf_unfiltered (gdb_stdlog, "Packet received: %s\n", str);
+ do_cleanups (old_chain);
}
/* Skip the ack char if we're in no-ack mode. */
if (remote_debug)
{
- fprintf_unfiltered (gdb_stdlog, " Notification received: ");
- fputstrn_unfiltered (*buf, val, 0, gdb_stdlog);
- fprintf_unfiltered (gdb_stdlog, "\n");
+ struct cleanup *old_chain;
+ char *str;
+
+ str = escape_buffer (*buf, val);
+ old_chain = make_cleanup (xfree, str);
+ fprintf_unfiltered (gdb_stdlog,
+ " Notification received: %s\n",
+ str);
+ do_cleanups (old_chain);
}
handle_notification (*buf, val);
}
static void
-remote_mourn (void)
+remote_mourn (struct target_ops *ops)
{
- remote_mourn_1 (&remote_ops);
+ remote_mourn_1 (ops);
}
/* Worker function for remote_mourn. */
}
static void
-extended_remote_mourn (void)
+extended_remote_mourn (struct target_ops *ops)
{
- extended_remote_mourn_1 (&extended_remote_ops);
+ extended_remote_mourn_1 (ops);
}
static int
}
static void
-extended_remote_create_inferior (char *exec_file, char *args,
+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);
return remote_read_qxfer (ops, "memory-map", annex, readbuf, offset, len,
&remote_protocol_packets[PACKET_qXfer_memory_map]);
+ case TARGET_OBJECT_OSDATA:
+ /* Should only get here if we're connected. */
+ gdb_assert (remote_desc);
+ return remote_read_qxfer
+ (ops, "osdata", annex, readbuf, offset, len,
+ &remote_protocol_packets[PACKET_qXfer_osdata]);
+
default:
return -1;
}
VEC_safe_push (remote_g_packet_guess_s, data->guesses, &new_guess);
}
+/* Return 1 if remote_read_description would do anything on this target
+ and architecture, 0 otherwise. */
+
+static int
+remote_read_description_p (struct target_ops *target)
+{
+ struct remote_g_packet_data *data
+ = gdbarch_data (target_gdbarch, remote_g_packet_data_handle);
+
+ if (!VEC_empty (remote_g_packet_guess_s, data->guesses))
+ return 1;
+
+ return 0;
+}
+
static const struct target_desc *
remote_read_description (struct target_ops *target)
{
struct remote_g_packet_data *data
= gdbarch_data (target_gdbarch, remote_g_packet_data_handle);
+ /* Do not try this during initial connection, when we do not know
+ whether there is a running but stopped thread. */
+ if (!target_has_execution || ptid_equal (inferior_ptid, null_ptid))
+ return NULL;
+
if (!VEC_empty (remote_g_packet_guess_s, data->guesses))
{
struct remote_g_packet_guess *guess;
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)
{
file = fopen (local_file, "rb");
if (file == NULL)
perror_with_name (local_file);
- back_to = make_cleanup (fclose_cleanup, file);
+ back_to = make_cleanup_fclose (file);
fd = remote_hostio_open (remote_file, (FILEIO_O_WRONLY | FILEIO_O_CREAT
| FILEIO_O_TRUNC),
file = fopen (local_file, "wb");
if (file == NULL)
perror_with_name (local_file);
- back_to = make_cleanup (fclose_cleanup, file);
+ back_to = make_cleanup_fclose (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. */
return remote_multi_process_p (rs);
}
+static int
+extended_remote_can_run (void)
+{
+ if (remote_desc != NULL)
+ return 1;
+
+ return 0;
+}
+
static void
init_remote_ops (void)
{
extended_remote_ops.to_detach = extended_remote_detach;
extended_remote_ops.to_attach = extended_remote_attach;
extended_remote_ops.to_kill = extended_remote_kill;
+ extended_remote_ops.to_can_run = extended_remote_can_run;
}
static int
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_qXfer_osdata],
+ "qXfer:osdata:read", "osdata", 0);
+
add_packet_config_cmd (&remote_protocol_packets[PACKET_qGetTLSAddr],
"qGetTLSAddr", "get-thread-local-storage-address",
0);