X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gdb%2Fremote.c;h=4a42da8ec27477149733bfe5c3a254044960d0be;hb=5d5658a1d3c3eb2a09c03f2f0662a1c01963c869;hp=5270bd281d370e16ae85434942f2aba712b1c7c8;hpb=799a2abe613be0645b84f5aaa050f2f91e6ae3f7;p=binutils-gdb.git diff --git a/gdb/remote.c b/gdb/remote.c index 5270bd281d3..4a42da8ec27 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-2015 Free Software Foundation, Inc. + Copyright (C) 1988-2016 Free Software Foundation, Inc. This file is part of GDB. @@ -119,12 +119,12 @@ struct remote_state; static int remote_vkill (int pid, struct remote_state *rs); +static void remote_kill_k (void); + static void remote_mourn (struct target_ops *ops); static void extended_remote_restart (void); -static void extended_remote_mourn (struct target_ops *); - static void remote_send (char **buf, long *sizeof_buf_p); static int readchar (int timeout); @@ -139,6 +139,8 @@ static int remote_is_async_p (struct target_ops *); static void remote_async (struct target_ops *ops, int enable); +static void remote_thread_events (struct target_ops *ops, int enable); + static void sync_remote_interrupt_twice (int signo); static void interrupt_query (void); @@ -1390,6 +1392,7 @@ enum { PACKET_qSupported, PACKET_qTStatus, PACKET_QPassSignals, + PACKET_QCatchSyscalls, PACKET_QProgramSignals, PACKET_qCRC, PACKET_qSearch_memory, @@ -1436,6 +1439,9 @@ enum { /* Support for the QNonStop packet. */ PACKET_QNonStop, + /* Support for the QThreadEvents packet. */ + PACKET_QThreadEvents, + /* Support for multi-process extensions. */ PACKET_multiprocess_feature, @@ -1480,6 +1486,12 @@ enum { /* Support for query supported vCont actions. */ PACKET_vContSupported, + /* Support remote CTRL-C. */ + PACKET_vCtrlC, + + /* Support TARGET_WAITKIND_NO_RESUMED. */ + PACKET_no_resumed, + PACKET_MAX }; @@ -1907,7 +1919,8 @@ demand_private_info (ptid_t ptid) info->priv = XNEW (struct private_thread_info); info->private_dtor = free_private_thread_info; info->priv->core = -1; - info->priv->extra = 0; + info->priv->extra = NULL; + info->priv->name = NULL; } return info->priv; @@ -1975,6 +1988,93 @@ remote_pass_signals (struct target_ops *self, } } +/* If 'QCatchSyscalls' is supported, tell the remote stub + to report syscalls to GDB. */ + +static int +remote_set_syscall_catchpoint (struct target_ops *self, + int pid, int needed, int any_count, + int table_size, int *table) +{ + char *catch_packet; + enum packet_result result; + int n_sysno = 0; + + if (packet_support (PACKET_QCatchSyscalls) == PACKET_DISABLE) + { + /* Not supported. */ + return 1; + } + + if (needed && !any_count) + { + int i; + + /* Count how many syscalls are to be caught (table[sysno] != 0). */ + for (i = 0; i < table_size; i++) + { + if (table[i] != 0) + n_sysno++; + } + } + + if (remote_debug) + { + fprintf_unfiltered (gdb_stdlog, + "remote_set_syscall_catchpoint " + "pid %d needed %d any_count %d n_sysno %d\n", + pid, needed, any_count, n_sysno); + } + + if (needed) + { + /* Prepare a packet with the sysno list, assuming max 8+1 + characters for a sysno. If the resulting packet size is too + big, fallback on the non-selective packet. */ + const int maxpktsz = strlen ("QCatchSyscalls:1") + n_sysno * 9 + 1; + + catch_packet = xmalloc (maxpktsz); + strcpy (catch_packet, "QCatchSyscalls:1"); + if (!any_count) + { + int i; + char *p; + + p = catch_packet; + p += strlen (p); + + /* Add in catch_packet each syscall to be caught (table[i] != 0). */ + for (i = 0; i < table_size; i++) + { + if (table[i] != 0) + p += xsnprintf (p, catch_packet + maxpktsz - p, ";%x", i); + } + } + if (strlen (catch_packet) > get_remote_packet_size ()) + { + /* catch_packet too big. Fallback to less efficient + non selective mode, with GDB doing the filtering. */ + catch_packet[sizeof ("QCatchSyscalls:1") - 1] = 0; + } + } + else + catch_packet = xstrdup ("QCatchSyscalls:0"); + + { + struct cleanup *old_chain = make_cleanup (xfree, catch_packet); + struct remote_state *rs = get_remote_state (); + + putpkt (catch_packet); + getpkt (&rs->buf, &rs->buf_size, 0); + result = packet_ok (rs->buf, &remote_protocol_packets[PACKET_QCatchSyscalls]); + do_cleanups (old_chain); + if (result == PACKET_OK) + return 0; + else + return -1; + } +} + /* If 'QProgramSignals' is supported, tell the remote stub what signals it should pass through to the inferior when detaching. */ @@ -2086,7 +2186,7 @@ set_general_process (void) struct remote_state *rs = get_remote_state (); /* If the remote can't handle multiple processes, don't bother. */ - if (!rs->extended || !remote_multi_process_p (rs)) + if (!remote_multi_process_p (rs)) return; /* We only need to change the remote current thread if it's pointing @@ -2903,6 +3003,7 @@ remote_newthread_step (threadref *ref, void *data) item.ptid = ptid_build (pid, threadref_to_int (ref), 0); item.core = -1; + item.name = NULL; item.extra = NULL; VEC_safe_push (thread_item_t, context->items, &item); @@ -3068,6 +3169,7 @@ remote_get_threads_with_qthreadinfo (struct target_ops *ops, item.ptid = read_ptid (bufp, &bufp); item.core = -1; + item.name = NULL; item.extra = NULL; VEC_safe_push (thread_item_t, context->items, &item); @@ -3867,7 +3969,9 @@ process_initial_stop_replies (int from_tty) && thread->suspend.waitstatus_pending_p) selected = thread; - if (lowest_stopped == NULL || thread->num < lowest_stopped->num) + if (lowest_stopped == NULL + || thread->inf->num < lowest_stopped->inf->num + || thread->per_inf_num < lowest_stopped->per_inf_num) lowest_stopped = thread; if (non_stop) @@ -4453,6 +4557,8 @@ static const struct protocol_feature remote_protocol_features[] = { PACKET_qXfer_traceframe_info }, { "QPassSignals", PACKET_DISABLE, remote_supported_packet, PACKET_QPassSignals }, + { "QCatchSyscalls", PACKET_DISABLE, remote_supported_packet, + PACKET_QCatchSyscalls }, { "QProgramSignals", PACKET_DISABLE, remote_supported_packet, PACKET_QProgramSignals }, { "QStartNoAckMode", PACKET_DISABLE, remote_supported_packet, @@ -4517,7 +4623,9 @@ static const struct protocol_feature remote_protocol_features[] = { PACKET_exec_event_feature }, { "Qbtrace-conf:pt:size", PACKET_DISABLE, remote_supported_packet, PACKET_Qbtrace_conf_pt_size }, - { "vContSupported", PACKET_DISABLE, remote_supported_packet, PACKET_vContSupported } + { "vContSupported", PACKET_DISABLE, remote_supported_packet, PACKET_vContSupported }, + { "QThreadEvents", PACKET_DISABLE, remote_supported_packet, PACKET_QThreadEvents }, + { "no-resumed", PACKET_DISABLE, remote_supported_packet, PACKET_no_resumed }, }; static char *remote_support_xml; @@ -4594,22 +4702,25 @@ remote_query_supported (void) q = remote_query_supported_append (q, "qRelocInsn+"); - if (rs->extended) - { - if (packet_set_cmd_state (PACKET_fork_event_feature) - != AUTO_BOOLEAN_FALSE) - q = remote_query_supported_append (q, "fork-events+"); - if (packet_set_cmd_state (PACKET_vfork_event_feature) - != AUTO_BOOLEAN_FALSE) - q = remote_query_supported_append (q, "vfork-events+"); - if (packet_set_cmd_state (PACKET_exec_event_feature) - != AUTO_BOOLEAN_FALSE) - q = remote_query_supported_append (q, "exec-events+"); - } + if (packet_set_cmd_state (PACKET_fork_event_feature) + != AUTO_BOOLEAN_FALSE) + q = remote_query_supported_append (q, "fork-events+"); + if (packet_set_cmd_state (PACKET_vfork_event_feature) + != AUTO_BOOLEAN_FALSE) + q = remote_query_supported_append (q, "vfork-events+"); + if (packet_set_cmd_state (PACKET_exec_event_feature) + != AUTO_BOOLEAN_FALSE) + q = remote_query_supported_append (q, "exec-events+"); if (packet_set_cmd_state (PACKET_vContSupported) != AUTO_BOOLEAN_FALSE) q = remote_query_supported_append (q, "vContSupported+"); + if (packet_set_cmd_state (PACKET_QThreadEvents) != AUTO_BOOLEAN_FALSE) + q = remote_query_supported_append (q, "QThreadEvents+"); + + if (packet_set_cmd_state (PACKET_no_resumed) != AUTO_BOOLEAN_FALSE) + q = remote_query_supported_append (q, "no-resumed+"); + /* Keep this one last to work around a gdbserver <= 7.10 bug in the qSupported:xmlRegisters=i386 handling. */ if (remote_support_xml != NULL) @@ -4954,7 +5065,8 @@ remote_detach_1 (const char *args, int from_tty) /* Tell the remote target to detach. */ remote_detach_pid (pid); - if (from_tty && !rs->extended) + /* Exit only if this is the only active inferior. */ + if (from_tty && !rs->extended && number_of_live_inferiors () == 1) puts_filtered (_("Ending remote debugging.\n")); /* Check to see if we are detaching a fork parent. Note that if we @@ -5050,10 +5162,11 @@ remote_disconnect (struct target_ops *target, const char *args, int from_tty) if (args) error (_("Argument given to \"disconnect\" when remotely debugging.")); - /* Make sure we unpush even the extended remote targets; mourn - won't do it. So call remote_mourn directly instead of - target_mourn_inferior. */ - remote_mourn (target); + /* 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 (target); + generic_mourn_inferior (); if (from_tty) puts_filtered ("Ending remote debugging.\n"); @@ -5581,7 +5694,7 @@ async_remote_interrupt (gdb_client_data arg) if (remote_debug) fprintf_unfiltered (gdb_stdlog, "async_remote_interrupt called\n"); - target_stop (inferior_ptid); + target_interrupt (inferior_ptid); } /* Perform interrupt, if the first attempt did not succeed. Just give @@ -5688,7 +5801,7 @@ remote_stop_ns (ptid_t ptid) process reports the interrupt. */ static void -remote_interrupt_as (ptid_t ptid) +remote_interrupt_as (void) { struct remote_state *rs = get_remote_state (); @@ -5704,6 +5817,38 @@ remote_interrupt_as (ptid_t ptid) send_interrupt_sequence (); } +/* Non-stop version of target_interrupt. Uses `vCtrlC' to interrupt + the remote target. It is undefined which thread of which process + reports the interrupt. Returns true if the packet is supported by + the server, false otherwise. */ + +static int +remote_interrupt_ns (void) +{ + struct remote_state *rs = get_remote_state (); + char *p = rs->buf; + char *endp = rs->buf + get_remote_packet_size (); + + xsnprintf (p, endp - p, "vCtrlC"); + + /* In non-stop, we get an immediate OK reply. The stop reply will + come in asynchronously by notification. */ + putpkt (rs->buf); + getpkt (&rs->buf, &rs->buf_size, 0); + + switch (packet_ok (rs->buf, &remote_protocol_packets[PACKET_vCtrlC])) + { + case PACKET_OK: + break; + case PACKET_UNKNOWN: + return 0; + case PACKET_ERROR: + error (_("Interrupting target failed: %s"), rs->buf); + } + + return 1; +} + /* Implement the to_stop function for the remote targets. */ static void @@ -5718,7 +5863,7 @@ remote_stop (struct target_ops *self, ptid_t ptid) { /* We don't currently have a way to transparently pause the remote target in all-stop mode. Interrupt it instead. */ - remote_interrupt_as (ptid); + remote_interrupt_as (); } } @@ -5730,14 +5875,27 @@ remote_interrupt (struct target_ops *self, ptid_t ptid) if (remote_debug) fprintf_unfiltered (gdb_stdlog, "remote_interrupt called\n"); - if (target_is_non_stop_p ()) + if (non_stop) { - /* We don't currently have a way to ^C the remote target in - non-stop mode. Stop it (with no signal) instead. */ + /* In non-stop mode, we always stop with no signal instead. */ remote_stop_ns (ptid); } else - remote_interrupt_as (ptid); + { + /* In all-stop, we emulate ^C-ing the remote target's + terminal. */ + if (target_is_non_stop_p ()) + { + if (!remote_interrupt_ns ()) + { + /* No support for ^C-ing the remote target. Stop it + (with no signal) instead. */ + remote_stop_ns (ptid); + } + } + else + remote_interrupt_as (); + } } /* Ask the user what to do when an interrupt is received. */ @@ -5997,10 +6155,9 @@ remove_child_of_pending_fork (QUEUE (stop_reply_p) *q, = (struct threads_listing_context *) param->input; if (event->ws.kind == TARGET_WAITKIND_FORKED - || event->ws.kind == TARGET_WAITKIND_VFORKED) - { - threads_listing_context_remove (&event->ws, context); - } + || event->ws.kind == TARGET_WAITKIND_VFORKED + || event->ws.kind == TARGET_WAITKIND_THREAD_EXITED) + threads_listing_context_remove (&event->ws, context); return 1; } @@ -6306,6 +6463,22 @@ Packet: '%s'\n"), if (strprefix (p, p1, "thread")) event->ptid = read_ptid (++p1, &p); + else if (strprefix (p, p1, "syscall_entry")) + { + ULONGEST sysno; + + event->ws.kind = TARGET_WAITKIND_SYSCALL_ENTRY; + p = unpack_varlen_hex (++p1, &sysno); + event->ws.value.syscall_number = (int) sysno; + } + else if (strprefix (p, p1, "syscall_return")) + { + ULONGEST sysno; + + event->ws.kind = TARGET_WAITKIND_SYSCALL_RETURN; + p = unpack_varlen_hex (++p1, &sysno); + event->ws.value.syscall_number = (int) sysno; + } else if (strprefix (p, p1, "watch") || strprefix (p, p1, "rwatch") || strprefix (p, p1, "awatch")) @@ -6398,6 +6571,11 @@ Packet: '%s'\n"), one used by the original program. */ skipregs = 1; } + else if (strprefix (p, p1, "create")) + { + event->ws.kind = TARGET_WAITKIND_THREAD_CREATED; + p = skip_to_semicolon (p1 + 1); + } else { ULONGEST pnum; @@ -6468,6 +6646,19 @@ Packet: '%s'\n"), event->ws.value.sig = GDB_SIGNAL_UNKNOWN; } break; + case 'w': /* Thread exited. */ + { + char *p; + ULONGEST value; + + event->ws.kind = TARGET_WAITKIND_THREAD_EXITED; + p = unpack_varlen_hex (&buf[1], &value); + event->ws.value.integer = value; + if (*p != ';') + error (_("stop reply packet badly formatted: %s"), buf); + event->ptid = read_ptid (++p, NULL); + break; + } case 'W': /* Target exited. */ case 'X': { @@ -6522,6 +6713,10 @@ Packet: '%s'\n"), event->ptid = pid_to_ptid (pid); } break; + case 'N': + event->ws.kind = TARGET_WAITKIND_NO_RESUMED; + event->ptid = minus_one_ptid; + break; } if (target_is_non_stop_p () && ptid_equal (event->ptid, null_ptid)) @@ -6623,7 +6818,8 @@ process_stop_reply (struct stop_reply *stop_reply, ptid = inferior_ptid; if (status->kind != TARGET_WAITKIND_EXITED - && status->kind != TARGET_WAITKIND_SIGNALLED) + && status->kind != TARGET_WAITKIND_SIGNALLED + && status->kind != TARGET_WAITKIND_NO_RESUMED) { struct remote_state *rs = get_remote_state (); struct private_thread_info *remote_thr; @@ -6801,7 +6997,7 @@ remote_wait_as (ptid_t ptid, struct target_waitstatus *status, int options) remote_fileio_request (buf, rs->ctrlc_pending_p); rs->ctrlc_pending_p = 0; break; - case 'T': case 'S': case 'X': case 'W': + case 'N': case 'T': case 'S': case 'X': case 'W': { struct stop_reply *stop_reply; @@ -6840,7 +7036,9 @@ remote_wait_as (ptid_t ptid, struct target_waitstatus *status, int options) break; } - if (status->kind == TARGET_WAITKIND_IGNORE) + if (status->kind == TARGET_WAITKIND_NO_RESUMED) + return minus_one_ptid; + else if (status->kind == TARGET_WAITKIND_IGNORE) { /* Nothing interesting happened. If we're doing a non-blocking poll, we're done. Otherwise, go back to waiting. */ @@ -8710,42 +8908,53 @@ kill_new_fork_children (int pid, struct remote_state *rs) } +/* Target hook to kill the current inferior. */ + static void remote_kill (struct target_ops *ops) { + int res = -1; + int pid = ptid_get_pid (inferior_ptid); + struct remote_state *rs = get_remote_state (); - /* Catch errors so the user can quit from gdb even when we - aren't on speaking terms with the remote system. */ - TRY + if (packet_support (PACKET_vKill) != PACKET_DISABLE) { - putpkt ("k"); - } - CATCH (ex, RETURN_MASK_ERROR) - { - if (ex.error == TARGET_CLOSE_ERROR) + /* If we're stopped while forking and we haven't followed yet, + kill the child task. We need to do this before killing the + parent task because if this is a vfork then the parent will + be sleeping. */ + kill_new_fork_children (pid, rs); + + res = remote_vkill (pid, rs); + if (res == 0) { - /* If we got an (EOF) error that caused the target - to go away, then we're done, that's what we wanted. - "k" is susceptible to cause a premature EOF, given - that the remote server isn't actually required to - reply to "k", and it can happen that it doesn't - even get to reply ACK to the "k". */ + target_mourn_inferior (); return; } + } - /* Otherwise, something went wrong. We didn't actually kill - the target. Just propagate the exception, and let the - user or higher layers decide what to do. */ - throw_exception (ex); + /* If we are in 'target remote' mode and we are killing the only + 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) + { + remote_kill_k (); + + /* We've killed the remote end, we get to mourn it. If we are + not in extended mode, mourning the inferior also unpushes + remote_ops from the target stack, which closes the remote + connection. */ + target_mourn_inferior (); + + return; } - END_CATCH - /* We've killed the remote end, we get to mourn it. Since this is - target remote, single-process, mourning the inferior also - unpushes remote_ops. */ - target_mourn_inferior (); + error (_("Can't kill process")); } +/* Send a kill request to the target using the 'vKill' packet. */ + static int remote_vkill (int pid, struct remote_state *rs) { @@ -8771,55 +8980,52 @@ remote_vkill (int pid, struct remote_state *rs) } } +/* Send a kill request to the target using the 'k' packet. */ + static void -extended_remote_kill (struct target_ops *ops) +remote_kill_k (void) { - int res; - int pid = ptid_get_pid (inferior_ptid); - struct remote_state *rs = get_remote_state (); - - /* If we're stopped while forking and we haven't followed yet, kill the - child task. We need to do this before killing the parent task - because if this is a vfork then the parent will be sleeping. */ - kill_new_fork_children (pid, rs); - - res = remote_vkill (pid, rs); - if (res == -1 && !(rs->extended && remote_multi_process_p (rs))) + /* Catch errors so the user can quit from gdb even when we + aren't on speaking terms with the remote system. */ + TRY { - /* Don't try 'k' on a multi-process aware stub -- it has no way - to specify the pid. */ - putpkt ("k"); -#if 0 - getpkt (&rs->buf, &rs->buf_size, 0); - if (rs->buf[0] != 'O' || rs->buf[0] != 'K') - res = 1; -#else - /* Don't wait for it to die. I'm not really sure it matters whether - we do or not. For the existing stubs, kill is a noop. */ - res = 0; -#endif } + CATCH (ex, RETURN_MASK_ERROR) + { + if (ex.error == TARGET_CLOSE_ERROR) + { + /* If we got an (EOF) error that caused the target + to go away, then we're done, that's what we wanted. + "k" is susceptible to cause a premature EOF, given + that the remote server isn't actually required to + reply to "k", and it can happen that it doesn't + even get to reply ACK to the "k". */ + return; + } - if (res != 0) - error (_("Can't kill process")); - - target_mourn_inferior (); + /* Otherwise, something went wrong. We didn't actually kill + the target. Just propagate the exception, and let the + user or higher layers decide what to do. */ + throw_exception (ex); + } + END_CATCH } static void remote_mourn (struct target_ops *target) { - unpush_target (target); + struct remote_state *rs = get_remote_state (); - /* remote_close takes care of doing most of the clean up. */ - generic_mourn_inferior (); -} + /* In 'target remote' mode with one inferior, we close the connection. */ + if (!rs->extended && number_of_live_inferiors () <= 1) + { + unpush_target (target); -static void -extended_remote_mourn (struct target_ops *target) -{ - struct remote_state *rs = get_remote_state (); + /* remote_close takes care of doing most of the clean up. */ + generic_mourn_inferior (); + return; + } /* In case we got here due to an error, but we're going to stay connected. */ @@ -8850,10 +9056,7 @@ extended_remote_mourn (struct target_ops *target) current thread. */ record_currthread (rs, minus_one_ptid); - /* Unlike "target remote", we do not want to unpush the target; then - the next time the user says "run", we won't be connected. */ - - /* Call common code to mark the inferior as not running. */ + /* Call common code to mark the inferior as not running. */ generic_mourn_inferior (); if (!have_inferiors ()) @@ -10375,7 +10578,7 @@ remote_pid_to_str (struct target_ops *ops, ptid_t ptid) { if (ptid_equal (magic_null_ptid, ptid)) xsnprintf (buf, sizeof buf, "Thread
"); - else if (rs->extended && remote_multi_process_p (rs)) + else if (remote_multi_process_p (rs)) if (ptid_get_lwp (ptid) == 0) return normal_pid_to_str (ptid); else @@ -11545,11 +11748,7 @@ remote_supports_multi_process (struct target_ops *self) { struct remote_state *rs = get_remote_state (); - /* Only extended-remote handles being attached to multiple - processes, even though plain remote can use the multi-process - thread id extensions, so that GDB knows the target process's - PID. */ - return rs->extended && remote_multi_process_p (rs); + return remote_multi_process_p (rs); } static int @@ -12885,6 +13084,7 @@ Specify the serial device it is connected to\n\ remote_ops.to_load = remote_load; remote_ops.to_mourn_inferior = remote_mourn; remote_ops.to_pass_signals = remote_pass_signals; + remote_ops.to_set_syscall_catchpoint = remote_set_syscall_catchpoint; remote_ops.to_program_signals = remote_program_signals; remote_ops.to_thread_alive = remote_thread_alive; remote_ops.to_thread_name = remote_thread_name; @@ -12917,6 +13117,7 @@ Specify the serial device it is connected to\n\ remote_ops.to_can_async_p = remote_can_async_p; remote_ops.to_is_async_p = remote_is_async_p; remote_ops.to_async = remote_async; + remote_ops.to_thread_events = remote_thread_events; remote_ops.to_can_do_single_step = remote_can_do_single_step; remote_ops.to_terminal_inferior = remote_terminal_inferior; remote_ops.to_terminal_ours = remote_terminal_ours; @@ -12980,6 +13181,14 @@ Specify the serial device it is connected to\n\ remote_ops.to_btrace_conf = remote_btrace_conf; remote_ops.to_augmented_libraries_svr4_read = remote_augmented_libraries_svr4_read; + remote_ops.to_follow_fork = remote_follow_fork; + remote_ops.to_follow_exec = remote_follow_exec; + remote_ops.to_insert_fork_catchpoint = remote_insert_fork_catchpoint; + remote_ops.to_remove_fork_catchpoint = remote_remove_fork_catchpoint; + remote_ops.to_insert_vfork_catchpoint = remote_insert_vfork_catchpoint; + remote_ops.to_remove_vfork_catchpoint = remote_remove_vfork_catchpoint; + remote_ops.to_insert_exec_catchpoint = remote_insert_exec_catchpoint; + remote_ops.to_remove_exec_catchpoint = remote_remove_exec_catchpoint; } /* Set up the extended remote vector by making a copy of the standard @@ -12998,27 +13207,11 @@ init_extended_remote_ops (void) Specify the serial device it is connected to (e.g. /dev/ttya)."; extended_remote_ops.to_open = extended_remote_open; extended_remote_ops.to_create_inferior = extended_remote_create_inferior; - extended_remote_ops.to_mourn_inferior = extended_remote_mourn; extended_remote_ops.to_detach = extended_remote_detach; extended_remote_ops.to_attach = extended_remote_attach; extended_remote_ops.to_post_attach = extended_remote_post_attach; - extended_remote_ops.to_kill = extended_remote_kill; extended_remote_ops.to_supports_disable_randomization = extended_remote_supports_disable_randomization; - extended_remote_ops.to_follow_fork = remote_follow_fork; - extended_remote_ops.to_follow_exec = remote_follow_exec; - extended_remote_ops.to_insert_fork_catchpoint - = remote_insert_fork_catchpoint; - extended_remote_ops.to_remove_fork_catchpoint - = remote_remove_fork_catchpoint; - extended_remote_ops.to_insert_vfork_catchpoint - = remote_insert_vfork_catchpoint; - extended_remote_ops.to_remove_vfork_catchpoint - = remote_remove_vfork_catchpoint; - extended_remote_ops.to_insert_exec_catchpoint - = remote_insert_exec_catchpoint; - extended_remote_ops.to_remove_exec_catchpoint - = remote_remove_exec_catchpoint; } static int @@ -13102,6 +13295,37 @@ remote_async (struct target_ops *ops, int enable) } } +/* Implementation of the to_thread_events method. */ + +static void +remote_thread_events (struct target_ops *ops, int enable) +{ + struct remote_state *rs = get_remote_state (); + size_t size = get_remote_packet_size (); + char *p = rs->buf; + + if (packet_support (PACKET_QThreadEvents) == PACKET_DISABLE) + return; + + xsnprintf (rs->buf, size, "QThreadEvents:%x", enable ? 1 : 0); + putpkt (rs->buf); + getpkt (&rs->buf, &rs->buf_size, 0); + + switch (packet_ok (rs->buf, + &remote_protocol_packets[PACKET_QThreadEvents])) + { + case PACKET_OK: + if (strcmp (rs->buf, "OK") != 0) + error (_("Remote refused setting thread events: %s"), rs->buf); + break; + case PACKET_ERROR: + warning (_("Remote failure reply: %s"), rs->buf); + break; + case PACKET_UNKNOWN: + break; + } +} + static void set_remote_cmd (char *args, int from_tty) { @@ -13427,6 +13651,9 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL, add_packet_config_cmd (&remote_protocol_packets[PACKET_QPassSignals], "QPassSignals", "pass-signals", 0); + add_packet_config_cmd (&remote_protocol_packets[PACKET_QCatchSyscalls], + "QCatchSyscalls", "catch-syscalls", 0); + add_packet_config_cmd (&remote_protocol_packets[PACKET_QProgramSignals], "QProgramSignals", "program-signals", 0); @@ -13643,6 +13870,15 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL, add_packet_config_cmd (&remote_protocol_packets[PACKET_exec_event_feature], "exec-event-feature", "exec-event-feature", 0); + add_packet_config_cmd (&remote_protocol_packets[PACKET_vCtrlC], + "vCtrlC", "ctrl-c", 0); + + add_packet_config_cmd (&remote_protocol_packets[PACKET_QThreadEvents], + "QThreadEvents", "thread-events", 0); + + add_packet_config_cmd (&remote_protocol_packets[PACKET_no_resumed], + "N stop reply", "no-resumed-stop-reply", 0); + /* Assert that we've registered "set remote foo-packet" commands for all packet configs. */ {