commit e6cdd38e8f0fead14cd3c528e9a4b666e1871752 Author: John Baldwin Date: Sun Jun 12 21:24:42 2016 -0700 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. diff --git gdb/config.in gdb/config.in index 905caf0..c82a5b4 100644 --- gdb/config.in +++ gdb/config.in @@ -456,6 +456,9 @@ /* Define to 1 if `struct ptrace_lwpinfo' is a member of `pl_tdname'. */ #undef HAVE_STRUCT_PTRACE_LWPINFO_PL_TDNAME +/* Define to 1 if `struct ptrace_lwpinfo' is a member of `pl_syscall_code'. */ +#undef HAVE_STRUCT_PTRACE_LWPINFO_PL_SYSCALL_CODE + /* Define to 1 if your system has struct reg in . */ #undef HAVE_STRUCT_REG diff --git gdb/configure gdb/configure index 60ea884..ea11b50 100755 --- gdb/configure +++ gdb/configure @@ -12927,6 +12927,20 @@ _ACEOF fi +# See if supports syscall fields on FreeBSD. The +# pl_syscall_code member of `struct ptrace_lwpinfo' was added in +# FreeBSD 10.3. +ac_fn_c_check_member "$LINENO" "struct ptrace_lwpinfo" "pl_syscall_code" "ac_cv_member_struct_ptrace_lwpinfo_pl_syscall_code" "#include +" +if test "x$ac_cv_member_struct_ptrace_lwpinfo_pl_syscall_code" = x""yes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_PTRACE_LWPINFO_PL_SYSCALL_CODE 1 +_ACEOF + + +fi + # Detect which type of /proc is in use, such as for Solaris. diff --git gdb/configure.ac gdb/configure.ac index 6a72f72..920c228 100644 --- gdb/configure.ac +++ gdb/configure.ac @@ -1526,6 +1526,11 @@ fi AC_CHECK_MEMBERS([struct ptrace_lwpinfo.pl_tdname], [], [], [#include ]) +# See if supports syscall fields on FreeBSD. The +# pl_syscall_code member of `struct ptrace_lwpinfo' was added in +# FreeBSD 10.3. +AC_CHECK_MEMBERS([struct ptrace_lwpinfo.pl_syscall_code], [], [], + [#include ]) # Detect which type of /proc is in use, such as for Solaris. diff --git gdb/data-directory/Makefile.in gdb/data-directory/Makefile.in index c05f379..0beca55 100644 --- gdb/data-directory/Makefile.in +++ gdb/data-directory/Makefile.in @@ -51,7 +51,8 @@ SYSCALLS_FILES = \ i386-linux.xml amd64-linux.xml \ sparc-linux.xml sparc64-linux.xml \ mips-o32-linux.xml mips-n32-linux.xml mips-n64-linux.xml \ - s390-linux.xml s390x-linux.xml + s390-linux.xml s390x-linux.xml \ + freebsd.xml PYTHON_DIR = python PYTHON_INSTALL_DIR = $(DESTDIR)$(GDB_DATADIR)/$(PYTHON_DIR) diff --git gdb/fbsd-nat.c gdb/fbsd-nat.c index dc65e29..c9548e9 100644 --- gdb/fbsd-nat.c +++ 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); } diff --git gdb/fbsd-tdep.c gdb/fbsd-tdep.c index e8f8605..4329f97 100644 --- gdb/fbsd-tdep.c +++ gdb/fbsd-tdep.c @@ -24,6 +24,7 @@ #include "regcache.h" #include "regset.h" #include "gdbthread.h" +#include "xml-syscall.h" #include "elf-bfd.h" #include "fbsd-tdep.h" @@ -317,6 +318,22 @@ fbsd_print_auxv_entry (struct gdbarch *gdbarch, struct ui_file *file, fprint_auxv_entry (file, name, description, format, type, val); } +/* Implement the "get_syscall_number" gdbarch method. */ + +static LONGEST +fbsd_get_syscall_number (struct gdbarch *gdbarch, + ptid_t ptid) +{ + + /* FreeBSD doesn't use gdbarch_get_syscall_number since FreeBSD + native targets fetch the system call number from the + 'pl_syscall_code' member of struct ptrace_lwpinfo in fbsd_wait. + However, system call catching requires this function to be + set. */ + + internal_error (__FILE__, __LINE__, _("fbsd_get_sycall_number called")); +} + /* To be called from GDB_OSABI_FREEBSD_ELF handlers. */ void @@ -326,4 +343,8 @@ fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) set_gdbarch_core_thread_name (gdbarch, fbsd_core_thread_name); set_gdbarch_make_corefile_notes (gdbarch, fbsd_make_corefile_notes); set_gdbarch_print_auxv_entry (gdbarch, fbsd_print_auxv_entry); + + /* `catch syscall' */ + set_xml_syscall_file_name (gdbarch, "syscalls/freebsd.xml"); + set_gdbarch_get_syscall_number (gdbarch, fbsd_get_syscall_number); } diff --git gdb/syscalls/freebsd.xml gdb/syscalls/freebsd.xml new file mode 100644 index 0000000..fb7c38b --- /dev/null +++ gdb/syscalls/freebsd.xml @@ -0,0 +1,410 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +