diff options
author | Josh Stone <jistone@redhat.com> | 2016-01-12 12:27:27 -0800 |
---|---|---|
committer | Josh Stone <jistone@redhat.com> | 2016-01-12 12:27:27 -0800 |
commit | 82075af2c14b1f8a54fa5796fb63f7ef23f98d9d (patch) | |
tree | 91cbb8ff3107608f7b93c82e3d0f532e5a739911 /gdb/remote.c | |
parent | 41549dfbcc747d0dc4a97c9a427c3a29e9878f05 (diff) | |
download | gdb-82075af2c14b1f8a54fa5796fb63f7ef23f98d9d.zip gdb-82075af2c14b1f8a54fa5796fb63f7ef23f98d9d.tar.gz gdb-82075af2c14b1f8a54fa5796fb63f7ef23f98d9d.tar.bz2 |
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.
Diffstat (limited to 'gdb/remote.c')
-rw-r--r-- | gdb/remote.c | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/gdb/remote.c b/gdb/remote.c index 528d863..e825d27 100644 --- a/gdb/remote.c +++ b/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); |