static int
remote_multi_process_p (struct remote_state *rs)
{
- return rs->extended && rs->multi_process_aware;
+ return rs->multi_process_aware;
}
/* This data could be associated with a target, but we do not always
const char interrupt_sequence_control_c[] = "Ctrl-C";
const char interrupt_sequence_break[] = "BREAK";
const char interrupt_sequence_break_g[] = "BREAK-g";
-static const char *interrupt_sequence_modes[] =
+static const char *const interrupt_sequence_modes[] =
{
interrupt_sequence_control_c,
interrupt_sequence_break,
PACKET_vFile_pwrite,
PACKET_vFile_close,
PACKET_vFile_unlink,
+ PACKET_vFile_readlink,
PACKET_qXfer_auxv,
PACKET_qXfer_features,
PACKET_qXfer_libraries,
return 0;
}
-/* Add PID to GDB's inferior table. Since we can be connected to a
- remote system before before knowing about any inferior, mark the
- target with execution when we find the first inferior. If ATTACHED
- is 1, then we had just attached to this inferior. If it is 0, then
- we just created this inferior. If it is -1, then try querying the
- remote stub to find out if it had attached to the inferior or
- not. */
+/* Add PID to GDB's inferior table. If FAKE_PID_P is true, then PID
+ has been invented by GDB, instead of reported by the target. Since
+ we can be connected to a remote system before before knowing about
+ any inferior, mark the target with execution when we find the first
+ inferior. If ATTACHED is 1, then we had just attached to this
+ inferior. If it is 0, then we just created this inferior. If it
+ is -1, then try querying the remote stub to find out if it had
+ attached to the inferior or not. */
static struct inferior *
-remote_add_inferior (int pid, int attached)
+remote_add_inferior (int fake_pid_p, int pid, int attached)
{
struct inferior *inf;
}
inf->attach_flag = attached;
+ inf->fake_pid_p = fake_pid_p;
return inf;
}
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)))
- inf = remote_add_inferior (ptid_get_pid (currthread), -1);
+ {
+ struct remote_state *rs = get_remote_state ();
+ int fake_pid_p = !remote_multi_process_p (rs);
+
+ inf = remote_add_inferior (fake_pid_p,
+ ptid_get_pid (currthread), -1);
+ }
/* This is really a new thread. Add it. */
remote_add_thread (currthread, running);
struct remote_state *rs = get_remote_state ();
/* If the remote can't handle multiple processes, don't bother. */
- if (!remote_multi_process_p (rs))
+ if (!rs->extended || !remote_multi_process_p (rs))
return;
/* We only need to change the remote current thread if it's pointing
interrupt_sequence_mode);
}
+/* Query the remote target for which is the current thread/process,
+ add it to our tables, and update INFERIOR_PTID. The caller is
+ responsible for setting the state such that the remote end is ready
+ to return the current thread. */
+
+static void
+add_current_inferior_and_thread (void)
+{
+ struct remote_state *rs = get_remote_state ();
+ int fake_pid_p = 0;
+ ptid_t ptid;
+
+ inferior_ptid = null_ptid;
+
+ /* Now, if we have thread information, update inferior_ptid. */
+ ptid = remote_current_thread (inferior_ptid);
+ if (!ptid_equal (ptid, null_ptid))
+ {
+ if (!remote_multi_process_p (rs))
+ fake_pid_p = 1;
+
+ inferior_ptid = ptid;
+ }
+ else
+ {
+ /* 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. */
+ inferior_ptid = magic_null_ptid;
+ fake_pid_p = 1;
+ }
+
+ remote_add_inferior (fake_pid_p, ptid_get_pid (inferior_ptid), -1);
+
+ /* Add the main thread. */
+ add_thread_silent (inferior_ptid);
+}
+
static void
remote_start_remote (int from_tty, struct target_ops *target, int extended_p)
{
/* Let the stub know that we want it to return the thread. */
set_continue_thread (minus_one_ptid);
- inferior_ptid = minus_one_ptid;
-
- /* Now, if we have thread information, update inferior_ptid. */
- ptid = remote_current_thread (inferior_ptid);
- if (!ptid_equal (ptid, minus_one_ptid))
- {
- if (ptid_get_pid (ptid) == -1)
- {
- ptid = ptid_build (ptid_get_pid (magic_null_ptid),
- ptid_get_lwp (ptid),
- ptid_get_tid (ptid));
- fake_pid_p = 1;
- }
-
- inferior_ptid = ptid;
- }
- else
- {
- /* 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 = magic_null_ptid;
- fake_pid_p = 1;
- }
-
- inf = remote_add_inferior (ptid_get_pid (inferior_ptid), -1);
- inf->fake_pid_p = fake_pid_p;
-
- /* Always add the main thread. */
- add_thread_silent (inferior_ptid);
+ add_current_inferior_and_thread ();
/* init_wait_for_inferior should be called before get_offsets in order
to manage `inserted' flag in bp loc in a correct state.
char *q = NULL;
struct cleanup *old_chain = make_cleanup (free_current_contents, &q);
- if (rs->extended)
- q = remote_query_supported_append (q, "multiprocess+");
+ q = remote_query_supported_append (q, "multiprocess+");
if (remote_support_xml)
q = remote_query_supported_append (q, remote_support_xml);
error (_("Attaching to %s failed"),
target_pid_to_str (pid_to_ptid (pid)));
- set_current_inferior (remote_add_inferior (pid, 1));
+ set_current_inferior (remote_add_inferior (0, pid, 1));
inferior_ptid = pid_to_ptid (pid);
struct remote_state *rs = get_remote_state ();
res = remote_vkill (pid, rs);
- if (res == -1 && !remote_multi_process_p (rs))
+ if (res == -1 && !(rs->extended && remote_multi_process_p (rs)))
{
/* Don't try 'k' on a multi-process aware stub -- it has no way
to specify the pid. */
init_wait_for_inferior ();
}
- /* Now mark the inferior as running before we do anything else. */
- inferior_ptid = magic_null_ptid;
-
- /* Now, if we have thread information, update inferior_ptid. */
- inferior_ptid = remote_current_thread (inferior_ptid);
-
- remote_add_inferior (ptid_get_pid (inferior_ptid), 0);
- add_thread_silent (inferior_ptid);
+ add_current_inferior_and_thread ();
/* Get updated offsets, if the stub uses qOffsets. */
get_offsets ();
char *buf;
/* XXX - see also remote_get_noisy_reply(). */
+ QUIT; /* Allow user to bail out with ^C. */
rs->buf[0] = '\0';
- getpkt (&rs->buf, &rs->buf_size, 0);
+ if (getpkt_sane (&rs->buf, &rs->buf_size, 0) == -1)
+ {
+ /* Timeout. Continue to (try to) read responses.
+ This is better than stopping with an error, assuming the stub
+ is still executing the (long) monitor command.
+ If needed, the user can interrupt gdb using C-c, obtaining
+ an effect similar to stop on timeout. */
+ continue;
+ }
buf = rs->buf;
if (buf[0] == '\0')
error (_("Target does not support this command."));
{
if (ptid_equal (magic_null_ptid, ptid))
xsnprintf (buf, sizeof buf, "Thread <main>");
- else if (remote_multi_process_p (rs))
+ else if (rs->extended && remote_multi_process_p (rs))
xsnprintf (buf, sizeof buf, "Thread %d.%ld",
ptid_get_pid (ptid), ptid_get_tid (ptid));
else
remote_errno, NULL, NULL);
}
+/* Read value of symbolic link FILENAME on the remote target. Return
+ a null-terminated string allocated via xmalloc, or NULL if an error
+ occurs (and set *REMOTE_ERRNO). */
+
+static char *
+remote_hostio_readlink (const char *filename, int *remote_errno)
+{
+ struct remote_state *rs = get_remote_state ();
+ char *p = rs->buf;
+ char *attachment;
+ int left = get_remote_packet_size ();
+ int len, attachment_len;
+ int read_len;
+ char *ret;
+
+ remote_buffer_add_string (&p, &left, "vFile:readlink:");
+
+ remote_buffer_add_bytes (&p, &left, (const gdb_byte *) filename,
+ strlen (filename));
+
+ len = remote_hostio_send_command (p - rs->buf, PACKET_vFile_readlink,
+ remote_errno, &attachment,
+ &attachment_len);
+
+ if (len < 0)
+ return NULL;
+
+ ret = xmalloc (len + 1);
+
+ read_len = remote_unescape_input (attachment, attachment_len,
+ ret, len);
+ if (read_len != len)
+ error (_("Readlink returned %d, but %d bytes."), len, read_len);
+
+ ret[len] = '\0';
+ return ret;
+}
+
static int
remote_fileio_errno_to_host (int errnum)
{
{
struct remote_state *rs = get_remote_state ();
- return remote_multi_process_p (rs);
+ /* Only extended-remote handles being attached to multiple
+ processes, even though plain remote can use the multi-process
+ thread id extensions, so that GDB knows the target process's
+ PID. */
+ return rs->extended && remote_multi_process_p (rs);
}
int
struct remote_state *rs = get_remote_state ();
char *reply;
+ /* If we're not debugging a process yet, the IPA can't be
+ loaded. */
+ if (!target_has_execution)
+ return 0;
+
+ /* Make sure the remote is pointing at the right process. */
+ set_general_process ();
+
sprintf (rs->buf, "qTMinFTPILen");
putpkt (rs->buf);
reply = remote_get_noisy_reply (&target_buf, &target_buf_size);
remote_ops.to_supports_multi_process = remote_supports_multi_process;
remote_ops.to_supports_disable_randomization
= remote_supports_disable_randomization;
+ remote_ops.to_fileio_open = remote_hostio_open;
+ remote_ops.to_fileio_pwrite = remote_hostio_pwrite;
+ remote_ops.to_fileio_pread = remote_hostio_pread;
+ remote_ops.to_fileio_close = remote_hostio_close;
+ remote_ops.to_fileio_unlink = remote_hostio_unlink;
+ remote_ops.to_fileio_readlink = remote_hostio_readlink;
remote_ops.to_supports_enable_disable_tracepoint = remote_supports_enable_disable_tracepoint;
remote_ops.to_supports_string_tracing = remote_supports_string_tracing;
remote_ops.to_trace_init = remote_trace_init;
add_packet_config_cmd (&remote_protocol_packets[PACKET_vFile_unlink],
"vFile:unlink", "hostio-unlink", 0);
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_vFile_readlink],
+ "vFile:readlink", "hostio-readlink", 0);
+
add_packet_config_cmd (&remote_protocol_packets[PACKET_vAttach],
"vAttach", "attach", 0);