aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/unix
diff options
context:
space:
mode:
authorJohn David Anglin <danglin@gcc.gnu.org>2024-12-19 11:30:09 -0500
committerJohn David Anglin <danglin@gcc.gnu.org>2024-12-19 11:30:09 -0500
commit57256971b041a72d9f928bedcec6ac0e651276ee (patch)
tree69d0477fc81045a53dbf6f5922b63f3c9c710ed0 /sysdeps/unix
parent5fcee06dc7f368770c17f9a69b59fa68119a1cec (diff)
downloadglibc-57256971b041a72d9f928bedcec6ac0e651276ee.zip
glibc-57256971b041a72d9f928bedcec6ac0e651276ee.tar.gz
glibc-57256971b041a72d9f928bedcec6ac0e651276ee.tar.bz2
hppa: Fix strace detach-vfork test
This change implements vfork.S for direct support of the vfork syscall. clone.S is revised to correct child support for the vfork case. The main bug was creating a frame prior to the clone syscall. This was done to allow the rp and r4 registers to be saved and restored from the stack frame. r4 was used to save and restore the PIC register, r19, across the system call and the call to set errno. But in the vfork case, it is undefined behavior for the child to return from the function in which vfork was called. It is surprising that this usually worked. Syscalls on hppa save and restore rp and r19, so we don't need to create a frame prior to the clone syscall. We only need a frame when __syscall_error is called. We also don't need to save and restore r19 around the call to $$dyncall as r19 is not used in the code after $$dyncall. This considerably simplifies clone.S. Signed-off-by: John David Anglin <dave.anglin@bell.net>
Diffstat (limited to 'sysdeps/unix')
-rw-r--r--sysdeps/unix/sysv/linux/hppa/clone.S58
-rw-r--r--sysdeps/unix/sysv/linux/hppa/vfork.S53
2 files changed, 64 insertions, 47 deletions
diff --git a/sysdeps/unix/sysv/linux/hppa/clone.S b/sysdeps/unix/sysv/linux/hppa/clone.S
index a31afea..c18163d 100644
--- a/sysdeps/unix/sysv/linux/hppa/clone.S
+++ b/sysdeps/unix/sysv/linux/hppa/clone.S
@@ -59,16 +59,6 @@
.text
ENTRY(__clone)
- /* Prologue */
- stwm %r4, 64(%sp)
- .cfi_def_cfa_offset -64
- .cfi_offset 4, 0
- stw %sp, -4(%sp)
-#ifdef PIC
- stw %r19, -32(%sp)
- .cfi_offset 19, 32
-#endif
-
/* Sanity check arguments. */
comib,=,n 0,%arg0,.LerrorSanity /* no NULL function pointers */
comib,=,n 0,%arg1,.LerrorSanity /* no NULL stack pointers */
@@ -87,54 +77,34 @@ ENTRY(__clone)
/* User stack pointer is in the correct register already */
/* Load args from stack... */
- ldw -116(%sp), %r24 /* Load parent_tidptr */
- ldw -120(%sp), %r23 /* Load newtls */
- ldw -124(%sp), %r22 /* Load child_tidptr */
-
- /* Save the PIC register. */
-#ifdef PIC
- copy %r19, %r4 /* parent */
-#endif
+ ldw -52(%sp), %r24 /* Load parent_tidptr */
+ ldw -56(%sp), %r23 /* Load newtls */
+ ldw -60(%sp), %r22 /* Load child_tidptr */
/* Do the system call */
ble 0x100(%sr2, %r0)
ldi __NR_clone, %r20
ldi -4096, %r1
- comclr,>>= %r1, %ret0, %r0 /* Note: unsigned compare. */
- b,n .LerrorRest
-
- /* Restore the PIC register. */
-#ifdef PIC
- copy %r4, %r19 /* parent */
-#endif
-
+ comb,<<,n %r1, %ret0, .LerrorRest /* Note: unsigned compare. */
comib,=,n 0, %ret0, .LthreadStart
-
- /* Successful return from the parent
- No need to restore the PIC register,
- since we return immediately. */
-
- ldw -84(%sp), %rp
- bv %r0(%rp)
- ldwm -64(%sp), %r4
+ bv,n %r0(%rp)
.LerrorRest:
- /* Something bad happened -- no child created */
+ /* Something bad happened -- no child created -- need a frame */
+ ldo 64(%sp),%sp
+ .cfi_def_cfa_offset -64
bl __syscall_error, %rp
sub %r0, %ret0, %arg0
ldw -84(%sp), %rp
/* Return after setting errno, ret0 is set to -1 by __syscall_error. */
bv %r0(%rp)
- ldwm -64(%sp), %r4
+ ldo -64(%sp), %sp
.LerrorSanity:
/* Sanity checks failed, return -1, and set errno to EINVAL. */
- bl __syscall_error, %rp
- ldi EINVAL, %arg0
- ldw -84(%sp), %rp
- bv %r0(%rp)
- ldwm -64(%sp), %r4
+ b .LerrorRest
+ ldi -EINVAL, %ret0
.LthreadStart:
/* Load up the arguments. */
@@ -144,14 +114,8 @@ ENTRY(__clone)
/* $$dyncall fixes child's PIC register */
/* Call the user's function */
-#ifdef PIC
- copy %r19, %r4
-#endif
bl $$dyncall, %r31
copy %r31, %rp
-#ifdef PIC
- copy %r4, %r19
-#endif
copy %r28, %r26
ble 0x100(%sr2, %r0)
ldi __NR_exit, %r20
diff --git a/sysdeps/unix/sysv/linux/hppa/vfork.S b/sysdeps/unix/sysv/linux/hppa/vfork.S
new file mode 100644
index 0000000..5fd368f
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/hppa/vfork.S
@@ -0,0 +1,53 @@
+/* Copyright (C) 1999-2024 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#define _ERRNO_H 1
+#include <bits/errno.h>
+
+/* Clone the calling process, but without copying the whole address space.
+ The calling process is suspended until the new process exits or is
+ replaced by a call to `execve'. Return -1 for errors, 0 to the new process,
+ and the process ID of the new process to the old process. */
+
+ENTRY (__vfork)
+ ble 0x100(%sr2, %r0)
+ ldi __NR_vfork, %r20
+
+ ldi -4096, %r1
+ comclr,<< %r1, %ret0, %r0 /* Note: unsigned compare. */
+ bv,n %r0(%rp)
+
+ /* Something bad happened -- no child created -- we need a frame */
+ ldo 64(%sp), %sp
+ .cfi_def_cfa_offset -64
+
+ /* Set errno */
+ bl __syscall_error, %rp
+ sub %r0, %ret0, %arg0
+
+ /* ret0 is set to -1 by __syscall_error */
+ ldw -84(%sp), %rp
+ bv %r0(%rp)
+ ldo -64(%sp), %sp
+
+PSEUDO_END (__vfork)
+libc_hidden_def (__vfork)
+
+weak_alias (__vfork, vfork)
+strong_alias (__vfork, __libc_vfork)