/* Remote target communications for serial-line targets in custom GDB protocol
- Copyright (C) 1988-2015 Free Software Foundation, Inc.
+ Copyright (C) 1988-2016 Free Software Foundation, Inc.
This file is part of GDB.
static int remote_vkill (int pid, struct remote_state *rs);
+static void remote_kill_k (void);
+
static void remote_mourn (struct target_ops *ops);
static void extended_remote_restart (void);
-static void extended_remote_mourn (struct target_ops *);
-
static void remote_send (char **buf, long *sizeof_buf_p);
static int readchar (int timeout);
remote_register_number_and_offset (struct gdbarch *gdbarch, int regnum,
int *pnum, int *poffset)
{
- int sizeof_g_packet;
struct packet_reg *regs;
struct cleanup *old_chain;
regs = XCNEWVEC (struct packet_reg, gdbarch_num_regs (gdbarch));
old_chain = make_cleanup (xfree, regs);
- sizeof_g_packet = map_regcache_remote_table (gdbarch, regs);
+ map_regcache_remote_table (gdbarch, regs);
*pnum = regs[regnum].pnum;
*poffset = regs[regnum].offset;
PACKET_qSupported,
PACKET_qTStatus,
PACKET_QPassSignals,
+ PACKET_QCatchSyscalls,
PACKET_QProgramSignals,
PACKET_qCRC,
PACKET_qSearch_memory,
/* Support remote CTRL-C. */
PACKET_vCtrlC,
+ /* Support TARGET_WAITKIND_NO_RESUMED. */
+ PACKET_no_resumed,
+
PACKET_MAX
};
according to RUNNING. */
static void
-remote_add_thread (ptid_t ptid, int running)
+remote_add_thread (ptid_t ptid, int running, int executing)
{
struct remote_state *rs = get_remote_state ();
else
add_thread (ptid);
- set_executing (ptid, running);
+ set_executing (ptid, executing);
set_running (ptid, running);
}
It may be the first time we hear about such thread, so take the
opportunity to add it to GDB's thread list. In case this is the
first time we're noticing its corresponding inferior, add it to
- GDB's inferior list as well. */
+ GDB's inferior list as well. EXECUTING indicates whether the
+ thread is (internally) executing or stopped. */
static void
-remote_notice_new_inferior (ptid_t currthread, int running)
+remote_notice_new_inferior (ptid_t currthread, int executing)
{
+ /* In non-stop mode, we assume new found threads are (externally)
+ running until proven otherwise with a stop reply. In all-stop,
+ we can only get here if all threads are stopped. */
+ int running = target_is_non_stop_p () ? 1 : 0;
+
/* 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. */
{
/* We're seeing an event on a thread id we knew had exited.
This has to be a new thread reusing the old id. Add it. */
- remote_add_thread (currthread, running);
+ remote_add_thread (currthread, running, executing);
return;
}
thread_change_ptid (inferior_ptid, currthread);
else
{
- remote_add_thread (currthread, running);
+ remote_add_thread (currthread, running, executing);
inferior_ptid = currthread;
}
return;
}
/* This is really a new thread. Add it. */
- remote_add_thread (currthread, running);
+ remote_add_thread (currthread, running, executing);
/* If we found a new inferior, let the common code do whatever
it needs to with it (e.g., read shared libraries, insert
struct remote_state *rs = get_remote_state ();
if (!rs->starting_up)
- notice_new_inferior (currthread, running, 0);
+ notice_new_inferior (currthread, executing, 0);
}
}
}
info->priv = XNEW (struct private_thread_info);
info->private_dtor = free_private_thread_info;
info->priv->core = -1;
- info->priv->extra = 0;
+ info->priv->extra = NULL;
+ info->priv->name = NULL;
}
return info->priv;
}
}
+/* If 'QCatchSyscalls' is supported, tell the remote stub
+ to report syscalls to GDB. */
+
+static int
+remote_set_syscall_catchpoint (struct target_ops *self,
+ int pid, int needed, int any_count,
+ int table_size, int *table)
+{
+ char *catch_packet;
+ enum packet_result result;
+ int n_sysno = 0;
+
+ if (packet_support (PACKET_QCatchSyscalls) == PACKET_DISABLE)
+ {
+ /* Not supported. */
+ return 1;
+ }
+
+ if (needed && !any_count)
+ {
+ int i;
+
+ /* Count how many syscalls are to be caught (table[sysno] != 0). */
+ for (i = 0; i < table_size; i++)
+ {
+ if (table[i] != 0)
+ n_sysno++;
+ }
+ }
+
+ if (remote_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog,
+ "remote_set_syscall_catchpoint "
+ "pid %d needed %d any_count %d n_sysno %d\n",
+ pid, needed, any_count, n_sysno);
+ }
+
+ if (needed)
+ {
+ /* Prepare a packet with the sysno list, assuming max 8+1
+ characters for a sysno. If the resulting packet size is too
+ big, fallback on the non-selective packet. */
+ const int maxpktsz = strlen ("QCatchSyscalls:1") + n_sysno * 9 + 1;
+
+ catch_packet = (char *) xmalloc (maxpktsz);
+ strcpy (catch_packet, "QCatchSyscalls:1");
+ if (!any_count)
+ {
+ int i;
+ char *p;
+
+ p = catch_packet;
+ p += strlen (p);
+
+ /* Add in catch_packet each syscall to be caught (table[i] != 0). */
+ for (i = 0; i < table_size; i++)
+ {
+ if (table[i] != 0)
+ p += xsnprintf (p, catch_packet + maxpktsz - p, ";%x", i);
+ }
+ }
+ if (strlen (catch_packet) > get_remote_packet_size ())
+ {
+ /* catch_packet too big. Fallback to less efficient
+ non selective mode, with GDB doing the filtering. */
+ catch_packet[sizeof ("QCatchSyscalls:1") - 1] = 0;
+ }
+ }
+ else
+ catch_packet = xstrdup ("QCatchSyscalls:0");
+
+ {
+ struct cleanup *old_chain = make_cleanup (xfree, catch_packet);
+ struct remote_state *rs = get_remote_state ();
+
+ putpkt (catch_packet);
+ getpkt (&rs->buf, &rs->buf_size, 0);
+ result = packet_ok (rs->buf, &remote_protocol_packets[PACKET_QCatchSyscalls]);
+ do_cleanups (old_chain);
+ if (result == PACKET_OK)
+ return 0;
+ else
+ return -1;
+ }
+}
+
/* If 'QProgramSignals' is supported, tell the remote stub what
signals it should pass through to the inferior when detaching. */
struct remote_state *rs = get_remote_state ();
/* If the remote can't handle multiple processes, don't bother. */
- if (!rs->extended || !remote_multi_process_p (rs))
+ if (!remote_multi_process_p (rs))
return;
/* We only need to change the remote current thread if it's pointing
static int
remote_thread_always_alive (struct target_ops *ops, ptid_t ptid)
{
- struct remote_state *rs = get_remote_state ();
- char *p, *endp;
-
if (ptid_equal (ptid, magic_null_ptid))
/* The main thread is always alive. */
return 1;
item.ptid = ptid_build (pid, threadref_to_int (ref), 0);
item.core = -1;
+ item.name = NULL;
item.extra = NULL;
VEC_safe_push (thread_item_t, context->items, &item);
item.ptid = read_ptid (bufp, &bufp);
item.core = -1;
+ item.name = NULL;
item.extra = NULL;
VEC_safe_push (thread_item_t, context->items, &item);
static void
remote_update_thread_list (struct target_ops *ops)
{
- struct remote_state *rs = get_remote_state ();
struct threads_listing_context context;
struct cleanup *old_chain;
int got_list = 0;
{
struct private_thread_info *info;
/* In non-stop mode, we assume new found threads are
- running until proven otherwise with a stop reply. In
- all-stop, we can only get here if all threads are
+ executing until proven otherwise with a stop reply.
+ In all-stop, we can only get here if all threads are
stopped. */
- int running = target_is_non_stop_p () ? 1 : 0;
+ int executing = target_is_non_stop_p () ? 1 : 0;
- remote_notice_new_inferior (item->ptid, running);
+ remote_notice_new_inferior (item->ptid, executing);
info = demand_private_info (item->ptid);
info->core = item->core;
that as current. */
ALL_NON_EXITED_THREADS (thread)
{
- struct target_waitstatus *ws;
-
if (first == NULL)
first = thread;
else if (thread->state != THREAD_STOPPED)
continue;
- ws = &thread->suspend.waitstatus;
-
if (selected == NULL
&& thread->suspend.waitstatus_pending_p)
selected = thread;
- if (lowest_stopped == NULL || thread->num < lowest_stopped->num)
+ if (lowest_stopped == NULL
+ || thread->inf->num < lowest_stopped->inf->num
+ || thread->per_inf_num < lowest_stopped->per_inf_num)
lowest_stopped = thread;
if (non_stop)
if (!target_is_non_stop_p ())
{
- ptid_t ptid;
- int fake_pid_p = 0;
- struct inferior *inf;
-
if (rs->buf[0] == 'W' || rs->buf[0] == 'X')
{
if (!extended_p)
{
struct remote_state *rs = get_remote_state ();
char *msg, *reply, *tmp;
- struct bound_minimal_symbol sym;
int end;
+ long reply_size;
struct cleanup *old_chain;
/* The remote side has no concept of inferiors that aren't running
because we need both at the same time. */
msg = (char *) xmalloc (get_remote_packet_size ());
old_chain = make_cleanup (xfree, msg);
+ reply = (char *) xmalloc (get_remote_packet_size ());
+ make_cleanup (free_current_contents, &reply);
+ reply_size = get_remote_packet_size ();
/* Invite target to request symbol lookups. */
putpkt ("qSymbol::");
- getpkt (&rs->buf, &rs->buf_size, 0);
- packet_ok (rs->buf, &remote_protocol_packets[PACKET_qSymbol]);
- reply = rs->buf;
+ getpkt (&reply, &reply_size, 0);
+ packet_ok (reply, &remote_protocol_packets[PACKET_qSymbol]);
while (startswith (reply, "qSymbol:"))
{
}
putpkt (msg);
- getpkt (&rs->buf, &rs->buf_size, 0);
- reply = rs->buf;
+ getpkt (&reply, &reply_size, 0);
}
do_cleanups (old_chain);
PACKET_qXfer_traceframe_info },
{ "QPassSignals", PACKET_DISABLE, remote_supported_packet,
PACKET_QPassSignals },
+ { "QCatchSyscalls", PACKET_DISABLE, remote_supported_packet,
+ PACKET_QCatchSyscalls },
{ "QProgramSignals", PACKET_DISABLE, remote_supported_packet,
PACKET_QProgramSignals },
{ "QStartNoAckMode", PACKET_DISABLE, remote_supported_packet,
PACKET_Qbtrace_conf_pt_size },
{ "vContSupported", PACKET_DISABLE, remote_supported_packet, PACKET_vContSupported },
{ "QThreadEvents", PACKET_DISABLE, remote_supported_packet, PACKET_QThreadEvents },
+ { "no-resumed", PACKET_DISABLE, remote_supported_packet, PACKET_no_resumed },
};
static char *remote_support_xml;
q = remote_query_supported_append (q, "qRelocInsn+");
- if (rs->extended)
- {
- if (packet_set_cmd_state (PACKET_fork_event_feature)
- != AUTO_BOOLEAN_FALSE)
- q = remote_query_supported_append (q, "fork-events+");
- if (packet_set_cmd_state (PACKET_vfork_event_feature)
- != AUTO_BOOLEAN_FALSE)
- q = remote_query_supported_append (q, "vfork-events+");
- if (packet_set_cmd_state (PACKET_exec_event_feature)
- != AUTO_BOOLEAN_FALSE)
- q = remote_query_supported_append (q, "exec-events+");
- }
+ if (packet_set_cmd_state (PACKET_fork_event_feature)
+ != AUTO_BOOLEAN_FALSE)
+ q = remote_query_supported_append (q, "fork-events+");
+ if (packet_set_cmd_state (PACKET_vfork_event_feature)
+ != AUTO_BOOLEAN_FALSE)
+ q = remote_query_supported_append (q, "vfork-events+");
+ if (packet_set_cmd_state (PACKET_exec_event_feature)
+ != AUTO_BOOLEAN_FALSE)
+ q = remote_query_supported_append (q, "exec-events+");
if (packet_set_cmd_state (PACKET_vContSupported) != AUTO_BOOLEAN_FALSE)
q = remote_query_supported_append (q, "vContSupported+");
if (packet_set_cmd_state (PACKET_QThreadEvents) != AUTO_BOOLEAN_FALSE)
q = remote_query_supported_append (q, "QThreadEvents+");
+ if (packet_set_cmd_state (PACKET_no_resumed) != AUTO_BOOLEAN_FALSE)
+ q = remote_query_supported_append (q, "no-resumed+");
+
/* Keep this one last to work around a gdbserver <= 7.10 bug in
the qSupported:xmlRegisters=i386 handling. */
if (remote_support_xml != NULL)
/* Tell the remote target to detach. */
remote_detach_pid (pid);
- if (from_tty && !rs->extended)
+ /* Exit only if this is the only active inferior. */
+ if (from_tty && !rs->extended && number_of_live_inferiors () == 1)
puts_filtered (_("Ending remote debugging.\n"));
/* Check to see if we are detaching a fork parent. Note that if we
if (args)
error (_("Argument given to \"disconnect\" when remotely debugging."));
- /* Make sure we unpush even the extended remote targets; mourn
- won't do it. So call remote_mourn directly instead of
- target_mourn_inferior. */
- remote_mourn (target);
+ /* Make sure we unpush even the extended remote targets. Calling
+ target_mourn_inferior won't unpush, and remote_mourn won't
+ unpush if there is more than one inferior left. */
+ unpush_target (target);
+ generic_mourn_inferior ();
if (from_tty)
puts_filtered ("Ending remote debugging.\n");
fork child threads from the CONTEXT list. */
ALL_NON_EXITED_THREADS (thread)
{
- struct target_waitstatus *ws = &thread->pending_follow;
+ struct target_waitstatus *ws;
+
+ if (thread->suspend.waitstatus_pending_p)
+ ws = &thread->suspend.waitstatus;
+ else
+ ws = &thread->pending_follow;
if (is_pending_fork_parent (ws, pid, thread->ptid))
{
static void
discard_pending_stop_replies (struct inferior *inf)
{
- int i;
struct queue_iter_param param;
struct stop_reply *reply;
struct remote_state *rs = get_remote_state ();
stop_reply_match_ptid_and_ws, &ptid);
}
-/* Skip PACKET until the next semi-colon (or end of string). */
-
-static char *
-skip_to_semicolon (char *p)
-{
- while (*p != '\0' && *p != ';')
- p++;
- return p;
-}
-
/* Helper for remote_parse_stop_reply. Return nonzero if the substring
starting with P and ending with PEND matches PREFIX. */
if (strprefix (p, p1, "thread"))
event->ptid = read_ptid (++p1, &p);
+ else if (strprefix (p, p1, "syscall_entry"))
+ {
+ ULONGEST sysno;
+
+ event->ws.kind = TARGET_WAITKIND_SYSCALL_ENTRY;
+ p = unpack_varlen_hex (++p1, &sysno);
+ event->ws.value.syscall_number = (int) sysno;
+ }
+ else if (strprefix (p, p1, "syscall_return"))
+ {
+ ULONGEST sysno;
+
+ event->ws.kind = TARGET_WAITKIND_SYSCALL_RETURN;
+ p = unpack_varlen_hex (++p1, &sysno);
+ event->ws.value.syscall_number = (int) sysno;
+ }
else if (strprefix (p, p1, "watch")
|| strprefix (p, p1, "rwatch")
|| strprefix (p, p1, "awatch"))
/* The value part is documented as "must be empty",
though we ignore it, in case we ever decide to make
use of it in a backward compatible way. */
- p = skip_to_semicolon (p1 + 1);
+ p = strchrnul (p1 + 1, ';');
}
else if (strprefix (p, p1, "hwbreak"))
{
error (_("Unexpected hwbreak stop reason"));
/* See above. */
- p = skip_to_semicolon (p1 + 1);
+ p = strchrnul (p1 + 1, ';');
}
else if (strprefix (p, p1, "library"))
{
event->ws.kind = TARGET_WAITKIND_LOADED;
- p = skip_to_semicolon (p1 + 1);
+ p = strchrnul (p1 + 1, ';');
}
else if (strprefix (p, p1, "replaylog"))
{
event->ws.kind = TARGET_WAITKIND_NO_HISTORY;
/* p1 will indicate "begin" or "end", but it makes
no difference for now, so ignore it. */
- p = skip_to_semicolon (p1 + 1);
+ p = strchrnul (p1 + 1, ';');
}
else if (strprefix (p, p1, "core"))
{
else if (strprefix (p, p1, "vforkdone"))
{
event->ws.kind = TARGET_WAITKIND_VFORK_DONE;
- p = skip_to_semicolon (p1 + 1);
+ p = strchrnul (p1 + 1, ';');
}
else if (strprefix (p, p1, "exec"))
{
else if (strprefix (p, p1, "create"))
{
event->ws.kind = TARGET_WAITKIND_THREAD_CREATED;
- p = skip_to_semicolon (p1 + 1);
+ p = strchrnul (p1 + 1, ';');
}
else
{
if (skipregs)
{
- p = skip_to_semicolon (p1 + 1);
+ p = strchrnul (p1 + 1, ';');
p++;
continue;
}
{
/* Not a number. Silently skip unknown optional
info. */
- p = skip_to_semicolon (p1 + 1);
+ p = strchrnul (p1 + 1, ';');
}
}
event->ws.value.integer = value;
if (*p != ';')
error (_("stop reply packet badly formatted: %s"), buf);
- event->ptid = read_ptid (++p, &p);
+ event->ptid = read_ptid (++p, NULL);
break;
}
case 'W': /* Target exited. */
event->ptid = pid_to_ptid (pid);
}
break;
+ case 'N':
+ event->ws.kind = TARGET_WAITKIND_NO_RESUMED;
+ event->ptid = minus_one_ptid;
+ break;
}
if (target_is_non_stop_p () && ptid_equal (event->ptid, null_ptid))
ptid = inferior_ptid;
if (status->kind != TARGET_WAITKIND_EXITED
- && status->kind != TARGET_WAITKIND_SIGNALLED)
+ && status->kind != TARGET_WAITKIND_SIGNALLED
+ && status->kind != TARGET_WAITKIND_NO_RESUMED)
{
- struct remote_state *rs = get_remote_state ();
struct private_thread_info *remote_thr;
/* Expedited registers. */
/* If the user hit C-c before this packet, or between packets,
pretend that it was hit right here. */
if (check_quit_flag ())
- {
- clear_quit_flag ();
- sync_remote_interrupt (SIGINT);
- }
+ sync_remote_interrupt (SIGINT);
}
/* FIXME: cagney/1999-09-27: If we're in async mode we should
status->value.sig = GDB_SIGNAL_0;
break;
case 'F': /* File-I/O request. */
+ /* GDB may access the inferior memory while handling the File-I/O
+ request, but we don't want GDB accessing memory while waiting
+ for a stop reply. See the comments in putpkt_binary. Set
+ waiting_for_stop_reply to 0 temporarily. */
+ rs->waiting_for_stop_reply = 0;
remote_fileio_request (buf, rs->ctrlc_pending_p);
rs->ctrlc_pending_p = 0;
+ /* GDB handled the File-I/O request, and the target is running
+ again. Keep waiting for events. */
+ rs->waiting_for_stop_reply = 1;
break;
- case 'T': case 'S': case 'X': case 'W':
+ case 'N': case 'T': case 'S': case 'X': case 'W':
{
struct stop_reply *stop_reply;
break;
}
- if (status->kind == TARGET_WAITKIND_IGNORE)
+ if (status->kind == TARGET_WAITKIND_NO_RESUMED)
+ return minus_one_ptid;
+ else if (status->kind == TARGET_WAITKIND_IGNORE)
{
/* Nothing interesting happened. If we're doing a non-blocking
poll, we're done. Otherwise, go back to waiting. */
int ch;
int tcount = 0;
char *p;
- char *message;
/* Catch cases like trying to read memory or listing threads while
we're waiting for a stop reply. The remote server wouldn't be
long *sizeof_buf,
int forever)
{
- int timed_out;
-
- timed_out = getpkt_sane (buf, sizeof_buf, forever);
+ getpkt_sane (buf, sizeof_buf, forever);
}
}
\f
+/* Target hook to kill the current inferior. */
+
static void
remote_kill (struct target_ops *ops)
{
+ int res = -1;
+ int pid = ptid_get_pid (inferior_ptid);
+ struct remote_state *rs = get_remote_state ();
- /* Catch errors so the user can quit from gdb even when we
- aren't on speaking terms with the remote system. */
- TRY
+ if (packet_support (PACKET_vKill) != PACKET_DISABLE)
{
- putpkt ("k");
- }
- CATCH (ex, RETURN_MASK_ERROR)
- {
- if (ex.error == TARGET_CLOSE_ERROR)
+ /* If we're stopped while forking and we haven't followed yet,
+ kill the child task. We need to do this before killing the
+ parent task because if this is a vfork then the parent will
+ be sleeping. */
+ kill_new_fork_children (pid, rs);
+
+ res = remote_vkill (pid, rs);
+ if (res == 0)
{
- /* If we got an (EOF) error that caused the target
- to go away, then we're done, that's what we wanted.
- "k" is susceptible to cause a premature EOF, given
- that the remote server isn't actually required to
- reply to "k", and it can happen that it doesn't
- even get to reply ACK to the "k". */
+ target_mourn_inferior ();
return;
}
+ }
- /* Otherwise, something went wrong. We didn't actually kill
- the target. Just propagate the exception, and let the
- user or higher layers decide what to do. */
- throw_exception (ex);
+ /* If we are in 'target remote' mode and we are killing the only
+ inferior, then we will tell gdbserver to exit and unpush the
+ target. */
+ if (res == -1 && !remote_multi_process_p (rs)
+ && number_of_live_inferiors () == 1)
+ {
+ remote_kill_k ();
+
+ /* We've killed the remote end, we get to mourn it. If we are
+ not in extended mode, mourning the inferior also unpushes
+ remote_ops from the target stack, which closes the remote
+ connection. */
+ target_mourn_inferior ();
+
+ return;
}
- END_CATCH
- /* We've killed the remote end, we get to mourn it. Since this is
- target remote, single-process, mourning the inferior also
- unpushes remote_ops. */
- target_mourn_inferior ();
+ error (_("Can't kill process"));
}
+/* Send a kill request to the target using the 'vKill' packet. */
+
static int
remote_vkill (int pid, struct remote_state *rs)
{
}
}
+/* Send a kill request to the target using the 'k' packet. */
+
static void
-extended_remote_kill (struct target_ops *ops)
+remote_kill_k (void)
{
- int res;
- int pid = ptid_get_pid (inferior_ptid);
- struct remote_state *rs = get_remote_state ();
-
- /* If we're stopped while forking and we haven't followed yet, kill the
- child task. We need to do this before killing the parent task
- because if this is a vfork then the parent will be sleeping. */
- kill_new_fork_children (pid, rs);
-
- res = remote_vkill (pid, rs);
- if (res == -1 && !(rs->extended && remote_multi_process_p (rs)))
+ /* Catch errors so the user can quit from gdb even when we
+ aren't on speaking terms with the remote system. */
+ TRY
{
- /* Don't try 'k' on a multi-process aware stub -- it has no way
- to specify the pid. */
-
putpkt ("k");
-#if 0
- getpkt (&rs->buf, &rs->buf_size, 0);
- if (rs->buf[0] != 'O' || rs->buf[0] != 'K')
- res = 1;
-#else
- /* Don't wait for it to die. I'm not really sure it matters whether
- we do or not. For the existing stubs, kill is a noop. */
- res = 0;
-#endif
}
+ CATCH (ex, RETURN_MASK_ERROR)
+ {
+ if (ex.error == TARGET_CLOSE_ERROR)
+ {
+ /* If we got an (EOF) error that caused the target
+ to go away, then we're done, that's what we wanted.
+ "k" is susceptible to cause a premature EOF, given
+ that the remote server isn't actually required to
+ reply to "k", and it can happen that it doesn't
+ even get to reply ACK to the "k". */
+ return;
+ }
- if (res != 0)
- error (_("Can't kill process"));
-
- target_mourn_inferior ();
+ /* Otherwise, something went wrong. We didn't actually kill
+ the target. Just propagate the exception, and let the
+ user or higher layers decide what to do. */
+ throw_exception (ex);
+ }
+ END_CATCH
}
static void
remote_mourn (struct target_ops *target)
{
- unpush_target (target);
+ struct remote_state *rs = get_remote_state ();
- /* remote_close takes care of doing most of the clean up. */
- generic_mourn_inferior ();
-}
+ /* In 'target remote' mode with one inferior, we close the connection. */
+ if (!rs->extended && number_of_live_inferiors () <= 1)
+ {
+ unpush_target (target);
-static void
-extended_remote_mourn (struct target_ops *target)
-{
- struct remote_state *rs = get_remote_state ();
+ /* remote_close takes care of doing most of the clean up. */
+ generic_mourn_inferior ();
+ return;
+ }
/* In case we got here due to an error, but we're going to stay
connected. */
current thread. */
record_currthread (rs, minus_one_ptid);
- /* Unlike "target remote", we do not want to unpush the target; then
- the next time the user says "run", we won't be connected. */
-
- /* Call common code to mark the inferior as not running. */
+ /* Call common code to mark the inferior as not running. */
generic_mourn_inferior ();
if (!have_inferiors ())
{
struct agent_expr *aexpr = NULL;
int i, ix;
- char *pkt;
- char *buf_start = buf;
if (VEC_empty (agent_expr_p, bp_tgt->conditions))
return 0;
struct remote_state *rs;
char *p, *endbuf;
int bpsize;
- struct condition_list *cond = NULL;
/* Make sure the remote is pointing at the right process, if
necessary. */
static int
remote_supports_stopped_by_sw_breakpoint (struct target_ops *ops)
{
- struct remote_state *rs = get_remote_state ();
-
return (packet_support (PACKET_swbreak_feature) == PACKET_ENABLE);
}
static int
remote_supports_stopped_by_hw_breakpoint (struct target_ops *ops)
{
- struct remote_state *rs = get_remote_state ();
-
return (packet_support (PACKET_hwbreak_feature) == PACKET_ENABLE);
}
/* Only handle flash writes. */
if (writebuf != NULL)
{
- LONGEST xfered;
-
switch (object)
{
case TARGET_OBJECT_FLASH:
{
if (ptid_equal (magic_null_ptid, ptid))
xsnprintf (buf, sizeof buf, "Thread <main>");
- else if (rs->extended && remote_multi_process_p (rs))
+ else if (remote_multi_process_p (rs))
if (ptid_get_lwp (ptid) == 0)
return normal_pid_to_str (ptid);
else
{
struct remote_state *rs = get_remote_state ();
- /* 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);
+ return remote_multi_process_p (rs);
}
static int
enum btrace_read_type type)
{
struct packet_config *packet = &remote_protocol_packets[PACKET_qXfer_btrace];
- struct remote_state *rs = get_remote_state ();
struct cleanup *cleanup;
const char *annex;
char *xml;
remote_ops.to_load = remote_load;
remote_ops.to_mourn_inferior = remote_mourn;
remote_ops.to_pass_signals = remote_pass_signals;
+ remote_ops.to_set_syscall_catchpoint = remote_set_syscall_catchpoint;
remote_ops.to_program_signals = remote_program_signals;
remote_ops.to_thread_alive = remote_thread_alive;
remote_ops.to_thread_name = remote_thread_name;
remote_ops.to_btrace_conf = remote_btrace_conf;
remote_ops.to_augmented_libraries_svr4_read =
remote_augmented_libraries_svr4_read;
+ remote_ops.to_follow_fork = remote_follow_fork;
+ remote_ops.to_follow_exec = remote_follow_exec;
+ remote_ops.to_insert_fork_catchpoint = remote_insert_fork_catchpoint;
+ remote_ops.to_remove_fork_catchpoint = remote_remove_fork_catchpoint;
+ remote_ops.to_insert_vfork_catchpoint = remote_insert_vfork_catchpoint;
+ remote_ops.to_remove_vfork_catchpoint = remote_remove_vfork_catchpoint;
+ remote_ops.to_insert_exec_catchpoint = remote_insert_exec_catchpoint;
+ remote_ops.to_remove_exec_catchpoint = remote_remove_exec_catchpoint;
}
/* Set up the extended remote vector by making a copy of the standard
Specify the serial device it is connected to (e.g. /dev/ttya).";
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;
extended_remote_ops.to_post_attach = extended_remote_post_attach;
- extended_remote_ops.to_kill = extended_remote_kill;
extended_remote_ops.to_supports_disable_randomization
= extended_remote_supports_disable_randomization;
- extended_remote_ops.to_follow_fork = remote_follow_fork;
- extended_remote_ops.to_follow_exec = remote_follow_exec;
- extended_remote_ops.to_insert_fork_catchpoint
- = remote_insert_fork_catchpoint;
- extended_remote_ops.to_remove_fork_catchpoint
- = remote_remove_fork_catchpoint;
- extended_remote_ops.to_insert_vfork_catchpoint
- = remote_insert_vfork_catchpoint;
- extended_remote_ops.to_remove_vfork_catchpoint
- = remote_remove_vfork_catchpoint;
- extended_remote_ops.to_insert_exec_catchpoint
- = remote_insert_exec_catchpoint;
- extended_remote_ops.to_remove_exec_catchpoint
- = remote_remove_exec_catchpoint;
}
static int
static void
remote_async_serial_handler (struct serial *scb, void *context)
{
- struct remote_state *rs = (struct remote_state *) context;
-
/* Don't propogate error information up to the client. Instead let
the client find out about the error by querying the target. */
inferior_event_handler (INF_REG_EVENT, NULL);
{
struct remote_state *rs = get_remote_state ();
size_t size = get_remote_packet_size ();
- char *p = rs->buf;
if (packet_support (PACKET_QThreadEvents) == PACKET_DISABLE)
return;
void
_initialize_remote (void)
{
- struct remote_state *rs;
struct cmd_list_element *cmd;
const char *cmd_name;
add_packet_config_cmd (&remote_protocol_packets[PACKET_QPassSignals],
"QPassSignals", "pass-signals", 0);
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_QCatchSyscalls],
+ "QCatchSyscalls", "catch-syscalls", 0);
+
add_packet_config_cmd (&remote_protocol_packets[PACKET_QProgramSignals],
"QProgramSignals", "program-signals", 0);
add_packet_config_cmd (&remote_protocol_packets[PACKET_QThreadEvents],
"QThreadEvents", "thread-events", 0);
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_no_resumed],
+ "N stop reply", "no-resumed-stop-reply", 0);
+
/* Assert that we've registered "set remote foo-packet" commands
for all packet configs. */
{