public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] [gdb/tdep] Use PTRACE_GET_SYSCALL_INFO for syscall number
@ 2023-11-20 10:34 Tom de Vries
  2023-11-21  0:15 ` John Baldwin
  0 siblings, 1 reply; 3+ messages in thread
From: Tom de Vries @ 2023-11-20 10:34 UTC (permalink / raw)
  To: gdb-patches

When stopped at syscall-enter-stop or syscall-exit-stop, we currently use the
architecture-specific hook gdbarch_get_syscall_number to get the number of the
current syscall.

This approach requires supporting architectures to implement the hook, which
possibly relies on architecture specific co-operation from the kernel.

Starting linux kernel version 5.3, ptrace supports a PTRACE_GET_SYSCALL_INFO
request.

Use the ptrace request, if available, to get the syscall number.

It's unfortunate that the request only returns the syscall number for
PTRACE_SYSCALL_INFO_ENTRY, and not for PTRACE_SYSCALL_INFO_EXIT, so we still
need the hook for syscall-exit-stop.

The kernel commit 201766a20e30 ("ptrace: add PTRACE_GET_SYSCALL_INFO
request") names a few properties of the new request:
- syscall number identification is more reliable in some corner cases,
- tracers don't need to support any architecture specific code, and
- syscall-enter-stop / syscall-exit-stop detection is no longer necessary.

This first is a good reason for this patch.

The second less so, because as mentioned we still need to support the hook for
syscall-exit-stop.

The third could be used as well in gdb, but that's out-of-scope for this
patch, which focuses on getting the syscall number.

Tested on x86_64-linux, and verified with a simple test-case that I see the
ptrace request in the strace.
---
 gdb/linux-nat.c | 26 +++++++++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
index d3e9560c2fc..ad36c964852 100644
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -1750,6 +1750,30 @@ kill_lwp (int lwpid, int signo)
   return ret;
 }
 
+/* Return current syscall.  */
+
+static LONGEST
+linux_get_syscall_number (struct gdbarch *gdbarch, thread_info *thread)
+{
+#ifdef PTRACE_GET_SYSCALL_INFO
+  {
+    __ptrace_syscall_info info;
+    pid_t pid = (thread->ptid.tid_p ()
+		 ? thread->ptid.tid ()
+		 : thread->ptid.pid ());
+
+    long res = ptrace (PTRACE_GET_SYSCALL_INFO, pid, sizeof (info), &info);
+
+    /* It's unfortunate that for PTRACE_SYSCALL_INFO_EXIT there's no syscall
+       number.  */
+    if (res != -1 && info.op == PTRACE_SYSCALL_INFO_ENTRY)
+      return info.entry.nr;
+  }
+#endif
+
+  return gdbarch_get_syscall_number (gdbarch, thread);
+}
+
 /* Handle a GNU/Linux syscall trap wait response.  If we see a syscall
    event, check if the core is interested in it: if not, ignore the
    event, and keep waiting; otherwise, we need to toggle the LWP's
@@ -1762,7 +1786,7 @@ linux_handle_syscall_trap (struct lwp_info *lp, int stopping)
   struct target_waitstatus *ourstatus = &lp->waitstatus;
   struct gdbarch *gdbarch = target_thread_architecture (lp->ptid);
   thread_info *thread = linux_target->find_thread (lp->ptid);
-  int syscall_number = (int) gdbarch_get_syscall_number (gdbarch, thread);
+  int syscall_number = (int) linux_get_syscall_number (gdbarch, thread);
 
   if (stopping)
     {

base-commit: 11788869e0a3713e847733be8712e4b3b5e4dfd9
-- 
2.35.3


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] [gdb/tdep] Use PTRACE_GET_SYSCALL_INFO for syscall number
  2023-11-20 10:34 [PATCH] [gdb/tdep] Use PTRACE_GET_SYSCALL_INFO for syscall number Tom de Vries
@ 2023-11-21  0:15 ` John Baldwin
  2023-11-21  9:03   ` Tom de Vries
  0 siblings, 1 reply; 3+ messages in thread
From: John Baldwin @ 2023-11-21  0:15 UTC (permalink / raw)
  To: Tom de Vries, gdb-patches

On 11/20/23 2:34 AM, Tom de Vries wrote:
> When stopped at syscall-enter-stop or syscall-exit-stop, we currently use the
> architecture-specific hook gdbarch_get_syscall_number to get the number of the
> current syscall.
> 
> This approach requires supporting architectures to implement the hook, which
> possibly relies on architecture specific co-operation from the kernel.
> 
> Starting linux kernel version 5.3, ptrace supports a PTRACE_GET_SYSCALL_INFO
> request.
> 
> Use the ptrace request, if available, to get the syscall number.
> 
> It's unfortunate that the request only returns the syscall number for
> PTRACE_SYSCALL_INFO_ENTRY, and not for PTRACE_SYSCALL_INFO_EXIT, so we still
> need the hook for syscall-exit-stop.
> 
> The kernel commit 201766a20e30 ("ptrace: add PTRACE_GET_SYSCALL_INFO
> request") names a few properties of the new request:
> - syscall number identification is more reliable in some corner cases,
> - tracers don't need to support any architecture specific code, and
> - syscall-enter-stop / syscall-exit-stop detection is no longer necessary.
> 
> This first is a good reason for this patch.
> 
> The second less so, because as mentioned we still need to support the hook for
> syscall-exit-stop.
> 
> The third could be used as well in gdb, but that's out-of-scope for this
> patch, which focuses on getting the syscall number.
> 
> Tested on x86_64-linux, and verified with a simple test-case that I see the
> ptrace request in the strace.
> ---
>   gdb/linux-nat.c | 26 +++++++++++++++++++++++++-
>   1 file changed, 25 insertions(+), 1 deletion(-)
> 
> diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
> index d3e9560c2fc..ad36c964852 100644
> --- a/gdb/linux-nat.c
> +++ b/gdb/linux-nat.c
> @@ -1750,6 +1750,30 @@ kill_lwp (int lwpid, int signo)
>     return ret;
>   }
>   
> +/* Return current syscall.  */
> +
> +static LONGEST
> +linux_get_syscall_number (struct gdbarch *gdbarch, thread_info *thread)
> +{
> +#ifdef PTRACE_GET_SYSCALL_INFO
> +  {
> +    __ptrace_syscall_info info;
> +    pid_t pid = (thread->ptid.tid_p ()
> +		 ? thread->ptid.tid ()
> +		 : thread->ptid.pid ());
> +
> +    long res = ptrace (PTRACE_GET_SYSCALL_INFO, pid, sizeof (info), &info);
> +
> +    /* It's unfortunate that for PTRACE_SYSCALL_INFO_EXIT there's no syscall
> +       number.  */
> +    if (res != -1 && info.op == PTRACE_SYSCALL_INFO_ENTRY)
> +      return info.entry.nr;
> +  }
> +#endif
> +
> +  return gdbarch_get_syscall_number (gdbarch, thread);
> +}
> +
>   /* Handle a GNU/Linux syscall trap wait response.  If we see a syscall
>      event, check if the core is interested in it: if not, ignore the
>      event, and keep waiting; otherwise, we need to toggle the LWP's
> @@ -1762,7 +1786,7 @@ linux_handle_syscall_trap (struct lwp_info *lp, int stopping)
>     struct target_waitstatus *ourstatus = &lp->waitstatus;
>     struct gdbarch *gdbarch = target_thread_architecture (lp->ptid);
>     thread_info *thread = linux_target->find_thread (lp->ptid);
> -  int syscall_number = (int) gdbarch_get_syscall_number (gdbarch, thread);
> +  int syscall_number = (int) linux_get_syscall_number (gdbarch, thread);
>   
>     if (stopping)
>       {
> 
> base-commit: 11788869e0a3713e847733be8712e4b3b5e4dfd9

This looks ok to me.  I wonder if upstream could be convinced to make
the system call number available for syscall exit as well?  Perhaps you could
"remember" the syscall numer on each entry and re-use it for the next exit?
(I wonder if that is upstream's reason for only making it available for entry
assuming that tracers will do that.)

FWIW, on FreeBSD the number is available for both entry/exit from ptrace in
an architecture-neutral manner, so that might be useful as an argument to
ask upstream to make it available.  The implementation on FreeBSD is that we
cache the effective syscall number in the kernel's internal 'struct thread'
for the life of a system call spanning both the entry and exit ptrace hooks.

-- 
John Baldwin


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] [gdb/tdep] Use PTRACE_GET_SYSCALL_INFO for syscall number
  2023-11-21  0:15 ` John Baldwin
