public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] [gdb/tdep] Fix catching syscall execve exit for arm
@ 2023-11-16 16:19 Tom de Vries
  2023-11-21 10:36 ` Luis Machado
  0 siblings, 1 reply; 3+ messages in thread
From: Tom de Vries @ 2023-11-16 16:19 UTC (permalink / raw)
  To: gdb-patches; +Cc: Luis Machado

When running test-case gdb.base/catch-syscall.exp on a pinebook (64-bit
aarch64 kernel, 32-bit userland) I run into:
...
(gdb) PASS: $exp: execve: syscall(s) execve appears in 'info breakpoints'
continue^M
Continuing.^M
^M
Catchpoint 18 (call to syscall execve), 0xf7726318 in execve () from \
  /lib/arm-linux-gnueabihf/libc.so.6^M
(gdb) PASS: gdb.base/catch-syscall.exp: execve: program has called execve
continue^M
Continuing.^M
process 32392 is executing new program: catch-syscall^M
Cannot access memory at address 0xf77c6a7c^M
(gdb) FAIL: $exp: execve: syscall execve has returned
...

The memory error is thrown by arm_linux_get_syscall_number, when doing:
...
     /* PC gets incremented before the syscall-stop, so read the
         previous instruction.  */
      unsigned long this_instr =
        read_memory_unsigned_integer (pc - 4, 4, byte_order_for_code);
...

The reason for the error is that we're stopped at the syscall exit of syscall
execve, and the pc is at the first insn of the new exec, which also happens to
be the first insn in the code segment, so consequently we cannot read the
previous insn.

Fix this by detecting the situation by looking at the register state, similar
to what is done in aarch64_linux_get_syscall_number.

Furthermore, catch the memory error by using safe_read_memory_unsigned_integer
and return -1 instead, matching the documented behaviour of
arm_linux_get_syscall_number.

Finally, rather than using a hardcoded constant 11, introduce an ad-hoc
arm_sys_execve.

Tested on pinebook.

PR tdep/31071
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31071
---
 gdb/arm-linux-tdep.c | 42 ++++++++++++++++++++++++++++++++++++++----
 1 file changed, 38 insertions(+), 4 deletions(-)

diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c
index dfa816990ff..86fa3de0fd2 100644
--- a/gdb/arm-linux-tdep.c
+++ b/gdb/arm-linux-tdep.c
@@ -813,6 +813,32 @@ arm_linux_sigreturn_next_pc (struct regcache *regcache,
   return next_pc;
 }
 
+/* Return true if we're at execve syscall-exit-stop.  */
+
+static bool
+is_execve_syscall_exit (struct regcache *regs)
+{
+  ULONGEST reg = -1;
+
+  /* Check that lr is 0.  */
+  regcache_cooked_read_unsigned (regs, ARM_LR_REGNUM, &reg);
+  if (reg != 0)
+    return false;
+
+  /* Check that r0-r8 is 0.  */
+  for (int i = 0; i <= 8; ++i)
+    {
+      reg = -1;
+      regcache_cooked_read_unsigned (regs, ARM_A1_REGNUM + i, &reg);
+      if (reg != 0)
+	return false;
+    }
+
+  return true;
+}
+
+#define arm_sys_execve 11
+
 /* At a ptrace syscall-stop, return the syscall number.  This either
    comes from the SWI instruction (OABI) or from r7 (EABI).
 
@@ -830,6 +856,9 @@ arm_linux_get_syscall_number (struct gdbarch *gdbarch,
   int is_thumb;
   ULONGEST svc_number = -1;
 
+  if (is_execve_syscall_exit (regs))
+    return arm_sys_execve;
+
   regcache_cooked_read_unsigned (regs, ARM_PC_REGNUM, &pc);
   regcache_cooked_read_unsigned (regs, ARM_PS_REGNUM, &cpsr);
   is_thumb = (cpsr & t_bit) != 0;
@@ -845,9 +874,14 @@ arm_linux_get_syscall_number (struct gdbarch *gdbarch,
 
       /* PC gets incremented before the syscall-stop, so read the
 	 previous instruction.  */
-      unsigned long this_instr = 
-	read_memory_unsigned_integer (pc - 4, 4, byte_order_for_code);
-
+      unsigned long this_instr;
+      {
+	ULONGEST val;
+	if (!safe_read_memory_unsigned_integer (pc - 4, 4, byte_order_for_code,
+						&val))
+	  return -1;
+	this_instr = val;
+      }
       unsigned long svc_operand = (0x00ffffff & this_instr);
 
       if (svc_operand)
@@ -1265,7 +1299,7 @@ arm_canonicalize_syscall (int syscall)
     case 8: return gdb_sys_creat;
     case 9: return gdb_sys_link;
     case 10: return gdb_sys_unlink;
-    case 11: return gdb_sys_execve;
+    case arm_sys_execve: return gdb_sys_execve;
     case 12: return gdb_sys_chdir;
     case 13: return gdb_sys_time;
     case 14: return gdb_sys_mknod;

base-commit: 311276f10c4f85827d3264a2682ae9219917060f
-- 
2.35.3


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

* Re: [PATCH] [gdb/tdep] Fix catching syscall execve exit for arm
  2023-11-16 16:19 [PATCH] [gdb/tdep] Fix catching syscall execve exit for arm Tom de Vries
@ 2023-11-21 10:36 ` Luis Machado
  2023-11-21 10:46   ` Tom de Vries
  0 siblings, 1 reply; 3+ messages in thread
From: Luis Machado @ 2023-11-21 10:36 UTC (permalink / raw)
  To: Tom de Vries, gdb-patches

On 11/16/23 16:19, Tom de Vries wrote:
> When running test-case gdb.base/catch-syscall.exp on a pinebook (64-bit
> aarch64 kernel, 32-bit userland) I run into:
> ...
> (gdb) PASS: $exp: execve: syscall(s) execve appears in 'info breakpoints'
> continue^M
> Continuing.^M
> ^M
> Catchpoint 18 (call to syscall execve), 0xf7726318 in execve () from \
>   /lib/arm-linux-gnueabihf/libc.so.6^M
> (gdb) PASS: gdb.base/catch-syscall.exp: execve: program has called execve
> continue^M
> Continuing.^M
> process 32392 is executing new program: catch-syscall^M
> Cannot access memory at address 0xf77c6a7c^M
> (gdb) FAIL: $exp: execve: syscall execve has returned
> ...
> 
> The memory error is thrown by arm_linux_get_syscall_number, when doing:
> ...
>      /* PC gets incremented before the syscall-stop, so read the
>          previous instruction.  */
>       unsigned long this_instr =
>         read_memory_unsigned_integer (pc - 4, 4, byte_order_for_code);
> ...
> 
> The reason for the error is that we're stopped at the syscall exit of syscall
> execve, and the pc is at the first insn of the new exec, which also happens to
> be the first insn in the code segment, so consequently we cannot read the
> previous insn.
> 
> Fix this by detecting the situation by looking at the register state, similar
> to what is done in aarch64_linux_get_syscall_number.
> 
> Furthermore, catch the memory error by using safe_read_memory_unsigned_integer
> and return -1 instead, matching the documented behaviour of
> arm_linux_get_syscall_number.
> 
> Finally, rather than using a hardcoded constant 11, introduce an ad-hoc
> arm_sys_execve.
> 
> Tested on pinebook.
> 
> PR tdep/31071
> Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31071
> ---
>  gdb/arm-linux-tdep.c | 42 ++++++++++++++++++++++++++++++++++++++----
>  1 file changed, 38 insertions(+), 4 deletions(-)
> 
> diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c
> index dfa816990ff..86fa3de0fd2 100644
> --- a/gdb/arm-linux-tdep.c
> +++ b/gdb/arm-linux-tdep.c
> @@ -813,6 +813,32 @@ arm_linux_sigreturn_next_pc (struct regcache *regcache,
>    return next_pc;
>  }
>  
> +/* Return true if we're at execve syscall-exit-stop.  */
> +
> +static bool
> +is_execve_syscall_exit (struct regcache *regs)
> +{
> +  ULONGEST reg = -1;
> +
> +  /* Check that lr is 0.  */
> +  regcache_cooked_read_unsigned (regs, ARM_LR_REGNUM, &reg);
> +  if (reg != 0)
> +    return false;
> +
> +  /* Check that r0-r8 is 0.  */
> +  for (int i = 0; i <= 8; ++i)
> +    {
> +      reg = -1;
> +      regcache_cooked_read_unsigned (regs, ARM_A1_REGNUM + i, &reg);
> +      if (reg != 0)
> +	return false;
> +    }
> +
> +  return true;
> +}
> +
> +#define arm_sys_execve 11
> +
>  /* At a ptrace syscall-stop, return the syscall number.  This either
>     comes from the SWI instruction (OABI) or from r7 (EABI).
>  
> @@ -830,6 +856,9 @@ arm_linux_get_syscall_number (struct gdbarch *gdbarch,
>    int is_thumb;
>    ULONGEST svc_number = -1;
>  
> +  if (is_execve_syscall_exit (regs))
> +    return arm_sys_execve;
> +
>    regcache_cooked_read_unsigned (regs, ARM_PC_REGNUM, &pc);
>    regcache_cooked_read_unsigned (regs, ARM_PS_REGNUM, &cpsr);
>    is_thumb = (cpsr & t_bit) != 0;
> @@ -845,9 +874,14 @@ arm_linux_get_syscall_number (struct gdbarch *gdbarch,
>  
>        /* PC gets incremented before the syscall-stop, so read the
>  	 previous instruction.  */
> -      unsigned long this_instr = 
> -	read_memory_unsigned_integer (pc - 4, 4, byte_order_for_code);
> -
> +      unsigned long this_instr;
> +      {
> +	ULONGEST val;
> +	if (!safe_read_memory_unsigned_integer (pc - 4, 4, byte_order_for_code,
> +						&val))
> +	  return -1;
> +	this_instr = val;
> +      }
>        unsigned long svc_operand = (0x00ffffff & this_instr);
>  
>        if (svc_operand)
> @@ -1265,7 +1299,7 @@ arm_canonicalize_syscall (int syscall)
>      case 8: return gdb_sys_creat;
>      case 9: return gdb_sys_link;
>      case 10: return gdb_sys_unlink;
> -    case 11: return gdb_sys_execve;
> +    case arm_sys_execve: return gdb_sys_execve;
>      case 12: return gdb_sys_chdir;
>      case 13: return gdb_sys_time;
>      case 14: return gdb_sys_mknod;
> 
> base-commit: 311276f10c4f85827d3264a2682ae9219917060f

Thanks for addressing this.

Approved-by: Luis Machado  <luis.machado@arm.com>

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

* Re: [PATCH] [gdb/tdep] Fix catching syscall execve exit for arm
  2023-11-21 10:36 ` Luis Machado
@ 2023-11-21 10:46   ` Tom de Vries
  0 siblings, 0 replies; 3+ messages in thread
From: Tom de Vries @ 2023-11-21 10:46 UTC (permalink / raw)
  To: Luis Machado, gdb-patches

On 11/21/23 11:36, Luis Machado wrote:
> Thanks for addressing this.
> 
> Approved-by: Luis Machado  <luis.machado@arm.com>

Thanks for the review.

Unfortunately I forgot to apply the tag when committing, my apologies.

Thanks,
- Tom

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

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

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-11-16 16:19 [PATCH] [gdb/tdep] Fix catching syscall execve exit for arm Tom de Vries
2023-11-21 10:36 ` Luis Machado
2023-11-21 10:46   ` 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).