diff --git a/gdb/NEWS b/gdb/NEWS index 0cf51e1858b5..f68de613a393 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -55,6 +55,18 @@ show remote multiprocess-extensions-packet * Support for reading/writing memory and extracting values on architectures whose memory is addressable in units of any integral multiple of 8 bits. +* New remote packets + +QCatchSyscalls:1 [;SYSNO]... +QCatchSyscalls:0 + Enable ("QCatchSyscalls:1") or disable ("QCatchSyscalls:0") + catching syscalls from the inferior process. + +* New features in the GDB remote stub, GDBserver + + ** GDBserver now supports catch syscall. Currently enabled + on x86/x86_64 GNU/Linux targets. + *** Changes in GDB 7.10 * Support for process record-replay and reverse debugging on aarch64*-linux* diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index cd0abad9bb11..f26d5f7ab2f8 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -20129,6 +20129,10 @@ are: @tab @code{qSupported} @tab Remote communications parameters +@item @code{catch-syscalls} +@tab @code{QCatchSyscalls} +@tab @code{catch syscall} + @item @code{pass-signals} @tab @code{QPassSignals} @tab @code{handle @var{signal}} @@ -35422,6 +35426,11 @@ The currently defined stop reasons are: The packet indicates a watchpoint hit, and @var{r} is the data address, in hex. +@item syscall_entry +@itemx syscall_return +The packet indicates a syscall entry or return, and @var{r} is the +syscall number, in hex. + @cindex shared library events, remote reply @item library The packet indicates that the loaded libraries have changed. @@ -35870,6 +35879,44 @@ by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}). Use of this packet is controlled by the @code{set non-stop} command; @pxref{Non-Stop Mode}. +@item QCatchSyscalls:1 @r{[};@var{sysno}@r{]}@dots{} +@itemx QCatchSyscalls:0 +@cindex catch syscalls from inferior, remote request +@cindex @samp{QCatchSyscalls} packet +@anchor{QCatchSyscalls} +Enable (@samp{QCatchSyscalls:1}) or disable (@samp{QCatchSyscalls:0}) +catching syscalls from the inferior process. + +For @samp{QCatchSyscalls:1}, each listed syscall @var{sysno} (encoded +in hex) should be reported to @value{GDBN}. If no syscall @var{sysno} +is listed, every system call should be reported. + +Note that if a syscall not member of the list is reported, @value{GDBN} +will filter it if this syscall is not caught. It is however more efficient +to only report the needed syscalls. + +Multiple @samp{QCatchSyscalls:1} packets do not +combine; any earlier @samp{QCatchSyscalls:1} list is completely replaced by the +new list. + +Reply: +@table @samp +@item OK +The request succeeded. + +@item E @var{nn} +An error occurred. @var{nn} are hex digits. + +@item @w{} +An empty reply indicates that @samp{QCatchSyscalls} is not supported by +the stub. +@end table + +Use of this packet is controlled by the @code{set remote catch-syscalls} +command (@pxref{Remote Configuration, set remote catch-syscalls}). +This packet is not probed by default; the remote stub must request it, +by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}). + @item QPassSignals: @var{signal} @r{[};@var{signal}@r{]}@dots{} @cindex pass signals to inferior, remote request @cindex @samp{QPassSignals} packet @@ -36278,6 +36325,11 @@ These are the currently defined stub features and their properties: @tab @samp{-} @tab Yes +@item @samp{QCatchSyscalls} +@tab No +@tab @samp{-} +@tab Yes + @item @samp{QPassSignals} @tab No @tab @samp{-} @@ -36466,6 +36518,10 @@ packet (@pxref{qXfer fdpic loadmap read}). The remote stub understands the @samp{QNonStop} packet (@pxref{QNonStop}). +@item QCatchSyscalls +The remote stub understands the @samp{QCatchSyscalls} packet +(@pxref{QCatchSyscalls}). + @item QPassSignals The remote stub understands the @samp{QPassSignals} packet (@pxref{QPassSignals}). diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index 4256bc56bce5..0987dee7443b 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -74,6 +74,11 @@ #define W_STOPCODE(sig) ((sig) << 8 | 0x7f) #endif +/* Unlike other extended result codes, WSTOPSIG (status) on + PTRACE_O_TRACESYSGOOD syscall events doesn't return SIGTRAP, but + instead SIGTRAP with bit 7 set. */ +#define SYSCALL_SIGTRAP (SIGTRAP | 0x80) + /* This is the kernel's hard limit. Not to be confused with SIGRTMIN. */ #ifndef __SIGRTMIN @@ -601,6 +606,38 @@ get_pc (struct lwp_info *lwp) return pc; } +/* This function should only be called if LWP got a SIGTRAP_SYSCALL. + Fill *SYSNO with the syscall nr trapped. Fill *SYSRET with the + return code. */ + +static void +get_syscall_trapinfo (struct lwp_info *lwp, int *sysno, int *sysret) +{ + struct thread_info *saved_thread; + struct regcache *regcache; + + if (the_low_target.get_syscall_trapinfo == NULL) + { + /* If we cannot get the syscall trapinfo, report an unknown + system call using -1 values. */ + *sysno = -1; + *sysret = -1; + return; + } + + saved_thread = current_thread; + current_thread = get_lwp_thread (lwp); + + regcache = get_thread_regcache (current_thread, 1); + (*the_low_target.get_syscall_trapinfo) (regcache, sysno, sysret); + + if (debug_threads) + fprintf (stderr, "get_syscall_trapinfo sysno %d sysret %d\n", + *sysno, *sysret); + + current_thread = saved_thread; +} + /* This function should only be called if LWP got a SIGTRAP. The SIGTRAP could mean several things. @@ -2098,6 +2135,8 @@ linux_low_ptrace_options (int attached) if (report_vfork_events) options |= (PTRACE_O_TRACEVFORK | PTRACE_O_TRACEVFORKDONE); + options |= PTRACE_O_TRACESYSGOOD; + return options; } @@ -2165,8 +2204,18 @@ linux_low_filter_event (int lwpid, int wstat) { struct process_info *proc; - /* Architecture-specific setup after inferior is running. */ proc = find_process_pid (pid_of (thread)); + + /* Set ptrace flags ASAP, so no events can be missed. */ + if (child->must_set_ptrace_flags) + { + int options = linux_low_ptrace_options (proc->attached); + + linux_enable_event_reporting (lwpid, options); + child->must_set_ptrace_flags = 0; + } + + /* Architecture-specific setup after inferior is running. */ if (proc->tdesc == NULL) { if (proc->attached) @@ -2195,15 +2244,6 @@ linux_low_filter_event (int lwpid, int wstat) } } - if (WIFSTOPPED (wstat) && child->must_set_ptrace_flags) - { - struct process_info *proc = find_process_pid (pid_of (thread)); - int options = linux_low_ptrace_options (proc->attached); - - linux_enable_event_reporting (lwpid, options); - child->must_set_ptrace_flags = 0; - } - /* Be careful to not overwrite stop_pc until check_stopped_by_breakpoint is called. */ if (WIFSTOPPED (wstat) && WSTOPSIG (wstat) == SIGTRAP @@ -2805,6 +2845,29 @@ ignore_event (struct target_waitstatus *ourstatus) return null_ptid; } +/* Returns 1 if GDB is interested in the event_child syscall. + Only to be called when stopped reason is SIGTRAP_SYSCALL. */ + +static int +gdb_catch_this_syscall_p (struct lwp_info *event_child) +{ + int i; + int sysno, sysret; + + if (!catching_syscalls_p) + return 0; + + if (syscalls_to_catch_size == 0) + return 1; + + get_syscall_trapinfo (event_child, &sysno, &sysret); + for (i = 0; i < syscalls_to_catch_size; i++) + if (syscalls_to_catch[i] == sysno) + return 1; + + return 0; +} + /* Wait for process, returns status. */ static ptid_t @@ -3110,6 +3173,19 @@ linux_wait_1 (ptid_t ptid, /* Check whether GDB would be interested in this event. */ + /* Check if GDB is interested in this syscall. */ + if (WIFSTOPPED (w) + && WSTOPSIG (w) == SYSCALL_SIGTRAP + && !gdb_catch_this_syscall_p (event_child)) + { + if (debug_threads) + fprintf (stderr, "Ignored syscall for LWP %ld.\n", + lwpid_of (current_thread)); + linux_resume_one_lwp (event_child, event_child->stepping, + 0, NULL); + return ignore_event (ourstatus); + } + /* If GDB is not interested in this signal, don't stop other threads, and don't report it to GDB. Just resume the inferior right away. We do this for threading-related signals as well as @@ -3364,7 +3440,24 @@ linux_wait_1 (ptid_t ptid, } } - if (current_thread->last_resume_kind == resume_stop + if (WSTOPSIG (w) == SYSCALL_SIGTRAP) + { + int sysret; + + get_syscall_trapinfo (event_child, + &ourstatus->value.syscall_number, &sysret); + /* Differentiate entry from return using the return code + -ENOSYS. This is not ideal as a syscall return from a not + implemented syscall will be seen as an entry. However, this + resists well to enabling/disabling catch syscall at various + moment. A better way to differentiate entry/return in GDB + and GDBSERVER would be nice. */ + if (sysret == -ENOSYS) + ourstatus->kind = TARGET_WAITKIND_SYSCALL_ENTRY; + else + ourstatus->kind = TARGET_WAITKIND_SYSCALL_RETURN; + } + else if (current_thread->last_resume_kind == resume_stop && WSTOPSIG (w) == SIGSTOP) { /* A thread that has been requested to stop by GDB with vCont;t, @@ -3782,6 +3875,7 @@ linux_resume_one_lwp_throw (struct lwp_info *lwp, struct thread_info *thread = get_lwp_thread (lwp); struct thread_info *saved_thread; int fast_tp_collecting; + int ptrace_request; struct process_info *proc = get_thread_process (thread); /* Note that target description may not be initialised @@ -3967,7 +4061,14 @@ linux_resume_one_lwp_throw (struct lwp_info *lwp, regcache_invalidate_thread (thread); errno = 0; lwp->stepping = step; - ptrace (step ? PTRACE_SINGLESTEP : PTRACE_CONT, lwpid_of (thread), + if (step) + ptrace_request = PTRACE_SINGLESTEP; + else if (catching_syscalls_p) + ptrace_request = PTRACE_SYSCALL; + else + ptrace_request = PTRACE_CONT; + ptrace (ptrace_request, + lwpid_of (thread), (PTRACE_TYPE_ARG3) 0, /* Coerce to a uintptr_t first to avoid potential gcc warning of coercing an 8 byte integer to a 4 byte pointer. */ @@ -6047,6 +6148,13 @@ linux_process_qsupported (const char *query) } static int +linux_supports_catch_syscall (void) +{ + return (the_low_target.get_syscall_trapinfo != NULL + && linux_supports_tracesysgood()); +} + +static int linux_supports_tracepoints (void) { if (*the_low_target.supports_tracepoints == NULL) @@ -6900,6 +7008,7 @@ static struct target_ops linux_target_ops = { linux_common_core_of_thread, linux_read_loadmap, linux_process_qsupported, + linux_supports_catch_syscall, linux_supports_tracepoints, linux_read_pc, linux_write_pc, diff --git a/gdb/gdbserver/linux-low.h b/gdb/gdbserver/linux-low.h index f8f6e78a0017..05287ef1668e 100644 --- a/gdb/gdbserver/linux-low.h +++ b/gdb/gdbserver/linux-low.h @@ -191,6 +191,12 @@ struct linux_target_ops /* Hook to support target specific qSupported. */ void (*process_qsupported) (const char *); + /* Fill *SYSNO with the syscall nr trapped. Fill *SYSRET with the + return code. Only to be called when inferior is stopped + due to SYSCALL_SIGTRAP. */ + void (*get_syscall_trapinfo) (struct regcache *regcache, + int *sysno, int *sysret); + /* Returns true if the low target supports tracepoints. */ int (*supports_tracepoints) (void); diff --git a/gdb/gdbserver/linux-x86-low.c b/gdb/gdbserver/linux-x86-low.c index 20d4257e5fb0..a64ad2fe01a5 100644 --- a/gdb/gdbserver/linux-x86-low.c +++ b/gdb/gdbserver/linux-x86-low.c @@ -1432,6 +1432,36 @@ x86_arch_setup (void) current_process ()->tdesc = x86_linux_read_description (); } +/* Fill *SYSNO and *SYSRET with the syscall nr trapped and the syscall return + code. This should only be called if LWP got a SIGTRAP_SYSCALL. */ + +static void +x86_get_syscall_trapinfo (struct regcache *regcache, int *sysno, int *sysret) +{ + int use_64bit = register_size (regcache->tdesc, 0) == 8; + + if (use_64bit) + { + long l_sysno; + long l_sysret; + + collect_register_by_name (regcache, "orig_rax", &l_sysno); + collect_register_by_name (regcache, "rax", &l_sysret); + *sysno = (int) l_sysno; + *sysret = (int) l_sysret; + } + else + { + int l_sysno; + int l_sysret; + + collect_register_by_name (regcache, "orig_eax", &l_sysno); + collect_register_by_name (regcache, "eax", &l_sysret); + *sysno = (int) l_sysno; + *sysret = (int) l_sysret; + } +} + static int x86_supports_tracepoints (void) { @@ -3283,6 +3313,7 @@ struct linux_target_ops the_low_target = x86_linux_new_fork, x86_linux_prepare_to_resume, x86_linux_process_qsupported, + x86_get_syscall_trapinfo, x86_supports_tracepoints, x86_get_thread_area, x86_install_fast_tracepoint_jump_pad, diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c index 0c4a69364396..060739387568 100644 --- a/gdb/gdbserver/remote-utils.c +++ b/gdb/gdbserver/remote-utils.c @@ -1117,6 +1117,8 @@ prepare_resume_reply (char *buf, ptid_t ptid, case TARGET_WAITKIND_STOPPED: case TARGET_WAITKIND_FORKED: case TARGET_WAITKIND_VFORKED: + case TARGET_WAITKIND_SYSCALL_ENTRY: + case TARGET_WAITKIND_SYSCALL_RETURN: { struct thread_info *saved_thread; const char **regp; @@ -1134,6 +1136,16 @@ prepare_resume_reply (char *buf, ptid_t ptid, buf = write_ptid (buf, status->value.related_pid); strcat (buf, ";"); } + else if ((status->kind == TARGET_WAITKIND_SYSCALL_ENTRY) + || (status->kind == TARGET_WAITKIND_SYSCALL_RETURN)) + { + enum gdb_signal signal = GDB_SIGNAL_TRAP; + const char *event = (status->kind == TARGET_WAITKIND_SYSCALL_ENTRY + ? "syscall_entry" : "syscall_return"); + + sprintf (buf, "T%02x%s:%x;", signal, event, + status->value.syscall_number); + } else sprintf (buf, "T%02x", status->value.sig); diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index c52cf168d946..27ae4fa0771c 100644 --- a/gdb/gdbserver/server.c +++ b/gdb/gdbserver/server.c @@ -73,6 +73,10 @@ int pass_signals[GDB_SIGNAL_LAST]; int program_signals[GDB_SIGNAL_LAST]; int program_signals_p; +int catching_syscalls_p; +int syscalls_to_catch_size; +int *syscalls_to_catch; + /* 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 @@ -586,6 +590,46 @@ handle_general_set (char *own_buf) return; } + if (startswith (own_buf, "QCatchSyscalls:1")) + { + int i; + const char *p; + CORE_ADDR sysno; + + catching_syscalls_p = 1; + if (syscalls_to_catch != NULL) + { + xfree (syscalls_to_catch); + syscalls_to_catch = NULL; + } + syscalls_to_catch_size = 0; + p = own_buf + strlen("QCatchSyscalls:1"); + while (*p) + { + if (*p++ == ';') + syscalls_to_catch_size++; + } + if (syscalls_to_catch_size > 0) + { + syscalls_to_catch = xmalloc (syscalls_to_catch_size * sizeof (int)); + p = strchr(own_buf, ';') + 1; + for (i = 0; i < syscalls_to_catch_size; i++) + { + p = decode_address_to_semicolon (&sysno, p); + syscalls_to_catch[i] = (int) sysno; + } + } + strcpy (own_buf, "OK"); + return; + } + + if (strcmp ("QCatchSyscalls:0", own_buf) == 0) + { + catching_syscalls_p = 0; + strcpy (own_buf, "OK"); + return; + } + if (startswith (own_buf, "QProgramSignals:")) { int numsigs = (int) GDB_SIGNAL_LAST, i; @@ -2124,6 +2168,9 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p) "PacketSize=%x;QPassSignals+;QProgramSignals+", PBUFSIZ - 1); + if (target_supports_catch_syscall ()) + strcat (own_buf, ";QCatchSyscalls+"); + if (the_target->qxfer_libraries_svr4 != NULL) strcat (own_buf, ";qXfer:libraries-svr4:read+" ";augmented-libraries-svr4-read+"); diff --git a/gdb/gdbserver/server.h b/gdb/gdbserver/server.h index 6020d7206d60..08ec11b3dbba 100644 --- a/gdb/gdbserver/server.h +++ b/gdb/gdbserver/server.h @@ -77,6 +77,14 @@ extern int pass_signals[]; extern int program_signals[]; extern int program_signals_p; +/* Set to 1 if GDB is catching some (or all) syscalls, zero otherwise. */ +extern int catching_syscalls_p; +/* syscalls_to_catch is the list of syscalls to report to GDB. + If catching_syscalls_p and syscalls_to_catch == NULL, it means + all syscalls must be reported. */ +extern int syscalls_to_catch_size; +extern int *syscalls_to_catch; + extern int disable_packet_vCont; extern int disable_packet_Tthread; extern int disable_packet_qC; diff --git a/gdb/gdbserver/target.h b/gdb/gdbserver/target.h index 3e3b80fe2c5d..93d8dcc62d80 100644 --- a/gdb/gdbserver/target.h +++ b/gdb/gdbserver/target.h @@ -307,6 +307,10 @@ struct target_ops /* Target specific qSupported support. */ void (*process_qsupported) (const char *); + /* Return 1 if the target supports catch syscall, 0 (or leave the + callback NULL) otherwise. */ + int (*supports_catch_syscall) (void); + /* Return 1 if the target supports tracepoints, 0 (or leave the callback NULL) otherwise. */ int (*supports_tracepoints) (void); @@ -510,6 +514,10 @@ int kill_inferior (int); the_target->process_qsupported (query); \ } while (0) +#define target_supports_catch_syscall() \ + (the_target->supports_catch_syscall ? \ + (*the_target->supports_catch_syscall) () : 0) + #define target_supports_tracepoints() \ (the_target->supports_tracepoints \ ? (*the_target->supports_tracepoints) () : 0) diff --git a/gdb/gdbserver/win32-low.c b/gdb/gdbserver/win32-low.c index 86386ce70c84..97c324e24932 100644 --- a/gdb/gdbserver/win32-low.c +++ b/gdb/gdbserver/win32-low.c @@ -1837,6 +1837,7 @@ static struct target_ops win32_target_ops = { NULL, /* core_of_thread */ NULL, /* read_loadmap */ NULL, /* process_qsupported */ + NULL, /* supports_catch_syscall */ NULL, /* supports_tracepoints */ NULL, /* read_pc */ NULL, /* write_pc */ diff --git a/gdb/remote.c b/gdb/remote.c index 3afcaf41c93b..ffb2dd55245f 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -1317,6 +1317,7 @@ enum { PACKET_qSupported, PACKET_qTStatus, PACKET_QPassSignals, + PACKET_QCatchSyscalls, PACKET_QProgramSignals, PACKET_qCRC, PACKET_qSearch_memory, @@ -1868,6 +1869,99 @@ 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, *p; + enum packet_result result; + int n_sysno = 0; + + if (remote_protocol_packets[PACKET_QCatchSyscalls].support == 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]) + 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 char *q1 = "QCatchSyscalls:1"; + int i; + const int maxpktsz = strlen (q1) + n_sysno * 9 + 1; + + catch_packet = xmalloc (maxpktsz); + strcpy (catch_packet, q1); + if (!any_count) + { + 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]) + { + xsnprintf (p, catch_packet + maxpktsz - p, + ";%x", i); + p += strlen (p); + } + } + } + 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[strlen (q1)] = 0; + } + } + else + { + catch_packet = xmalloc (strlen ("QCatchSyscalls:0") + 1); + strcpy (catch_packet, "QCatchSyscalls:0"); + } + + { + struct remote_state *rs = get_remote_state (); + char *buf = rs->buf; + + putpkt (catch_packet); + getpkt (&rs->buf, &rs->buf_size, 0); + result = packet_ok (buf, + &remote_protocol_packets[PACKET_QCatchSyscalls]); + xfree (catch_packet); + 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. */ @@ -4219,6 +4313,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, @@ -6021,6 +6117,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")) @@ -12543,6 +12655,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_update_thread_list = remote_update_thread_list; @@ -13062,6 +13175,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); diff --git a/gdb/testsuite/gdb.base/catch-syscall.exp b/gdb/testsuite/gdb.base/catch-syscall.exp index 499da322267c..26743813919d 100644 --- a/gdb/testsuite/gdb.base/catch-syscall.exp +++ b/gdb/testsuite/gdb.base/catch-syscall.exp @@ -19,7 +19,15 @@ # It was written by Sergio Durigan Junior # on September/2008. -if { [is_remote target] || ![isnative] } then { +if { ![isnative] } then { + continue +} + +# This shall be updated whenever QCatchSyscalls packet support is implemented +# on some gdbserver architecture. +if { [is_remote target] + && ![istarget "x86_64-*-linux*"] + && ![istarget "i\[34567\]86-*-linux*"] } { continue }