@ 2023-11-21  9:03   ` Tom de Vries
  0 siblings, 0 replies; 3+ messages in thread
From: Tom de Vries @ 2023-11-21  9:03 UTC (permalink / raw)
  To: John Baldwin, gdb-patches

On 11/21/23 01:15, John Baldwin wrote:
> On 11/20/23 2:34 AM, Tom de Vries wrote:
>> When stopped at syscall-enter-stop or syscall-exit-stop, we currently 
>> use the
>> architecture-specific hook gdbarch_get_syscall_number to get the 
>> number of the
>> current syscall.
>>
>> This approach requires supporting architectures to implement the hook, 
>> which
>> possibly relies on architecture specific co-operation from the kernel.
>>
>> Starting linux kernel version 5.3, ptrace supports a 
>> PTRACE_GET_SYSCALL_INFO
>> request.
>>
>> Use the ptrace request, if available, to get the syscall number.
>>
>> It's unfortunate that the request only returns the syscall number for
>> PTRACE_SYSCALL_INFO_ENTRY, and not for PTRACE_SYSCALL_INFO_EXIT, so we 
>> still
>> need the hook for syscall-exit-stop.
>>
>> The kernel commit 201766a20e30 ("ptrace: add PTRACE_GET_SYSCALL_INFO
>> request") names a few properties of the new request:
>> - syscall number identification is more reliable in some corner cases,
>> - tracers don't need to support any architecture specific code, and
>> - syscall-enter-stop / syscall-exit-stop detection is no longer 
>> necessary.
>>
>> This first is a good reason for this patch.
>>
>> The second less so, because as mentioned we still need to support the 
>> hook for
>> syscall-exit-stop.
>>
>> The third could be used as well in gdb, but that's out-of-scope for this
>> patch, which focuses on getting the syscall number.
>>
>> Tested on x86_64-linux, and verified with a simple test-case that I 
>> see the
>> ptrace request in the strace.
>> ---
>>   gdb/linux-nat.c | 26 +++++++++++++++++++++++++-
>>   1 file changed, 25 insertions(+), 1 deletion(-)
>>
>> diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
>> index d3e9560c2fc..ad36c964852 100644
>> --- a/gdb/linux-nat.c
>> +++ b/gdb/linux-nat.c
>> @@ -1750,6 +1750,30 @@ kill_lwp (int lwpid, int signo)
>>     return ret;
>>   }
>> +/* Return current syscall.  */
>> +
>> +static LONGEST
>> +linux_get_syscall_number (struct gdbarch *gdbarch, thread_info *thread)
>> +{
>> +#ifdef PTRACE_GET_SYSCALL_INFO
>> +  {
>> +    __ptrace_syscall_info info;
>> +    pid_t pid = (thread->ptid.tid_p ()
>> +         ? thread->ptid.tid ()
>> +         : thread->ptid.pid ());
>> +
>> +    long res = ptrace (PTRACE_GET_SYSCALL_INFO, pid, sizeof (info), 
>> &info);
>> +
>> +    /* It's unfortunate that for PTRACE_SYSCALL_INFO_EXIT there's no 
>> syscall
>> +       number.  */
>> +    if (res != -1 && info.op == PTRACE_SYSCALL_INFO_ENTRY)
>> +      return info.entry.nr;
>> +  }
>> +#endif
>> +
>> +  return gdbarch_get_syscall_number (gdbarch, thread);
>> +}
>> +
>>   /* Handle a GNU/Linux syscall trap wait response.  If we see a syscall
>>      event, check if the core is interested in it: if not, ignore the
>>      event, and keep waiting; otherwise, we need to toggle the LWP's
>> @@ -1762,7 +1786,7 @@ linux_handle_syscall_trap (struct lwp_info *lp, 
>> int stopping)
>>     struct target_waitstatus *ourstatus = &lp->waitstatus;
>>     struct gdbarch *gdbarch = target_thread_architecture (lp->ptid);
>>     thread_info *thread = linux_target->find_thread (lp->ptid);
>> -  int syscall_number = (int) gdbarch_get_syscall_number (gdbarch, 
>> thread);
>> +  int syscall_number = (int) linux_get_syscall_number (gdbarch, thread);
>>     if (stopping)
>>       {
>>
>> base-commit: 11788869e0a3713e847733be8712e4b3b5e4dfd9
> 
> This looks ok to me.  I wonder if upstream could be convinced to make
> the system call number available for syscall exit as well? 

I wondered that as well.  Now filed here ( 
https://bugzilla.kernel.org/show_bug.cgi?id=218170 ).

> Perhaps you 
> could
> "remember" the syscall numer on each entry and re-use it for the next exit?

[ FTR, I've implemented a patch for this ( 
https://sourceware.org/pipermail/gdb-patches/2023-November/204275.html ). ]

> (I wonder if that is upstream's reason for only making it available for 
> entry
> assuming that tracers will do that.)
> 
> FWIW, on FreeBSD the number is available for both entry/exit from ptrace in
> an architecture-neutral manner, so that might be useful as an argument to
> ask upstream to make it available.

I've mentioned that.

Thanks,
- Tom

> The implementation on FreeBSD is 
> that we
> cache the effective syscall number in the kernel's internal 'struct thread'
> for the life of a system call spanning both the entry and exit ptrace 
> hooks.
> 


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2023-11-21  9:01 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-11-20 10:34 [PATCH] [gdb/tdep] Use PTRACE_GET_SYSCALL_INFO for syscall number Tom de Vries
2023-11-21  0:15 ` John Baldwin
2023-11-21  9:03   ` Tom de Vries

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).