#include "gdbsupport/selftest.h"
#include "gdbsupport/scope-exit.h"
+#include "gdbsupport/gdb_select.h"
#define require_running_or_return(BUF) \
if (!target_running ()) \
/* Whether to report TARGET_WAITKIND_NO_RESUMED events. */
static bool report_no_resumed;
+/* The event loop checks this to decide whether to continue accepting
+ events. */
+static bool keep_processing_events = true;
+
bool non_stop;
static struct {
bool disable_packet_Tthread;
bool disable_packet_qC;
bool disable_packet_qfThreadInfo;
+bool disable_packet_T;
static unsigned char *mem_buf;
}
req_str = req ? "non-stop" : "all-stop";
- if (start_non_stop (req) != 0)
+ if (the_target->start_non_stop (req == 1) != 0)
{
fprintf (stderr, "Setting %s mode failed\n", req_str);
write_enn (own_buf);
: chunk_size);
if (gdb_read_memory (read_addr, search_buf + keep_len,
- nr_to_read) != search_buf_size)
+ nr_to_read) != nr_to_read)
{
warning ("Unable to access %ld bytes of target memory "
"at 0x%lx, halting search.",
debug_printf ("Forcing non-stop mode\n");
non_stop = true;
- start_non_stop (1);
+ the_target->start_non_stop (true);
}
process->gdb_detached = 1;
gdb_byte *readbuf, const gdb_byte *writebuf,
ULONGEST offset, LONGEST len)
{
- if (!the_target->pt->supports_read_auxv () || writebuf != NULL)
+ if (!the_target->supports_read_auxv () || writebuf != NULL)
return -2;
if (annex[0] != '\0' || current_thread == NULL)
return -1;
- return the_target->pt->read_auxv (offset, readbuf, len);
+ return the_target->read_auxv (offset, readbuf, len);
}
/* Handle qXfer:exec-file:read. */
ULONGEST pid;
int total_len;
- if (the_target->pid_to_exec_file == NULL || writebuf != NULL)
+ if (!the_target->supports_pid_to_exec_file () || writebuf != NULL)
return -2;
if (annex[0] == '\0')
if (pid <= 0)
return -1;
- file = (*the_target->pid_to_exec_file) (pid);
+ file = the_target->pid_to_exec_file (pid);
if (file == NULL)
return -1;
if (writebuf != NULL)
return -2;
- if (current_thread == NULL || the_target->qxfer_libraries_svr4 == NULL)
+ if (current_thread == NULL
+ || !the_target->supports_qxfer_libraries_svr4 ())
return -1;
- return the_target->qxfer_libraries_svr4 (annex, readbuf, writebuf, offset, len);
+ return the_target->qxfer_libraries_svr4 (annex, readbuf, writebuf,
+ offset, len);
}
/* Handle qXfer:osadata:read. */
gdb_byte *readbuf, const gdb_byte *writebuf,
ULONGEST offset, LONGEST len)
{
- if (the_target->qxfer_osdata == NULL || writebuf != NULL)
+ if (!the_target->supports_qxfer_osdata () || writebuf != NULL)
return -2;
- return (*the_target->qxfer_osdata) (annex, readbuf, NULL, offset, len);
+ return the_target->qxfer_osdata (annex, readbuf, NULL, offset, len);
}
/* Handle qXfer:siginfo:read and qXfer:siginfo:write. */
gdb_byte *readbuf, const gdb_byte *writebuf,
ULONGEST offset, LONGEST len)
{
- if (the_target->qxfer_siginfo == NULL)
+ if (!the_target->supports_qxfer_siginfo ())
return -2;
if (annex[0] != '\0' || current_thread == NULL)
return -1;
- return (*the_target->qxfer_siginfo) (annex, readbuf, writebuf, offset, len);
+ return the_target->qxfer_siginfo (annex, readbuf, writebuf, offset, len);
}
/* Handle qXfer:statictrace:read. */
handle_qxfer_fdpic (const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
{
- if (the_target->read_loadmap == NULL)
+ if (!the_target->supports_read_loadmap ())
return -2;
if (current_thread == NULL)
return -1;
- return (*the_target->read_loadmap) (annex, offset, readbuf, len);
+ return the_target->read_loadmap (annex, offset, readbuf, len);
}
/* Handle qXfer:btrace:read. */
tracepoint_look_up_symbols ();
if (current_thread != NULL)
- the_target->pt->look_up_symbols ();
+ the_target->look_up_symbols ();
current_thread = save_thread;
}
}
- if (the_target->pt->supports_read_offsets ()
+ if (the_target->supports_read_offsets ()
&& strcmp ("qOffsets", own_buf) == 0)
{
CORE_ADDR text, data;
require_running_or_return (own_buf);
- if (the_target->pt->read_offsets (&text, &data))
+ if (the_target->read_offsets (&text, &data))
sprintf (own_buf, "Text=%lX;Data=%lX;Bss=%lX",
(long)text, (long)data, (long)data);
else
if (target_supports_catch_syscall ())
strcat (own_buf, ";QCatchSyscalls+");
- if (the_target->qxfer_libraries_svr4 != NULL)
+ if (the_target->supports_qxfer_libraries_svr4 ())
strcat (own_buf, ";qXfer:libraries-svr4:read+"
";augmented-libraries-svr4-read+");
else
strcat (own_buf, ";qXfer:libraries:read+");
}
- if (the_target->pt->supports_read_auxv ())
+ if (the_target->supports_read_auxv ())
strcat (own_buf, ";qXfer:auxv:read+");
- if (the_target->qxfer_siginfo != NULL)
+ if (the_target->supports_qxfer_siginfo ())
strcat (own_buf, ";qXfer:siginfo:read+;qXfer:siginfo:write+");
- if (the_target->read_loadmap != NULL)
+ if (the_target->supports_read_loadmap ())
strcat (own_buf, ";qXfer:fdpic:read+");
/* We always report qXfer:features:read, as targets may
if (cs.transport_is_reliable)
strcat (own_buf, ";QStartNoAckMode+");
- if (the_target->qxfer_osdata != NULL)
+ if (the_target->supports_qxfer_osdata ())
strcat (own_buf, ";qXfer:osdata:read+");
if (target_supports_multi_process ())
if (target_supports_stopped_by_hw_breakpoint ())
strcat (own_buf, ";hwbreak+");
- if (the_target->pid_to_exec_file != NULL)
+ if (the_target->supports_pid_to_exec_file ())
strcat (own_buf, ";qXfer:exec-file:read+");
strcat (own_buf, ";vContSupported+");
}
/* Thread-local storage support. */
- if (the_target->pt->supports_get_tls_address ()
+ if (the_target->supports_get_tls_address ()
&& startswith (own_buf, "qGetTLSAddr:"))
{
char *p = own_buf + 12;
if (thread == NULL)
err = 2;
else
- err = the_target->pt->get_tls_address (thread, parts[0], parts[1],
- &address);
+ err = the_target->get_tls_address (thread, parts[0], parts[1],
+ &address);
}
if (err == 0)
}
/* Windows OS Thread Information Block address support. */
- if (the_target->get_tib_address != NULL
+ if (the_target->supports_get_tib_address ()
&& startswith (own_buf, "qGetTIBAddr:"))
{
const char *annex;
CORE_ADDR tlb;
ptid_t ptid = read_ptid (own_buf + 12, &annex);
- n = (*the_target->get_tib_address) (ptid, &tlb);
+ n = the_target->get_tib_address (ptid, &tlb);
if (n == 1)
{
strcpy (own_buf, paddress(tlb));
write_ok (own_buf);
- if (the_target->handle_monitor_command == NULL
- || (*the_target->handle_monitor_command) (mon) == 0)
+ if (the_target->handle_monitor_command (mon) == 0)
/* Default processing. */
handle_monitor_command (mon, own_buf);
enable_async_io ();
}
- the_target->pt->resume (actions, num_actions);
+ the_target->resume (actions, num_actions);
if (non_stop)
write_ok (cs.own_buf);
else if (p == next_p)
{
/* Empty argument. */
- new_argv.push_back (xstrdup ("''"));
+ new_argv.push_back (xstrdup (""));
}
else
{
if (*next_p)
next_p++;
}
- new_argv.push_back (NULL);
if (new_program_name == NULL)
{
{
if (strcmp (own_buf, "vCtrlC") == 0)
{
- the_target->pt->request_interrupt ();
+ the_target->request_interrupt ();
write_ok (own_buf);
return;
}
{
/* For now, assume targets that don't have this callback also don't
manage the thread's last_status field. */
- if (the_target->thread_stopped == NULL)
+ if (!the_target->supports_thread_stopped ())
{
struct vstop_notif *new_notif = new struct vstop_notif;
}
else
{
- if (thread_stopped (thread))
+ if (target_thread_stopped (thread))
{
if (debug_threads)
{
{
thread_info *thread = NULL;
- pause_all (0);
- stabilize_threads ();
+ target_pause_all (false);
+ target_stabilize_threads ();
gdb_wants_all_threads_stopped ();
/* We can only report one status, but we might be coming out of
" threads \tAll of the above\n");
}
+/* Start up the event loop. This is the entry point to the event
+ loop. */
+
+static void
+start_event_loop ()
+{
+ /* Loop until there is nothing to do. This is the entry point to
+ the event loop engine. If nothing is ready at this time, wait
+ for something to happen (via wait_for_event), then process it.
+ Return when there are no longer event sources to wait for. */
+
+ keep_processing_events = true;
+ while (keep_processing_events)
+ {
+ /* Any events already waiting in the queue? */
+ int res = gdb_do_one_event ();
+
+ /* Was there an error? */
+ if (res == -1)
+ break;
+ }
+
+ /* We are done with the event loop. There are no more event sources
+ to listen to. So we exit gdbserver. */
+}
+
static void
kill_inferior_callback (process_info *process)
{
disable_packet_qC = true;
else if (strcmp ("qfThreadInfo", tok) == 0)
disable_packet_qfThreadInfo = true;
+ else if (strcmp ("T", tok) == 0)
+ disable_packet_T = true;
else if (strcmp ("threads", tok) == 0)
{
disable_packet_vCont = true;
initialize_async_io ();
initialize_low ();
have_job_control ();
- initialize_event_loop ();
if (target_supports_tracepoints ())
initialize_tracepoint ();
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);
/* Wait till we are at first instruction in program. */
target_create_inferior (program_path.get (), program_args);
down without informing GDB. */
if (!non_stop)
{
- if (start_non_stop (1))
+ if (the_target->start_non_stop (true))
non_stop = 1;
/* Detaching implicitly resumes all threads;
/* Event-loop callback for serial events. */
-int
+void
handle_serial_event (int err, gdb_client_data client_data)
{
if (debug_threads)
/* Really handle it. */
if (process_serial_event () < 0)
- return -1;
+ {
+ keep_processing_events = false;
+ return;
+ }
/* Be sure to not change the selected thread behind GDB's back.
Important in the non-stop mode asynchronous protocol. */
set_desired_thread ();
-
- return 0;
}
/* Push a stop notification on the notification queue. */
/* Event-loop callback for target events. */
-int
+void
handle_target_event (int err, gdb_client_data client_data)
{
client_state &cs = get_client_state ();
/* Be sure to not change the selected thread behind GDB's back.
Important in the non-stop mode asynchronous protocol. */
set_desired_thread ();
+}
+
+/* See gdbsupport/event-loop.h. */
+int
+invoke_async_signal_handlers ()
+{
+ return 0;
+}
+
+/* See gdbsupport/event-loop.h. */
+
+int
+check_async_event_handlers ()
+{
return 0;
}
+/* See gdbsupport/errors.h */
+
+void
+flush_streams ()
+{
+ fflush (stdout);
+ fflush (stderr);
+}
+
+/* See gdbsupport/gdb_select.h. */
+
+int
+gdb_select (int n, fd_set *readfds, fd_set *writefds,
+ fd_set *exceptfds, struct timeval *timeout)
+{
+ return select (n, readfds, writefds, exceptfds, timeout);
+}
+
#if GDB_SELF_TEST
namespace selftests
{