Commit 82075af2 authored by Josh Stone's avatar Josh Stone
Browse files

Implement 'catch syscall' for gdbserver

This adds a new QCatchSyscalls packet to enable 'catch syscall', and new
stop reasons "syscall_entry" and "syscall_return" for those events.  It
is currently only supported on Linux x86 and x86_64.

gdb/ChangeLog:

2016-01-12  Josh Stone  <jistone@redhat.com>
	    Philippe Waroquiers  <philippe.waroquiers@skynet.be>

	* NEWS (Changes since GDB 7.10): Mention QCatchSyscalls and the
	syscall_entry and syscall_return stop reasons.  Mention GDB
	support for remote catch syscall.
	* remote.c (PACKET_QCatchSyscalls): New enum.
	(remote_set_syscall_catchpoint): New function.
	(remote_protocol_features): New element for QCatchSyscalls.
	(remote_parse_stop_reply): Parse syscall_entry/return stops.
	(init_remote_ops): Install remote_set_syscall_catchpoint.
	(_initialize_remote): Config QCatchSyscalls.
	* linux-nat.h (struct lwp_info) <syscall_state>: Comment typo.

gdb/doc/ChangeLog:

2016-01-12  Josh Stone  <jistone@redhat.com>
	    Philippe Waroquiers  <philippe.waroquiers@skynet.be>

	* gdb.texinfo (Remote Configuration): List the QCatchSyscalls packet.
	(Stop Reply Packets): List the syscall entry and return stop reasons.
	(General Query Packets): Describe QCatchSyscalls, and add it to the
	table and the detailed list of stub features.

gdb/gdbserver/ChangeLog:

2016-01-12  Josh Stone  <jistone@redhat.com>
	    Philippe Waroquiers  <philippe.waroquiers@skynet.be>

	* inferiors.h: Include "gdb_vecs.h".
	(struct process_info): Add syscalls_to_catch.
	* inferiors.c (remove_process): Free syscalls_to_catch.
	* remote-utils.c (prepare_resume_reply): Report syscall_entry and
	syscall_return stops.
	* server.h (UNKNOWN_SYSCALL, ANY_SYSCALL): Define.
	* server.c (handle_general_set): Handle QCatchSyscalls.
	(handle_query): Report support for QCatchSyscalls.
	* target.h (struct target_ops): Add supports_catch_syscall.
	(target_supports_catch_syscall): New macro.
	* linux-low.h (struct linux_target_ops): Add get_syscall_trapinfo.
	(struct lwp_info): Add syscall_state.
	* linux-low.c (handle_extended_wait): Mark syscall_state as an entry.
	Maintain syscall_state and syscalls_to_catch across exec.
	(get_syscall_trapinfo): New function, proxy to the_low_target.
	(linux_low_ptrace_options): Enable PTRACE_O_TRACESYSGOOD.
	(linux_low_filter_event): Toggle syscall_state entry/return for
	syscall traps, and set it ignored for all others.
	(gdb_catching_syscalls_p): New function.
	(gdb_catch_this_syscall_p): New function.
	(linux_wait_1): Handle SYSCALL_SIGTRAP.
	(linux_resume_one_lwp_throw): Add PTRACE_SYSCALL possibility.
	(linux_supports_catch_syscall): New function.
	(linux_target_ops): Install it.
	* linux-x86-low.c (x86_get_syscall_trapinfo): New function.
	(the_low_target): Install it.

gdb/testsuite/ChangeLog:

2016-01-12  Josh Stone  <jistone@redhat.com>
	    Philippe Waroquiers  <philippe.waroquiers@skynet.be>

	* gdb.base/catch-syscall.c (do_execve): New variable.
	(main): Conditionally trigger an execve.
	* gdb.base/catch-syscall.exp: Enable testing for remote targets.
	(test_catch_syscall_execve): New, check entry/return across execve.
	(do_syscall_tests): Call test_catch_syscall_execve.
