Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Kamil Rytarowski <n54@gmx.com>
To: gdb-patches <gdb-patches@sourceware.org>
Subject: Re: [PATCH] Add basic event handling in the NetBSD target
Date: Mon, 20 Apr 2020 12:28:11 +0200	[thread overview]
Message-ID: <aad65895-a4fd-fd0a-7f81-3cc5361e242c@gmx.com> (raw)
In-Reply-To: <20200417144508.6366-1-n54@gmx.com>


[-- Attachment #1.1: Type: text/plain, Size: 11718 bytes --]

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  <n54@gmx.com>
> +
> +	* 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  <n54@gmx.com>
> 
>  	* 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 <sys/types.h>
>  #include <sys/ptrace.h>
>  #include <sys/sysctl.h>
> +#include <sys/wait.h>
> 
>  /* 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<const int> 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<const int> 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
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

  reply	other threads:[~2020-04-20 10:29 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-17 14:45 Kamil Rytarowski
2020-04-20 10:28 ` Kamil Rytarowski [this message]
2020-04-24  1:33 ` Simon Marchi
2020-04-24 10:09   ` Kamil Rytarowski
2020-04-26 21:14     ` Simon Marchi
2020-04-29  9:12       ` Kamil Rytarowski
2020-04-29 11:08   ` [PATCH v2] " Kamil Rytarowski
2020-04-29 15:44     ` Simon Marchi
2020-04-29 11:47 ` [PATCH v2] Implement the following events: - single step (TRAP_TRACE) - software breakpoint (TRAP_DBREG) - exec() (TRAP_EXEC) - syscall entry/exit (TRAP_SCE / TRAP_SCX) Kamil Rytarowski
2020-04-29 12:07 ` [PATCH v2] Add basic event handling in the NetBSD target Kamil Rytarowski

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=aad65895-a4fd-fd0a-7f81-3cc5361e242c@gmx.com \
    --to=n54@gmx.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox