/* Main code for remote server for GDB.
- Copyright (C) 1989-2019 Free Software Foundation, Inc.
+ Copyright (C) 1989-2020 Free Software Foundation, Inc.
This file is part of GDB.
#include "server.h"
#include "gdbthread.h"
-#include "common/agent.h"
+#include "gdbsupport/agent.h"
#include "notif.h"
#include "tdesc.h"
-#include "common/rsp-low.h"
-#include "common/signals-state-save-restore.h"
+#include "gdbsupport/rsp-low.h"
+#include "gdbsupport/signals-state-save-restore.h"
#include <ctype.h>
#include <unistd.h>
#if HAVE_SIGNAL_H
#include <signal.h>
#endif
-#include "common/gdb_vecs.h"
-#include "common/gdb_wait.h"
-#include "common/btrace-common.h"
-#include "common/filestuff.h"
+#include "gdbsupport/gdb_vecs.h"
+#include "gdbsupport/gdb_wait.h"
+#include "gdbsupport/btrace-common.h"
+#include "gdbsupport/filestuff.h"
#include "tracepoint.h"
#include "dll.h"
#include "hostio.h"
#include <vector>
-#include "common/common-inferior.h"
-#include "common/job-control.h"
-#include "common/environ.h"
+#include "gdbsupport/common-inferior.h"
+#include "gdbsupport/job-control.h"
+#include "gdbsupport/environ.h"
#include "filenames.h"
-#include "common/pathstuff.h"
+#include "gdbsupport/pathstuff.h"
+#ifdef USE_XML
+#include "xml-builtin.h"
+#endif
-#include "common/selftest.h"
+#include "gdbsupport/selftest.h"
+#include "gdbsupport/scope-exit.h"
#define require_running_or_return(BUF) \
if (!target_running ()) \
static gdb_environ our_environ;
-/* Start the inferior using a shell. */
-
-/* We always try to start the inferior using a shell. */
+bool server_waiting;
-int startup_with_shell = 1;
-
-int server_waiting;
-
-static int extended_protocol;
-static int response_needed;
-static int exit_requested;
+static bool extended_protocol;
+static bool response_needed;
+static bool exit_requested;
/* --once: Exit after the first connection has closed. */
-int run_once;
+bool run_once;
-/* Whether to report TARGET_WAITKING_NO_RESUMED events. */
-static int report_no_resumed;
+/* Whether to report TARGET_WAITKIND_NO_RESUMED events. */
+static bool report_no_resumed;
-int non_stop;
+bool non_stop;
static struct {
/* Set the PROGRAM_PATH. Here we adjust the path of the provided
/* Set if you want to disable optional thread related packets support
in gdbserver, for the sake of testing GDB against stubs that don't
support them. */
-int disable_packet_vCont;
-int disable_packet_Tthread;
-int disable_packet_qC;
-int disable_packet_qfThreadInfo;
+bool disable_packet_vCont;
+bool disable_packet_Tthread;
+bool disable_packet_qC;
+bool disable_packet_qfThreadInfo;
static unsigned char *mem_buf;
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;
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 (vstop_event->ptid.matches (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 (vstop_event->ptid.matches (filter_ptid))
- return 0;
+ 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)
&& vstop_event->status.value.related_pid.matches (filter_ptid))
- return 0;
+ 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
return get_first_thread () != NULL;
}
-/* See common/common-inferior.h. */
+/* See gdbsupport/common-inferior.h. */
const char *
get_exec_wrapper ()
return !wrapper_argv.empty () ? wrapper_argv.c_str () : NULL;
}
-/* See common/common-inferior.h. */
+/* See gdbsupport/common-inferior.h. */
-char *
+const char *
get_exec_file (int err)
{
if (err && program_path.get () == NULL)
return 0;
}
-extern int remote_debug;
-
/* Decode a qXfer read request. Return 0 if everything looks OK,
or -1 otherwise. */
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;
}
return;
}
- non_stop = req;
+ non_stop = (req != 0);
if (remote_debug)
debug_printf ("[%s mode enabled]\n", req_str);
#ifdef USE_XML
{
- extern const char *const xml_builtin[][2];
int i;
/* Look for the annex. */
if (ret == 0)
{
if (set_desired_thread ())
- ret = write_inferior_memory (memaddr, myaddr, len);
+ ret = target_write_memory (memaddr, myaddr, len);
else
ret = EIO;
done_accessing_memory ();
if (debug_threads)
debug_printf ("Forcing non-stop mode\n");
- non_stop = 1;
+ non_stop = true;
start_non_stop (1);
}
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)
- exit_requested = 1;
+ exit_requested = true;
else
{
monitor_output ("Unknown monitor command.\n\n");
for (const dll_info &dll : all_dlls)
document += string_printf
- (" <library name=\"%s\"><segment address=\"0x%lx\"/></library>\n",
- dll.name.c_str (), (long) dll.base_addr);
+ (" <library name=\"%s\"><segment address=\"0x%s\"/></library>\n",
+ dll.name.c_str (), paddress (dll.base_addr));
document += "</library-list>\n";
return (*the_target->qxfer_siginfo) (annex, readbuf, writebuf, offset, len);
}
-/* Handle qXfer:spu:read and qXfer:spu:write. */
-
-static int
-handle_qxfer_spu (const char *annex,
- gdb_byte *readbuf, const gdb_byte *writebuf,
- ULONGEST offset, LONGEST len)
-{
- if (the_target->qxfer_spu == NULL)
- return -2;
-
- if (current_thread == NULL)
- return -1;
-
- return (*the_target->qxfer_spu) (annex, readbuf, writebuf, offset, len);
-}
-
/* Handle qXfer:statictrace:read. */
static int
{
buffer_free (&cache);
- TRY
+ try
{
result = target_read_btrace (thread->btrace, &cache, type);
if (result != 0)
memcpy (cs.own_buf, cache.buffer, cache.used_size);
}
- CATCH (exception, RETURN_MASK_ERROR)
+ catch (const gdb_exception_error &exception)
{
- sprintf (cs.own_buf, "E.%s", exception.message);
+ sprintf (cs.own_buf, "E.%s", exception.what ());
result = -1;
}
- END_CATCH
if (result != 0)
return -3;
{
buffer_free (&cache);
- TRY
+ try
{
result = target_read_btrace_conf (thread->btrace, &cache);
if (result != 0)
memcpy (cs.own_buf, cache.buffer, cache.used_size);
}
- CATCH (exception, RETURN_MASK_ERROR)
+ catch (const gdb_exception_error &exception)
{
- sprintf (cs.own_buf, "E.%s", exception.message);
+ sprintf (cs.own_buf, "E.%s", exception.what ());
result = -1;
}
- END_CATCH
if (result != 0)
return -3;
{ "libraries-svr4", handle_qxfer_libraries_svr4 },
{ "osdata", handle_qxfer_osdata },
{ "siginfo", handle_qxfer_siginfo },
- { "spu", handle_qxfer_spu },
{ "statictrace", handle_qxfer_statictrace },
{ "threads", handle_qxfer_threads },
{ "traceframe-info", handle_qxfer_traceframe_info },
/* Two passes, to avoid nested strtok calls in
target_process_qsupported. */
- for (p = strtok (p + 1, ";");
+ char *saveptr;
+ for (p = strtok_r (p + 1, ";", &saveptr);
p != NULL;
- p = strtok (NULL, ";"))
+ p = strtok_r (NULL, ";", &saveptr))
{
count++;
qsupported = XRESIZEVEC (char *, qsupported, count);
{
/* GDB supports and wants TARGET_WAITKIND_NO_RESUMED
events. */
- report_no_resumed = 1;
+ report_no_resumed = true;
}
else
{
if (the_target->read_auxv != NULL)
strcat (own_buf, ";qXfer:auxv:read+");
- if (the_target->qxfer_spu != NULL)
- strcat (own_buf, ";qXfer:spu:read+;qXfer:spu:write+");
-
if (the_target->qxfer_siginfo != NULL)
strcat (own_buf, ";qXfer:siginfo:read+;qXfer:siginfo:write+");
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
{
gdbserver_version (void)
{
printf ("GNU gdbserver %s%s\n"
- "Copyright (C) 2019 Free Software Foundation, Inc.\n"
+ "Copyright (C) 2020 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"
/* 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,
}
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);
}
else if (startswith (*next_arg, "--disable-packet="))
{
- char *packets, *tok;
-
- packets = *next_arg += sizeof ("--disable-packet=") - 1;
- for (tok = strtok (packets, ",");
+ char *packets = *next_arg += sizeof ("--disable-packet=") - 1;
+ char *saveptr;
+ for (char *tok = strtok_r (packets, ",", &saveptr);
tok != NULL;
- tok = strtok (NULL, ","))
+ tok = strtok_r (NULL, ",", &saveptr))
{
if (strcmp ("vCont", tok) == 0)
- disable_packet_vCont = 1;
+ disable_packet_vCont = true;
else if (strcmp ("Tthread", tok) == 0)
- disable_packet_Tthread = 1;
+ disable_packet_Tthread = true;
else if (strcmp ("qC", tok) == 0)
- disable_packet_qC = 1;
+ disable_packet_qC = true;
else if (strcmp ("qfThreadInfo", tok) == 0)
- disable_packet_qfThreadInfo = 1;
+ disable_packet_qfThreadInfo = true;
else if (strcmp ("threads", tok) == 0)
{
- disable_packet_vCont = 1;
- disable_packet_Tthread = 1;
- disable_packet_qC = 1;
- disable_packet_qfThreadInfo = 1;
+ disable_packet_vCont = true;
+ disable_packet_Tthread = true;
+ disable_packet_qC = true;
+ disable_packet_qfThreadInfo = true;
}
else
{
else if (strcmp (*next_arg, "--no-startup-with-shell") == 0)
startup_with_shell = false;
else if (strcmp (*next_arg, "--once") == 0)
- run_once = 1;
+ run_once = true;
else if (strcmp (*next_arg, "--selftest") == 0)
selftest = true;
else if (startswith (*next_arg, "--selftest="))
initialize_event_loop ();
if (target_supports_tracepoints ())
initialize_tracepoint ();
- initialize_notif ();
mem_buf = (unsigned char *) xmalloc (PBUFSIZ);
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);
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
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)
{
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");
}
disable_async_io ();
- response_needed = 0;
+ response_needed = false;
packet_len = getpkt (cs.own_buf);
if (packet_len <= 0)
{
/* Force an event loop break. */
return -1;
}
- response_needed = 1;
+ response_needed = true;
char ch = cs.own_buf[0];
switch (ch)
handle_detach (cs.own_buf);
break;
case '!':
- extended_protocol = 1;
+ extended_protocol = true;
write_ok (cs.own_buf);
break;
case '?':
break;
}
case 'k':
- response_needed = 0;
+ response_needed = false;
if (!target_running ())
/* The packet we received doesn't make sense - but we can't
reply to it, either. */
}
break;
case 'R':
- response_needed = 0;
+ response_needed = false;
/* Restarting the inferior is only supported in the extended
protocol. */
else
putpkt (cs.own_buf);
- response_needed = 0;
+ response_needed = false;
if (exit_requested)
return -1;
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. */