diff options
author | John Baldwin <jhb@FreeBSD.org> | 2016-06-12 21:24:42 -0700 |
---|---|---|
committer | John Baldwin <jhb@FreeBSD.org> | 2016-06-24 10:46:03 -0700 |
commit | e6cdd38e8f0fead14cd3c528e9a4b666e1871752 (patch) | |
tree | 357ce93c54e5400c660476da9aac57d511aca674 /gdb/fbsd-nat.c | |
parent | 82372b2f2747d347e24bb10ddc7bc7e828222a42 (diff) | |
download | gdb-e6cdd38e8f0fead14cd3c528e9a4b666e1871752.zip gdb-e6cdd38e8f0fead14cd3c528e9a4b666e1871752.tar.gz gdb-e6cdd38e8f0fead14cd3c528e9a4b666e1871752.tar.bz2 |
Add support for catching system calls to native FreeBSD targets.
All platforms on FreeBSD use a shared system call table, so use a
single XML file to describe the system calls available on each FreeBSD
platform.
Recent versions of FreeBSD include the identifier of the current
system call when reporting a system call entry or exit event in the
ptrace_lwpinfo structure obtained via PT_LWPINFO in fbsd_wait. As
such, FreeBSD native targets do not use the gdbarch method to fetch
the system call code. In addition, FreeBSD register sets fetched via
ptrace do not include an equivalent of 'orig_rax' (on amd64 for
example), so the system call code cannot be extracted from the
available registers during a system call exit. However, GDB assumes
that system call catch points are not supported if the gdbarch method
is not present. As a workaround, FreeBSD ABIs install a dummy gdbarch
method that throws an internal_error if it is ever invoked.
gdb/ChangeLog:
* configure.ac: Check for support for system call LWP fields on
FreeBSD.
* config.in, configure: Rebuild.
* data-directory/Makefile.in (SYSCALLS_FILES): Add freebsd.xml.
* fbsd-nat.c (fbsd_wait) [HAVE_STRUCT_PTRACE_LWPINFO_PL_SYSCALL_CODE]:
Report system call events.
[HAVE_STRUCT_PTRACE_LWPINFO_PL_SYSCALL_CODE]
(fbsd_set_syscall_catchpoint): New function.
(fbsd_nat_add_target) [HAVE_STRUCT_PTRACE_LWPINFO_PL_SYSCALL_CODE]:
Set "to_set_syscall_catchpoint" to "fbsd_set_syscall_catchpoint".
* fbsd-tdep.c: Include xml-syscall.h
(fbsd_get_syscall_number): New function.
(fbsd_init_abi): Set XML system call file name.
Add "get_syscall_number" gdbarch method.
* syscalls/freebsd.xml: New file.
Diffstat (limited to 'gdb/fbsd-nat.c')
-rw-r--r-- | gdb/fbsd-nat.c | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/gdb/fbsd-nat.c b/gdb/fbsd-nat.c index dc65e29..c9548e9 100644 --- a/gdb/fbsd-nat.c +++ b/gdb/fbsd-nat.c @@ -779,6 +779,40 @@ fbsd_wait (struct target_ops *ops, return wptid; } #endif + + /* Note that PL_FLAG_SCE is set for any event reported while + a thread is executing a system call in the kernel. In + particular, signals that interrupt a sleep in a system + call will report this flag as part of their event. Stops + explicitly for system call entry and exit always use + SIGTRAP, so only treat SIGTRAP events as system call + entry/exit events. */ + if (pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX) + && ourstatus->value.sig == SIGTRAP) + { +#ifdef HAVE_STRUCT_PTRACE_LWPINFO_PL_SYSCALL_CODE + if (catch_syscall_enabled ()) + { + if (catching_syscall_number (pl.pl_syscall_code)) + { + if (pl.pl_flags & PL_FLAG_SCE) + ourstatus->kind = TARGET_WAITKIND_SYSCALL_ENTRY; + else + ourstatus->kind = TARGET_WAITKIND_SYSCALL_RETURN; + ourstatus->value.syscall_number = pl.pl_syscall_code; + return wptid; + } + } +#endif + /* If the core isn't interested in this event, just + continue the process explicitly and wait for another + event. Note that PT_SYSCALL is "sticky" on FreeBSD + and once system call stops are enabled on a process + it stops for all system call entries and exits. */ + if (ptrace (PT_CONTINUE, pid, (caddr_t) 1, 0) == -1) + perror_with_name (("ptrace")); + continue; + } } return wptid; } @@ -889,6 +923,19 @@ fbsd_remove_exec_catchpoint (struct target_ops *self, int pid) return 0; } #endif + +#ifdef HAVE_STRUCT_PTRACE_LWPINFO_PL_SYSCALL_CODE +static int +fbsd_set_syscall_catchpoint (struct target_ops *self, int pid, int needed, + int any_count, int table_size, int *table) +{ + + /* Ignore the arguments. inf-ptrace.c will use PT_SYSCALL which + will catch all system call entries and exits. The system calls + are filtered by GDB rather than the kernel. */ + return 0; +} +#endif #endif void @@ -925,6 +972,9 @@ fbsd_nat_add_target (struct target_ops *t) t->to_insert_exec_catchpoint = fbsd_insert_exec_catchpoint; t->to_remove_exec_catchpoint = fbsd_remove_exec_catchpoint; #endif +#ifdef HAVE_STRUCT_PTRACE_LWPINFO_PL_SYSCALL_CODE + t->to_set_syscall_catchpoint = fbsd_set_syscall_catchpoint; +#endif #endif add_target (t); } |