131 lines
4.0 KiB
Diff
131 lines
4.0 KiB
Diff
From e2a2cb30bc4e85f462b817bac5393b3fee1ecf9f Mon Sep 17 00:00:00 2001
|
|
From: Tom de Vries <tdevries@suse.de>
|
|
Date: Tue, 21 Nov 2023 11:44:07 +0100
|
|
Subject: [PATCH 3/7] [gdb/tdep] Fix catching syscall execve exit for arm
|
|
|
|
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 33748731cfd..8116c1368ff 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, ®);
|
|
+ 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, ®);
|
|
+ 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;
|
|
--
|
|
2.35.3
|
|
|