parent 41549dfb
2016-01-12 Josh Stone <jistone@redhat.com>
Philippe Waroquiers <philippe.waroquiers@skynet.be>
* NEWS (Changes since GDB 7.10): Mention QCatchSyscalls and the
syscall_entry and syscall_return stop reasons. Mention GDB
support for remote catch syscall.
* remote.c (PACKET_QCatchSyscalls): New enum.
(remote_set_syscall_catchpoint): New function.
(remote_protocol_features): New element for QCatchSyscalls.
(remote_parse_stop_reply): Parse syscall_entry/return stops.
(init_remote_ops): Install remote_set_syscall_catchpoint.
(_initialize_remote): Config QCatchSyscalls.
* linux-nat.h (struct lwp_info) <syscall_state>: Comment typo.
2016-01-12 Yao Qi <yao.qi@linaro.org>
* nat/linux-ptrace.c (linux_child_function): Cast child_stack
......
......@@ -120,6 +120,21 @@ N stop reply
threads are stopped). The remote stub reports support for this stop
reply to GDB's qSupported query.
QCatchSyscalls:1 [;SYSNO]...
QCatchSyscalls:0
Enable ("QCatchSyscalls:1") or disable ("QCatchSyscalls:0")
catching syscalls from the inferior process.
syscall_entry stop reason
Indicates that a syscall was just called.
syscall_return stop reason
Indicates that a syscall just returned.
QCatchSyscalls:1 in qSupported
The qSupported packet may now include QCatchSyscalls:1 in the reply
to indicate support for catching syscalls.
* Extended-remote exec events
** GDB now has support for exec events on extended-remote Linux targets.
......@@ -142,6 +157,15 @@ show remote exec-event-feature-packet
this enables follow-fork-mode, detach-on-fork, follow-exec-mode, and
fork and exec catchpoints.
* Remote syscall events
** GDB now has support for catch syscall on remote Linux targets,
currently enabled on x86/x86_64 architectures.
set remote catch-syscall-packet
show remote catch-syscall-packet
Set/show the use of the remote catch syscall feature.
* MI changes
** The -var-set-format command now accepts the zero-hexadecimal
......
2016-01-12 Josh Stone <jistone@redhat.com>
Philippe Waroquiers <philippe.waroquiers@skynet.be>
* gdb.texinfo (Remote Configuration): List the QCatchSyscalls packet.
(Stop Reply Packets): List the syscall entry and return stop reasons.
(General Query Packets): Describe QCatchSyscalls, and add it to the
table and the detailed list of stub features.
2016-01-12 Pedro Alves <palves@redhat.com>
Remove use of the registered trademark symbol throughout.
......
......@@ -20261,6 +20261,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}}
......@@ -35580,6 +35584,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.
......@@ -36072,6 +36081,49 @@ 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 in the list is reported, @value{GDBN} will
still filter the event according to its own list from all corresponding
@code{catch syscall} commands. However, it is more efficient to only
report the requested syscalls.
Multiple @samp{QCatchSyscalls:1} packets do not combine; any earlier
@samp{QCatchSyscalls:1} list is completely replaced by the new list.
If the inferior process execs, the state of @samp{QCatchSyscalls} is
kept for the new process too. On targets where exec may affect syscall
numbers, for example with exec between 32 and 64-bit processes, the
client should send a new packet with the new syscall 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
......@@ -36523,6 +36575,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{-}
......@@ -36726,6 +36783,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}).
2016-01-12 Josh Stone <jistone@redhat.com>
Philippe Waroquiers <philippe.waroquiers@skynet.be>
* inferiors.h: Include "gdb_vecs.h".
(struct process_info): Add syscalls_to_catch.
* inferiors.c (remove_process): Free syscalls_to_catch.
* remote-utils.c (prepare_resume_reply): Report syscall_entry and
syscall_return stops.
* server.h (UNKNOWN_SYSCALL, ANY_SYSCALL): Define.
* server.c (handle_general_set): Handle QCatchSyscalls.
(handle_query): Report support for QCatchSyscalls.
* target.h (struct target_ops): Add supports_catch_syscall.
(target_supports_catch_syscall): New macro.
* linux-low.h (struct linux_target_ops): Add get_syscall_trapinfo.
(struct lwp_info): Add syscall_state.
* linux-low.c (handle_extended_wait): Mark syscall_state as an entry.
Maintain syscall_state and syscalls_to_catch across exec.
(get_syscall_trapinfo): New function, proxy to the_low_target.
(linux_low_ptrace_options): Enable PTRACE_O_TRACESYSGOOD.
(linux_low_filter_event): Toggle syscall_state entry/return for
syscall traps, and set it ignored for all others.
(gdb_catching_syscalls_p): New function.
(gdb_catch_this_syscall_p): New function.
(linux_wait_1): Handle SYSCALL_SIGTRAP.
(linux_resume_one_lwp_throw): Add PTRACE_SYSCALL possibility.
(linux_supports_catch_syscall): New function.
(linux_target_ops): Install it.
* linux-x86-low.c (x86_get_syscall_trapinfo): New function.
(the_low_target): Install it.
2016-01-12 Mike Frysinger <vapier@gentoo.org>
* acinclude.m4: Include new ../warning.m4 file.
......
......@@ -339,6 +339,7 @@ remove_process (struct process_info *process)
free_all_breakpoints (process);
gdb_assert (find_thread_process (process) == NULL);
remove_inferior (&all_processes, &process->entry);
VEC_free (int, process->syscalls_to_catch);
free (process);
}
......
......@@ -19,6 +19,8 @@
#ifndef INFERIORS_H
#define INFERIORS_H
#include "gdb_vecs.h"
/* Generic information for tracking a list of ``inferiors'' - threads,
processes, etc. */
struct inferior_list
......@@ -67,6 +69,10 @@ struct process_info
/* The list of installed fast tracepoints. */
struct fast_tracepoint_jump *fast_tracepoint_jumps;
/* The list of syscalls to report, or just a single element, ANY_SYSCALL,
for unfiltered syscall reporting. */
VEC (int) *syscalls_to_catch;
const struct target_desc *tdesc;
/* Private target data. */
......
......@@ -461,6 +461,11 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat)
gdb_assert (event_lwp->waitstatus.kind == TARGET_WAITKIND_IGNORE);
/* All extended events we currently use are mid-syscall. Only
PTRACE_EVENT_STOP is delivered more like a signal-stop, but
you have to be using PTRACE_SEIZE to get that. */
event_lwp->syscall_state = TARGET_WAITKIND_SYSCALL_ENTRY;
if ((event == PTRACE_EVENT_FORK) || (event == PTRACE_EVENT_VFORK)
|| (event == PTRACE_EVENT_CLONE))
{
......@@ -611,6 +616,7 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat)
else if (event == PTRACE_EVENT_EXEC && report_exec_events)
{
struct process_info *proc;
VEC (int) *syscalls_to_catch;
ptid_t event_ptid;
pid_t event_pid;
......@@ -624,8 +630,12 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat)
event_ptid = ptid_of (event_thr);
event_pid = ptid_get_pid (event_ptid);
/* Delete the execing process and all its threads. */
/* Save the syscall list from the execing process. */
proc = get_thread_process (event_thr);
syscalls_to_catch = proc->syscalls_to_catch;
proc->syscalls_to_catch = NULL;
/* Delete the execing process and all its threads. */
linux_mourn (proc);
current_thread = NULL;
......@@ -648,6 +658,14 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat)
event_thr->last_resume_kind = resume_continue;
event_thr->last_status.kind = TARGET_WAITKIND_IGNORE;
/* Update syscall state in the new lwp, effectively mid-syscall too. */
event_lwp->syscall_state = TARGET_WAITKIND_SYSCALL_ENTRY;
/* Restore the list to catch. Don't rely on the client, which is free
to avoid sending a new list when the architecture doesn't change.
Also, for ANY_SYSCALL, the architecture doesn't really matter. */
proc->syscalls_to_catch = syscalls_to_catch;
/* Report the event. */
*orig_event_lwp = event_lwp;
return 0;
......@@ -682,6 +700,40 @@ get_pc (struct lwp_info *lwp)
return pc;
}
/* This function should only be called if LWP got a SYSCALL_SIGTRAP.
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 number and -ENOSYS return value. */
*sysno = UNKNOWN_SYSCALL;
*sysret = -ENOSYS;
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)
{
debug_printf ("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.
......@@ -2236,6 +2288,8 @@ linux_low_ptrace_options (int attached)
if (report_exec_events)
options |= PTRACE_O_TRACEEXEC;
options |= PTRACE_O_TRACESYSGOOD;
return options;
}
......@@ -2364,6 +2418,21 @@ linux_low_filter_event (int lwpid, int wstat)
child->must_set_ptrace_flags = 0;
}
/* Always update syscall_state, even if it will be filtered later. */
if (WIFSTOPPED (wstat) && WSTOPSIG (wstat) == SYSCALL_SIGTRAP)
{
child->syscall_state
= (child->syscall_state == TARGET_WAITKIND_SYSCALL_ENTRY
? TARGET_WAITKIND_SYSCALL_RETURN
: TARGET_WAITKIND_SYSCALL_ENTRY);
}
else
{
/* Almost all other ptrace-stops are known to be outside of system
calls, with further exceptions in handle_extended_wait. */
child->syscall_state = TARGET_WAITKIND_IGNORE;
}
/* Be careful to not overwrite stop_pc until
check_stopped_by_breakpoint is called. */
if (WIFSTOPPED (wstat) && WSTOPSIG (wstat) == SIGTRAP
......@@ -2973,6 +3042,44 @@ filter_exit_event (struct lwp_info *event_child,
return ptid;
}
/* Returns 1 if GDB is interested in any event_child syscalls. */
static int
gdb_catching_syscalls_p (struct lwp_info *event_child)
{
struct thread_info *thread = get_lwp_thread (event_child);
struct process_info *proc = get_thread_process (thread);
return !VEC_empty (int, proc->syscalls_to_catch);
}
/* Returns 1 if GDB is interested in the event_child syscall.
Only to be called when stopped reason is SYSCALL_SIGTRAP. */
static int
gdb_catch_this_syscall_p (struct lwp_info *event_child)
{
int i, iter;
int sysno, sysret;
struct thread_info *thread = get_lwp_thread (event_child);
struct process_info *proc = get_thread_process (thread);
if (VEC_empty (int, proc->syscalls_to_catch))
return 0;
if (VEC_index (int, proc->syscalls_to_catch, 0) == ANY_SYSCALL)
return 1;
get_syscall_trapinfo (event_child, &sysno, &sysret);
for (i = 0;
VEC_iterate (int, proc->syscalls_to_catch, i, iter);
i++)
if (iter == sysno)
return 1;
return 0;
}
/* Wait for process, returns status. */
static ptid_t
......@@ -3307,6 +3414,22 @@ 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)
{
debug_printf ("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
......@@ -3559,8 +3682,16 @@ linux_wait_1 (ptid_t ptid,
}
}
if (current_thread->last_resume_kind == resume_stop
&& WSTOPSIG (w) == SIGSTOP)
if (WSTOPSIG (w) == SYSCALL_SIGTRAP)
{
int sysret;
get_syscall_trapinfo (event_child,
&ourstatus->value.syscall_number, &sysret);
ourstatus->kind = event_child->syscall_state;
}
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,
and it stopped cleanly, so report as SIG0. The use of
......@@ -4017,6 +4148,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
......@@ -4204,7 +4336,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 (gdb_catching_syscalls_p (lwp))
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. */
......@@ -6285,6 +6424,13 @@ linux_process_qsupported (char **features, int count)
the_low_target.process_qsupported (features, count);
}
static int
linux_supports_catch_syscall (void)
{
return (the_low_target.get_syscall_trapinfo != NULL
&& linux_supports_tracesysgood ());
}
static int
linux_supports_tracepoints (void)
{
......@@ -7209,7 +7355,8 @@ static struct target_ops linux_target_ops = {
linux_sw_breakpoint_from_kind,
linux_proc_tid_get_name,
linux_breakpoint_kind_from_current_state,
linux_supports_software_single_step
linux_supports_software_single_step,
linux_supports_catch_syscall,
};
#ifdef HAVE_LINUX_REGSETS
......
......@@ -240,6 +240,12 @@ struct linux_target_ops
/* See target.h. */
int (*supports_hardware_single_step) (void);
/* 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);
};
extern struct linux_target_ops the_low_target;
......@@ -278,6 +284,13 @@ struct lwp_info
event already received in a wait()). */
int stopped;
/* Signal whether we are in a SYSCALL_ENTRY or
in a SYSCALL_RETURN event.
Values:
- TARGET_WAITKIND_SYSCALL_ENTRY
- TARGET_WAITKIND_SYSCALL_RETURN */
enum target_waitkind syscall_state;
/* When stopped is set, the last wait status recorded for this lwp. */
int last_status;
......
......@@ -1438,6 +1438,31 @@ 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 SYSCALL_SIGTRAP. */
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
{
collect_register_by_name (regcache, "orig_eax", sysno);
collect_register_by_name (regcache, "eax", sysret);
}
}
static int
x86_supports_tracepoints (void)
{
......@@ -3315,6 +3340,7 @@ struct linux_target_ops the_low_target =
x86_supports_range_stepping,
NULL, /* breakpoint_kind_from_current_state */
x86_supports_hardware_single_step,
x86_get_syscall_trapinfo,
};
void
......
......@@ -1132,6 +1132,8 @@ prepare_resume_reply (char *buf, ptid_t ptid,
case TARGET_WAITKIND_VFORK_DONE:
case TARGET_WAITKIND_EXECD:
case TARGET_WAITKIND_THREAD_CREATED:
case TARGET_WAITKIND_SYSCALL_ENTRY:
case TARGET_WAITKIND_SYSCALL_RETURN:
{
struct thread_info *saved_thread;
const char **regp;
......@@ -1181,6 +1183,16 @@ prepare_resume_reply (char *buf, ptid_t ptid,
sprintf (buf, "T%02xcreate:;", signal);
}
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);
......
......@@ -624,6 +624,54 @@ handle_general_set (char *own_buf)
return;
}
if (startswith (own_buf, "QCatchSyscalls:"))
{
const char *p = own_buf + sizeof ("QCatchSyscalls:") - 1;
int enabled = -1;
CORE_ADDR sysno;
struct process_info *process;
if (!target_running () || !target_supports_catch_syscall ())
{
write_enn (own_buf);
return;
}
if (strcmp (p, "0") == 0)
enabled = 0;
else if (p[0] == '1' && (p[1] == ';' || p[1] == '\0'))
enabled = 1;
else
{
fprintf (stderr, "Unknown catch-syscalls mode requested: %s\n",
own_buf);
write_enn (own_buf);
return;
}
process = current_process ();
VEC_truncate (int, process->syscalls_to_catch, 0);
if (enabled)
{
p += 1;
if (*p == ';')
{
p += 1;
while (*p != '\0')
{
p = decode_address_to_semicolon (&sysno, p);
VEC_safe_push (int, process->syscalls_to_catch, (int) sysno);
}
}
else
VEC_safe_push (int, process->syscalls_to_catch, ANY_SYSCALL);
}
write_ok (own_buf);
return;
}
if (strcmp (own_buf, "QStartNoAckMode") == 0)
{
if (remote_debug)
......@@ -2200,6 +2248,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+");