Ping? On 17.04.2020 16:45, Kamil Rytarowski wrote: > Implement the following events: > - single step (TRAP_TRACE) > - software breakpoint (TRAP_DBREG) > - exec() (TRAP_EXEC) > - syscall entry/exit (TRAP_SCE / TRAP_SCX) > > Add support for NetBSD specific ::wait () and ::resume (). > > Instruct the generic code that exec and syscall events are supported. > > Define an empty nbsd_get_syscall_number as it is prerequisite for > catching syscall entry and exit events, even if it is unused. > This function is used to detect whether the gdbarch supports the > 'catch syscall' feature. > > gdb/ChangeLog: > > * nbsd-nat.c: Include "sys/wait.h". > * (nbsd_nat_target::resume, nbsd_wait, nbsd_nat_target::wait) > (nbsd_nat_target::insert_exec_catchpoint) > (nbsd_nat_target::remove_exec_catchpoint) > (nbsd_nat_target::set_syscall_catchpoint): Add. > * nbsd-nat.h (nbsd_nat_target::resume, nbsd_nat_target::wait) > (nbsd_nat_target::insert_exec_catchpoint) > (nbsd_nat_target::remove_exec_catchpoint) > (nbsd_nat_target::set_syscall_catchpoint): Add. > * nbsd-tdep.c (nbsd_get_syscall_number): Add. > (nbsd_init_abi): Call `set_gdbarch_get_syscall_number' and pass > `nbsd_get_syscall_number'. > --- > gdb/ChangeLog | 15 ++++ > gdb/nbsd-nat.c | 211 ++++++++++++++++++++++++++++++++++++++++++++++++ > gdb/nbsd-nat.h | 9 +++ > gdb/nbsd-tdep.c | 18 +++++ > 4 files changed, 253 insertions(+) > > diff --git a/gdb/ChangeLog b/gdb/ChangeLog > index 0caeca04e79..9652daabbbd 100644 > --- a/gdb/ChangeLog > +++ b/gdb/ChangeLog > @@ -1,3 +1,18 @@ > +2020-04-16 Kamil Rytarowski > + > + * nbsd-nat.c: Include "sys/wait.h". > + * (nbsd_nat_target::resume, nbsd_wait, nbsd_nat_target::wait) > + (nbsd_nat_target::insert_exec_catchpoint) > + (nbsd_nat_target::remove_exec_catchpoint) > + (nbsd_nat_target::set_syscall_catchpoint): Add. > + * nbsd-nat.h (nbsd_nat_target::resume, nbsd_nat_target::wait) > + (nbsd_nat_target::insert_exec_catchpoint) > + (nbsd_nat_target::remove_exec_catchpoint) > + (nbsd_nat_target::set_syscall_catchpoint): Add. > + * nbsd-tdep.c (nbsd_get_syscall_number): Add. > + (nbsd_init_abi): Call `set_gdbarch_get_syscall_number' and pass > + `nbsd_get_syscall_number'. > + > 2020-04-16 Kamil Rytarowski > > * inf-ptrace.h (follow_fork, insert_fork_catchpoint) > diff --git a/gdb/nbsd-nat.c b/gdb/nbsd-nat.c > index d41cfc815d3..f9e85e10b16 100644 > --- a/gdb/nbsd-nat.c > +++ b/gdb/nbsd-nat.c > @@ -28,6 +28,7 @@ > #include > #include > #include > +#include > > /* Return the name of a file that can be opened to get the symbols for > the child process identified by PID. */ > @@ -539,3 +540,213 @@ nbsd_nat_target::info_proc (const char *args, enum info_proc_what what) > > return true; > } > + > +/* Resume execution of thread PTID, or all threads if PTID is -1. If > + STEP is nonzero, single-step it. If SIGNAL is nonzero, give it > + that signal. */ > + > +void > +nbsd_nat_target::resume (ptid_t ptid, int step, enum gdb_signal signal) > +{ > + int request; > + > + if (ptid.lwp_p ()) > + { > + /* If ptid is a specific LWP, suspend all other LWPs in the process. */ > + inferior *inf = find_inferior_ptid (this, ptid); > + > + for (thread_info *tp : inf->non_exited_threads ()) > + { > + if (tp->ptid.lwp () == ptid.lwp ()) > + request = PT_RESUME; > + else > + request = PT_SUSPEND; > + > + if (ptrace (request, tp->ptid.pid (), NULL, tp->ptid.lwp ()) == -1) > + perror_with_name (("ptrace")); > + } > + } > + else > + { > + /* If ptid is a wildcard, resume all matching threads (they won't run > + until the process is continued however). */ > + for (thread_info *tp : all_non_exited_threads (this, ptid)) > + if (ptrace (PT_RESUME, tp->ptid.pid (), NULL, tp->ptid.lwp ()) == -1) > + perror_with_name (("ptrace")); > + ptid = inferior_ptid; > + } > + > + if (step) > + { > + for (thread_info *tp : all_non_exited_threads (this, ptid)) > + if (ptrace (PT_SETSTEP, tp->ptid.pid (), NULL, tp->ptid.lwp ()) == -1) > + perror_with_name (("ptrace")); > + } > + else > + { > + for (thread_info *tp : all_non_exited_threads (this, ptid)) > + if (ptrace (PT_CLEARSTEP, tp->ptid.pid (), NULL, tp->ptid.lwp ()) == -1) > + perror_with_name (("ptrace")); > + } > + > + if (minus_one_ptid == ptid) > + /* Resume all threads. Traditionally ptrace() only supports > + single-threaded processes, so simply resume the inferior. */ > + ptid = ptid_t (inferior_ptid.pid ()); > + > + if (catch_syscall_enabled () > 0) > + request = PT_SYSCALL; > + else > + request = PT_CONTINUE; > + > + /* An address of (void *)1 tells ptrace to continue from > + where it was. If GDB wanted it to start some other way, we have > + already written a new program counter value to the child. */ > + if (ptrace (request, ptid.pid (), (void *)1, gdb_signal_to_host (signal)) == -1) > + perror_with_name (("ptrace")); > +} > + > +/* Implement the "update_thread_list" target_ops method. */ > + > +static ptid_t > +nbsd_wait (ptid_t ptid, struct target_waitstatus *ourstatus, int options) > +{ > + pid_t pid; > + int status; > + > + set_sigint_trap (); > + > + do > + { > + /* The common code passes WNOHANG that leads to crashes, overwrite it. */ > + pid = waitpid (ptid.pid (), &status, 0); > + } > + while (pid == -1 && errno == EINTR); > + > + clear_sigint_trap (); > + > + if (pid == -1) > + perror_with_name (_("Child process unexpectedly missing")); > + > + store_waitstatus (ourstatus, status); > + return ptid_t (pid); > +} > + > +/* Wait for the child specified by PTID to do something. Return the > + process ID of the child, or MINUS_ONE_PTID in case of error; store > + the status in *OURSTATUS. */ > + > +ptid_t > +nbsd_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus, > + int target_options) > +{ > + ptid_t wptid = nbsd_wait(ptid, ourstatus, target_options); > + > + /* If the child stopped, keep investigating its status. */ > + if (ourstatus->kind != TARGET_WAITKIND_STOPPED) > + return wptid; > + > + pid_t pid = wptid.pid (); > + > + /* Extract the event and thread that received a signal. */ > + ptrace_siginfo_t psi; > + if (ptrace (PT_GET_SIGINFO, pid, &psi, sizeof (psi)) == -1) > + perror_with_name (("ptrace")); > + > + /* Pick child's siginfo_t. */ > + siginfo_t *si = &psi.psi_siginfo; > + > + int lwp = psi.psi_lwpid; > + > + int signo = si->si_signo; > + const int code = si->si_code; > + > + /* Construct PTID with a specified thread that received the event. > + If a signal was targeted to the whole process, lwp is 0. */ > + wptid = ptid_t (pid, lwp, 0); > + > + /* Bail out on non-debugger oriented signals.. */ > + if (signo != SIGTRAP) > + return wptid; > + > + /* Stop examining non-debugger oriented SIGTRAP codes. */ > + if (code <= SI_USER || code == SI_NOINFO) > + return wptid; > + > + if (in_thread_list (this, ptid_t (pid))) > + { > + thread_change_ptid (this, ptid_t (pid), wptid); > + } > + > + if (code == TRAP_EXEC) > + { > + ourstatus->kind = TARGET_WAITKIND_EXECD; > + ourstatus->value.execd_pathname = xstrdup (pid_to_exec_file (pid)); > + return wptid; > + } > + > + if (code == TRAP_TRACE) > + { > + /* Unhandled at this level. */ > + return wptid; > + } > + > + if (code == TRAP_SCE || code == TRAP_SCX) > + { > + int sysnum = si->si_sysnum; > + > + if (!catch_syscall_enabled () || !catching_syscall_number (sysnum)) > + { > + /* If the core isn't interested in this event, ignore it. */ > + ourstatus->kind = TARGET_WAITKIND_SPURIOUS; > + return wptid; > + } > + > + ourstatus->kind = > + (code == TRAP_SCE) ? TARGET_WAITKIND_SYSCALL_ENTRY : > + TARGET_WAITKIND_SYSCALL_RETURN; > + ourstatus->value.syscall_number = sysnum; > + return wptid; > + } > + > + if (code == TRAP_BRKPT) > + { > + /* Unhandled at this level. */ > + return wptid; > + } > + > + /* Unclassified SIGTRAP event. */ > + ourstatus->kind = TARGET_WAITKIND_SPURIOUS; > + return wptid; > +} > + > +/* Implement the "insert_exec_catchpoint" target_ops method. */ > + > +int > +nbsd_nat_target::insert_exec_catchpoint (int pid) > +{ > + /* Nothing to do. */ > + return 0; > +} > + > +/* Implement the "remove_exec_catchpoint" target_ops method. */ > + > +int > +nbsd_nat_target::remove_exec_catchpoint (int pid) > +{ > + /* Nothing to do. */ > + return 0; > +} > + > +/* Implement the "set_syscall_catchpoint" target_ops method. */ > + > +int > +nbsd_nat_target::set_syscall_catchpoint (int pid, bool needed, > + int any_count, > + gdb::array_view syscall_counts) > +{ > + /* 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; > +} > diff --git a/gdb/nbsd-nat.h b/gdb/nbsd-nat.h > index 256db4b9017..6e14cbb889d 100644 > --- a/gdb/nbsd-nat.h > +++ b/gdb/nbsd-nat.h > @@ -38,6 +38,15 @@ struct nbsd_nat_target : public inf_ptrace_target > > int find_memory_regions (find_memory_region_ftype func, void *data) override; > bool info_proc (const char *, enum info_proc_what) override; > + > + void resume (ptid_t, int, enum gdb_signal) override; > + ptid_t wait (ptid_t, struct target_waitstatus *, int) override; > + int insert_exec_catchpoint (int pid) override; > + int remove_exec_catchpoint (int pid) override; > + int set_syscall_catchpoint (int pid, bool needed, int any_count, > + gdb::array_view syscall_counts) > + override; > + > }; > > #endif /* nbsd-nat.h */ > diff --git a/gdb/nbsd-tdep.c b/gdb/nbsd-tdep.c > index 52e0640e35c..d5d1b7211c1 100644 > --- a/gdb/nbsd-tdep.c > +++ b/gdb/nbsd-tdep.c > @@ -444,6 +444,21 @@ nbsd_info_proc_mappings_entry (int addr_bit, ULONGEST kve_start, > } > } > > +/* Implement the "get_syscall_number" gdbarch method. */ > + > +static LONGEST > +nbsd_get_syscall_number (struct gdbarch *gdbarch, thread_info *thread) > +{ > + > + /* FreeBSD doesn't use gdbarch_get_syscall_number since NetBSD > + native targets fetch the system call number from the > + 'si_sysnum' member of siginfo_t in nbsd_nat_target::wait. > + However, system call catching requires this function to be > + set. */ > + > + internal_error (__FILE__, __LINE__, _("nbsd_get_sycall_number called")); > +} > + > /* See nbsd-tdep.h. */ > > void > @@ -453,4 +468,7 @@ nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) > set_gdbarch_gdb_signal_to_target (gdbarch, nbsd_gdb_signal_to_target); > set_gdbarch_skip_solib_resolver (gdbarch, nbsd_skip_solib_resolver); > set_gdbarch_auxv_parse (gdbarch, svr4_auxv_parse); > + > + /* `catch syscall' */ > + set_gdbarch_get_syscall_number (gdbarch, nbsd_get_syscall_number); > } > -- > 2.25.0 >