/* Main code for remote server for GDB.
- Copyright (C) 1989-2018 Free Software Foundation, Inc.
+ Copyright (C) 1989-2019 Free Software Foundation, Inc.
This file is part of GDB.
#include "server.h"
#include "gdbthread.h"
-#include "agent.h"
+#include "common/agent.h"
#include "notif.h"
#include "tdesc.h"
-#include "rsp-low.h"
-#include "signals-state-save-restore.h"
+#include "common/rsp-low.h"
+#include "common/signals-state-save-restore.h"
#include <ctype.h>
#include <unistd.h>
#if HAVE_SIGNAL_H
#include <signal.h>
#endif
-#include "gdb_vecs.h"
-#include "gdb_wait.h"
-#include "btrace-common.h"
-#include "filestuff.h"
+#include "common/gdb_vecs.h"
+#include "common/gdb_wait.h"
+#include "common/btrace-common.h"
+#include "common/filestuff.h"
#include "tracepoint.h"
#include "dll.h"
#include "hostio.h"
#include <vector>
-#include "common-inferior.h"
-#include "job-control.h"
-#include "environ.h"
+#include "common/common-inferior.h"
+#include "common/job-control.h"
+#include "common/environ.h"
#include "filenames.h"
-#include "pathstuff.h"
+#include "common/pathstuff.h"
#include "common/selftest.h"
+#include "common/scope-exit.h"
#define require_running_or_return(BUF) \
if (!target_running ()) \
int startup_with_shell = 1;
-/* The thread set with an `Hc' packet. `Hc' is deprecated in favor of
- `vCont'. Note the multi-process extensions made `vCont' a
- requirement, so `Hc pPID.TID' is pretty much undefined. So
- CONT_THREAD can be null_ptid for no `Hc' thread, minus_one_ptid for
- resuming all threads of the process (again, `Hc' isn't used for
- multi-process), or a specific thread ptid_t. */
-ptid_t cont_thread;
-
-/* The thread set with an `Hg' packet. */
-ptid_t general_thread;
-
int server_waiting;
static int extended_protocol;
/* --once: Exit after the first connection has closed. */
int run_once;
-int multi_process;
-int report_fork_events;
-int report_vfork_events;
-int report_exec_events;
-int report_thread_events;
-
/* Whether to report TARGET_WAITKING_NO_RESUMED events. */
static int report_no_resumed;
int non_stop;
-int swbreak_feature;
-int hwbreak_feature;
-
-/* True if the "vContSupported" feature is active. In that case, GDB
- wants us to report whether single step is supported in the reply to
- "vCont?" packet. */
-static int vCont_supported;
-
-/* Whether we should attempt to disable the operating system's address
- space randomization feature before starting an inferior. */
-int disable_randomization = 1;
static struct {
/* Set the PROGRAM_PATH. Here we adjust the path of the provided
static std::vector<char *> program_args;
static std::string wrapper_argv;
-int pass_signals[GDB_SIGNAL_LAST];
-int program_signals[GDB_SIGNAL_LAST];
-int program_signals_p;
-
/* The PID of the originally created or attached inferior. Used to
send signals to the process when GDB sends us an asynchronous interrupt
(user hitting Control-C in the client), and to wait for the child to exit
int disable_packet_qC;
int disable_packet_qfThreadInfo;
-/* Last status reported to GDB. */
-struct target_waitstatus last_status;
-ptid_t last_ptid;
-
-char *own_buf;
static unsigned char *mem_buf;
/* A sub-class of 'struct notif_event' for stop, holding information
relative to a single stop reply. We keep a queue of these to
push to GDB in non-stop mode. */
-struct vstop_notif
+struct vstop_notif : public notif_event
{
- struct notif_event base;
-
/* Thread or process that got the event. */
ptid_t ptid;
btrace configuration. */
static struct btrace_config current_btrace_conf;
-DEFINE_QUEUE_P (notif_event_p);
+/* The client remote protocol state. */
+
+static client_state g_client_state;
+
+client_state &
+get_client_state ()
+{
+ client_state &cs = g_client_state;
+ return cs;
+}
+
/* Put a stop reply to the stop reply queue. */
static void
queue_stop_reply (ptid_t ptid, struct target_waitstatus *status)
{
- struct vstop_notif *new_notif = XNEW (struct vstop_notif);
+ struct vstop_notif *new_notif = new struct vstop_notif;
new_notif->ptid = ptid;
new_notif->status = *status;
- notif_event_enque (¬if_stop, (struct notif_event *) new_notif);
+ notif_event_enque (¬if_stop, new_notif);
}
-static int
-remove_all_on_match_ptid (QUEUE (notif_event_p) *q,
- QUEUE_ITER (notif_event_p) *iter,
- struct notif_event *event,
- void *data)
+static bool
+remove_all_on_match_ptid (struct notif_event *event, ptid_t filter_ptid)
{
- ptid_t filter_ptid = *(ptid_t *) data;
struct vstop_notif *vstop_event = (struct vstop_notif *) event;
- if (ptid_match (vstop_event->ptid, filter_ptid))
- {
- if (q->free_func != NULL)
- q->free_func (event);
-
- QUEUE_remove_elem (notif_event_p, q, iter);
- }
-
- return 1;
+ return vstop_event->ptid.matches (filter_ptid);
}
/* See server.h. */
void
discard_queued_stop_replies (ptid_t ptid)
{
- QUEUE_iterate (notif_event_p, notif_stop.queue,
- remove_all_on_match_ptid, &ptid);
+ std::list<notif_event *>::iterator iter, next, end;
+ end = notif_stop.queue.end ();
+ for (iter = notif_stop.queue.begin (); iter != end; iter = next)
+ {
+ next = iter;
+ ++next;
+
+ if (remove_all_on_match_ptid (*iter, ptid))
+ {
+ delete *iter;
+ notif_stop.queue.erase (iter);
+ }
+ }
}
static void
prepare_resume_reply (own_buf, vstop->ptid, &vstop->status);
}
-/* QUEUE_iterate callback helper for in_queued_stop_replies. */
+/* Helper for in_queued_stop_replies. */
-static int
-in_queued_stop_replies_ptid (QUEUE (notif_event_p) *q,
- QUEUE_ITER (notif_event_p) *iter,
- struct notif_event *event,
- void *data)
+static bool
+in_queued_stop_replies_ptid (struct notif_event *event, ptid_t filter_ptid)
{
- ptid_t filter_ptid = *(ptid_t *) data;
struct vstop_notif *vstop_event = (struct vstop_notif *) event;
- if (ptid_match (vstop_event->ptid, filter_ptid))
- return 0;
+ if (vstop_event->ptid.matches (filter_ptid))
+ return true;
/* Don't resume fork children that GDB does not know about yet. */
if ((vstop_event->status.kind == TARGET_WAITKIND_FORKED
|| vstop_event->status.kind == TARGET_WAITKIND_VFORKED)
- && ptid_match (vstop_event->status.value.related_pid, filter_ptid))
- return 0;
+ && vstop_event->status.value.related_pid.matches (filter_ptid))
+ return true;
- return 1;
+ return false;
}
/* See server.h. */
int
in_queued_stop_replies (ptid_t ptid)
{
- return !QUEUE_iterate (notif_event_p, notif_stop.queue,
- in_queued_stop_replies_ptid, &ptid);
+ for (notif_event *event : notif_stop.queue)
+ {
+ if (in_queued_stop_replies_ptid (event, ptid))
+ return true;
+ }
+
+ return false;
}
struct notif_server notif_stop =
{
- "vStopped", "Stop", NULL, vstop_notif_reply,
+ "vStopped", "Stop", {}, vstop_notif_reply,
};
static int
static int
attach_inferior (int pid)
{
+ client_state &cs = get_client_state ();
/* myattach should return -1 if attaching is unsupported,
0 if it succeeded, and call error() otherwise. */
+ if (find_process_pid (pid) != nullptr)
+ error ("Already attached to process %d\n", pid);
+
if (myattach (pid) != 0)
return -1;
if (!non_stop)
{
- last_ptid = mywait (pid_to_ptid (pid), &last_status, 0, 0);
+ cs.last_ptid = mywait (ptid_t (pid), &cs.last_status, 0, 0);
/* GDB knows to ignore the first SIGSTOP after attaching to a running
process using the "attach" command, but this is different; it's
just using "target remote". Pretend it's just starting up. */
- if (last_status.kind == TARGET_WAITKIND_STOPPED
- && last_status.value.sig == GDB_SIGNAL_STOP)
- last_status.value.sig = GDB_SIGNAL_TRAP;
+ if (cs.last_status.kind == TARGET_WAITKIND_STOPPED
+ && cs.last_status.value.sig == GDB_SIGNAL_STOP)
+ cs.last_status.value.sig = GDB_SIGNAL_TRAP;
current_thread->last_resume_kind = resume_stop;
- current_thread->last_status = last_status;
+ current_thread->last_status = cs.last_status;
}
return 0;
}
-extern int remote_debug;
-
/* Decode a qXfer read request. Return 0 if everything looks OK,
or -1 otherwise. */
static int
handle_btrace_general_set (char *own_buf)
{
+ client_state &cs = get_client_state ();
struct thread_info *thread;
char *op;
op = own_buf + strlen ("Qbtrace:");
- if (ptid_equal (general_thread, null_ptid)
- || ptid_equal (general_thread, minus_one_ptid))
+ if (cs.general_thread == null_ptid
+ || cs.general_thread == minus_one_ptid)
{
strcpy (own_buf, "E.Must select a single thread.");
return -1;
}
- thread = find_thread_ptid (general_thread);
+ thread = find_thread_ptid (cs.general_thread);
if (thread == NULL)
{
strcpy (own_buf, "E.No such thread.");
return -1;
}
- TRY
+ try
{
if (strcmp (op, "bts") == 0)
handle_btrace_enable_bts (thread);
write_ok (own_buf);
}
- CATCH (exception, RETURN_MASK_ERROR)
+ catch (const gdb_exception_error &exception)
{
- sprintf (own_buf, "E.%s", exception.message);
+ sprintf (own_buf, "E.%s", exception.what ());
}
- END_CATCH
return 1;
}
static int
handle_btrace_conf_general_set (char *own_buf)
{
+ client_state &cs = get_client_state ();
struct thread_info *thread;
char *op;
op = own_buf + strlen ("Qbtrace-conf:");
- if (ptid_equal (general_thread, null_ptid)
- || ptid_equal (general_thread, minus_one_ptid))
+ if (cs.general_thread == null_ptid
+ || cs.general_thread == minus_one_ptid)
{
strcpy (own_buf, "E.Must select a single thread.");
return -1;
}
- thread = find_thread_ptid (general_thread);
+ thread = find_thread_ptid (cs.general_thread);
if (thread == NULL)
{
strcpy (own_buf, "E.No such thread.");
static void
handle_general_set (char *own_buf)
{
+ client_state &cs = get_client_state ();
if (startswith (own_buf, "QPassSignals:"))
{
int numsigs = (int) GDB_SIGNAL_LAST, i;
{
if (i == cursig)
{
- pass_signals[i] = 1;
+ cs.pass_signals[i] = 1;
if (*p == '\0')
/* Keep looping, to clear the remaining signals. */
cursig = -1;
p = decode_address_to_semicolon (&cursig, p);
}
else
- pass_signals[i] = 0;
+ cs.pass_signals[i] = 0;
}
strcpy (own_buf, "OK");
return;
const char *p = own_buf + strlen ("QProgramSignals:");
CORE_ADDR cursig;
- program_signals_p = 1;
+ cs.program_signals_p = 1;
p = decode_address_to_semicolon (&cursig, p);
for (i = 0; i < numsigs; i++)
{
if (i == cursig)
{
- program_signals[i] = 1;
+ cs.program_signals[i] = 1;
if (*p == '\0')
/* Keep looping, to clear the remaining signals. */
cursig = -1;
p = decode_address_to_semicolon (&cursig, p);
}
else
- program_signals[i] = 0;
+ cs.program_signals[i] = 0;
}
strcpy (own_buf, "OK");
return;
debug_flush ();
}
- noack_mode = 1;
+ cs.noack_mode = 1;
write_ok (own_buf);
return;
}
ULONGEST setting;
unpack_varlen_hex (packet, &setting);
- disable_randomization = setting;
+ cs.disable_randomization = setting;
if (remote_debug)
{
- debug_printf (disable_randomization
+ debug_printf (cs.disable_randomization
? "[address space randomization disabled]\n"
: "[address space randomization enabled]\n");
}
req = TRIBOOL_TRUE;
else
{
- char *mode_copy = xstrdup (mode);
-
/* We don't know what this mode is, so complain to GDB. */
sprintf (own_buf, "E.Unknown thread-events mode requested: %s\n",
- mode_copy);
- xfree (mode_copy);
+ mode);
return;
}
- report_thread_events = (req == TRIBOOL_TRUE);
+ cs.report_thread_events = (req == TRIBOOL_TRUE);
if (remote_debug)
{
- const char *req_str = report_thread_events ? "enabled" : "disabled";
+ const char *req_str = cs.report_thread_events ? "enabled" : "disabled";
debug_printf ("[thread events are now %s]\n", req_str);
}
if (strcmp (annex, "target.xml") == 0)
{
- const char *ret = tdesc_get_features_xml ((target_desc*) desc);
+ const char *ret = tdesc_get_features_xml (desc);
if (*ret == '@')
return ret + 1;
static int
gdb_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
{
+ client_state &cs = get_client_state ();
int res;
- if (current_traceframe >= 0)
+ if (cs.current_traceframe >= 0)
{
ULONGEST nbytes;
ULONGEST length = len;
- if (traceframe_read_mem (current_traceframe,
+ if (traceframe_read_mem (cs.current_traceframe,
memaddr, myaddr, len, &nbytes))
return -1;
/* Data read from trace buffer, we're done. */
static int
gdb_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
{
- if (current_traceframe >= 0)
+ client_state &cs = get_client_state ();
+ if (cs.current_traceframe >= 0)
return EIO;
else
{
static void
handle_detach (char *own_buf)
{
- require_running_or_return (own_buf);
+ client_state &cs = get_client_state ();
- int pid;
+ process_info *process;
- if (multi_process)
+ if (cs.multi_process)
{
/* skip 'D;' */
- pid = strtol (&own_buf[2], NULL, 16);
+ int pid = strtol (&own_buf[2], NULL, 16);
+
+ process = find_process_pid (pid);
}
else
- pid = ptid_get_pid (current_ptid);
-
- if ((tracing && disconnected_tracing) || any_persistent_commands ())
{
- struct process_info *process = find_process_pid (pid);
+ process = (current_thread != nullptr
+ ? get_thread_process (current_thread)
+ : nullptr);
+ }
- if (process == NULL)
- {
- write_enn (own_buf);
- return;
- }
+ if (process == NULL)
+ {
+ write_enn (own_buf);
+ return;
+ }
+ if ((tracing && disconnected_tracing) || any_persistent_commands (process))
+ {
if (tracing && disconnected_tracing)
fprintf (stderr,
"Disconnected tracing in effect, "
"leaving gdbserver attached to the process\n");
- if (any_persistent_commands ())
+ if (any_persistent_commands (process))
fprintf (stderr,
"Persistent commands are present, "
"leaving gdbserver attached to the process\n");
return;
}
- fprintf (stderr, "Detaching from process %d\n", pid);
+ fprintf (stderr, "Detaching from process %d\n", process->pid);
stop_tracing ();
- if (detach_inferior (pid) != 0)
+
+ /* We'll need this after PROCESS has been destroyed. */
+ int pid = process->pid;
+
+ if (detach_inferior (process) != 0)
write_enn (own_buf);
else
{
- discard_queued_stop_replies (pid_to_ptid (pid));
+ discard_queued_stop_replies (ptid_t (pid));
write_ok (own_buf);
if (extended_protocol || target_running ())
/* There is still at least one inferior remaining or
we are in extended mode, so don't terminate gdbserver,
and instead treat this like a normal program exit. */
- last_status.kind = TARGET_WAITKIND_EXITED;
- last_status.value.integer = 0;
- last_ptid = pid_to_ptid (pid);
+ cs.last_status.kind = TARGET_WAITKIND_EXITED;
+ cs.last_status.value.integer = 0;
+ cs.last_ptid = ptid_t (pid);
current_thread = NULL;
}
write_enn (own_buf);
}
}
+ else if (strcmp (mon, "set debug-file") == 0)
+ debug_set_output (nullptr);
+ else if (startswith (mon, "set debug-file "))
+ debug_set_output (mon + sizeof ("set debug-file ") - 1);
else if (strcmp (mon, "help") == 0)
monitor_show_help ();
else if (strcmp (mon, "exit") == 0)
gdb_byte *readbuf, const gdb_byte *writebuf,
ULONGEST offset, LONGEST len)
{
+ client_state &cs = get_client_state ();
ULONGEST nbytes;
if (writebuf != NULL)
return -2;
- if (annex[0] != '\0' || current_thread == NULL || current_traceframe == -1)
+ if (annex[0] != '\0' || current_thread == NULL
+ || cs.current_traceframe == -1)
return -1;
- if (traceframe_read_sdata (current_traceframe, offset,
+ if (traceframe_read_sdata (cs.current_traceframe, offset,
readbuf, len, &nbytes))
return -1;
return nbytes;
gdb_byte *readbuf, const gdb_byte *writebuf,
ULONGEST offset, LONGEST len)
{
+ client_state &cs = get_client_state ();
static char *result = 0;
static unsigned int result_length = 0;
if (writebuf != NULL)
return -2;
- if (!target_running () || annex[0] != '\0' || current_traceframe == -1)
+ if (!target_running () || annex[0] != '\0' || cs.current_traceframe == -1)
return -1;
if (offset == 0)
buffer_init (&buffer);
- traceframe_read_info (current_traceframe, &buffer);
+ traceframe_read_info (cs.current_traceframe, &buffer);
result = buffer_finish (&buffer);
result_length = strlen (result);
gdb_byte *readbuf, const gdb_byte *writebuf,
ULONGEST offset, LONGEST len)
{
+ client_state &cs = get_client_state ();
static struct buffer cache;
struct thread_info *thread;
enum btrace_read_type type;
if (writebuf != NULL)
return -2;
- if (ptid_equal (general_thread, null_ptid)
- || ptid_equal (general_thread, minus_one_ptid))
+ if (cs.general_thread == null_ptid
+ || cs.general_thread == minus_one_ptid)
{
- strcpy (own_buf, "E.Must select a single thread.");
+ strcpy (cs.own_buf, "E.Must select a single thread.");
return -3;
}
- thread = find_thread_ptid (general_thread);
+ thread = find_thread_ptid (cs.general_thread);
if (thread == NULL)
{
- strcpy (own_buf, "E.No such thread.");
+ strcpy (cs.own_buf, "E.No such thread.");
return -3;
}
if (thread->btrace == NULL)
{
- strcpy (own_buf, "E.Btrace not enabled.");
+ strcpy (cs.own_buf, "E.Btrace not enabled.");
return -3;
}
type = BTRACE_READ_DELTA;
else
{
- strcpy (own_buf, "E.Bad annex.");
+ strcpy (cs.own_buf, "E.Bad annex.");
return -3;
}
{
buffer_free (&cache);
- TRY
+ try
{
result = target_read_btrace (thread->btrace, &cache, type);
if (result != 0)
- memcpy (own_buf, cache.buffer, cache.used_size);
+ memcpy (cs.own_buf, cache.buffer, cache.used_size);
}
- CATCH (exception, RETURN_MASK_ERROR)
+ catch (const gdb_exception_error &exception)
{
- sprintf (own_buf, "E.%s", exception.message);
+ sprintf (cs.own_buf, "E.%s", exception.what ());
result = -1;
}
- END_CATCH
if (result != 0)
return -3;
gdb_byte *readbuf, const gdb_byte *writebuf,
ULONGEST offset, LONGEST len)
{
+ client_state &cs = get_client_state ();
static struct buffer cache;
struct thread_info *thread;
int result;
if (annex[0] != '\0')
return -1;
- if (ptid_equal (general_thread, null_ptid)
- || ptid_equal (general_thread, minus_one_ptid))
+ if (cs.general_thread == null_ptid
+ || cs.general_thread == minus_one_ptid)
{
- strcpy (own_buf, "E.Must select a single thread.");
+ strcpy (cs.own_buf, "E.Must select a single thread.");
return -3;
}
- thread = find_thread_ptid (general_thread);
+ thread = find_thread_ptid (cs.general_thread);
if (thread == NULL)
{
- strcpy (own_buf, "E.No such thread.");
+ strcpy (cs.own_buf, "E.No such thread.");
return -3;
}
if (thread->btrace == NULL)
{
- strcpy (own_buf, "E.Btrace not enabled.");
+ strcpy (cs.own_buf, "E.Btrace not enabled.");
return -3;
}
{
buffer_free (&cache);
- TRY
+ try
{
result = target_read_btrace_conf (thread->btrace, &cache);
if (result != 0)
- memcpy (own_buf, cache.buffer, cache.used_size);
+ memcpy (cs.own_buf, cache.buffer, cache.used_size);
}
- CATCH (exception, RETURN_MASK_ERROR)
+ catch (const gdb_exception_error &exception)
{
- sprintf (own_buf, "E.%s", exception.message);
+ sprintf (cs.own_buf, "E.%s", exception.what ());
result = -1;
}
- END_CATCH
if (result != 0)
return -3;
static void
handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
{
+ client_state &cs = get_client_state ();
static std::list<thread_info *>::const_iterator thread_iter;
/* Reply the current thread id. */
ptid_t ptid;
require_running_or_return (own_buf);
- if (general_thread != null_ptid && general_thread != minus_one_ptid)
- ptid = general_thread;
+ if (cs.general_thread != null_ptid && cs.general_thread != minus_one_ptid)
+ ptid = cs.general_thread;
else
{
thread_iter = all_threads.begin ();
if (current_thread == NULL)
{
current_thread
- = find_any_thread_of_pid (ptid_get_pid (general_thread));
+ = find_any_thread_of_pid (cs.general_thread.pid ());
/* Just in case, if we didn't find a thread, then bail out
instead of crashing. */
/* GDB supports and wants multi-process support if
possible. */
if (target_supports_multi_process ())
- multi_process = 1;
+ cs.multi_process = 1;
}
else if (strcmp (p, "qRelocInsn+") == 0)
{
by a software breakpoint and for us to handle PC
adjustment if necessary on this target. */
if (target_supports_stopped_by_sw_breakpoint ())
- swbreak_feature = 1;
+ cs.swbreak_feature = 1;
}
else if (strcmp (p, "hwbreak+") == 0)
{
/* GDB wants us to report whether a trap is caused
by a hardware breakpoint. */
if (target_supports_stopped_by_hw_breakpoint ())
- hwbreak_feature = 1;
+ cs.hwbreak_feature = 1;
}
else if (strcmp (p, "fork-events+") == 0)
{
/* GDB supports and wants fork events if possible. */
if (target_supports_fork_events ())
- report_fork_events = 1;
+ cs.report_fork_events = 1;
}
else if (strcmp (p, "vfork-events+") == 0)
{
/* GDB supports and wants vfork events if possible. */
if (target_supports_vfork_events ())
- report_vfork_events = 1;
+ cs.report_vfork_events = 1;
}
else if (strcmp (p, "exec-events+") == 0)
{
/* GDB supports and wants exec events if possible. */
if (target_supports_exec_events ())
- report_exec_events = 1;
+ cs.report_exec_events = 1;
}
else if (strcmp (p, "vContSupported+") == 0)
- vCont_supported = 1;
+ cs.vCont_supported = 1;
else if (strcmp (p, "QThreadEvents+") == 0)
;
else if (strcmp (p, "no-resumed+") == 0)
qXfer:feature:read at all, we will never be re-queried. */
strcat (own_buf, ";qXfer:features:read+");
- if (transport_is_reliable)
+ if (cs.transport_is_reliable)
strcat (own_buf, ";QStartNoAckMode+");
if (the_target->qxfer_osdata != NULL)
{
const struct thread_resume *action = &actions[i];
- if (ptid_equal (action->thread, minus_one_ptid)
- || ptid_equal (action->thread, thread->id)
- || ((ptid_get_pid (action->thread)
+ if (action->thread == minus_one_ptid
+ || action->thread == thread->id
+ || ((action->thread.pid ()
== thread->id.pid ())
- && ptid_get_lwp (action->thread) == -1))
+ && action->thread.lwp () == -1))
{
if ((*callback) (action, thread))
return true;
handle_pending_status (const struct thread_resume *resumption,
struct thread_info *thread)
{
+ client_state &cs = get_client_state ();
if (thread->status_pending_p)
{
thread->status_pending_p = 0;
- last_status = thread->last_status;
- last_ptid = thread->id;
- prepare_resume_reply (own_buf, last_ptid, &last_status);
+ cs.last_status = thread->last_status;
+ cs.last_ptid = thread->id;
+ prepare_resume_reply (cs.own_buf, cs.last_ptid, &cs.last_status);
return 1;
}
return 0;
static void
resume (struct thread_resume *actions, size_t num_actions)
{
+ client_state &cs = get_client_state ();
if (!non_stop)
{
/* Check if among the threads that GDB wants actioned, there's
(*the_target->resume) (actions, num_actions);
if (non_stop)
- write_ok (own_buf);
+ write_ok (cs.own_buf);
else
{
- last_ptid = mywait (minus_one_ptid, &last_status, 0, 1);
+ cs.last_ptid = mywait (minus_one_ptid, &cs.last_status, 0, 1);
- if (last_status.kind == TARGET_WAITKIND_NO_RESUMED
+ if (cs.last_status.kind == TARGET_WAITKIND_NO_RESUMED
&& !report_no_resumed)
{
/* The client does not support this stop reply. At least
return error. */
- sprintf (own_buf, "E.No unwaited-for children left.");
+ sprintf (cs.own_buf, "E.No unwaited-for children left.");
disable_async_io ();
return;
}
- if (last_status.kind != TARGET_WAITKIND_EXITED
- && last_status.kind != TARGET_WAITKIND_SIGNALLED
- && last_status.kind != TARGET_WAITKIND_NO_RESUMED)
- current_thread->last_status = last_status;
+ if (cs.last_status.kind != TARGET_WAITKIND_EXITED
+ && cs.last_status.kind != TARGET_WAITKIND_SIGNALLED
+ && cs.last_status.kind != TARGET_WAITKIND_NO_RESUMED)
+ current_thread->last_status = cs.last_status;
/* From the client's perspective, all-stop mode always stops all
threads implicitly (and the target backend has already done
so by now). Tag all threads as "want-stopped", so we don't
resume them implicitly without the client telling us to. */
gdb_wants_all_threads_stopped ();
- prepare_resume_reply (own_buf, last_ptid, &last_status);
+ prepare_resume_reply (cs.own_buf, cs.last_ptid, &cs.last_status);
disable_async_io ();
- if (last_status.kind == TARGET_WAITKIND_EXITED
- || last_status.kind == TARGET_WAITKIND_SIGNALLED)
- target_mourn_inferior (last_ptid);
+ if (cs.last_status.kind == TARGET_WAITKIND_EXITED
+ || cs.last_status.kind == TARGET_WAITKIND_SIGNALLED)
+ target_mourn_inferior (cs.last_ptid);
}
}
static int
handle_v_attach (char *own_buf)
{
+ client_state &cs = get_client_state ();
int pid;
pid = strtol (own_buf + 8, NULL, 16);
write_ok (own_buf);
}
else
- prepare_resume_reply (own_buf, last_ptid, &last_status);
+ prepare_resume_reply (own_buf, cs.last_ptid, &cs.last_status);
return 1;
}
static int
handle_v_run (char *own_buf)
{
+ client_state &cs = get_client_state ();
char *p, *next_p;
std::vector<char *> new_argv;
char *new_program_name = NULL;
create_inferior (program_path.get (), program_args);
- if (last_status.kind == TARGET_WAITKIND_STOPPED)
+ if (cs.last_status.kind == TARGET_WAITKIND_STOPPED)
{
- prepare_resume_reply (own_buf, last_ptid, &last_status);
+ prepare_resume_reply (own_buf, cs.last_ptid, &cs.last_status);
/* In non-stop, sending a resume reply doesn't set the general
thread, but GDB assumes a vRun sets it (this is so GDB can
query which is the main thread of the new inferior. */
if (non_stop)
- general_thread = last_ptid;
+ cs.general_thread = cs.last_ptid;
return 1;
}
static int
handle_v_kill (char *own_buf)
{
+ client_state &cs = get_client_state ();
int pid;
char *p = &own_buf[6];
- if (multi_process)
+ if (cs.multi_process)
pid = strtol (p, NULL, 16);
else
pid = signal_pid;
- if (pid != 0 && kill_inferior (pid) == 0)
+
+ process_info *proc = find_process_pid (pid);
+
+ if (proc != nullptr && kill_inferior (proc) == 0)
{
- last_status.kind = TARGET_WAITKIND_SIGNALLED;
- last_status.value.sig = GDB_SIGNAL_KILL;
- last_ptid = pid_to_ptid (pid);
- discard_queued_stop_replies (last_ptid);
+ cs.last_status.kind = TARGET_WAITKIND_SIGNALLED;
+ cs.last_status.value.sig = GDB_SIGNAL_KILL;
+ cs.last_ptid = ptid_t (pid);
+ discard_queued_stop_replies (cs.last_ptid);
write_ok (own_buf);
return 1;
}
void
handle_v_requests (char *own_buf, int packet_len, int *new_packet_len)
{
+ client_state &cs = get_client_state ();
if (!disable_packet_vCont)
{
if (strcmp (own_buf, "vCtrlC") == 0)
if (target_supports_hardware_single_step ()
|| target_supports_software_single_step ()
- || !vCont_supported)
+ || !cs.vCont_supported)
{
/* If target supports single step either by hardware or by
software, add actions s and S to the list of supported
if (startswith (own_buf, "vAttach;"))
{
- if ((!extended_protocol || !multi_process) && target_running ())
+ if ((!extended_protocol || !cs.multi_process) && target_running ())
{
fprintf (stderr, "Already debugging a process\n");
write_enn (own_buf);
if (startswith (own_buf, "vRun;"))
{
- if ((!extended_protocol || !multi_process) && target_running ())
+ if ((!extended_protocol || !cs.multi_process) && target_running ())
{
fprintf (stderr, "Already debugging a process\n");
write_enn (own_buf);
static void
myresume (char *own_buf, int step, int sig)
{
+ client_state &cs = get_client_state ();
struct thread_resume resume_info[2];
int n = 0;
int valid_cont_thread;
- valid_cont_thread = (!ptid_equal (cont_thread, null_ptid)
- && !ptid_equal (cont_thread, minus_one_ptid));
+ valid_cont_thread = (cs.cont_thread != null_ptid
+ && cs.cont_thread != minus_one_ptid);
if (step || sig || valid_cont_thread)
{
manage the thread's last_status field. */
if (the_target->thread_stopped == NULL)
{
- struct vstop_notif *new_notif = XNEW (struct vstop_notif);
+ struct vstop_notif *new_notif = new struct vstop_notif;
new_notif->ptid = thread->id;
new_notif->status = thread->last_status;
/* Pass the last stop reply back to GDB, but don't notify
yet. */
- notif_event_enque (¬if_stop,
- (struct notif_event *) new_notif);
+ notif_event_enque (¬if_stop, new_notif);
}
else
{
static void
handle_status (char *own_buf)
{
+ client_state &cs = get_client_state ();
+
/* GDB is connected, don't forward events to the target anymore. */
for_each_process ([] (process_info *process) {
process->gdb_detached = 0;
/* The first is sent immediatly. OK is sent if there is no
stopped thread, which is the same handling of the vStopped
packet (by design). */
- notif_write_event (¬if_stop, own_buf);
+ notif_write_event (¬if_stop, cs.own_buf);
}
else
{
/* Prefer the last thread that reported an event to GDB (even if
that was a GDB_SIGNAL_TRAP). */
- if (last_status.kind != TARGET_WAITKIND_IGNORE
- && last_status.kind != TARGET_WAITKIND_EXITED
- && last_status.kind != TARGET_WAITKIND_SIGNALLED)
- thread = find_thread_ptid (last_ptid);
+ if (cs.last_status.kind != TARGET_WAITKIND_IGNORE
+ && cs.last_status.kind != TARGET_WAITKIND_EXITED
+ && cs.last_status.kind != TARGET_WAITKIND_SIGNALLED)
+ thread = find_thread_ptid (cs.last_ptid);
/* If the last event thread is not found for some reason, look
for some other thread that might have an event to report. */
if (thread == NULL)
- thread = find_thread ([] (thread_info *thread)
+ thread = find_thread ([] (thread_info *thr_arg)
{
- return thread->status_pending_p;
+ return thr_arg->status_pending_p;
});
/* If we're still out of luck, simply pick the first thread in
/* GDB assumes the current thread is the thread we're
reporting the status for. */
- general_thread = thread->id;
+ cs.general_thread = thread->id;
set_desired_thread ();
gdb_assert (tp->last_status.kind != TARGET_WAITKIND_IGNORE);
gdbserver_version (void)
{
printf ("GNU gdbserver %s%s\n"
- "Copyright (C) 2018 Free Software Foundation, Inc.\n"
+ "Copyright (C) 2019 Free Software Foundation, Inc.\n"
"gdbserver is free software, covered by the "
"GNU General Public License.\n"
"This gdbserver was configured as \"%s\"\n",
"Debug options:\n"
"\n"
" --debug Enable general debugging output.\n"
- " --debug-format=opt1[,opt2,...]\n"
+ " --debug-format=OPT1[,OPT2,...]\n"
" Specify extra content in debugging output.\n"
" Options:\n"
" all\n"
" none\n"
" timestamp\n"
" --remote-debug Enable remote protocol debugging output.\n"
- " --disable-packet=opt1[,opt2,...]\n"
+ " --disable-packet=OPT1[,OPT2,...]\n"
" Disable support for RSP packets or features.\n"
" Options:\n"
" vCont, Tthread, qC, qfThreadInfo and \n"
static void
kill_inferior_callback (process_info *process)
{
- int pid = process->pid;
-
- kill_inferior (pid);
- discard_queued_stop_replies (pid_to_ptid (pid));
+ kill_inferior (process);
+ discard_queued_stop_replies (ptid_t (process->pid));
}
/* Call this when exiting gdbserver with possible inferiors that need
int pid = process->pid;
if (process->attached)
- detach_inferior (pid);
+ detach_inferior (process);
else
- kill_inferior (pid);
+ kill_inferior (process);
- discard_queued_stop_replies (pid_to_ptid (pid));
+ discard_queued_stop_replies (ptid_t (pid));
});
}
/* Value that will be passed to exit(3) when gdbserver exits. */
static int exit_code;
-/* Cleanup version of detach_or_kill_for_exit. */
+/* Wrapper for detach_or_kill_for_exit that catches and prints
+ errors. */
static void
-detach_or_kill_for_exit_cleanup (void *ignore)
+detach_or_kill_for_exit_cleanup ()
{
-
- TRY
+ try
{
detach_or_kill_for_exit ();
}
-
- CATCH (exception, RETURN_MASK_ALL)
+ catch (const gdb_exception &exception)
{
fflush (stdout);
- fprintf (stderr, "Detach or kill failed: %s\n", exception.message);
+ fprintf (stderr, "Detach or kill failed: %s\n",
+ exception.what ());
exit_code = 1;
}
- END_CATCH
}
/* Main function. This is called by the real "main" function,
#endif
current_directory = getcwd (NULL, 0);
+ client_state &cs = get_client_state ();
+
if (current_directory == NULL)
{
error (_("Could not find current working directory: %s"),
}
else if (strcmp (*next_arg, "--remote-debug") == 0)
remote_debug = 1;
+ else if (startswith (*next_arg, "--debug-file="))
+ debug_set_output ((*next_arg) + sizeof ("--debug-file=") -1);
else if (strcmp (*next_arg, "--disable-packet") == 0)
{
gdbserver_show_disableable (stdout);
break;
}
else if (strcmp (*next_arg, "--disable-randomization") == 0)
- disable_randomization = 1;
+ cs.disable_randomization = 1;
else if (strcmp (*next_arg, "--no-disable-randomization") == 0)
- disable_randomization = 0;
+ cs.disable_randomization = 0;
else if (strcmp (*next_arg, "--startup-with-shell") == 0)
startup_with_shell = true;
else if (strcmp (*next_arg, "--no-startup-with-shell") == 0)
initialize_event_loop ();
if (target_supports_tracepoints ())
initialize_tracepoint ();
- initialize_notif ();
- own_buf = (char *) xmalloc (PBUFSIZ + 1);
mem_buf = (unsigned char *) xmalloc (PBUFSIZ);
if (selftest)
#if GDB_SELF_TEST
selftests::run_tests (selftest_filter);
#else
- printf (_("Selftests are not available in a non-development build.\n"));
+ printf (_("Selftests have been disabled for this build.\n"));
#endif
throw_quit ("Quit");
}
int i, n;
n = argc - (next_arg - argv);
- program_path.set (gdb::unique_xmalloc_ptr<char> (xstrdup (next_arg[0])));
+ program_path.set (make_unique_xstrdup (next_arg[0]));
for (i = 1; i < n; i++)
program_args.push_back (xstrdup (next_arg[i]));
program_args.push_back (NULL);
}
else
{
- last_status.kind = TARGET_WAITKIND_EXITED;
- last_status.value.integer = 0;
- last_ptid = minus_one_ptid;
+ cs.last_status.kind = TARGET_WAITKIND_EXITED;
+ cs.last_status.value.integer = 0;
+ cs.last_ptid = minus_one_ptid;
}
- make_cleanup (detach_or_kill_for_exit_cleanup, NULL);
+
+ SCOPE_EXIT { detach_or_kill_for_exit_cleanup (); };
/* Don't report shared library events on the initial connection,
even if some libraries are preloaded. Avoids the "stopped by
shared library event" notice on gdb side. */
dlls_changed = 0;
- if (last_status.kind == TARGET_WAITKIND_EXITED
- || last_status.kind == TARGET_WAITKIND_SIGNALLED)
+ if (cs.last_status.kind == TARGET_WAITKIND_EXITED
+ || cs.last_status.kind == TARGET_WAITKIND_SIGNALLED)
was_running = 0;
else
was_running = 1;
while (1)
{
-
- noack_mode = 0;
- multi_process = 0;
- report_fork_events = 0;
- report_vfork_events = 0;
- report_exec_events = 0;
+ cs.noack_mode = 0;
+ cs.multi_process = 0;
+ cs.report_fork_events = 0;
+ cs.report_vfork_events = 0;
+ cs.report_exec_events = 0;
/* Be sure we're out of tfind mode. */
- current_traceframe = -1;
- cont_thread = null_ptid;
- swbreak_feature = 0;
- hwbreak_feature = 0;
- vCont_supported = 0;
+ cs.current_traceframe = -1;
+ cs.cont_thread = null_ptid;
+ cs.swbreak_feature = 0;
+ cs.hwbreak_feature = 0;
+ cs.vCont_supported = 0;
remote_open (port);
- TRY
+ try
{
/* Wait for events. This will return when all event sources
are removed from the event loop. */
}
}
}
- CATCH (exception, RETURN_MASK_ERROR)
+ catch (const gdb_exception_error &exception)
{
fflush (stdout);
- fprintf (stderr, "gdbserver: %s\n", exception.message);
+ fprintf (stderr, "gdbserver: %s\n", exception.what ());
if (response_needed)
{
- write_enn (own_buf);
- putpkt (own_buf);
+ write_enn (cs.own_buf);
+ putpkt (cs.own_buf);
}
if (run_once)
throw_quit ("Quit");
}
- END_CATCH
}
}
main (int argc, char *argv[])
{
- TRY
+ try
{
captured_main (argc, argv);
}
- CATCH (exception, RETURN_MASK_ALL)
+ catch (const gdb_exception &exception)
{
if (exception.reason == RETURN_ERROR)
{
fflush (stdout);
- fprintf (stderr, "%s\n", exception.message);
+ fprintf (stderr, "%s\n", exception.what ());
fprintf (stderr, "Exiting\n");
exit_code = 1;
}
exit (exit_code);
}
- END_CATCH
gdb_assert_not_reached ("captured_main should never return");
}
static int
process_serial_event (void)
{
+ client_state &cs = get_client_state ();
int signal;
unsigned int len;
- int res;
CORE_ADDR mem_addr;
unsigned char sig;
int packet_len;
disable_async_io ();
response_needed = 0;
- packet_len = getpkt (own_buf);
+ packet_len = getpkt (cs.own_buf);
if (packet_len <= 0)
{
remote_close ();
}
response_needed = 1;
- char ch = own_buf[0];
+ char ch = cs.own_buf[0];
switch (ch)
{
case 'q':
- handle_query (own_buf, packet_len, &new_packet_len);
+ handle_query (cs.own_buf, packet_len, &new_packet_len);
break;
case 'Q':
- handle_general_set (own_buf);
+ handle_general_set (cs.own_buf);
break;
case 'D':
- handle_detach (own_buf);
+ handle_detach (cs.own_buf);
break;
case '!':
extended_protocol = 1;
- write_ok (own_buf);
+ write_ok (cs.own_buf);
break;
case '?':
- handle_status (own_buf);
+ handle_status (cs.own_buf);
break;
case 'H':
- if (own_buf[1] == 'c' || own_buf[1] == 'g' || own_buf[1] == 's')
+ if (cs.own_buf[1] == 'c' || cs.own_buf[1] == 'g' || cs.own_buf[1] == 's')
{
- require_running_or_break (own_buf);
+ require_running_or_break (cs.own_buf);
- ptid_t thread_id = read_ptid (&own_buf[2], NULL);
+ ptid_t thread_id = read_ptid (&cs.own_buf[2], NULL);
if (thread_id == null_ptid || thread_id == minus_one_ptid)
thread_id = null_ptid;
if (thread == NULL)
{
- write_enn (own_buf);
+ write_enn (cs.own_buf);
break;
}
/* The ptid represents a lwp/tid. */
if (find_thread_ptid (thread_id) == NULL)
{
- write_enn (own_buf);
+ write_enn (cs.own_buf);
break;
}
}
- if (own_buf[1] == 'g')
+ if (cs.own_buf[1] == 'g')
{
- if (ptid_equal (thread_id, null_ptid))
+ if (thread_id == null_ptid)
{
/* GDB is telling us to choose any thread. Check if
the currently selected thread is still valid. If
it is not, select the first available. */
- thread_info *thread = find_thread_ptid (general_thread);
+ thread_info *thread = find_thread_ptid (cs.general_thread);
if (thread == NULL)
thread = get_first_thread ();
thread_id = thread->id;
}
- general_thread = thread_id;
+ cs.general_thread = thread_id;
set_desired_thread ();
gdb_assert (current_thread != NULL);
}
- else if (own_buf[1] == 'c')
- cont_thread = thread_id;
+ else if (cs.own_buf[1] == 'c')
+ cs.cont_thread = thread_id;
- write_ok (own_buf);
+ write_ok (cs.own_buf);
}
else
{
/* Silently ignore it so that gdb can extend the protocol
without compatibility headaches. */
- own_buf[0] = '\0';
+ cs.own_buf[0] = '\0';
}
break;
case 'g':
- require_running_or_break (own_buf);
- if (current_traceframe >= 0)
+ require_running_or_break (cs.own_buf);
+ if (cs.current_traceframe >= 0)
{
struct regcache *regcache
= new_register_cache (current_target_desc ());
- if (fetch_traceframe_registers (current_traceframe,
+ if (fetch_traceframe_registers (cs.current_traceframe,
regcache, -1) == 0)
- registers_to_string (regcache, own_buf);
+ registers_to_string (regcache, cs.own_buf);
else
- write_enn (own_buf);
+ write_enn (cs.own_buf);
free_register_cache (regcache);
}
else
struct regcache *regcache;
if (!set_desired_thread ())
- write_enn (own_buf);
+ write_enn (cs.own_buf);
else
{
regcache = get_thread_regcache (current_thread, 1);
- registers_to_string (regcache, own_buf);
+ registers_to_string (regcache, cs.own_buf);
}
}
break;
case 'G':
- require_running_or_break (own_buf);
- if (current_traceframe >= 0)
- write_enn (own_buf);
+ require_running_or_break (cs.own_buf);
+ if (cs.current_traceframe >= 0)
+ write_enn (cs.own_buf);
else
{
struct regcache *regcache;
if (!set_desired_thread ())
- write_enn (own_buf);
+ write_enn (cs.own_buf);
else
{
regcache = get_thread_regcache (current_thread, 1);
- registers_from_string (regcache, &own_buf[1]);
- write_ok (own_buf);
+ registers_from_string (regcache, &cs.own_buf[1]);
+ write_ok (cs.own_buf);
}
}
break;
case 'm':
- require_running_or_break (own_buf);
- decode_m_packet (&own_buf[1], &mem_addr, &len);
- res = gdb_read_memory (mem_addr, mem_buf, len);
- if (res < 0)
- write_enn (own_buf);
- else
- bin2hex (mem_buf, own_buf, res);
+ {
+ require_running_or_break (cs.own_buf);
+ decode_m_packet (&cs.own_buf[1], &mem_addr, &len);
+ int res = gdb_read_memory (mem_addr, mem_buf, len);
+ if (res < 0)
+ write_enn (cs.own_buf);
+ else
+ bin2hex (mem_buf, cs.own_buf, res);
+ }
break;
case 'M':
- require_running_or_break (own_buf);
- decode_M_packet (&own_buf[1], &mem_addr, &len, &mem_buf);
+ require_running_or_break (cs.own_buf);
+ decode_M_packet (&cs.own_buf[1], &mem_addr, &len, &mem_buf);
if (gdb_write_memory (mem_addr, mem_buf, len) == 0)
- write_ok (own_buf);
+ write_ok (cs.own_buf);
else
- write_enn (own_buf);
+ write_enn (cs.own_buf);
break;
case 'X':
- require_running_or_break (own_buf);
- if (decode_X_packet (&own_buf[1], packet_len - 1,
+ require_running_or_break (cs.own_buf);
+ if (decode_X_packet (&cs.own_buf[1], packet_len - 1,
&mem_addr, &len, &mem_buf) < 0
|| gdb_write_memory (mem_addr, mem_buf, len) != 0)
- write_enn (own_buf);
+ write_enn (cs.own_buf);
else
- write_ok (own_buf);
+ write_ok (cs.own_buf);
break;
case 'C':
- require_running_or_break (own_buf);
- hex2bin (own_buf + 1, &sig, 1);
+ require_running_or_break (cs.own_buf);
+ hex2bin (cs.own_buf + 1, &sig, 1);
if (gdb_signal_to_host_p ((enum gdb_signal) sig))
signal = gdb_signal_to_host ((enum gdb_signal) sig);
else
signal = 0;
- myresume (own_buf, 0, signal);
+ myresume (cs.own_buf, 0, signal);
break;
case 'S':
- require_running_or_break (own_buf);
- hex2bin (own_buf + 1, &sig, 1);
+ require_running_or_break (cs.own_buf);
+ hex2bin (cs.own_buf + 1, &sig, 1);
if (gdb_signal_to_host_p ((enum gdb_signal) sig))
signal = gdb_signal_to_host ((enum gdb_signal) sig);
else
signal = 0;
- myresume (own_buf, 1, signal);
+ myresume (cs.own_buf, 1, signal);
break;
case 'c':
- require_running_or_break (own_buf);
+ require_running_or_break (cs.own_buf);
signal = 0;
- myresume (own_buf, 0, signal);
+ myresume (cs.own_buf, 0, signal);
break;
case 's':
- require_running_or_break (own_buf);
+ require_running_or_break (cs.own_buf);
signal = 0;
- myresume (own_buf, 1, signal);
+ myresume (cs.own_buf, 1, signal);
break;
case 'Z': /* insert_ ... */
/* Fallthrough. */
char *dataptr;
ULONGEST addr;
int kind;
- char type = own_buf[1];
+ char type = cs.own_buf[1];
int res;
const int insert = ch == 'Z';
- const char *p = &own_buf[3];
+ const char *p = &cs.own_buf[3];
p = unpack_varlen_hex (p, &addr);
kind = strtol (p + 1, &dataptr, 16);
res = delete_gdb_breakpoint (type, addr, kind);
if (res == 0)
- write_ok (own_buf);
+ write_ok (cs.own_buf);
else if (res == 1)
/* Unsupported. */
- own_buf[0] = '\0';
+ cs.own_buf[0] = '\0';
else
- write_enn (own_buf);
+ write_enn (cs.own_buf);
break;
}
case 'k':
running. The traditional protocol will exit instead. */
if (extended_protocol)
{
- last_status.kind = TARGET_WAITKIND_EXITED;
- last_status.value.sig = GDB_SIGNAL_KILL;
+ cs.last_status.kind = TARGET_WAITKIND_EXITED;
+ cs.last_status.value.sig = GDB_SIGNAL_KILL;
return 0;
}
else
case 'T':
{
- require_running_or_break (own_buf);
+ require_running_or_break (cs.own_buf);
- ptid_t thread_id = read_ptid (&own_buf[1], NULL);
+ ptid_t thread_id = read_ptid (&cs.own_buf[1], NULL);
if (find_thread_ptid (thread_id) == NULL)
{
- write_enn (own_buf);
+ write_enn (cs.own_buf);
break;
}
if (mythread_alive (thread_id))
- write_ok (own_buf);
+ write_ok (cs.own_buf);
else
- write_enn (own_buf);
+ write_enn (cs.own_buf);
}
break;
case 'R':
{
create_inferior (program_path.get (), program_args);
- if (last_status.kind == TARGET_WAITKIND_STOPPED)
+ if (cs.last_status.kind == TARGET_WAITKIND_STOPPED)
{
/* Stopped at the first instruction of the target
process. */
- general_thread = last_ptid;
+ cs.general_thread = cs.last_ptid;
}
else
{
/* Something went wrong. */
- general_thread = null_ptid;
+ cs.general_thread = null_ptid;
}
}
else
{
- last_status.kind = TARGET_WAITKIND_EXITED;
- last_status.value.sig = GDB_SIGNAL_KILL;
+ cs.last_status.kind = TARGET_WAITKIND_EXITED;
+ cs.last_status.value.sig = GDB_SIGNAL_KILL;
}
return 0;
}
/* It is a request we don't understand. Respond with an
empty packet so that gdb knows that we don't support this
request. */
- own_buf[0] = '\0';
+ cs.own_buf[0] = '\0';
break;
}
case 'v':
/* Extended (long) request. */
- handle_v_requests (own_buf, packet_len, &new_packet_len);
+ handle_v_requests (cs.own_buf, packet_len, &new_packet_len);
break;
default:
/* It is a request we don't understand. Respond with an empty
packet so that gdb knows that we don't support this
request. */
- own_buf[0] = '\0';
+ cs.own_buf[0] = '\0';
break;
}
if (new_packet_len != -1)
- putpkt_binary (own_buf, new_packet_len);
+ putpkt_binary (cs.own_buf, new_packet_len);
else
- putpkt (own_buf);
+ putpkt (cs.own_buf);
response_needed = 0;
static void
push_stop_notification (ptid_t ptid, struct target_waitstatus *status)
{
- struct vstop_notif *vstop_notif = XNEW (struct vstop_notif);
+ struct vstop_notif *vstop_notif = new struct vstop_notif;
vstop_notif->status = *status;
vstop_notif->ptid = ptid;
/* Push Stop notification. */
- notif_push (¬if_stop, (struct notif_event *) vstop_notif);
+ notif_push (¬if_stop, vstop_notif);
}
/* Event-loop callback for target events. */
int
handle_target_event (int err, gdb_client_data client_data)
{
+ client_state &cs = get_client_state ();
if (debug_threads)
debug_printf ("handling possible target event\n");
- last_ptid = mywait (minus_one_ptid, &last_status,
+ cs.last_ptid = mywait (minus_one_ptid, &cs.last_status,
TARGET_WNOHANG, 1);
- if (last_status.kind == TARGET_WAITKIND_NO_RESUMED)
+ if (cs.last_status.kind == TARGET_WAITKIND_NO_RESUMED)
{
if (gdb_connected () && report_no_resumed)
- push_stop_notification (null_ptid, &last_status);
+ push_stop_notification (null_ptid, &cs.last_status);
}
- else if (last_status.kind != TARGET_WAITKIND_IGNORE)
+ else if (cs.last_status.kind != TARGET_WAITKIND_IGNORE)
{
- int pid = ptid_get_pid (last_ptid);
+ int pid = cs.last_ptid.pid ();
struct process_info *process = find_process_pid (pid);
int forward_event = !gdb_connected () || process->gdb_detached;
- if (last_status.kind == TARGET_WAITKIND_EXITED
- || last_status.kind == TARGET_WAITKIND_SIGNALLED)
+ if (cs.last_status.kind == TARGET_WAITKIND_EXITED
+ || cs.last_status.kind == TARGET_WAITKIND_SIGNALLED)
{
mark_breakpoints_out (process);
- target_mourn_inferior (last_ptid);
+ target_mourn_inferior (cs.last_ptid);
}
- else if (last_status.kind == TARGET_WAITKIND_THREAD_EXITED)
+ else if (cs.last_status.kind == TARGET_WAITKIND_THREAD_EXITED)
;
else
{
"want-stopped" state to what the client wants, until it
gets a new resume action. */
current_thread->last_resume_kind = resume_stop;
- current_thread->last_status = last_status;
+ current_thread->last_status = cs.last_status;
}
if (forward_event)
exit (0);
}
- if (last_status.kind == TARGET_WAITKIND_EXITED
- || last_status.kind == TARGET_WAITKIND_SIGNALLED
- || last_status.kind == TARGET_WAITKIND_THREAD_EXITED)
+ if (cs.last_status.kind == TARGET_WAITKIND_EXITED
+ || cs.last_status.kind == TARGET_WAITKIND_SIGNALLED
+ || cs.last_status.kind == TARGET_WAITKIND_THREAD_EXITED)
;
else
{
if (debug_threads)
debug_printf ("GDB not connected; forwarding event %d for"
" [%s]\n",
- (int) last_status.kind,
- target_pid_to_str (last_ptid));
+ (int) cs.last_status.kind,
+ target_pid_to_str (cs.last_ptid));
- if (last_status.kind == TARGET_WAITKIND_STOPPED)
- signal = last_status.value.sig;
+ if (cs.last_status.kind == TARGET_WAITKIND_STOPPED)
+ signal = cs.last_status.value.sig;
else
signal = GDB_SIGNAL_0;
- target_continue (last_ptid, signal);
+ target_continue (cs.last_ptid, signal);
}
}
else
- push_stop_notification (last_ptid, &last_status);
+ push_stop_notification (cs.last_ptid, &cs.last_status);
}
/* Be sure to not change the selected thread behind GDB's back.