X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fremote.c;h=c73eb6e9e136f4d611aeb631b3641ceda5b238b1;hb=a350efd4fb368a35ada608f6bc26ccd3bed0ae6b;hp=4e2f82a68d5dc3551c843164d6d87dcde5f991e8;hpb=39ef2f6256737db92f5d60fa201fe0b301bb8100;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/remote.c b/gdb/remote.c index 4e2f82a68d..c73eb6e9e1 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -1,6 +1,6 @@ /* Remote target communications for serial-line targets in custom GDB protocol - Copyright (C) 1988-2019 Free Software Foundation, Inc. + Copyright (C) 1988-2020 Free Software Foundation, Inc. This file is part of GDB. @@ -49,7 +49,7 @@ #include "gdbsupport/gdb_sys_time.h" -#include "event-loop.h" +#include "gdbsupport/event-loop.h" #include "event-top.h" #include "inf-loop.h" @@ -77,6 +77,7 @@ #include "gdbsupport/byte-vector.h" #include #include +#include "async-event.h" /* The remote target. */ @@ -278,6 +279,9 @@ public: /* data */ /* The status of the stub support for the various vCont actions. */ vCont_action_support supports_vCont; + /* Whether vCont support was probed already. This is a workaround + until packet_support is per-connection. */ + bool supports_vCont_probed; /* True if the user has pressed Ctrl-C, but the target hasn't responded to that. */ @@ -403,6 +407,8 @@ public: const target_info &info () const override { return remote_target_info; } + const char *connection_string () override; + thread_control_capabilities get_thread_control_capabilities () override { return tc_schedlock; } @@ -537,6 +543,8 @@ public: void async (int) override; + int async_wait_fd () override; + void thread_events (int) override; int can_do_single_step () override; @@ -667,7 +675,7 @@ public: const struct btrace_config *btrace_conf (const struct btrace_target_info *) override; bool augmented_libraries_svr4_read () override; - int follow_fork (int, int) override; + bool follow_fork (bool, bool) override; void follow_exec (struct inferior *, const char *) override; int insert_fork_catchpoint (int) override; int remove_fork_catchpoint (int) override; @@ -1026,7 +1034,7 @@ static void remote_console_output (const char *msg); static void remote_btrace_reset (remote_state *rs); -static void remote_unpush_and_throw (void); +static void remote_unpush_and_throw (remote_target *target); /* For "remote". */ @@ -1041,11 +1049,6 @@ static struct cmd_list_element *remote_show_cmdlist; static bool use_range_stepping = true; -/* The max number of chars in debug output. The rest of chars are - omitted. */ - -#define REMOTE_DEBUG_MAX_CHAR 512 - /* Private data that we'll store in (struct thread_info)->priv. */ struct remote_thread_info : public private_thread_info { @@ -1273,7 +1276,7 @@ static void show_remote_exec_file (struct ui_file *file, int from_tty, struct cmd_list_element *cmd, const char *value) { - fprintf_filtered (file, "%s\n", remote_exec_file_var); + fprintf_filtered (file, "%s\n", get_remote_exec_file ()); } static int @@ -1381,7 +1384,7 @@ remote_arch_state::remote_arch_state (struct gdbarch *gdbarch) static remote_target * get_current_remote_target () { - target_ops *proc_target = find_target_at (process_stratum); + target_ops *proc_target = current_inferior ()->process_target (); return dynamic_cast (proc_target); } @@ -1662,6 +1665,7 @@ show_memory_packet_size (struct memory_packet_config *config) } } +/* FIXME: needs to be per-remote-target. */ static struct memory_packet_config memory_write_packet_config = { "memory-write-packet-size", @@ -1712,12 +1716,30 @@ show_hardware_breakpoint_limit (struct ui_file *file, int from_tty, "breakpoints is %s.\n"), value); } +/* Controls the maximum number of characters to display in the debug output + for each remote packet. The remaining characters are omitted. */ + +static int remote_packet_max_chars = 512; + +/* Show the maximum number of characters to display for each remote packet + when remote debugging is enabled. */ + +static void +show_remote_packet_max_chars (struct ui_file *file, int from_tty, + struct cmd_list_element *c, + const char *value) +{ + fprintf_filtered (file, _("Number of remote packet characters to " + "display is %s.\n"), value); +} + long remote_target::get_memory_write_packet_size () { return get_memory_packet_size (&memory_write_packet_config); } +/* FIXME: needs to be per-remote-target. */ static struct memory_packet_config memory_read_packet_config = { "memory-read-packet-size", @@ -2074,6 +2096,9 @@ enum { PACKET_MAX }; +/* FIXME: needs to be per-remote-target. Ignoring this for now, + assuming all remote targets are the same server (thus all support + the same packets). */ static struct packet_config remote_protocol_packets[PACKET_MAX]; /* Returns the packet's corresponding "set remote foo-packet" command @@ -2355,6 +2380,27 @@ remote_target::remote_add_inferior (bool fake_pid_p, int pid, int attached, between program/address spaces. We simply bind the inferior to the program space's address space. */ inf = current_inferior (); + + /* However, if the current inferior is already bound to a + process, find some other empty inferior. */ + if (inf->pid != 0) + { + inf = nullptr; + for (inferior *it : all_inferiors ()) + if (it->pid == 0) + { + inf = it; + break; + } + } + if (inf == nullptr) + { + /* Since all inferiors were already bound to a process, add + a new inferior. */ + inf = add_inferior_with_spaces (); + } + switch_to_inferior_no_thread (inf); + push_target (this); inferior_appeared (inf, pid); } @@ -2366,11 +2412,15 @@ remote_target::remote_add_inferior (bool fake_pid_p, int pid, int attached, if (try_open_exec && get_exec_file (0) == NULL) exec_file_locate_attach (pid, 0, 1); + /* Check for exec file mismatch, and let the user solve it. */ + validate_exec_file (1); + return inf; } static remote_thread_info *get_remote_thread_info (thread_info *thread); -static remote_thread_info *get_remote_thread_info (ptid_t ptid); +static remote_thread_info *get_remote_thread_info (remote_target *target, + ptid_t ptid); /* Add thread PTID to GDB's thread list. Tag it as executing/running according to RUNNING. */ @@ -2388,13 +2438,13 @@ remote_target::remote_add_thread (ptid_t ptid, bool running, bool executing) might be confusing to the user. Be silent then, preserving the age old behavior. */ if (rs->starting_up) - thread = add_thread_silent (ptid); + thread = add_thread_silent (this, ptid); else - thread = add_thread (ptid); + thread = add_thread (this, ptid); get_remote_thread_info (thread)->vcont_resumed = executing; - set_executing (ptid, executing); - set_running (ptid, running); + set_executing (this, ptid, executing); + set_running (this, ptid, running); return thread; } @@ -2417,7 +2467,7 @@ remote_target::remote_notice_new_inferior (ptid_t currthread, int executing) /* If this is a new thread, add it to GDB's thread list. If we leave it up to WFI to do this, bad things will happen. */ - thread_info *tp = find_thread_ptid (currthread); + thread_info *tp = find_thread_ptid (this, currthread); if (tp != NULL && tp->state == THREAD_EXITED) { /* We're seeing an event on a thread id we knew had exited. @@ -2426,7 +2476,7 @@ remote_target::remote_notice_new_inferior (ptid_t currthread, int executing) return; } - if (!in_thread_list (currthread)) + if (!in_thread_list (this, currthread)) { struct inferior *inf = NULL; int pid = currthread.pid (); @@ -2439,8 +2489,8 @@ remote_target::remote_notice_new_inferior (ptid_t currthread, int executing) stub doesn't support qC. This is the first stop reported after an attach, so this is the main thread. Update the ptid in the thread list. */ - if (in_thread_list (ptid_t (pid))) - thread_change_ptid (inferior_ptid, currthread); + if (in_thread_list (this, ptid_t (pid))) + thread_change_ptid (this, inferior_ptid, currthread); else { remote_add_thread (currthread, running, executing); @@ -2456,7 +2506,7 @@ remote_target::remote_notice_new_inferior (ptid_t currthread, int executing) doesn't support qC. This is the first stop reported after an attach, so this is the main thread. Update the ptid in the thread list. */ - thread_change_ptid (inferior_ptid, currthread); + thread_change_ptid (this, inferior_ptid, currthread); return; } @@ -2464,7 +2514,7 @@ remote_target::remote_notice_new_inferior (ptid_t currthread, int executing) extended-remote which already was debugging an inferior, we may not know about it yet. Add it before adding its child thread, so notifications are emitted in a sensible order. */ - if (find_inferior_pid (currthread.pid ()) == NULL) + if (find_inferior_pid (this, currthread.pid ()) == NULL) { struct remote_state *rs = get_remote_state (); bool fake_pid_p = !remote_multi_process_p (rs); @@ -2504,10 +2554,12 @@ get_remote_thread_info (thread_info *thread) return static_cast (thread->priv.get ()); } +/* Return PTID's private thread data, creating it if necessary. */ + static remote_thread_info * -get_remote_thread_info (ptid_t ptid) +get_remote_thread_info (remote_target *target, ptid_t ptid) { - thread_info *thr = find_thread_ptid (ptid); + thread_info *thr = find_thread_ptid (target, ptid); return get_remote_thread_info (thr); } @@ -2563,8 +2615,7 @@ remote_target::pass_signals (gdb::array_view pass_signals) putpkt (pass_packet); getpkt (&rs->buf, 0); packet_ok (rs->buf, &remote_protocol_packets[PACKET_QPassSignals]); - if (rs->last_pass_packet) - xfree (rs->last_pass_packet); + xfree (rs->last_pass_packet); rs->last_pass_packet = pass_packet; } else @@ -2829,7 +2880,7 @@ remote_target::thread_name (struct thread_info *info) /* About these extended threadlist and threadinfo packets. They are variable length packets but, the fields within them are often fixed - length. They are redundent enough to send over UDP as is the + length. They are redundant enough to send over UDP as is the remote protocol in general. There is a matching unit test module in libstub. */ @@ -3733,6 +3784,18 @@ remote_target::remote_get_threads_with_qthreadinfo (threads_listing_context *con return 0; } +/* Return true if INF only has one non-exited thread. */ + +static bool +has_single_non_exited_thread (inferior *inf) +{ + int count = 0; + for (thread_info *tp ATTRIBUTE_UNUSED : inf->non_exited_threads ()) + if (++count > 1) + break; + return count == 1; +} + /* Implement the to_update_thread_list function for the remote targets. */ @@ -3767,8 +3830,19 @@ remote_target::update_thread_list () target. */ for (thread_info *tp : all_threads_safe ()) { + if (tp->inf->process_target () != this) + continue; + if (!context.contains_thread (tp->ptid)) { + /* Do not remove the thread if it is the last thread in + the inferior. This situation happens when we have a + pending exit process status to process. Otherwise we + may end up with a seemingly live inferior (i.e. pid + != 0) that has no threads. */ + if (has_single_non_exited_thread (tp->inf)) + continue; + /* Not found. */ delete_thread (tp); } @@ -3792,7 +3866,7 @@ remote_target::update_thread_list () remote_notice_new_inferior (item.ptid, executing); - thread_info *tp = find_thread_ptid (item.ptid); + thread_info *tp = find_thread_ptid (this, item.ptid); remote_thread_info *info = get_remote_thread_info (tp); info->core = item.core; info->extra = std::move (item.extra); @@ -3994,13 +4068,6 @@ remote_target::close () /* Make sure we leave stdin registered in the event loop. */ terminal_ours (); - /* We don't have a connection to the remote stub anymore. Get rid - of all the inferiors and their threads we were controlling. - Reset inferior_ptid to null_ptid first, as otherwise has_stack_frame - will be unable to find the thread corresponding to (pid, 0, 0). */ - inferior_ptid = null_ptid; - discard_all_inferiors (); - trace_reset_local_state (); delete this; @@ -4037,8 +4104,6 @@ remote_target::get_offsets () char *ptr; int lose, num_segments = 0, do_sections, do_segments; CORE_ADDR text_addr, data_addr, bss_addr, segments[2]; - struct section_offsets *offs; - struct symfile_segment_data *data; if (symfile_objfile == NULL) return; @@ -4116,12 +4181,10 @@ remote_target::get_offsets () else if (*ptr != '\0') warning (_("Target reported unsupported offsets: %s"), buf); - offs = ((struct section_offsets *) - alloca (SIZEOF_N_SECTION_OFFSETS (symfile_objfile->num_sections))); - memcpy (offs, symfile_objfile->section_offsets, - SIZEOF_N_SECTION_OFFSETS (symfile_objfile->num_sections)); + section_offsets offs = symfile_objfile->section_offsets; - data = get_symfile_segment_data (symfile_objfile->obfd); + symfile_segment_data_up data + = get_symfile_segment_data (symfile_objfile->obfd); do_segments = (data != NULL); do_sections = num_segments == 0; @@ -4134,10 +4197,10 @@ remote_target::get_offsets () by assuming that the .text and .data offsets apply to the whole text and data segments. Convert the offsets given in the packet to base addresses for symfile_map_offsets_to_segments. */ - else if (data && data->num_segments == 2) + else if (data != nullptr && data->segments.size () == 2) { - segments[0] = data->segment_bases[0] + text_addr; - segments[1] = data->segment_bases[1] + data_addr; + segments[0] = data->segments[0].base + text_addr; + segments[1] = data->segments[1].base + data_addr; num_segments = 2; } /* If the object file has only one segment, assume that it is text @@ -4145,9 +4208,9 @@ remote_target::get_offsets () but programs with no code are useless. Of course the code might have ended up in the data segment... to detect that we would need the permissions here. */ - else if (data && data->num_segments == 1) + else if (data && data->segments.size () == 1) { - segments[0] = data->segment_bases[0] + text_addr; + segments[0] = data->segments[0].base + text_addr; num_segments = 1; } /* There's no way to relocate by segment. */ @@ -4156,8 +4219,9 @@ remote_target::get_offsets () if (do_segments) { - int ret = symfile_map_offsets_to_segments (symfile_objfile->obfd, data, - offs, num_segments, segments); + int ret = symfile_map_offsets_to_segments (symfile_objfile->obfd, + data.get (), offs, + num_segments, segments); if (ret == 0 && !do_sections) error (_("Can not handle qOffsets TextSeg " @@ -4167,20 +4231,17 @@ remote_target::get_offsets () do_sections = 0; } - if (data) - free_symfile_segment_data (data); - if (do_sections) { - offs->offsets[SECT_OFF_TEXT (symfile_objfile)] = text_addr; + offs[SECT_OFF_TEXT (symfile_objfile)] = text_addr; /* This is a temporary kludge to force data and bss to use the same offsets because that's what nlmconv does now. The real solution requires changes to the stub and remote.c that I don't have time to do right now. */ - offs->offsets[SECT_OFF_DATA (symfile_objfile)] = data_addr; - offs->offsets[SECT_OFF_BSS (symfile_objfile)] = data_addr; + offs[SECT_OFF_DATA (symfile_objfile)] = data_addr; + offs[SECT_OFF_BSS (symfile_objfile)] = data_addr; } objfile_relocate (symfile_objfile, offs); @@ -4310,7 +4371,7 @@ remote_target::add_current_inferior_and_thread (char *wait_status) /* Add the main thread and switch to it. Don't try reading registers yet, since we haven't fetched the target description yet. */ - thread_info *tp = add_thread_silent (curr_ptid); + thread_info *tp = add_thread_silent (this, curr_ptid); switch_to_thread_no_regs (tp); } @@ -4386,7 +4447,7 @@ remote_target::process_initial_stop_replies (int from_tty) if (ignore_event) continue; - struct thread_info *evthread = find_thread_ptid (event_ptid); + thread_info *evthread = find_thread_ptid (this, event_ptid); if (ws.kind == TARGET_WAITKIND_STOPPED) { @@ -4406,14 +4467,14 @@ remote_target::process_initial_stop_replies (int from_tty) || ws.value.sig != GDB_SIGNAL_0) evthread->suspend.waitstatus_pending_p = 1; - set_executing (event_ptid, 0); - set_running (event_ptid, 0); + set_executing (this, event_ptid, false); + set_running (this, event_ptid, false); get_remote_thread_info (evthread)->vcont_resumed = 0; } /* "Notice" the new inferiors before anything related to registers/memory. */ - for (inferior *inf : all_non_exited_inferiors ()) + for (inferior *inf : all_non_exited_inferiors (this)) { inf->needs_setup = 1; @@ -4434,7 +4495,7 @@ remote_target::process_initial_stop_replies (int from_tty) /* If all threads of an inferior were already stopped, we haven't setup the inferior yet. */ - for (inferior *inf : all_non_exited_inferiors ()) + for (inferior *inf : all_non_exited_inferiors (this)) { if (inf->needs_setup) { @@ -4448,7 +4509,7 @@ remote_target::process_initial_stop_replies (int from_tty) /* Now go over all threads that are stopped, and print their current frame. If all-stop, then if there's a signalled thread, pick that as current. */ - for (thread_info *thread : all_non_exited_threads ()) + for (thread_info *thread : all_non_exited_threads (this)) { if (first == NULL) first = thread; @@ -4487,7 +4548,7 @@ remote_target::process_initial_stop_replies (int from_tty) /* For "info program". */ thread_info *thread = inferior_thread (); if (thread->state == THREAD_STOPPED) - set_last_target_status (inferior_ptid, thread->suspend.waitstatus); + set_last_target_status (this, inferior_ptid, thread->suspend.waitstatus); } /* Start the remote connection and sync state. */ @@ -4660,7 +4721,7 @@ remote_target::start_remote (int from_tty, int extended_p) /* Let the stub know that we want it to return the thread. */ set_continue_thread (minus_one_ptid); - if (thread_count () == 0) + if (thread_count (this) == 0) { /* Target has no concept of threads at all. GDB treats non-threaded target as single-threaded; add a main @@ -4673,8 +4734,8 @@ remote_target::start_remote (int from_tty, int extended_p) says should be current. If we're reconnecting to a multi-threaded program, this will ideally be the thread that last reported an event before GDB disconnected. */ - inferior_ptid = get_current_thread (wait_status); - if (inferior_ptid == null_ptid) + ptid_t curr_thread = get_current_thread (wait_status); + if (curr_thread == null_ptid) { /* Odd... The target was able to list threads, but not tell us which thread was current (no "thread" @@ -4686,8 +4747,15 @@ remote_target::start_remote (int from_tty, int extended_p) "warning: couldn't determine remote " "current thread; picking first in list.\n"); - inferior_ptid = inferior_list->thread_list->ptid; + for (thread_info *tp : all_non_exited_threads (this, + minus_one_ptid)) + { + switch_to_thread (tp); + break; + } } + else + switch_to_thread (find_thread_ptid (this, curr_thread)); } /* init_wait_for_inferior should be called before get_offsets in order @@ -4746,7 +4814,7 @@ remote_target::start_remote (int from_tty, int extended_p) remote_notif_get_pending_events (notif); } - if (thread_count () == 0) + if (thread_count (this) == 0) { if (!extended_p) error (_("The target is not running (try extended-remote?)")); @@ -4808,6 +4876,17 @@ remote_target::start_remote (int from_tty, int extended_p) insert_breakpoints (); } +const char * +remote_target::connection_string () +{ + remote_state *rs = get_remote_state (); + + if (rs->remote_desc->name != NULL) + return rs->remote_desc->name; + else + return NULL; +} + /* Open a connection to a remote debugger. NAME is the filename used for communication. */ @@ -5044,7 +5123,7 @@ remote_target::remote_packet_size (const protocol_feature *feature, rs->explicit_packet_size = packet_size; } -void +static void remote_packet_size (remote_target *remote, const protocol_feature *feature, enum packet_support support, const char *value) { @@ -5169,7 +5248,8 @@ register_remote_support_xml (const char *xml) else { char *copy = xstrdup (remote_support_xml + 13); - char *p = strtok (copy, ","); + char *saveptr; + char *p = strtok_r (copy, ",", &saveptr); do { @@ -5180,7 +5260,7 @@ register_remote_support_xml (const char *xml) return; } } - while ((p = strtok (NULL, ",")) != NULL); + while ((p = strtok_r (NULL, ",", &saveptr)) != NULL); xfree (copy); remote_support_xml = reconcat (remote_support_xml, @@ -5399,7 +5479,7 @@ remote_target::remote_serial_quit_handler () { if (query (_("The target is not responding to GDB commands.\n" "Stop debugging it? "))) - remote_unpush_and_throw (); + remote_unpush_and_throw (this); } /* If ^C has already been sent once, offer to disconnect. */ else if (!target_terminal::is_ours () && rs->ctrlc_pending_p) @@ -5423,19 +5503,29 @@ remote_serial_quit_handler () curr_quit_handler_target->remote_serial_quit_handler (); } -/* Remove any of the remote.c targets from target stack. Upper targets depend - on it so remove them first. */ +/* Remove the remote target from the target stack of each inferior + that is using it. Upper targets depend on it so remove them + first. */ static void -remote_unpush_target (void) +remote_unpush_target (remote_target *target) { - pop_all_targets_at_and_above (process_stratum); + /* We have to unpush the target from all inferiors, even those that + aren't running. */ + scoped_restore_current_inferior restore_current_inferior; + + for (inferior *inf : all_inferiors (target)) + { + switch_to_inferior_no_thread (inf); + pop_all_targets_at_and_above (process_stratum); + generic_mourn_inferior (); + } } static void -remote_unpush_and_throw (void) +remote_unpush_and_throw (remote_target *target) { - remote_unpush_target (); + remote_unpush_target (target); throw_error (TARGET_CLOSE_ERROR, _("Disconnected from target.")); } @@ -5452,7 +5542,7 @@ remote_target::open_1 (const char *name, int from_tty, int extended_p) /* If we're connected to a running target, target_preopen will kill it. Ask this question first, before target_preopen has a chance to kill anything. */ - if (curr_remote != NULL && !have_inferiors ()) + if (curr_remote != NULL && !target_has_execution) { if (from_tty && !query (_("Already connected to a remote target. Disconnect? "))) @@ -5581,7 +5671,7 @@ remote_target::open_1 (const char *name, int from_tty, int extended_p) /* Pop the partially set up target - unless something else did already before throwing the exception. */ if (ex.error != TARGET_CLOSE_ERROR) - remote_unpush_target (); + remote_unpush_target (remote); throw; } } @@ -5645,10 +5735,10 @@ remote_target::remote_detach_1 (inferior *inf, int from_tty) remote_detach_pid (pid); /* Exit only if this is the only active inferior. */ - if (from_tty && !rs->extended && number_of_live_inferiors () == 1) + if (from_tty && !rs->extended && number_of_live_inferiors (this) == 1) puts_filtered (_("Ending remote debugging.\n")); - struct thread_info *tp = find_thread_ptid (inferior_ptid); + thread_info *tp = find_thread_ptid (this, inferior_ptid); /* Check to see if we are detaching a fork parent. Note that if we are detaching a fork child, tp == NULL. */ @@ -5694,8 +5784,8 @@ extended_remote_target::detach (inferior *inf, int from_tty) it is named remote_follow_fork in anticipation of using it for the remote target as well. */ -int -remote_target::follow_fork (int follow_child, int detach_fork) +bool +remote_target::follow_fork (bool follow_child, bool detach_fork) { struct remote_state *rs = get_remote_state (); enum target_waitkind kind = inferior_thread ()->pending_follow.kind; @@ -5721,7 +5811,8 @@ remote_target::follow_fork (int follow_child, int detach_fork) remote_detach_pid (child_pid); } } - return 0; + + return false; } /* Target follow-exec function for remote targets. Save EXECD_PATHNAME @@ -5750,10 +5841,10 @@ remote_target::disconnect (const char *args, int from_tty) error (_("Argument given to \"disconnect\" when remotely debugging.")); /* Make sure we unpush even the extended remote targets. Calling - target_mourn_inferior won't unpush, and remote_mourn won't - unpush if there is more than one inferior left. */ - unpush_target (this); - generic_mourn_inferior (); + target_mourn_inferior won't unpush, and + remote_target::mourn_inferior won't unpush if there is more than + one inferior left. */ + remote_unpush_target (this); if (from_tty) puts_filtered ("Ending remote debugging.\n"); @@ -5779,7 +5870,7 @@ extended_remote_target::attach (const char *args, int from_tty) if (from_tty) { - char *exec_file = get_exec_file (0); + const char *exec_file = get_exec_file (0); if (exec_file) printf_unfiltered (_("Attaching to program: %s, %s\n"), exec_file, @@ -5841,10 +5932,10 @@ extended_remote_target::attach (const char *args, int from_tty) inferior_ptid = remote_current_thread (inferior_ptid); /* Add the main thread to the thread list. */ - thread_info *thr = add_thread_silent (inferior_ptid); + thread_info *thr = add_thread_silent (this, inferior_ptid); /* Don't consider the thread stopped until we've processed the saved stop reply. */ - set_executing (thr->ptid, true); + set_executing (this, thr->ptid, true); } /* Next, if the target can specify a description, read it. We do @@ -5946,6 +6037,7 @@ remote_target::remote_vcont_probe () } packet_ok (rs->buf, &remote_protocol_packets[PACKET_vCont]); + rs->supports_vCont_probed = true; } /* Helper function for building "vCont" resumptions. Write a @@ -5983,10 +6075,10 @@ remote_target::append_resumption (char *p, char *endp, { /* If we don't know about the target thread's tid, then we're resuming magic_null_ptid (see caller). */ - tp = find_thread_ptid (magic_null_ptid); + tp = find_thread_ptid (this, magic_null_ptid); } else - tp = find_thread_ptid (ptid); + tp = find_thread_ptid (this, ptid); gdb_assert (tp != NULL); if (tp->control.may_range_step) @@ -6049,7 +6141,7 @@ char * remote_target::append_pending_thread_resumptions (char *p, char *endp, ptid_t ptid) { - for (thread_info *thread : all_non_exited_threads (ptid)) + for (thread_info *thread : all_non_exited_threads (this, ptid)) if (inferior_ptid != thread->ptid && thread->suspend.stop_signal != GDB_SIGNAL_0) { @@ -6082,7 +6174,7 @@ remote_target::remote_resume_with_hc (ptid_t ptid, int step, else set_continue_thread (ptid); - for (thread_info *thread : all_non_exited_threads ()) + for (thread_info *thread : all_non_exited_threads (this)) resume_clear_thread_private_info (thread); buf = rs->buf.data (); @@ -6219,9 +6311,9 @@ remote_target::resume (ptid_t ptid, int step, enum gdb_signal siggnal) remote_thread_info *remote_thr; if (minus_one_ptid == ptid || ptid.is_pid ()) - remote_thr = get_remote_thread_info (inferior_ptid); + remote_thr = get_remote_thread_info (this, inferior_ptid); else - remote_thr = get_remote_thread_info (ptid); + remote_thr = get_remote_thread_info (this, ptid); remote_thr->last_resume_step = step; remote_thr->last_resume_sig = siggnal; @@ -6453,7 +6545,7 @@ remote_target::commit_resume () may_global_wildcard_vcont = 1; /* And assume every process is individually wildcard-able too. */ - for (inferior *inf : all_non_exited_inferiors ()) + for (inferior *inf : all_non_exited_inferiors (this)) { remote_inferior *priv = get_remote_inferior (inf); @@ -6464,7 +6556,7 @@ remote_target::commit_resume () disable process and global wildcard resumes appropriately. */ check_pending_events_prevent_wildcard_vcont (&may_global_wildcard_vcont); - for (thread_info *tp : all_non_exited_threads ()) + for (thread_info *tp : all_non_exited_threads (this)) { /* If a thread of a process is not meant to be resumed, then we can't wildcard that process. */ @@ -6493,7 +6585,7 @@ remote_target::commit_resume () struct vcont_builder vcont_builder (this); /* Threads first. */ - for (thread_info *tp : all_non_exited_threads ()) + for (thread_info *tp : all_non_exited_threads (this)) { remote_thread_info *remote_thr = get_remote_thread_info (tp); @@ -6522,7 +6614,7 @@ remote_target::commit_resume () supposed to be resumed. */ any_process_wildcard = 0; - for (inferior *inf : all_non_exited_inferiors ()) + for (inferior *inf : all_non_exited_inferiors (this)) { if (get_remote_inferior (inf)->may_wildcard_vcont) { @@ -6543,7 +6635,7 @@ remote_target::commit_resume () } else { - for (inferior *inf : all_non_exited_inferiors ()) + for (inferior *inf : all_non_exited_inferiors (this)) { if (get_remote_inferior (inf)->may_wildcard_vcont) { @@ -6570,7 +6662,10 @@ remote_target::remote_stop_ns (ptid_t ptid) char *p = rs->buf.data (); char *endp = p + get_remote_packet_size (); - if (packet_support (PACKET_vCont) == PACKET_SUPPORT_UNKNOWN) + /* FIXME: This supports_vCont_probed check is a workaround until + packet_support is per-connection. */ + if (packet_support (PACKET_vCont) == PACKET_SUPPORT_UNKNOWN + || !rs->supports_vCont_probed) remote_vcont_probe (); if (!rs->supports_vCont.t) @@ -6727,7 +6822,7 @@ remote_target::interrupt_query () if (query (_("The target is not responding to interrupt requests.\n" "Stop debugging it? "))) { - remote_unpush_target (); + remote_unpush_target (this); throw_error (TARGET_CLOSE_ERROR, _("Disconnected from target.")); } } @@ -6769,9 +6864,9 @@ remote_console_output (const char *msg) tb[0] = c; tb[1] = 0; - fputs_unfiltered (tb, gdb_stdtarg); + gdb_stdtarg->puts (tb); } - gdb_flush (gdb_stdtarg); + gdb_stdtarg->flush (); } struct stop_reply : public notif_event @@ -6813,7 +6908,7 @@ remote_target::stop_reply_queue_length () return rs->stop_reply_queue.size (); } -void +static void remote_notif_stop_parse (remote_target *remote, struct notif_client *self, const char *buf, struct notif_event *event) @@ -6934,7 +7029,7 @@ remote_target::remove_new_fork_children (threads_listing_context *context) /* For any threads stopped at a fork event, remove the corresponding fork child threads from the CONTEXT list. */ - for (thread_info *thread : all_non_exited_threads ()) + for (thread_info *thread : all_non_exited_threads (this)) { struct target_waitstatus *ws = thread_pending_fork_status (thread); @@ -6976,7 +7071,7 @@ remote_target::check_pending_events_prevent_wildcard_vcont || event->ws.kind == TARGET_WAITKIND_VFORKED) *may_global_wildcard = 0; - struct inferior *inf = find_inferior_ptid (event->ptid); + struct inferior *inf = find_inferior_ptid (this, event->ptid); /* This may be the first time we heard about this process. Regardless, we must not do a global wildcard resume, otherwise @@ -7326,25 +7421,22 @@ Packet: '%s'\n"), reported expedited registers. */ if (event->ptid == null_ptid) { + /* If there is no thread-id information then leave + the event->ptid as null_ptid. Later in + process_stop_reply we will pick a suitable + thread. */ const char *thr = strstr (p1 + 1, ";thread:"); if (thr != NULL) event->ptid = read_ptid (thr + strlen (";thread:"), NULL); - else - { - /* Either the current thread hasn't changed, - or the inferior is not multi-threaded. - The event must be for the thread we last - set as (or learned as being) current. */ - event->ptid = event->rs->general_thread; - } } if (rsa == NULL) { - inferior *inf = (event->ptid == null_ptid - ? NULL - : find_inferior_ptid (event->ptid)); + inferior *inf + = (event->ptid == null_ptid + ? NULL + : find_inferior_ptid (this, event->ptid)); /* If this is the first time we learn anything about this process, skip the registers included in this packet, since we don't yet @@ -7432,7 +7524,6 @@ Packet: '%s'\n"), case 'W': /* Target exited. */ case 'X': { - int pid; ULONGEST value; /* GDB used to accept only 2 hex chars here. Stubs should @@ -7456,8 +7547,9 @@ Packet: '%s'\n"), event->ws.value.sig = GDB_SIGNAL_UNKNOWN; } - /* If no process is specified, assume inferior_ptid. */ - pid = inferior_ptid.pid (); + /* If no process is specified, return null_ptid, and let the + caller figure out the right process to use. */ + int pid = 0; if (*p == '\0') ; else if (*p == ';') @@ -7487,9 +7579,6 @@ Packet: '%s'\n"), event->ptid = minus_one_ptid; break; } - - if (target_is_non_stop_p () && event->ptid == null_ptid) - error (_("No process or thread specified in stop reply: %s"), buf); } /* When the stub wants to tell GDB about a new notification reply, it @@ -7591,10 +7680,61 @@ remote_target::process_stop_reply (struct stop_reply *stop_reply, *status = stop_reply->ws; ptid = stop_reply->ptid; - /* If no thread/process was reported by the stub, assume the current - inferior. */ + /* If no thread/process was reported by the stub then use the first + non-exited thread in the current target. */ if (ptid == null_ptid) - ptid = inferior_ptid; + { + /* Some stop events apply to all threads in an inferior, while others + only apply to a single thread. */ + bool is_stop_for_all_threads + = (status->kind == TARGET_WAITKIND_EXITED + || status->kind == TARGET_WAITKIND_SIGNALLED); + + for (thread_info *thr : all_non_exited_threads (this)) + { + if (ptid != null_ptid + && (!is_stop_for_all_threads + || ptid.pid () != thr->ptid.pid ())) + { + static bool warned = false; + + if (!warned) + { + /* If you are seeing this warning then the remote target + has stopped without specifying a thread-id, but the + target does have multiple threads (or inferiors), and + so GDB is having to guess which thread stopped. + + Examples of what might cause this are the target + sending and 'S' stop packet, or a 'T' stop packet and + not including a thread-id. + + Additionally, the target might send a 'W' or 'X + packet without including a process-id, when the target + has multiple running inferiors. */ + if (is_stop_for_all_threads) + warning (_("multi-inferior target stopped without " + "sending a process-id, using first " + "non-exited inferior")); + else + warning (_("multi-threaded target stopped without " + "sending a thread-id, using first " + "non-exited thread")); + warned = true; + } + break; + } + + /* If this is a stop for all threads then don't use a particular + threads ptid, instead create a new ptid where only the pid + field is set. */ + if (is_stop_for_all_threads) + ptid = ptid_t (thr->ptid.pid ()); + else + ptid = thr->ptid; + } + gdb_assert (ptid != null_ptid); + } if (status->kind != TARGET_WAITKIND_EXITED && status->kind != TARGET_WAITKIND_SIGNALLED @@ -7604,7 +7744,7 @@ remote_target::process_stop_reply (struct stop_reply *stop_reply, if (!stop_reply->regcache.empty ()) { struct regcache *regcache - = get_thread_arch_regcache (ptid, stop_reply->arch); + = get_thread_arch_regcache (this, ptid, stop_reply->arch); for (cached_reg_t ® : stop_reply->regcache) { @@ -7616,7 +7756,7 @@ remote_target::process_stop_reply (struct stop_reply *stop_reply, } remote_notice_new_inferior (ptid, 0); - remote_thread_info *remote_thr = get_remote_thread_info (ptid); + remote_thread_info *remote_thr = get_remote_thread_info (this, ptid); remote_thr->core = stop_reply->core; remote_thr->stop_reason = stop_reply->stop_reason; remote_thr->watch_data_address = stop_reply->watch_data_address; @@ -7683,6 +7823,17 @@ remote_target::wait_ns (ptid_t ptid, struct target_waitstatus *status, int optio } } +/* Return the first resumed thread. */ + +static ptid_t +first_remote_resumed_thread (remote_target *target) +{ + for (thread_info *tp : all_non_exited_threads (target, minus_one_ptid)) + if (tp->resumed) + return tp->ptid; + return null_ptid; +} + /* Wait until the remote machine stops, then return, storing status in STATUS just as `wait' would. */ @@ -7819,11 +7970,19 @@ remote_target::wait_as (ptid_t ptid, target_waitstatus *status, int options) if (event_ptid != null_ptid) record_currthread (rs, event_ptid); else - event_ptid = inferior_ptid; + event_ptid = first_remote_resumed_thread (this); } else - /* A process exit. Invalidate our notion of current thread. */ - record_currthread (rs, minus_one_ptid); + { + /* A process exit. Invalidate our notion of current thread. */ + record_currthread (rs, minus_one_ptid); + /* It's possible that the packet did not include a pid. */ + if (event_ptid == null_ptid) + event_ptid = first_remote_resumed_thread (this); + /* EVENT_PTID could still be NULL_PTID. Double-check. */ + if (event_ptid == null_ptid) + event_ptid = magic_null_ptid; + } return event_ptid; } @@ -8934,11 +9093,11 @@ remote_target::files_info () for output compatibility with throw_perror_with_name. */ static void -unpush_and_perror (const char *string) +unpush_and_perror (remote_target *target, const char *string) { int saved_errno = errno; - remote_unpush_target (); + remote_unpush_target (target); throw_error (TARGET_CLOSE_ERROR, "%s: %s.", string, safe_strerror (saved_errno)); } @@ -8974,12 +9133,12 @@ remote_target::readchar (int timeout) switch ((enum serial_rc) ch) { case SERIAL_EOF: - remote_unpush_target (); + remote_unpush_target (this); throw_error (TARGET_CLOSE_ERROR, _("Remote connection closed")); /* no return */ case SERIAL_ERROR: - unpush_and_perror (_("Remote communication error. " - "Target disconnected.")); + unpush_and_perror (this, _("Remote communication error. " + "Target disconnected.")); /* no return */ case SERIAL_TIMEOUT: break; @@ -9007,8 +9166,8 @@ remote_target::remote_serial_write (const char *str, int len) if (serial_write (rs->remote_desc, str, len)) { - unpush_and_perror (_("Remote communication error. " - "Target disconnected.")); + unpush_and_perror (this, _("Remote communication error. " + "Target disconnected.")); } if (rs->got_ctrlc_during_io) @@ -9118,15 +9277,21 @@ remote_target::putpkt_binary (const char *buf, int cnt) *p = '\0'; int len = (int) (p - buf2); + int max_chars; + + if (remote_packet_max_chars < 0) + max_chars = len; + else + max_chars = remote_packet_max_chars; std::string str - = escape_buffer (buf2, std::min (len, REMOTE_DEBUG_MAX_CHAR)); + = escape_buffer (buf2, std::min (len, max_chars)); fprintf_unfiltered (gdb_stdlog, "Sending packet: %s", str.c_str ()); - if (len > REMOTE_DEBUG_MAX_CHAR) + if (len > max_chars) fprintf_unfiltered (gdb_stdlog, "[%d bytes omitted]", - len - REMOTE_DEBUG_MAX_CHAR); + len - max_chars); fprintf_unfiltered (gdb_stdlog, "..."); @@ -9525,7 +9690,7 @@ remote_target::getpkt_or_notif_sane_1 (gdb::char_vector *buf, if (forever) /* Watchdog went off? Kill the target. */ { - remote_unpush_target (); + remote_unpush_target (this); throw_error (TARGET_CLOSE_ERROR, _("Watchdog timeout has expired. " "Target detached.")); @@ -9562,16 +9727,23 @@ remote_target::getpkt_or_notif_sane_1 (gdb::char_vector *buf, { if (remote_debug) { + int max_chars; + + if (remote_packet_max_chars < 0) + max_chars = val; + else + max_chars = remote_packet_max_chars; + std::string str = escape_buffer (buf->data (), - std::min (val, REMOTE_DEBUG_MAX_CHAR)); + std::min (val, max_chars)); fprintf_unfiltered (gdb_stdlog, "Packet received: %s", str.c_str ()); - if (val > REMOTE_DEBUG_MAX_CHAR) + if (val > max_chars) fprintf_unfiltered (gdb_stdlog, "[%d bytes omitted]", - val - REMOTE_DEBUG_MAX_CHAR); + val - max_chars); fprintf_unfiltered (gdb_stdlog, "\n"); } @@ -9635,7 +9807,7 @@ remote_target::kill_new_fork_children (int pid) /* Kill the fork child threads of any threads in process PID that are stopped at a fork event. */ - for (thread_info *thread : all_non_exited_threads ()) + for (thread_info *thread : all_non_exited_threads (this)) { struct target_waitstatus *ws = &thread->pending_follow; @@ -9695,7 +9867,7 @@ remote_target::kill () inferior, then we will tell gdbserver to exit and unpush the target. */ if (res == -1 && !remote_multi_process_p (rs) - && number_of_live_inferiors () == 1) + && number_of_live_inferiors (this) == 1) { remote_kill_k (); @@ -9781,12 +9953,9 @@ remote_target::mourn_inferior () discard_pending_stop_replies (current_inferior ()); /* In 'target remote' mode with one inferior, we close the connection. */ - if (!rs->extended && number_of_live_inferiors () <= 1) + if (!rs->extended && number_of_live_inferiors (this) <= 1) { - unpush_target (this); - - /* remote_close takes care of doing most of the clean up. */ - generic_mourn_inferior (); + remote_unpush_target (this); return; } @@ -9821,26 +9990,6 @@ remote_target::mourn_inferior () /* Call common code to mark the inferior as not running. */ generic_mourn_inferior (); - - if (!have_inferiors ()) - { - if (!remote_multi_process_p (rs)) - { - /* Check whether the target is running now - some remote stubs - automatically restart after kill. */ - putpkt ("?"); - getpkt (&rs->buf, 0); - - if (rs->buf[0] == 'S' || rs->buf[0] == 'T') - { - /* Assume that the target has been restarted. Set - inferior_ptid so that bits of core GDB realizes - there's something here, e.g., so that the user can - say "kill" again. */ - inferior_ptid = magic_null_ptid; - } - } - } } bool @@ -12568,12 +12717,6 @@ remote_delete_command (const char *args, int from_tty) remote_file_delete (argv[0], from_tty); } -static void -remote_command (const char *args, int from_tty) -{ - help_list (remote_cmdlist, "remote ", all_commands, gdb_stdout); -} - bool remote_target::can_execute_reverse () { @@ -12728,7 +12871,7 @@ remote_target::download_tracepoint (struct bp_location *loc) encode_actions_rsp (loc, &tdp_actions, &stepping_actions); tpaddr = loc->address; - sprintf_vma (addrbuf, tpaddr); + strcpy (addrbuf, phex (tpaddr, sizeof (CORE_ADDR))); ret = snprintf (buf.data (), buf.size (), "QTDP:%x:%s:%c:%lx:%x", b->number, addrbuf, /* address */ (b->enable_state == bp_enabled ? 'E' : 'D'), @@ -12990,11 +13133,10 @@ void remote_target::enable_tracepoint (struct bp_location *location) { struct remote_state *rs = get_remote_state (); - char addr_buf[40]; - sprintf_vma (addr_buf, location->address); xsnprintf (rs->buf.data (), get_remote_packet_size (), "QTEnable:%x:%s", - location->owner->number, addr_buf); + location->owner->number, + phex (location->address, sizeof (CORE_ADDR))); putpkt (rs->buf); remote_get_noisy_reply (); if (rs->buf[0] == '\0') @@ -13007,11 +13149,10 @@ void remote_target::disable_tracepoint (struct bp_location *location) { struct remote_state *rs = get_remote_state (); - char addr_buf[40]; - sprintf_vma (addr_buf, location->address); xsnprintf (rs->buf.data (), get_remote_packet_size (), "QTDisable:%x:%s", - location->owner->number, addr_buf); + location->owner->number, + phex (location->address, sizeof (CORE_ADDR))); putpkt (rs->buf); remote_get_noisy_reply (); if (rs->buf[0] == '\0') @@ -13390,7 +13531,7 @@ remote_target::set_disconnected_tracing (int val) int remote_target::core_of_thread (ptid_t ptid) { - struct thread_info *info = find_thread_ptid (ptid); + thread_info *info = find_thread_ptid (this, ptid); if (info != NULL && info->priv != NULL) return get_remote_thread_info (info)->core; @@ -13670,7 +13811,7 @@ remote_target::remote_btrace_maybe_reopen () scoped_restore_current_thread restore_thread; - for (thread_info *tp : all_non_exited_threads ()) + for (thread_info *tp : all_non_exited_threads (this)) { set_general_thread (tp->ptid); @@ -13886,13 +14027,12 @@ char * remote_target::pid_to_exec_file (int pid) { static gdb::optional filename; - struct inferior *inf; char *annex = NULL; if (packet_support (PACKET_qXfer_exec_file) != PACKET_ENABLE) return NULL; - inf = find_inferior_pid (pid); + inferior *inf = find_inferior_pid (this, pid); if (inf == NULL) internal_error (__FILE__, __LINE__, _("not currently attached to process %d"), pid); @@ -13953,7 +14093,7 @@ remote_target::thread_handle_to_thread_info (const gdb_byte *thread_handle, int handle_len, inferior *inf) { - for (thread_info *tp : all_non_exited_threads ()) + for (thread_info *tp : all_non_exited_threads (this)) { remote_thread_info *priv = get_remote_thread_info (tp); @@ -14025,6 +14165,13 @@ remote_async_inferior_event_handler (gdb_client_data data) inferior_event_handler (INF_REG_EVENT, data); } +int +remote_target::async_wait_fd () +{ + struct remote_state *rs = get_remote_state (); + return rs->remote_desc->fd; +} + void remote_target::async (int enable) { @@ -14088,12 +14235,6 @@ remote_target::thread_events (int enable) } } -static void -set_remote_cmd (const char *args, int from_tty) -{ - help_list (remote_set_cmdlist, "set remote ", all_commands, gdb_stdout); -} - static void show_remote_cmd (const char *args, int from_tty) { @@ -14223,8 +14364,9 @@ set_range_stepping (const char *ignore_args, int from_tty, } } +void _initialize_remote (); void -_initialize_remote (void) +_initialize_remote () { struct cmd_list_element *cmd; const char *cmd_name; @@ -14245,12 +14387,12 @@ _initialize_remote (void) /* set/show remote ... */ - add_prefix_cmd ("remote", class_maintenance, set_remote_cmd, _("\ + add_basic_prefix_cmd ("remote", class_maintenance, _("\ Remote protocol specific variables.\n\ Configure various remote-protocol specific variables such as\n\ the packets being used."), - &remote_set_cmdlist, "set remote ", - 0 /* allow-unknown */, &setlist); + &remote_set_cmdlist, "set remote ", + 0 /* allow-unknown */, &setlist); add_prefix_cmd ("remote", class_maintenance, show_remote_cmd, _("\ Remote protocol specific variables.\n\ Configure various remote-protocol specific variables such as\n\ @@ -14671,11 +14813,11 @@ packets."), `Z' packets is %s. */ &remote_set_cmdlist, &remote_show_cmdlist); - add_prefix_cmd ("remote", class_files, remote_command, _("\ + add_basic_prefix_cmd ("remote", class_files, _("\ Manipulate files on the remote system.\n\ Transfer files to and from the remote target system."), - &remote_cmdlist, "remote ", - 0 /* allow-unknown */, &cmdlist); + &remote_cmdlist, "remote ", + 0 /* allow-unknown */, &cmdlist); add_cmd ("put", class_files, remote_put_command, _("Copy a local file to the remote system."), @@ -14722,6 +14864,14 @@ of time passes without a response from the target, an error occurs."), show_watchdog, &setlist, &showlist); + add_setshow_zuinteger_unlimited_cmd ("remote-packet-max-chars", no_class, + &remote_packet_max_chars, _("\ +Set the maximum number of characters to display for each remote packet."), _("\ +Show the maximum number of characters to display for each remote packet."), _("\ +Specify \"unlimited\" to display all the characters."), + NULL, show_remote_packet_max_chars, + &setdebuglist, &showdebuglist); + /* Eventually initialize fileio. See fileio.c */ - initialize_remote_fileio (remote_set_cmdlist, remote_show_cmdlist); + initialize_remote_fileio (&remote_set_cmdlist, &remote_show_cmdlist); }