X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fgdbserver%2Fserver.c;h=3fc026f78ebba4db17134befd3b7607e68ed04ff;hb=e8319fde715960466aca2461c74cec8907abd391;hp=892d76571496a9097fd69839c1f65c334318ca08;hpb=9c80ecd646a604fadcc290fca23b34c9454f5feb;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index 892d765714..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-2017 Free Software Foundation, Inc. + Copyright (C) 1989-2020 Free Software Foundation, Inc. This file is part of GDB. @@ -18,29 +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 "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 ()) \ @@ -56,66 +62,60 @@ break; \ } -/* The environment to pass to the inferior when creating it. */ - -static gdb_environ our_environ; - -/* Start the inferior using a shell. */ - -/* We always try to start the inferior using a shell. */ +/* String containing the current directory (what getwd would return). */ -int startup_with_shell = 1; +char *current_directory; -/* 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 environment to pass to the inferior when creating it. */ -/* The thread set with an `Hg' packet. */ -ptid_t general_thread; +static gdb_environ our_environ; -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; +bool non_stop; -int non_stop; -int swbreak_feature; -int hwbreak_feature; +static struct { + /* Set the PROGRAM_PATH. Here we adjust the path of the provided + binary if needed. */ + void set (gdb::unique_xmalloc_ptr &&path) + { + m_path = std::move (path); -/* 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; + /* Make sure we're using the absolute path of the inferior when + creating it. */ + if (!contains_dir_separator (m_path.get ())) + { + int reg_file_errno; -/* Whether we should attempt to disable the operating system's address - space randomization feature before starting an inferior. */ -int disable_randomization = 1; + /* Check if the file is in our CWD. If it is, then we prefix + its name with CURRENT_DIRECTORY. Otherwise, we leave the + name as-is because we'll try searching for it in $PATH. */ + if (is_regular_file (m_path.get (), ®_file_errno)) + m_path = gdb_abspath (m_path.get ()); + } + } -static char *program_name = NULL; + /* Return the PROGRAM_PATH. */ + char *get () + { return m_path.get (); } + +private: + /* The program name, adjusted if needed. */ + gdb::unique_xmalloc_ptr m_path; +} program_path; 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 @@ -126,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; - -/* Last status reported to GDB. */ -struct target_waitstatus last_status; -ptid_t last_ptid; +bool disable_packet_vCont; +bool disable_packet_Tthread; +bool disable_packet_qC; +bool disable_packet_qfThreadInfo; -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; @@ -157,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. */ @@ -197,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 @@ -209,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. */ @@ -237,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 @@ -252,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 () @@ -260,15 +263,15 @@ 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_name == NULL) + if (err && program_path.get () == NULL) error (_("No executable file specified.")); - return program_name; + return program_path.get (); } /* See server.h. */ @@ -282,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; @@ -298,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. */ @@ -380,50 +385,41 @@ write_qxfer_response (char *buf, const gdb_byte *data, int len, int is_more) /* Handle btrace enabling in BTS format. */ -static const char * +static void handle_btrace_enable_bts (struct thread_info *thread) { if (thread->btrace != NULL) - return "E.Btrace already enabled."; + error (_("Btrace already enabled.")); current_btrace_conf.format = BTRACE_FORMAT_BTS; thread->btrace = target_enable_btrace (thread->id, ¤t_btrace_conf); - if (thread->btrace == NULL) - return "E.Could not enable btrace."; - - return NULL; } /* Handle btrace enabling in Intel Processor Trace format. */ -static const char * +static void handle_btrace_enable_pt (struct thread_info *thread) { if (thread->btrace != NULL) - return "E.Btrace already enabled."; + error (_("Btrace already enabled.")); current_btrace_conf.format = BTRACE_FORMAT_PT; thread->btrace = target_enable_btrace (thread->id, ¤t_btrace_conf); - if (thread->btrace == NULL) - return "E.Could not enable btrace."; - - return NULL; } /* Handle btrace disabling. */ -static const char * +static void handle_btrace_disable (struct thread_info *thread) { if (thread->btrace == NULL) - return "E.Branch tracing not enabled."; + error (_("Branch tracing not enabled.")); if (target_disable_btrace (thread->btrace) != 0) - return "E.Could not disable branch tracing."; + error (_("Could not disable branch tracing.")); thread->btrace = NULL; - return NULL; } /* Handle the "Qbtrace" packet. */ @@ -431,8 +427,8 @@ 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; - const char *err; char *op; if (!startswith (own_buf, "Qbtrace:")) @@ -440,35 +436,37 @@ 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; } - err = NULL; - - if (strcmp (op, "bts") == 0) - err = handle_btrace_enable_bts (thread); - else if (strcmp (op, "pt") == 0) - err = handle_btrace_enable_pt (thread); - else if (strcmp (op, "off") == 0) - err = handle_btrace_disable (thread); - else - err = "E.Bad Qbtrace operation. Use bts, pt, or off."; + try + { + if (strcmp (op, "bts") == 0) + handle_btrace_enable_bts (thread); + else if (strcmp (op, "pt") == 0) + handle_btrace_enable_pt (thread); + else if (strcmp (op, "off") == 0) + handle_btrace_disable (thread); + else + error (_("Bad Qbtrace operation. Use bts, pt, or off.")); - if (err != 0) - strcpy (own_buf, err); - else - write_ok (own_buf); + write_ok (own_buf); + } + catch (const gdb_exception_error &exception) + { + sprintf (own_buf, "E.%s", exception.what ()); + } return 1; } @@ -478,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; @@ -486,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."); @@ -545,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; @@ -556,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; @@ -564,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; @@ -576,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; @@ -591,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; @@ -623,7 +623,7 @@ handle_general_set (char *own_buf) } process = current_process (); - VEC_truncate (int, process->syscalls_to_catch, 0); + process->syscalls_to_catch.clear (); if (enabled) { @@ -634,11 +634,11 @@ handle_general_set (char *own_buf) while (*p != '\0') { p = decode_address_to_semicolon (&sysno, p); - VEC_safe_push (int, process->syscalls_to_catch, (int) sysno); + process->syscalls_to_catch.push_back (sysno); } } else - VEC_safe_push (int, process->syscalls_to_catch, ANY_SYSCALL); + process->syscalls_to_catch.push_back (ANY_SYSCALL); } write_ok (own_buf); @@ -714,7 +714,7 @@ handle_general_set (char *own_buf) debug_flush (); } - noack_mode = 1; + cs.noack_mode = 1; write_ok (own_buf); return; } @@ -747,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); @@ -762,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"); } @@ -820,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); } @@ -916,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; @@ -926,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. */ @@ -974,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. */ @@ -1014,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 { @@ -1024,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 (); @@ -1189,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"); @@ -1231,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); } @@ -1244,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 ()) @@ -1258,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; } @@ -1282,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. @@ -1295,13 +1301,9 @@ handle_detach (char *own_buf) to gdb's "set debug foo on|off" because we also use this function to parse "--debug-format=foo,bar". */ -static char * +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; @@ -1309,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) @@ -1337,17 +1340,11 @@ parse_debug_format_options (const char *arg, int is_monitor) continue; } else - { - char *msg = xstrprintf ("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 NULL; + return std::string (); } /* Handle monitor commands not handled by target-specific handlers. */ @@ -1387,22 +1384,25 @@ handle_monitor_command (char *mon, char *own_buf) } else if (startswith (mon, "set debug-format ")) { - char *error_msg + std::string error_msg = parse_debug_format_options (mon + sizeof ("set debug-format ") - 1, 1); - if (error_msg != NULL) + if (!error_msg.empty ()) { - monitor_output (error_msg); + monitor_output (error_msg.c_str ()); monitor_show_help (); write_enn (own_buf); - xfree (error_msg); } } + 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"); @@ -1548,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"; @@ -1609,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 @@ -1632,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; @@ -1650,9 +1636,8 @@ handle_qxfer_statictrace (const char *annex, Emit the XML to describe the thread of INF. */ static void -handle_qxfer_threads_worker (thread_info *thread, void *arg) +handle_qxfer_threads_worker (thread_info *thread, struct buffer *buffer) { - struct buffer *buffer = (struct buffer *) arg; ptid_t ptid = ptid_of (thread); char ptid_s[100]; int core = target_core_of_thread (ptid); @@ -1692,8 +1677,10 @@ handle_qxfer_threads_proper (struct buffer *buffer) { buffer_grow_str (buffer, "\n"); - for_each_inferior_with_data (&all_threads, handle_qxfer_threads_worker, - buffer); + for_each_thread ([&] (thread_info *thread) + { + handle_qxfer_threads_worker (thread, buffer); + }); buffer_grow_str0 (buffer, "\n"); } @@ -1755,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) @@ -1775,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); @@ -1820,31 +1808,32 @@ 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; int result; - if (the_target->read_btrace == NULL || writebuf != NULL) + 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; } @@ -1856,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; } @@ -1864,12 +1853,20 @@ handle_qxfer_btrace (const char *annex, { buffer_free (&cache); - result = target_read_btrace (thread->btrace, &cache, type); - if (result != 0) + try + { + result = target_read_btrace (thread->btrace, &cache, type); + if (result != 0) + memcpy (cs.own_buf, cache.buffer, cache.used_size); + } + catch (const gdb_exception_error &exception) { - memcpy (own_buf, cache.buffer, cache.used_size); - return -3; + sprintf (cs.own_buf, "E.%s", exception.what ()); + result = -1; } + + if (result != 0) + return -3; } else if (offset > cache.used_size) { @@ -1892,33 +1889,34 @@ 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; - if (the_target->read_btrace_conf == NULL || writebuf != NULL) + if (writebuf != NULL) return -2; 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; } @@ -1926,12 +1924,20 @@ handle_qxfer_btrace_conf (const char *annex, { buffer_free (&cache); - result = target_read_btrace_conf (thread->btrace, &cache); - if (result != 0) + try { - memcpy (own_buf, cache.buffer, cache.used_size); - return -3; + result = target_read_btrace_conf (thread->btrace, &cache); + if (result != 0) + memcpy (cs.own_buf, cache.buffer, cache.used_size); } + catch (const gdb_exception_error &exception) + { + sprintf (cs.own_buf, "E.%s", exception.what ()); + result = -1; + } + + if (result != 0) + return -3; } else if (offset > cache.used_size) { @@ -1959,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 }, @@ -2111,27 +2116,10 @@ crc32 (CORE_ADDR base, int len, unsigned int crc) static void supported_btrace_packets (char *buf) { - int btrace_supported = 0; - - if (target_supports_btrace (BTRACE_FORMAT_BTS)) - { - strcat (buf, ";Qbtrace:bts+"); - strcat (buf, ";Qbtrace-conf:bts:size+"); - - btrace_supported = 1; - } - - if (target_supports_btrace (BTRACE_FORMAT_PT)) - { - strcat (buf, ";Qbtrace:pt+"); - strcat (buf, ";Qbtrace-conf:pt:size+"); - - btrace_supported = 1; - } - - if (!btrace_supported) - return; - + strcat (buf, ";Qbtrace:bts+"); + strcat (buf, ";Qbtrace-conf:bts:size+"); + strcat (buf, ";Qbtrace:pt+"); + strcat (buf, ";Qbtrace-conf:pt:size+"); strcat (buf, ";Qbtrace:off+"); strcat (buf, ";qXfer:btrace:read+"); strcat (buf, ";qXfer:btrace-conf:read+"); @@ -2142,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. */ @@ -2150,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 (); @@ -2176,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. */ @@ -2279,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); @@ -2296,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) { @@ -2309,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 { @@ -2387,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+"); @@ -2402,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) @@ -2677,46 +2664,33 @@ static void resume (struct thread_resume *actions, size_t n); typedef int (visit_actioned_threads_callback_ftype) (const struct thread_resume *, struct thread_info *); -/* Struct to pass data to visit_actioned_threads. */ - -struct visit_actioned_threads_data -{ - const struct thread_resume *actions; - size_t num_actions; - visit_actioned_threads_callback_ftype *callback; -}; - /* Call CALLBACK for any thread to which ACTIONS applies to. Returns true if CALLBACK returns true. Returns false if no matching thread is found or CALLBACK results false. - Note: This function is itself a callback for find_inferior. */ + Note: This function is itself a callback for find_thread. */ -static int -visit_actioned_threads (thread_info *thread, void *datap) +static bool +visit_actioned_threads (thread_info *thread, + const struct thread_resume *actions, + size_t num_actions, + visit_actioned_threads_callback_ftype *callback) { - struct visit_actioned_threads_data *data - = (struct visit_actioned_threads_data *) datap; - const struct thread_resume *actions = data->actions; - size_t num_actions = data->num_actions; - visit_actioned_threads_callback_ftype *callback = data->callback; - size_t i; - - for (i = 0; i < num_actions; i++) + for (size_t i = 0; i < num_actions; i++) { 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 1; + return true; } } - return 0; + return false; } /* Callback for visit_actioned_threads. If the thread has a pending @@ -2726,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; @@ -2852,18 +2827,21 @@ 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 one with a pending status to report. If so, skip actually resuming/stopping and report the pending event immediately. */ - struct visit_actioned_threads_data data; - data.actions = actions; - data.num_actions = num_actions; - data.callback = handle_pending_status; - if (find_inferior (&all_threads, visit_actioned_threads, &data) != NULL) + thread_info *thread_with_status = find_thread ([&] (thread_info *thread) + { + return visit_actioned_threads (thread, actions, num_actions, + handle_pending_status); + }); + + if (thread_with_status != NULL) return; enable_async_io (); @@ -2872,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); } } @@ -2910,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); @@ -2929,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; } @@ -2944,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; @@ -3034,7 +3014,7 @@ handle_v_run (char *own_buf) { /* GDB didn't specify a program to run. Use the program from the last run with the new argument list. */ - if (program_name == NULL) + if (program_path.get () == NULL) { write_enn (own_buf); free_vector_argv (new_argv); @@ -3042,26 +3022,23 @@ handle_v_run (char *own_buf) } } else - { - xfree (program_name); - program_name = new_program_name; - } + program_path.set (gdb::unique_xmalloc_ptr (new_program_name)); /* Free the old argv and install the new one. */ free_vector_argv (program_args); program_args = new_argv; - create_inferior (program_name, program_args); + 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; } @@ -3076,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; } @@ -3102,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) @@ -3123,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 @@ -3149,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); @@ -3161,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); @@ -3198,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) { @@ -3227,24 +3210,23 @@ myresume (char *own_buf, int step, int sig) resume (resume_info, n); } -/* Callback for for_each_inferior. Make a new stop reply for each +/* Callback for for_each_thread. Make a new stop reply for each stopped thread. */ -static int -queue_stop_reply_callback (thread_info *thread, void *arg) +static void +queue_stop_reply_callback (thread_info *thread) { /* 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) { - 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 { @@ -3267,8 +3249,6 @@ queue_stop_reply_callback (thread_info *thread, void *arg) queue_stop_reply (thread->id, &thread->last_status); } } - - return 0; } /* Set this inferior threads's state as "want-stopped". We won't @@ -3294,19 +3274,10 @@ gdb_wants_thread_stopped (thread_info *thread) static void gdb_wants_all_threads_stopped (void) { - for_each_inferior (&all_threads, gdb_wants_thread_stopped); + for_each_thread (gdb_wants_thread_stopped); } -/* Callback for for_each_inferior. Clear the thread's pending status - flag. */ - -static void -clear_pending_status_callback (thread_info *thread) -{ - thread->status_pending_p = 0; -} - -/* Callback for for_each_inferior. If the thread is stopped with an +/* Callback for for_each_thread. If the thread is stopped with an interesting event, mark it as having a pending event. */ static void @@ -3324,20 +3295,13 @@ set_pending_status_callback (thread_info *thread) thread->status_pending_p = 1; } -/* Callback for find_inferior. Return true if ENTRY (a thread) has a - pending status to report to GDB. */ - -static int -find_status_pending_thread_callback (thread_info *thread, void *data) -{ - return thread->status_pending_p; -} - /* Status handler for the '?' packet. */ 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; @@ -3349,12 +3313,12 @@ handle_status (char *own_buf) if (non_stop) { - find_inferior (&all_threads, queue_stop_reply_callback, NULL); + for_each_thread (queue_stop_reply_callback); /* 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 { @@ -3370,20 +3334,22 @@ handle_status (char *own_buf) reporting now pending. They'll be reported the next time the threads are resumed. Start by marking all interesting events as pending. */ - for_each_inferior (&all_threads, set_pending_status_callback); + for_each_thread (set_pending_status_callback); /* 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_inferior_id (&all_threads, 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_inferior (&all_threads, - find_status_pending_thread_callback, NULL); + thread = find_thread ([] (thread_info *thr_arg) + { + return thr_arg->status_pending_p; + }); /* If we're still out of luck, simply pick the first thread in the thread list. */ @@ -3400,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); @@ -3415,7 +3381,7 @@ static void gdbserver_version (void) { printf ("GNU gdbserver %s%s\n" - "Copyright (C) 2017 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", @@ -3463,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" @@ -3497,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 @@ -3542,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, @@ -3588,7 +3551,18 @@ captured_main (int argc, char *argv[]) volatile int attach = 0; int was_running; bool selftest = false; +#if GDB_SELF_TEST const char *selftest_filter = NULL; +#endif + + current_directory = getcwd (NULL, 0); + client_state &cs = get_client_state (); + + if (current_directory == NULL) + { + error (_("Could not find current working directory: %s"), + safe_strerror (errno)); + } while (*next_arg != NULL && **next_arg == '-') { @@ -3639,18 +3613,20 @@ captured_main (int argc, char *argv[]) debug_threads = 1; else if (startswith (*next_arg, "--debug-format=")) { - char *error_msg + std::string error_msg = parse_debug_format_options ((*next_arg) + sizeof ("--debug-format=") - 1, 0); - if (error_msg != NULL) + if (!error_msg.empty ()) { - fprintf (stderr, "%s", error_msg); + fprintf (stderr, "%s", error_msg.c_str ()); exit (1); } } 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); @@ -3658,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 { @@ -3698,21 +3673,23 @@ 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=")) { selftest = true; +#if GDB_SELF_TEST selftest_filter = *next_arg + strlen ("--selftest="); +#endif } else { @@ -3740,7 +3717,7 @@ captured_main (int argc, char *argv[]) opened by remote_prepare. */ notice_open_fds (); - save_original_signals_state (); + save_original_signals_state (false); /* We need to know whether the remote connection is stdio before starting the inferior. Inferiors created in this scenario have @@ -3783,14 +3760,16 @@ 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) { +#if GDB_SELF_TEST selftests::run_tests (selftest_filter); +#else + printf (_("Selftests have been disabled for this build.\n")); +#endif throw_quit ("Quit"); } @@ -3799,13 +3778,13 @@ captured_main (int argc, char *argv[]) int i, n; n = argc - (next_arg - argv); - program_name = 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); /* Wait till we are at first instruction in program. */ - create_inferior (program_name, program_args); + create_inferior (program_path.get (), program_args); /* We are now (hopefully) stopped at the first instruction of the target process. This assumes that the target process was @@ -3820,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; @@ -3842,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. */ @@ -3889,8 +3868,10 @@ captured_main (int argc, char *argv[]) (by the same GDB instance or another) will refresh all its state from scratch. */ discard_queued_stop_replies (minus_one_ptid); - for_each_inferior (&all_threads, - clear_pending_status_callback); + for_each_thread ([] (thread_info *thread) + { + thread->status_pending_p = 0; + }); if (tracing) { @@ -3920,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 } } @@ -3944,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"); } @@ -4023,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; @@ -4033,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; @@ -4078,7 +4057,7 @@ process_serial_event (void) if (thread == NULL) { - write_enn (own_buf); + write_enn (cs.own_buf); break; } @@ -4089,54 +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. */ - struct thread_info *thread = - (struct thread_info *) find_inferior_id (&all_threads, - 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 @@ -4144,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. */ @@ -4231,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); @@ -4262,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. */ @@ -4285,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 @@ -4294,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. */ @@ -4322,26 +4301,26 @@ process_serial_event (void) fprintf (stderr, "GDBserver restarting\n"); /* Wait till we are at 1st instruction in prog. */ - if (program_name != NULL) + if (program_path.get () != NULL) { - create_inferior (program_name, program_args); + 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; } @@ -4350,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; @@ -4403,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. */ @@ -4416,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 { @@ -4447,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) @@ -4458,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 { @@ -4472,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.