forked from Imagelibrary/binutils-gdb
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.
This commit is contained in:
110
gdb/remote.c
110
gdb/remote.c
@@ -1392,6 +1392,7 @@ enum {
|
||||
PACKET_qSupported,
|
||||
PACKET_qTStatus,
|
||||
PACKET_QPassSignals,
|
||||
PACKET_QCatchSyscalls,
|
||||
PACKET_QProgramSignals,
|
||||
PACKET_qCRC,
|
||||
PACKET_qSearch_memory,
|
||||
@@ -1987,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. */
|
||||
|
||||
@@ -4467,6 +4555,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,
|
||||
@@ -6371,6 +6461,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"))
|
||||
@@ -12976,6 +13082,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;
|
||||
@@ -13542,6 +13649,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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user