summaryrefslogtreecommitdiff
path: root/exec
diff options
context:
space:
mode:
authorPo Lu <luangruo@yahoo.com>2023-05-01 13:12:44 +0800
committerPo Lu <luangruo@yahoo.com>2023-05-01 13:12:44 +0800
commit6a30a74cb2ac2cba69aa01da12caf1eac7134f43 (patch)
treeccefc5b34446ec15fbc7362af0ae924c4d0ddc35 /exec
parentddc16de86964d445309dd38175a85221c14f05ab (diff)
downloademacs-6a30a74cb2ac2cba69aa01da12caf1eac7134f43.tar.gz
Fix syscall error reporting on aarch64
* exec/trace.c (process_system_call): Save and restore x0, x1 and x2 regs after replacing them with an invalid file descriptor.
Diffstat (limited to 'exec')
-rw-r--r--exec/trace.c21
1 files changed, 20 insertions, 1 deletions
diff --git a/exec/trace.c b/exec/trace.c
index cef699e8526..df5deacd9bb 100644
--- a/exec/trace.c
+++ b/exec/trace.c
@@ -627,6 +627,9 @@ process_system_call (struct exec_tracee *tracee)
USER_REGS_STRUCT regs;
int rc, wstatus;
USER_WORD callno, sp;
+#ifdef __aarch64__
+ USER_WORD old_w0, old_w1, old_w2;
+#endif /* __aarch64__ */
#ifdef __aarch64__
rc = aarch64_get_regs (tracee->pid, &regs);
@@ -692,7 +695,20 @@ process_system_call (struct exec_tracee *tracee)
Make sure that the stack pointer is restored to its original
position upon exit, or bad things can happen. */
+#ifndef __aarch64__
regs.SYSCALL_NUM_REG = -1;
+#else /* __aarch64__ */
+ /* ARM also requires the system call number to be valid. However, I
+ can't find any unused system call, so use fcntl instead, with
+ invalid arguments. */
+ regs.SYSCALL_NUM_REG = 72;
+ old_w0 = regs.regs[0];
+ old_w1 = regs.regs[1];
+ old_w2 = regs.regs[2];
+ regs.regs[0] = -1;
+ regs.regs[1] = -1;
+ regs.regs[2] = -1;
+#endif /* !__aarch64__ */
regs.STACK_POINTER = sp;
#ifdef __aarch64__
@@ -714,7 +730,6 @@ process_system_call (struct exec_tracee *tracee)
return;
#endif /* __aarch64__ */
-
/* Do this invalid system call. */
if (ptrace (PTRACE_SYSCALL, tracee->pid, NULL, NULL))
return;
@@ -740,6 +755,10 @@ process_system_call (struct exec_tracee *tracee)
/* Report errno. */
#ifdef __aarch64__
+ /* Restore x0, x1 and x2. */
+ regs.regs[0] = old_w0;
+ regs.regs[1] = old_w1;
+ regs.regs[2] = old_w2;
aarch64_set_regs (tracee->pid, &regs, false);
#else /* !__aarch64__ */
ptrace (PTRACE_SETREGS, tracee->pid, NULL, &regs);