X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fgdbserver%2Fserver.c;h=3fc026f78ebba4db17134befd3b7607e68ed04ff;hb=e8319fde715960466aca2461c74cec8907abd391;hp=ad327be0280343841ce80c03ee15e55d3e635e30;hpb=b1223e789040e9e8cdc6869a8a1fd1fd7acc109d;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index ad327be028..3fc026f78e 100644 --- a/gdb/gdbserver/server.c +++ b/gdb/gdbserver/server.c @@ -1,5 +1,5 @@ /* Main code for remote server for GDB. - Copyright (C) 1989-2018 Free Software Foundation, Inc. + Copyright (C) 1989-2020 Free Software Foundation, Inc. This file is part of GDB. @@ -18,31 +18,35 @@ #include "server.h" #include "gdbthread.h" -#include "agent.h" +#include "gdbsupport/agent.h" #include "notif.h" #include "tdesc.h" -#include "rsp-low.h" -#include "signals-state-save-restore.h" +#include "gdbsupport/rsp-low.h" +#include "gdbsupport/signals-state-save-restore.h" #include #include #if HAVE_SIGNAL_H #include #endif -#include "gdb_vecs.h" -#include "gdb_wait.h" -#include "btrace-common.h" -#include "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 -#include "common-inferior.h" -#include "job-control.h" -#include "environ.h" +#include "gdbsupport/common-inferior.h" +#include "gdbsupport/job-control.h" +#include "gdbsupport/environ.h" #include "filenames.h" -#include "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 ()) \ @@ -66,53 +70,19 @@ char *current_directory; static gdb_environ our_environ; -/* Start the inferior using a shell. */ - -/* We always try to start the inferior using a shell. */ - -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; +bool 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; -int multi_process; -int report_fork_events; -int report_vfork_events; -int report_exec_events; -int report_thread_events; +/* Whether to report TARGET_WAITKIND_NO_RESUMED events. */ +static bool report_no_resumed; -/* 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; +bool non_stop; static struct { /* Set the PROGRAM_PATH. Here we adjust the path of the provided @@ -146,10 +116,6 @@ private: static std::vector 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 @@ -160,26 +126,19 @@ unsigned long signal_pid; /* 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; -/* 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; @@ -191,39 +150,37 @@ struct vstop_notif 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. */ @@ -231,8 +188,19 @@ remove_all_on_match_ptid (QUEUE (notif_event_p) *q, void discard_queued_stop_replies (ptid_t ptid) { - QUEUE_iterate (notif_event_p, notif_stop.queue, - remove_all_on_match_ptid, &ptid); + std::list::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 @@ -243,27 +211,23 @@ vstop_notif_reply (struct notif_event *event, char *own_buf) 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. */ @@ -271,13 +235,18 @@ in_queued_stop_replies_ptid (QUEUE (notif_event_p) *q, 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 @@ -286,7 +255,7 @@ target_running (void) return get_first_thread () != NULL; } -/* See common/common-inferior.h. */ +/* See gdbsupport/common-inferior.h. */ const char * get_exec_wrapper () @@ -294,9 +263,9 @@ 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) @@ -316,9 +285,13 @@ get_environ () 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; @@ -332,24 +305,22 @@ attach_inferior (int pid) 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. */ @@ -456,6 +427,7 @@ handle_btrace_disable (struct thread_info *thread) static int handle_btrace_general_set (char *own_buf) { + client_state &cs = get_client_state (); struct thread_info *thread; char *op; @@ -464,21 +436,21 @@ handle_btrace_general_set (char *own_buf) 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); @@ -491,11 +463,10 @@ handle_btrace_general_set (char *own_buf) 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; } @@ -505,6 +476,7 @@ handle_btrace_general_set (char *own_buf) static int handle_btrace_conf_general_set (char *own_buf) { + client_state &cs = get_client_state (); struct thread_info *thread; char *op; @@ -513,14 +485,14 @@ handle_btrace_conf_general_set (char *own_buf) 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."); @@ -572,6 +544,7 @@ handle_btrace_conf_general_set (char *own_buf) 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; @@ -583,7 +556,7 @@ handle_general_set (char *own_buf) { if (i == cursig) { - pass_signals[i] = 1; + cs.pass_signals[i] = 1; if (*p == '\0') /* Keep looping, to clear the remaining signals. */ cursig = -1; @@ -591,7 +564,7 @@ handle_general_set (char *own_buf) p = decode_address_to_semicolon (&cursig, p); } else - pass_signals[i] = 0; + cs.pass_signals[i] = 0; } strcpy (own_buf, "OK"); return; @@ -603,14 +576,14 @@ handle_general_set (char *own_buf) 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; @@ -618,7 +591,7 @@ handle_general_set (char *own_buf) p = decode_address_to_semicolon (&cursig, p); } else - program_signals[i] = 0; + cs.program_signals[i] = 0; } strcpy (own_buf, "OK"); return; @@ -741,7 +714,7 @@ handle_general_set (char *own_buf) debug_flush (); } - noack_mode = 1; + cs.noack_mode = 1; write_ok (own_buf); return; } @@ -774,7 +747,7 @@ handle_general_set (char *own_buf) return; } - non_stop = req; + non_stop = (req != 0); if (remote_debug) debug_printf ("[%s mode enabled]\n", req_str); @@ -789,11 +762,11 @@ handle_general_set (char *own_buf) 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"); } @@ -847,20 +820,17 @@ handle_general_set (char *own_buf) 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); } @@ -943,7 +913,7 @@ get_features_xml (const char *annex) 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; @@ -953,7 +923,6 @@ get_features_xml (const char *annex) #ifdef USE_XML { - extern const char *const xml_builtin[][2]; int i; /* Look for the annex. */ @@ -1001,14 +970,15 @@ monitor_show_help (void) 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. */ @@ -1041,7 +1011,8 @@ gdb_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len) 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 { @@ -1051,7 +1022,7 @@ gdb_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len) 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 (); @@ -1216,34 +1187,38 @@ handle_search_memory (char *own_buf, int packet_len) 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"); @@ -1258,7 +1233,7 @@ handle_detach (char *own_buf) if (debug_threads) debug_printf ("Forcing non-stop mode\n"); - non_stop = 1; + non_stop = true; start_non_stop (1); } @@ -1271,13 +1246,17 @@ handle_detach (char *own_buf) 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 ()) @@ -1285,9 +1264,9 @@ handle_detach (char *own_buf) /* 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; } @@ -1309,8 +1288,8 @@ handle_detach (char *own_buf) ARG is the text after "--debug-format=" or "monitor set debug-format". IS_MONITOR is non-zero if we're invoked via "monitor set debug-format". This triggers calls to monitor_output. - The result is NULL if all options were parsed ok, otherwise an error - message which the caller must free. + The result is an empty string if all options were parsed ok, otherwise an + error message which the caller must free. N.B. These commands affect all debug format settings, they are not cumulative. If a format is not specified, it is turned off. @@ -1325,10 +1304,6 @@ handle_detach (char *own_buf) static std::string parse_debug_format_options (const char *arg, int is_monitor) { - VEC (char_ptr) *options; - int ix; - char *option; - /* First turn all debug format options off. */ debug_timestamp = 0; @@ -1336,23 +1311,24 @@ parse_debug_format_options (const char *arg, int is_monitor) while (isspace (*arg)) ++arg; - options = delim_string_to_char_ptr_vec (arg, ','); + std::vector> options + = delim_string_to_char_ptr_vec (arg, ','); - for (ix = 0; VEC_iterate (char_ptr, options, ix, option); ++ix) + for (const gdb::unique_xmalloc_ptr &option : options) { - if (strcmp (option, "all") == 0) + if (strcmp (option.get (), "all") == 0) { debug_timestamp = 1; if (is_monitor) monitor_output ("All extra debug format options enabled.\n"); } - else if (strcmp (option, "none") == 0) + else if (strcmp (option.get (), "none") == 0) { debug_timestamp = 0; if (is_monitor) monitor_output ("All extra debug format options disabled.\n"); } - else if (strcmp (option, "timestamp") == 0) + else if (strcmp (option.get (), "timestamp") == 0) { debug_timestamp = 1; if (is_monitor) @@ -1364,16 +1340,10 @@ parse_debug_format_options (const char *arg, int is_monitor) continue; } else - { - std::string msg - = string_printf ("Unknown debug-format argument: \"%s\"\n", option); - - free_char_ptr_vec (options); - return msg; - } + return string_printf ("Unknown debug-format argument: \"%s\"\n", + option.get ()); } - free_char_ptr_vec (options); return std::string (); } @@ -1425,10 +1395,14 @@ handle_monitor_command (char *mon, char *own_buf) 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"); @@ -1574,8 +1548,8 @@ handle_qxfer_libraries (const char *annex, for (const dll_info &dll : all_dlls) document += string_printf - (" \n", - dll.name.c_str (), (long) dll.base_addr); + (" \n", + dll.name.c_str (), paddress (dll.base_addr)); document += "\n"; @@ -1635,22 +1609,6 @@ handle_qxfer_siginfo (const char *annex, 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 @@ -1658,15 +1616,17 @@ handle_qxfer_statictrace (const char *annex, 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; @@ -1782,13 +1742,14 @@ handle_qxfer_traceframe_info (const char *annex, 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) @@ -1802,7 +1763,7 @@ handle_qxfer_traceframe_info (const char *annex, buffer_init (&buffer); - traceframe_read_info (current_traceframe, &buffer); + traceframe_read_info (cs.current_traceframe, &buffer); result = buffer_finish (&buffer); result_length = strlen (result); @@ -1847,6 +1808,7 @@ handle_qxfer_btrace (const char *annex, 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; @@ -1855,23 +1817,23 @@ handle_qxfer_btrace (const char *annex, 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; } @@ -1883,7 +1845,7 @@ handle_qxfer_btrace (const char *annex, type = BTRACE_READ_DELTA; else { - strcpy (own_buf, "E.Bad annex."); + strcpy (cs.own_buf, "E.Bad annex."); return -3; } @@ -1891,18 +1853,17 @@ handle_qxfer_btrace (const char *annex, { 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; @@ -1928,6 +1889,7 @@ handle_qxfer_btrace_conf (const char *annex, 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; @@ -1938,23 +1900,23 @@ handle_qxfer_btrace_conf (const char *annex, 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; } @@ -1962,18 +1924,17 @@ handle_qxfer_btrace_conf (const char *annex, { 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; @@ -2004,7 +1965,6 @@ static const struct qxfer qxfer_packets[] = { "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 }, @@ -2170,6 +2130,7 @@ supported_btrace_packets (char *buf) static void handle_query (char *own_buf, int packet_len, int *new_packet_len_p) { + client_state &cs = get_client_state (); static std::list::const_iterator thread_iter; /* Reply the current thread id. */ @@ -2178,8 +2139,8 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p) 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 (); @@ -2204,7 +2165,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p) 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. */ @@ -2307,9 +2268,10 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p) /* 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); @@ -2324,7 +2286,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p) /* 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) { @@ -2337,42 +2299,42 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p) 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) { /* GDB supports and wants TARGET_WAITKIND_NO_RESUMED events. */ - report_no_resumed = 1; + report_no_resumed = true; } else { @@ -2415,9 +2377,6 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p) 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+"); @@ -2430,7 +2389,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p) 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) @@ -2720,11 +2679,11 @@ visit_actioned_threads (thread_info *thread, { 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; @@ -2741,13 +2700,14 @@ static int 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; @@ -2867,6 +2827,7 @@ err: 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 @@ -2889,37 +2850,37 @@ resume (struct thread_resume *actions, size_t num_actions) (*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); } } @@ -2927,6 +2888,7 @@ resume (struct thread_resume *actions, size_t num_actions) static int handle_v_attach (char *own_buf) { + client_state &cs = get_client_state (); int pid; pid = strtol (own_buf + 8, NULL, 16); @@ -2946,7 +2908,7 @@ handle_v_attach (char *own_buf) 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; } @@ -2961,6 +2923,7 @@ handle_v_attach (char *own_buf) static int handle_v_run (char *own_buf) { + client_state &cs = get_client_state (); char *p, *next_p; std::vector new_argv; char *new_program_name = NULL; @@ -3067,15 +3030,15 @@ handle_v_run (char *own_buf) 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; } @@ -3090,18 +3053,22 @@ handle_v_run (char *own_buf) 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; } @@ -3116,6 +3083,7 @@ handle_v_kill (char *own_buf) 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) @@ -3137,7 +3105,7 @@ handle_v_requests (char *own_buf, int packet_len, int *new_packet_len) 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 @@ -3163,7 +3131,7 @@ handle_v_requests (char *own_buf, int packet_len, int *new_packet_len) 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); @@ -3175,7 +3143,7 @@ handle_v_requests (char *own_buf, int packet_len, int *new_packet_len) 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); @@ -3212,12 +3180,13 @@ handle_v_requests (char *own_buf, int packet_len, int *new_packet_len) 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) { @@ -3251,14 +3220,13 @@ queue_stop_reply_callback (thread_info *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 { @@ -3332,6 +3300,8 @@ set_pending_status_callback (thread_info *thread) 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; @@ -3348,7 +3318,7 @@ handle_status (char *own_buf) /* 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 { @@ -3368,17 +3338,17 @@ handle_status (char *own_buf) /* 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 @@ -3396,7 +3366,7 @@ handle_status (char *own_buf) /* 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); @@ -3411,7 +3381,7 @@ static void gdbserver_version (void) { printf ("GNU gdbserver %s%s\n" - "Copyright (C) 2018 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", @@ -3459,14 +3429,14 @@ gdbserver_usage (FILE *stream) "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" @@ -3493,10 +3463,8 @@ gdbserver_show_disableable (FILE *stream) 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 @@ -3538,35 +3506,34 @@ detach_or_kill_for_exit (void) 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, @@ -3589,6 +3556,8 @@ captured_main (int argc, char *argv[]) #endif current_directory = getcwd (NULL, 0); + client_state &cs = get_client_state (); + if (current_directory == NULL) { error (_("Could not find current working directory: %s"), @@ -3656,6 +3625,8 @@ captured_main (int argc, char *argv[]) } 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); @@ -3663,27 +3634,26 @@ captured_main (int argc, char *argv[]) } 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 { @@ -3703,15 +3673,15 @@ captured_main (int argc, char *argv[]) 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) 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=")) @@ -3790,9 +3760,7 @@ captured_main (int argc, char *argv[]) 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) @@ -3800,7 +3768,7 @@ captured_main (int argc, char *argv[]) #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"); } @@ -3810,7 +3778,7 @@ captured_main (int argc, char *argv[]) int i, n; n = argc - (next_arg - argv); - program_path.set (gdb::unique_xmalloc_ptr (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); @@ -3831,19 +3799,20 @@ captured_main (int argc, char *argv[]) } 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; @@ -3853,22 +3822,21 @@ captured_main (int argc, char *argv[]) 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. */ @@ -3933,21 +3901,20 @@ captured_main (int argc, char *argv[]) } } } - 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 } } @@ -3957,23 +3924,22 @@ int 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"); } @@ -4036,9 +4002,9 @@ process_point_options (struct gdb_breakpoint *bp, const char **packet) 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; @@ -4046,41 +4012,41 @@ process_serial_event (void) disable_async_io (); - response_needed = 0; - packet_len = getpkt (own_buf); + response_needed = false; + packet_len = getpkt (cs.own_buf); if (packet_len <= 0) { remote_close (); /* Force an event loop break. */ return -1; } - response_needed = 1; + response_needed = true; - 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); + extended_protocol = true; + 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; @@ -4091,7 +4057,7 @@ process_serial_event (void) if (thread == NULL) { - write_enn (own_buf); + write_enn (cs.own_buf); break; } @@ -4102,52 +4068,52 @@ process_serial_event (void) /* 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 @@ -4155,85 +4121,87 @@ process_serial_event (void) 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. */ @@ -4242,10 +4210,10 @@ process_serial_event (void) 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); @@ -4273,16 +4241,16 @@ process_serial_event (void) 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': - 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. */ @@ -4296,8 +4264,8 @@ process_serial_event (void) 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 @@ -4305,23 +4273,23 @@ process_serial_event (void) 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': - response_needed = 0; + response_needed = false; /* Restarting the inferior is only supported in the extended protocol. */ @@ -4337,22 +4305,22 @@ process_serial_event (void) { 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; } @@ -4361,28 +4329,28 @@ process_serial_event (void) /* 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; + response_needed = false; if (exit_requested) return -1; @@ -4414,12 +4382,12 @@ handle_serial_event (int err, gdb_client_data client_data) 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. */ @@ -4427,30 +4395,31 @@ push_stop_notification (ptid_t ptid, struct target_waitstatus *status) 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 { @@ -4458,7 +4427,7 @@ handle_target_event (int err, gdb_client_data client_data) "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) @@ -4469,9 +4438,9 @@ handle_target_event (int err, gdb_client_data client_data) 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 { @@ -4483,18 +4452,18 @@ handle_target_event (int err, gdb_client_data client_data) 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.