aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZack Weinberg <zackw@panix.com>2018-03-18 17:12:42 -0400
committerZack Weinberg <zackw@panix.com>2018-03-26 08:27:47 -0400
commit65a7c4c9272f1b14a2b87733bf4dbb564c3dd1d2 (patch)
tree4071e1a9510db7601199bd81d045374a94ab044c
parent3dfd23eb4bdc7707048b115548e2238dacef064e (diff)
downloadglibc-65a7c4c9272f1b14a2b87733bf4dbb564c3dd1d2.tar
glibc-65a7c4c9272f1b14a2b87733bf4dbb564c3dd1d2.tar.gz
glibc-65a7c4c9272f1b14a2b87733bf4dbb564c3dd1d2.tar.bz2
glibc-65a7c4c9272f1b14a2b87733bf4dbb564c3dd1d2.zip
RFC: Introduce pt-compat-stubs and use it to replace pt-vfork.
I am looking into the possibility of eliminating all of the duplicate function definitions from libpthread, replacing them with properly-tagged weak compatibility symbols that just call the definition in libc. Because one of the duplicated functions is vfork, the calls to libc absolutely must reuse the stack frame (a "sibcall" in GCC internals jargon), and on several important targets, GCC does not implement sibcalls, or only implements them for intra-module calls. But we only need to implement a single special case, sibcalling a function with exactly the same signature, from immediately after the caller's own entry point; so doing it by hand in assembly language is not a crazy notion. I believe I have managed to turn the trick for all currently-supported targets. This patch just converts the existing vfork stub, so that review can focus on the new sysdep.h SIBCALL macros. * sysdeps/generic/pt-compat-stubs.S: New file. * nptl/Makefile (libpthread-routines): Remove pt-vfork, add pt-compat-stubs. (libpthread-shared-only-routines): Add pt-compat-stubs. * posix/vfork.c: Define __libc_vfork as well as __vfork and vfork. * sysdeps/generic/sysdep.h (SIBCALL): New macro to perform sibling calls; the generic definition errors out if used. * sysdeps/aarch64/sysdep.h, sysdeps/arm/sysdep.h * sysdeps/hppa/sysdep.h, sysdeps/ia64/sysdep.h * sysdeps/m68k/sysdep.h, sysdeps/microblaze/sysdep.h * sysdeps/nios2/sysdep.h, sysdeps/powerpc/powerpc32/sysdep.h * sysdeps/powerpc/powerpc64/sysdep.h, sysdeps/s390/s390-32/sysdep.h * sysdeps/s390/s390-64/sysdep.h, sysdeps/tile/sysdep.h * sysdeps/unix/alpha/sysdep.h, sysdeps/unix/mips/mips32/sysdep.h * sysdeps/unix/mips/mips64/n32/sysdep.h * sysdeps/unix/mips/mips64/n64/sysdep.h * sysdeps/unix/sysv/linux/riscv/sysdep.h * sysdeps/x86/sysdep.h Provide appropriate architecture-specific definitions of SIBCALL and, if necessary, SIBCALL_ENTRY. * nptl/pt-vfork.c * sysdeps/unix/sysv/linux/aarch64/pt-vfork.c * sysdeps/unix/sysv/linux/m68k/pt-vfork.c * sysdeps/unix/sysv/linux/tile/pt-vfork.c * sysdeps/unix/sysv/linux/alpha/pt-vfork.S * sysdeps/unix/sysv/linux/hppa/pt-vfork.S * sysdeps/unix/sysv/linux/ia64/pt-vfork.S * sysdeps/unix/sysv/linux/microblaze/pt-vfork.S * sysdeps/unix/sysv/linux/mips/pt-vfork.S * sysdeps/unix/sysv/linux/riscv/pt-vfork.S * sysdeps/unix/sysv/linux/s390/pt-vfork.S * sysdeps/unix/sysv/linux/sh/pt-vfork.S * sysdeps/unix/sysv/linux/sparc/pt-vfork.S Remove file.
-rw-r--r--nptl/Makefile5
-rw-r--r--nptl/pt-vfork.c65
-rw-r--r--posix/vfork.c6
-rw-r--r--sysdeps/aarch64/sysdep.h9
-rw-r--r--sysdeps/arm/sysdep.h9
-rw-r--r--sysdeps/generic/pt-compat-stubs.S68
-rw-r--r--sysdeps/generic/sysdep.h13
-rw-r--r--sysdeps/hppa/sysdep.h10
-rw-r--r--sysdeps/ia64/sysdep.h9
-rw-r--r--sysdeps/m68k/sysdep.h9
-rw-r--r--sysdeps/microblaze/sysdep.h9
-rw-r--r--sysdeps/nios2/sysdep.h23
-rw-r--r--sysdeps/powerpc/powerpc32/sysdep.h8
-rw-r--r--sysdeps/powerpc/powerpc64/sysdep.h40
-rw-r--r--sysdeps/s390/s390-32/sysdep.h9
-rw-r--r--sysdeps/s390/s390-64/sysdep.h9
-rw-r--r--sysdeps/sh/sysdep.h14
-rw-r--r--sysdeps/sparc/sysdep.h9
-rw-r--r--sysdeps/tile/sysdep.h9
-rw-r--r--sysdeps/unix/alpha/sysdep.h10
-rw-r--r--sysdeps/unix/mips/mips32/sysdep.h25
-rw-r--r--sysdeps/unix/mips/mips64/n32/sysdep.h31
-rw-r--r--sysdeps/unix/mips/mips64/n64/sysdep.h23
-rw-r--r--sysdeps/unix/sysv/linux/aarch64/pt-vfork.c54
-rw-r--r--sysdeps/unix/sysv/linux/alpha/pt-vfork.S43
-rw-r--r--sysdeps/unix/sysv/linux/hppa/pt-vfork.S82
-rw-r--r--sysdeps/unix/sysv/linux/ia64/pt-vfork.S48
-rw-r--r--sysdeps/unix/sysv/linux/m68k/pt-vfork.c1
-rw-r--r--sysdeps/unix/sysv/linux/microblaze/pt-vfork.S49
-rw-r--r--sysdeps/unix/sysv/linux/mips/pt-vfork.S1
-rw-r--r--sysdeps/unix/sysv/linux/riscv/pt-vfork.S1
-rw-r--r--sysdeps/unix/sysv/linux/riscv/sysdep.h9
-rw-r--r--sysdeps/unix/sysv/linux/s390/pt-vfork.S1
-rw-r--r--sysdeps/unix/sysv/linux/sh/pt-vfork.S1
-rw-r--r--sysdeps/unix/sysv/linux/sparc/pt-vfork.S1
-rw-r--r--sysdeps/unix/sysv/linux/tile/pt-vfork.c1
-rw-r--r--sysdeps/x86/sysdep.h9
37 files changed, 368 insertions, 355 deletions
diff --git a/nptl/Makefile b/nptl/Makefile
index 94be92c789..18fbdfbee7 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -120,9 +120,10 @@ libpthread-routines = nptl-init vars events version pt-interp \
cancellation \
lowlevellock \
lll_timedlock_wait lll_timedwait_tid \
- pt-fork pt-vfork \
+ pt-fork \
$(pthread-compat-wrappers) \
pt-raise pt-system \
+ pt-compat-stubs \
flockfile ftrylockfile funlockfile \
sigaction \
herrno res pt-allocrtsig \
@@ -146,7 +147,7 @@ libpthread-routines = nptl-init vars events version pt-interp \
# pthread_setresgid
libpthread-shared-only-routines = version pt-interp pt-allocrtsig \
- unwind-forcedunwind
+ pt-compat-stubs unwind-forcedunwind
# Since cancellation handling is in large parts handled using exceptions
# we have to compile some files with exception handling enabled, some
diff --git a/nptl/pt-vfork.c b/nptl/pt-vfork.c
deleted file mode 100644
index 2f890d3f30..0000000000
--- a/nptl/pt-vfork.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/* vfork ABI-compatibility entry points for libpthread.
- Copyright (C) 2014-2018 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
- <http://www.gnu.org/licenses/>. */
-
-#include <unistd.h>
-#include <shlib-compat.h>
-
-/* libpthread used to have its own vfork implementation that differed
- from libc's only in having a pointless micro-optimization. There
- is no longer any use to having a separate copy in libpthread, but
- the historical ABI requires it. For static linking, there is no
- need to provide anything here--the libc version will be linked in.
- For shared library ABI compatibility, there must be __vfork and
- vfork symbols in libpthread.so; so we define them using IFUNC to
- redirect to the libc function. */
-
-/* Note! If the architecture doesn't support IFUNC, then we need an
- alternate target-specific mechanism to implement this. So we just
- assume IFUNC here and require that the target override this file
- if necessary.
-
- If the architecture can assume all supported versions of gcc will
- produce a tail-call to __libc_vfork, consider including the version
- in sysdeps/unix/sysv/linux/aarch64/pt-vfork.c. */
-
-#if !HAVE_IFUNC
-# error "must write pt-vfork for this machine or get IFUNC support"
-#endif
-
-#if (SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_20) \
- || SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_20))
-
-extern __typeof (vfork) __libc_vfork; /* Defined in libc. */
-
-# undef INIT_ARCH
-# define INIT_ARCH()
-# define DEFINE_VFORK(name) libc_ifunc (name, &__libc_vfork)
-
-#endif
-
-#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_20)
-extern __typeof(vfork) vfork_ifunc;
-DEFINE_VFORK (vfork_ifunc)
-compat_symbol (libpthread, vfork_ifunc, vfork, GLIBC_2_0);
-#endif
-
-#if SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_20)
-extern __typeof(vfork) __vfork_ifunc;
-DEFINE_VFORK (__vfork_ifunc)
-compat_symbol (libpthread, __vfork_ifunc, __vfork, GLIBC_2_1_2);
-#endif
diff --git a/posix/vfork.c b/posix/vfork.c
index d4e76ad21e..07cfca1885 100644
--- a/posix/vfork.c
+++ b/posix/vfork.c
@@ -21,10 +21,10 @@
/* If we don't have vfork, fork is close enough. */
__pid_t
-__vfork (void)
+__libc_vfork (void)
{
return __fork ();
}
+strong_alias (__libc_vfork, __vfork)
libc_hidden_def (__vfork)
-
-weak_alias (__vfork, vfork)
+weak_alias (__libc_vfork, vfork)
diff --git a/sysdeps/aarch64/sysdep.h b/sysdeps/aarch64/sysdep.h
index 5b30709436..a790e3b4ea 100644
--- a/sysdeps/aarch64/sysdep.h
+++ b/sysdeps/aarch64/sysdep.h
@@ -151,6 +151,15 @@
movk PTR_REG (R), #:abs_g0_nc:NAME;
#endif
+/* Make a "sibling call" to DEST -- that is, transfer control to DEST
+ as-if it had been the function called by the caller of this function.
+ DEST is likely to be defined in a different shared object. Only
+ ever used immediately after ENTRY. Must not touch the stack at
+ all, and must preserve all argument and call-saved registers. */
+#undef SIBCALL
+#define SIBCALL(dest) \
+ b JUMPTARGET(dest)
+
/* Since C identifiers are not normally prefixed with an underscore
on this system, the asm identifier `syscall_error' intrudes on the
C name space. Make sure we use an innocuous name. */
diff --git a/sysdeps/arm/sysdep.h b/sysdeps/arm/sysdep.h
index 21673feea2..b3a233bff5 100644
--- a/sysdeps/arm/sysdep.h
+++ b/sysdeps/arm/sysdep.h
@@ -121,6 +121,15 @@
#define CALL_MCOUNT /* Do nothing. */
#endif
+/* Make a "sibling call" to DEST -- that is, transfer control to DEST
+ as-if it had been the function called by the caller of this function.
+ DEST is likely to be defined in a different shared object. Only
+ ever used immediately after ENTRY. Must not touch the stack at
+ all, and must preserve all argument and call-saved registers. */
+#undef SIBCALL
+#define SIBCALL(dest) \
+ b PLTJMP(dest)
+
/* Since C identifiers are not normally prefixed with an underscore
on this system, the asm identifier `syscall_error' intrudes on the
C name space. Make sure we use an innocuous name. */
diff --git a/sysdeps/generic/pt-compat-stubs.S b/sysdeps/generic/pt-compat-stubs.S
new file mode 100644
index 0000000000..3055cfe3ca
--- /dev/null
+++ b/sysdeps/generic/pt-compat-stubs.S
@@ -0,0 +1,68 @@
+/* Compatibility stubs for functions formerly exposed by libpthread.
+ Copyright (C) 2018 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
+ <http://www.gnu.org/licenses/>. */
+
+/* The functions defined by this file used to have two different
+ definitions, one in libc.so and one in libpthread.so. Nowadays,
+ only the version in libc is necessary, but libpthread must continue
+ to expose these symbols for compatibility's sake. The stubs just
+ jump to the definition in libc.
+
+ This file is written in heavily macro-ized assembly language
+ because one of the stubs that it needs to define is vfork, and the
+ implementation of vfork must not touch the stack. Having done the
+ work to handle that, we may as well reuse the mechanism for all of
+ the stubs. */
+
+#include <shlib-compat.h>
+#include <sysdep.h>
+
+ compat_text_section
+
+#ifndef SIBCALL_ENTRY
+# define SIBCALL_ENTRY(name) ENTRY(name)
+#endif
+
+#define define_stub(name) \
+ define_stub_1(__pstub_##name, __libc_##name)
+#define define_stub_1(pstub_name, libc_name) \
+ SIBCALL_ENTRY(pstub_name) ASM_LINE_SEP \
+ SIBCALL(libc_name) ASM_LINE_SEP \
+ END(pstub_name)
+
+#define compat_stub(base, sym, ver) \
+ compat_stub_1(base, sym, ver, __COUNTER__)
+#define compat_stub_1(base, sym, ver, tag) \
+ compat_stub_2(base, sym, ver, tag)
+#define compat_stub_2(base, sym, ver, tag) \
+ compat_stub_3(__pstub_##base, __pstub_##base##_##tag, sym, ver)
+#define compat_stub_3(base, nonce, sym, ver) \
+ weak_alias(base, nonce) ASM_LINE_SEP \
+ compat_symbol(libpthread, nonce, sym, ver)
+
+#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_20) \
+ || SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_20)
+
+ define_stub(vfork)
+# if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_20)
+ compat_stub(vfork, vfork, GLIBC_2_0)
+# endif
+# if SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_20)
+ compat_stub(vfork, __vfork, GLIBC_2_1_2)
+# endif
+
+#endif
diff --git a/sysdeps/generic/sysdep.h b/sysdeps/generic/sysdep.h
index 934d4da839..59e8ec237a 100644
--- a/sysdeps/generic/sysdep.h
+++ b/sysdeps/generic/sysdep.h
@@ -33,9 +33,20 @@
# ifndef JUMPTARGET
# define JUMPTARGET(sym) sym
# endif
+
+/* Make a "sibling call" to DEST -- that is, transfer control to DEST
+ as-if it had been the function called by the caller of this function.
+ DEST is likely to be defined in a different shared object. Only
+ ever used immediately after ENTRY. Must not touch the stack at
+ all, and must preserve all argument and call-saved registers. */
+# ifndef SIBCALL
+# define SIBCALL(dest) \
+ .error "Missing definition of SIBCALL"
+# endif
#endif
-/* Makros to generate eh_frame unwind information. */
+
+/* Macros to generate eh_frame unwind information. */
#ifdef __ASSEMBLER__
# define cfi_startproc .cfi_startproc
# define cfi_endproc .cfi_endproc
diff --git a/sysdeps/hppa/sysdep.h b/sysdeps/hppa/sysdep.h
index 4b139228a1..12cfe51dc3 100644
--- a/sysdeps/hppa/sysdep.h
+++ b/sysdeps/hppa/sysdep.h
@@ -62,6 +62,16 @@
#define PSEUDO_END(name) \
END (name)
+
+/* Make a "sibling call" to DEST -- that is, transfer control to DEST
+ as-if it had been the function called by the caller of this function.
+ DEST is likely to be defined in a different shared object. Only
+ ever used immediately after ENTRY. Must not touch the stack at
+ all, and must preserve all argument and call-saved registers. */
+#undef SIBCALL
+#define SIBCALL(dest) \
+ b JUMPTARGET(dest)
+
#undef JUMPTARGET
#define JUMPTARGET(name) name
#define SYSCALL_PIC_SETUP /* Nothing. */
diff --git a/sysdeps/ia64/sysdep.h b/sysdeps/ia64/sysdep.h
index 6066ebd1d3..ba0e4a5ed2 100644
--- a/sysdeps/ia64/sysdep.h
+++ b/sysdeps/ia64/sysdep.h
@@ -59,4 +59,13 @@
#undef END
#define END(sym) .endp C_SYMBOL_NAME(sym)
+/* Make a "sibling call" to DEST -- that is, transfer control to DEST
+ as-if it had been the function called by the caller of this function.
+ DEST is likely to be defined in a different shared object. Only
+ ever used immediately after ENTRY. Must not touch the stack at
+ all, and must preserve all argument and call-saved registers. */
+#undef SIBCALL
+#define SIBCALL(dest) \
+ .mib; nop 0; nop 0; br.sptk.many C_SYMBOL_NAME(dest);;
+
#endif /* ASSEMBLER */
diff --git a/sysdeps/m68k/sysdep.h b/sysdeps/m68k/sysdep.h
index 0ecb3eae9f..ae085ed9f1 100644
--- a/sysdeps/m68k/sysdep.h
+++ b/sysdeps/m68k/sysdep.h
@@ -71,4 +71,13 @@
# define JUMPTARGET(name) name
# endif
+/* Make a "sibling call" to DEST -- that is, transfer control to DEST
+ as-if it had been the function called by the caller of this function.
+ DEST is likely to be defined in a different shared object. Only
+ ever used immediately after ENTRY. Must not touch the stack at
+ all, and must preserve all argument and call-saved registers. */
+#undef SIBCALL
+#define SIBCALL(dest) \
+ jbra JUMPTARGET(dest)
+
#endif /* __ASSEMBLER__ */
diff --git a/sysdeps/microblaze/sysdep.h b/sysdeps/microblaze/sysdep.h
index 86cd827a09..091986d221 100644
--- a/sysdeps/microblaze/sysdep.h
+++ b/sysdeps/microblaze/sysdep.h
@@ -70,6 +70,15 @@
# define PSEUDO_END(name) \
END (name)
+/* Make a "sibling call" to DEST -- that is, transfer control to DEST
+ as-if it had been the function called by the caller of this function.
+ DEST is likely to be defined in a different shared object. Only
+ ever used immediately after ENTRY. Must not touch the stack at
+ all, and must preserve all argument and call-saved registers. */
+#undef SIBCALL
+#define SIBCALL(dest) \
+ brid JUMPTARGET(dest); nop
+
# undef JUMPTARGET
# ifdef PIC
# define JUMPTARGET(name) name##@PLTPC
diff --git a/sysdeps/nios2/sysdep.h b/sysdeps/nios2/sysdep.h
index 38ea9456af..97a3e2eb24 100644
--- a/sysdeps/nios2/sysdep.h
+++ b/sysdeps/nios2/sysdep.h
@@ -53,7 +53,7 @@
# else
# define CALL_MCOUNT \
mov r8, ra; \
- call _mount; \
+ call _mcount; \
mov ra, r8; \
ret;
# endif
@@ -62,4 +62,25 @@
# define CALL_MCOUNT /* Do nothing. */
#endif
+/* Make a "sibling call" to DEST -- that is, transfer control to DEST
+ as-if it had been the function called by the caller of this function.
+ DEST is likely to be defined in a different shared object. Only
+ ever used immediately after ENTRY. Must not touch the stack at
+ all, and must preserve all argument and call-saved registers. */
+#undef SIBCALL
+#ifdef __PIC__
+#define SIBCALL(dest) \
+ nextpc r2; \
+1: \
+ movhi r3, %hiadj(_gp_got - 1b); \
+ addi r3, r3, %lo(_gp_got - 1b); \
+ addi r2, r2, r3; \
+ ldw r2, %call(dest)(r2); \
+ jmp r2
+#else
+#define SIBCALL(dest) \
+ jmpi dest
+#endif
+
+
#endif /* __ASSEMBLER__ */
diff --git a/sysdeps/powerpc/powerpc32/sysdep.h b/sysdeps/powerpc/powerpc32/sysdep.h
index 5f1294ead3..da67bf0e91 100644
--- a/sysdeps/powerpc/powerpc32/sysdep.h
+++ b/sysdeps/powerpc/powerpc32/sysdep.h
@@ -90,6 +90,14 @@ GOT_LABEL: ; \
cfi_endproc; \
ASM_SIZE_DIRECTIVE(name)
+/* Make a "sibling call" to DEST -- that is, transfer control to DEST
+ as-if it had been the function called by the caller of this function.
+ DEST is likely to be defined in a different shared object. Only
+ ever used immediately after ENTRY. Must not touch the stack at
+ all, and must preserve all argument and call-saved registers. */
+#define SIBCALL(dest) \
+ b JUMPTARGET(dest)
+
#if !IS_IN(rtld) && !defined(__SPE__)
# define ABORT_TRANSACTION_IMPL \
cmpwi 2,0; \
diff --git a/sysdeps/powerpc/powerpc64/sysdep.h b/sysdeps/powerpc/powerpc64/sysdep.h
index 2df1d9b6e6..596c40af9e 100644
--- a/sysdeps/powerpc/powerpc64/sysdep.h
+++ b/sysdeps/powerpc/powerpc64/sysdep.h
@@ -359,6 +359,46 @@ LT_LABELSUFFIX(name,_name_end): ; \
#define PSEUDO_END_ERRVAL(name) \
END (name)
+/* Make a "sibling call" to DEST -- that is, transfer control to DEST
+ as-if it had been the function called by the caller of this function.
+ DEST is likely to be defined in a different shared object. Only
+ ever used immediately after ENTRY. Must not touch the stack at
+ all, and must preserve all argument and call-saved registers.
+
+ The linker will not allow sibling calls through the PLT on
+ PowerPC-64, and even if it did, it wouldn't be safe, because the
+ PLT stub would clobber our caller's save slot for r2. Instead we
+ must perform a manual indirect jump. Even this is only safe
+ because the functions that use SIBCALL are never called from within
+ their own shared object; if they were, DEST would return to code
+ that wasn't expecting to need to restore r2. */
+#define SIBCALL_ENTRY(name) ENTRY_TOCLESS(name)
+#undef SIBCALL
+#if _CALL_ELF != 2
+#define SIBCALL(dest) \
+ addis 11, 2, 1f@toc@ha; \
+ ld 11, 1f@toc@l(11); \
+ ld 12, 0(11); \
+ ld 2, 8(11); \
+ mtctr 12; \
+ ld 11, 16(11); \
+ bctr; \
+ .section ".toc","aw"; \
+1: .quad dest; \
+ .previous
+#else
+#define SIBCALL(dest) \
+0: addis 12, 12, 1f-0b @ha; \
+ addi 12, 12, 1f-0b @l; \
+ ld 12, 0(12); \
+ mtctr 12; \
+ bctr; \
+ .section ".data.rel.ro","aw",@progbits; \
+1: .quad dest; \
+ .previous
+
+#endif
+
#else /* !__ASSEMBLER__ */
#if _CALL_ELF != 2
diff --git a/sysdeps/s390/s390-32/sysdep.h b/sysdeps/s390/s390-32/sysdep.h
index 7e2763fe92..6ba1496735 100644
--- a/sysdeps/s390/s390-32/sysdep.h
+++ b/sysdeps/s390/s390-32/sysdep.h
@@ -59,6 +59,15 @@
#define CALL_MCOUNT /* Do nothing. */
#endif
+/* Make a "sibling call" to DEST -- that is, transfer control to DEST
+ as-if it had been the function called by the caller of this function.
+ DEST is likely to be defined in a different shared object. Only
+ ever used immediately after ENTRY. Must not touch the stack at
+ all, and must preserve all argument and call-saved registers. */
+#undef SIBCALL
+#define SIBCALL(dest) \
+ jg JUMPTARGET(dest)
+
/* Since C identifiers are not normally prefixed with an underscore
on this system, the asm identifier `syscall_error' intrudes on the
C name space. Make sure we use an innocuous name. */
diff --git a/sysdeps/s390/s390-64/sysdep.h b/sysdeps/s390/s390-64/sysdep.h
index a573e08e92..67f8f09542 100644
--- a/sysdeps/s390/s390-64/sysdep.h
+++ b/sysdeps/s390/s390-64/sysdep.h
@@ -57,6 +57,15 @@
#define CALL_MCOUNT /* Do nothing. */
#endif
+/* Make a "sibling call" to DEST -- that is, transfer control to DEST
+ as-if it had been the function called by the caller of this function.
+ DEST is likely to be defined in a different shared object. Only
+ ever used immediately after ENTRY. Must not touch the stack at
+ all, and must preserve all argument and call-saved registers. */
+#undef SIBCALL
+#define SIBCALL(dest) \
+ jg JUMPTARGET(dest)
+
/* Since C identifiers are not normally prefixed with an underscore
on this system, the asm identifier `syscall_error' intrudes on the
C name space. Make sure we use an innocuous name. */
diff --git a/sysdeps/sh/sysdep.h b/sysdeps/sh/sysdep.h
index 37889fb0cc..63eab89001 100644
--- a/sysdeps/sh/sysdep.h
+++ b/sysdeps/sh/sysdep.h
@@ -66,6 +66,20 @@
#define CALL_MCOUNT /* Do nothing. */
#endif
+/* Make a "sibling call" to DEST -- that is, transfer control to DEST
+ as-if it had been the function called by the caller of this function.
+ DEST is likely to be defined in a different shared object. Only
+ ever used immediately after ENTRY. Must not touch the stack at
+ all, and must preserve all argument and call-saved registers. */
+#undef SIBCALL
+#define SIBCALL(dest) \
+ mov.l 1f, r1; \
+ braf r1; \
+ nop; \
+0: .align 2; \
+1: .long dest@PLT+(.-0b)
+
+
/* Since C identifiers are not normally prefixed with an underscore
on this system, the asm identifier `syscall_error' intrudes on the
C name space. Make sure we use an innocuous name. */
diff --git a/sysdeps/sparc/sysdep.h b/sysdeps/sparc/sysdep.h
index 487852c7ec..130d782b11 100644
--- a/sysdeps/sparc/sysdep.h
+++ b/sysdeps/sparc/sysdep.h
@@ -79,4 +79,13 @@ C_LABEL(name) \
#undef LOC
#define LOC(name) .L##name
+/* Make a "sibling call" to DEST -- that is, transfer control to DEST
+ as-if it had been the function called by the caller of this function.
+ DEST is likely to be defined in a different shared object. Only
+ ever used immediately after ENTRY. Must not touch the stack at
+ all, and must preserve all argument and call-saved registers. */
+#undef SIBCALL
+#define SIBCALL(dest) \
+ jmp dest
+
#endif /* __ASSEMBLER__ */
diff --git a/sysdeps/tile/sysdep.h b/sysdeps/tile/sysdep.h
index bb82d3ca6c..aee9893233 100644
--- a/sysdeps/tile/sysdep.h
+++ b/sysdeps/tile/sysdep.h
@@ -56,6 +56,15 @@
#define CALL_MCOUNT /* Do nothing. */
#endif
+/* Make a "sibling call" to DEST -- that is, transfer control to DEST
+ as-if it had been the function called by the caller of this function.
+ DEST is likely to be defined in a different shared object. Only
+ ever used immediately after ENTRY. Must not touch the stack at
+ all, and must preserve all argument and call-saved registers. */
+#undef SIBCALL
+#define SIBCALL(dest) \
+ j plt(dest)
+
/* Local label name for asm code. */
#define L(name) .L##name
diff --git a/sysdeps/unix/alpha/sysdep.h b/sysdeps/unix/alpha/sysdep.h
index 104aa8e48b..263117f805 100644
--- a/sysdeps/unix/alpha/sysdep.h
+++ b/sysdeps/unix/alpha/sysdep.h
@@ -148,6 +148,16 @@ __LABEL(name) \
#undef PSEUDO_END_ERRVAL
#define PSEUDO_END_ERRVAL(sym) END(sym)
+/* Make a "sibling call" to DEST -- that is, transfer control to DEST
+ as-if it had been the function called by the caller of this function.
+ DEST is likely to be defined in a different shared object. Only
+ ever used immediately after ENTRY. Must not touch the stack at
+ all, and must preserve all argument and call-saved registers. */
+#define SIBCALL(dest) \
+ ldgp gp, 0(pv); \
+ lda pv, dest; \
+ jmp (pv), dest
+
#define ret_ERRVAL ret
#define r0 v0
diff --git a/sysdeps/unix/mips/mips32/sysdep.h b/sysdeps/unix/mips/mips32/sysdep.h
index 825d007489..a45eba7430 100644
--- a/sysdeps/unix/mips/mips32/sysdep.h
+++ b/sysdeps/unix/mips/mips32/sysdep.h
@@ -54,3 +54,28 @@ L(syse1):
bne a3, zero, 99b; \
L(syse1):
#endif
+
+/* Make a "sibling call" to DEST -- that is, transfer control to DEST
+ as-if it had been the function called by the caller of this function.
+ DEST is likely to be defined in a different shared object. Only
+ ever used immediately after ENTRY. Must not touch the stack at
+ all, and must preserve all argument and call-saved registers. */
+#ifdef __PIC__
+#define SIBCALL(dest) \
+ .set nomips16; \
+ .set noreorder; \
+ .cpload $25; \
+ .set nomacro; \
+ lw $25, %call16(dest)($28); \
+ nop; \
+ .reloc 1f, R_MIPS_JALR, dest; \
+1: jr $25; \
+ nop
+#else
+#define SIBCALL(dest) \
+ .set nomips16; \
+ .set noreorder; \
+ .set nomacro; \
+ j dest; \
+ nop
+#endif
diff --git a/sysdeps/unix/mips/mips64/n32/sysdep.h b/sysdeps/unix/mips/mips64/n32/sysdep.h
index 78c1eca872..caae9a4b4d 100644
--- a/sysdeps/unix/mips/mips64/n32/sysdep.h
+++ b/sysdeps/unix/mips/mips64/n32/sysdep.h
@@ -61,4 +61,35 @@ L(syse1):
L(syse1):
#endif
+/* Make a "sibling call" to DEST -- that is, transfer control to DEST
+ as-if it had been the function called by the caller of this function.
+ DEST is likely to be defined in a different shared object. Only
+ ever used immediately after ENTRY. Must not touch the stack at
+ all, and must preserve all argument and call-saved registers. */
+#ifdef __PIC__
+/* There's no PLT on MIPS/n32, we are expected to load the address by
+ hand, but the usual gp register on MIPS ($28) is call-saved so we
+ can't use it. Use $at ($1) instead. */
+#define SIBCALL(dest) \
+ .set nomips16; \
+ .set noreorder; \
+ .set nomacro; \
+ .set noat; \
+0: lui $1, %hi(%neg(%gp_rel(0b))); \
+ addiu $1, $1, %lo(%neg(%gp_rel(0b))); \
+ addu $1, $1, $25; \
+ lw $1, %call16(dest)($1); \
+ nop; \
+ .reloc 1f, R_MIPS_JALR, dest; \
+1: jr $25; \
+ nop
+#else
+#define SIBCALL(dest) \
+ .set nomips16; \
+ .set noreorder; \
+ .set nomacro; \
+ j dest; \
+ nop
#endif
+
+#endif /* __ASSEMBLER__ */
diff --git a/sysdeps/unix/mips/mips64/n64/sysdep.h b/sysdeps/unix/mips/mips64/n64/sysdep.h
index a559917e64..167f330020 100644
--- a/sysdeps/unix/mips/mips64/n64/sysdep.h
+++ b/sysdeps/unix/mips/mips64/n64/sysdep.h
@@ -61,4 +61,27 @@ L(syse1):
L(syse1):
#endif
+/* Make a "sibling call" to DEST -- that is, transfer control to DEST
+ as-if it had been the function called by the caller of this function.
+ DEST is likely to be defined in a different shared object. Only
+ ever used immediately after ENTRY. Must not touch the stack at
+ all, and must preserve all argument and call-saved registers. */
+#define SIBCALL(dest) \
+/* There's no PLT on MIPS/n64, we are expected to load the address by
+ hand, but the usual gp register on MIPS ($28) is call-saved so we
+ can't use it. Use $at ($1) instead. */
+#define SIBCALL(dest) \
+ .set nomips16; \
+ .set noreorder; \
+ .set nomacro; \
+ .set noat; \
+0: lui $1, %hi(%neg(%gp_rel(0b))); \
+ daddiu $1, $1, %lo(%neg(%gp_rel(0b))); \
+ daddu $1, $1, $25; \
+ ld $1, %call16(dest)($1); \
+ nop; \
+ .reloc 1f, R_MIPS_JALR, dest; \
+1: jr $25; \
+ nop
+
#endif
diff --git a/sysdeps/unix/sysv/linux/aarch64/pt-vfork.c b/sysdeps/unix/sysv/linux/aarch64/pt-vfork.c
deleted file mode 100644
index 2b277f25ec..0000000000
--- a/sysdeps/unix/sysv/linux/aarch64/pt-vfork.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/* vfork ABI-compatibility entry points for libpthread.
- Copyright (C) 2014-2018 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
- <http://www.gnu.org/licenses/>. */
-
-#include <shlib-compat.h>
-
-/* libpthread used to have its own vfork implementation that differed
- from libc's only in having a pointless micro-optimization. There
- is no longer any use to having a separate copy in libpthread, but
- the historical ABI requires it. For static linking, there is no
- need to provide anything here--the libc version will be linked in.
- For shared library ABI compatibility, there must be __vfork and
- vfork symbols in libpthread.so. */
-
-#if HAVE_IFUNC
-# include <nptl/pt-vfork.c>
-#elif (SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_20) \
- || SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_20))
-
-/* Thankfully, on AArch64 we can rely on the compiler generating
- a tail call here. */
-
-extern void __libc_vfork (void);
-
-void
-vfork_compat (void)
-{
- __libc_vfork ();
-}
-
-# if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_20)
-compat_symbol (libpthread, vfork_compat, vfork, GLIBC_2_0);
-# endif
-
-# if SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_20)
-strong_alias (vfork_compat, vfork_compat2)
-compat_symbol (libpthread, vfork_compat2, __vfork, GLIBC_2_1_2);
-# endif
-
-#endif
diff --git a/sysdeps/unix/sysv/linux/alpha/pt-vfork.S b/sysdeps/unix/sysv/linux/alpha/pt-vfork.S
deleted file mode 100644
index 7ecaa78dd0..0000000000
--- a/sysdeps/unix/sysv/linux/alpha/pt-vfork.S
+++ /dev/null
@@ -1,43 +0,0 @@
-/* vfork ABI-compatibility entry points for libpthread.
- Copyright (C) 2014-2018 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
- <http://www.gnu.org/licenses/>. */
-
-#include <shlib-compat.h>
-
-/* libpthread used to have its own vfork implementation that differed
- from libc's only in having a pointless micro-optimization. There
- is no longer any use to having a separate copy in libpthread, but
- the historical ABI requires it. For static linking, there is no
- need to provide anything here--the libc version will be linked in.
- For shared library ABI compatibility, there must be __vfork and
- vfork symbols in libpthread.so. */
-
-#if (SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_20) \
- || SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_20))
-
-#include <vfork.S>
-
-#endif
-
-#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_20)
-compat_symbol (libpthread, __libc_vfork, vfork, GLIBC_2_0);
-#endif
-
-#if SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_20)
-strong_alias (__libc_vfork, __vfork_compat)
-compat_symbol (libpthread, __vfork_compat, __vfork, GLIBC_2_1_2);
-#endif
diff --git a/sysdeps/unix/sysv/linux/hppa/pt-vfork.S b/sysdeps/unix/sysv/linux/hppa/pt-vfork.S
deleted file mode 100644
index 45f7620d90..0000000000
--- a/sysdeps/unix/sysv/linux/hppa/pt-vfork.S
+++ /dev/null
@@ -1,82 +0,0 @@
-/* Copyright (C) 2005-2018 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
- <http://www.gnu.org/licenses/>. */
-
-#include <sysdep.h>
-#define _ERRNO_H 1
-#include <bits/errno.h>
-#include <tcb-offsets.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. */
-
-.Lthread_start: ASM_LINE_SEP
-
- /* r26, r25, r24, r23 are free since vfork has no arguments */
-ENTRY(__vfork)
- /* We must not create a frame. When the child unwinds to call
- exec it will clobber the same frame that the parent
- needs to unwind. */
-
- /* Save the PIC register. */
-#ifdef PIC
- copy %r19, %r25 /* parent */
-#endif
-
- /* Syscall saves and restores all register states */
- ble 0x100(%sr2,%r0)
- ldi __NR_vfork,%r20
-
- /* Check for error */
- ldi -4096,%r1
- comclr,>>= %r1,%ret0,%r0 /* Note: unsigned compare. */
- b,n .Lerror
-
- /* Return, and DO NOT restore rp. The child may have called
- functions that updated the frame's rp. This works because
- the kernel ensures rp is preserved across the vfork
- syscall. */
- bv,n %r0(%rp)
-
-.Lerror:
- /* Now we need a stack to call a function. We are assured
- that there is no child now, so it's safe to create
- a frame. */
- stw %rp, -20(%sp)
- .cfi_offset 2, -20
- stwm %r3, 64(%sp)
- .cfi_def_cfa_offset -64
- .cfi_offset 3, 0
- stw %sp, -4(%sp)
-
- sub %r0,%ret0,%r3
- SYSCALL_ERROR_HANDLER
- /* Restore the PIC register (in delay slot) on error */
-#ifdef PIC
- copy %r25, %r19 /* parent */
-#else
- nop
-#endif
- /* Write syscall return into errno location */
- stw %r3, 0(%ret0)
- ldw -84(%sp), %rp
- bv %r0(%rp)
- ldwm -64(%sp), %r3
-PSEUDO_END (__vfork)
-libc_hidden_def (__vfork)
-weak_alias (__vfork, vfork)
diff --git a/sysdeps/unix/sysv/linux/ia64/pt-vfork.S b/sysdeps/unix/sysv/linux/ia64/pt-vfork.S
deleted file mode 100644
index 61f3e387b4..0000000000
--- a/sysdeps/unix/sysv/linux/ia64/pt-vfork.S
+++ /dev/null
@@ -1,48 +0,0 @@
-/* vfork ABI-compatibility entry points for libpthread. IA64 version.
- Copyright (C) 2014-2018 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
- <http://www.gnu.org/licenses/>. */
-
-#include <sysdep.h>
-#include <shlib-compat.h>
-
-/* libpthread used to have its own vfork implementation that differed
- from libc's only in having a pointless micro-optimization. There
- is no longer any use to having a separate copy in libpthread, but
- the historical ABI requires it. For static linking, there is no
- need to provide anything here--the libc version will be linked in.
- For shared library ABI compatibility, there must be __vfork and
- vfork symbols in libpthread.so. */
-
-#if (SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_20) \
- || SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_20))
-
-LOCAL_LEAF (vfork_compat)
- br __libc_vfork
- ;;
-END (vfork_compat)
-
-#endif
-
-#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_20)
-weak_alias (vfork_compat, vfork)
-compat_symbol (libpthread, vfork_compat, vfork, GLIBC_2_0);
-#endif
-
-#if SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_20)
-strong_alias (vfork_compat, __vfork_compat)
-compat_symbol (libpthread, __vfork_compat, __vfork, GLIBC_2_1_2);
-#endif
diff --git a/sysdeps/unix/sysv/linux/m68k/pt-vfork.c b/sysdeps/unix/sysv/linux/m68k/pt-vfork.c
deleted file mode 100644
index 5fbc6526aa..0000000000
--- a/sysdeps/unix/sysv/linux/m68k/pt-vfork.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/aarch64/pt-vfork.c>
diff --git a/sysdeps/unix/sysv/linux/microblaze/pt-vfork.S b/sysdeps/unix/sysv/linux/microblaze/pt-vfork.S
deleted file mode 100644
index 74bc1cdf74..0000000000
--- a/sysdeps/unix/sysv/linux/microblaze/pt-vfork.S
+++ /dev/null
@@ -1,49 +0,0 @@
-/* vfork ABI-compatibility entry points for libpthread.
- Copyright (C) 2014-2018 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
- <http://www.gnu.org/licenses/>. */
-
-#include <sysdep.h>
-#include <shlib-compat.h>
-
-/* libpthread used to have its own vfork implementation that differed
- from libc's only in having a pointless micro-optimization. There
- is no longer any use to having a separate copy in libpthread, but
- the historical ABI requires it. For static linking, there is no
- need to provide anything here--the libc version will be linked in.
- For shared library ABI compatibility, there must be __vfork and
- vfork symbols in libpthread.so.
-
- As of GCC 7, microblaze can *not* rely on the compiler to generate
- a tail call from this vfork to __libc_vfork. */
-
-#if (SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_20) \
- || SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_20))
-
-ENTRY (vfork_compat)
- bri __libc_vfork@PLT
-END (vfork_compat)
-
-#endif
-
-#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_20)
-compat_symbol (libpthread, vfork_compat, vfork, GLIBC_2_0)
-#endif
-
-#if SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_20)
-strong_alias (vfork_compat, vfork_compat2)
-compat_symbol (libpthread, vfork_compat2, __vfork, GLIBC_2_1_2)
-#endif
diff --git a/sysdeps/unix/sysv/linux/mips/pt-vfork.S b/sysdeps/unix/sysv/linux/mips/pt-vfork.S
deleted file mode 100644
index 65cc3823ac..0000000000
--- a/sysdeps/unix/sysv/linux/mips/pt-vfork.S
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/alpha/pt-vfork.S>
diff --git a/sysdeps/unix/sysv/linux/riscv/pt-vfork.S b/sysdeps/unix/sysv/linux/riscv/pt-vfork.S
deleted file mode 100644
index 1cc8931700..0000000000
--- a/sysdeps/unix/sysv/linux/riscv/pt-vfork.S
+++ /dev/null
@@ -1 +0,0 @@
-/* Not needed. */
diff --git a/sysdeps/unix/sysv/linux/riscv/sysdep.h b/sysdeps/unix/sysv/linux/riscv/sysdep.h
index 5470ea3d2a..0a2c2f8696 100644
--- a/sysdeps/unix/sysv/linux/riscv/sysdep.h
+++ b/sysdeps/unix/sysv/linux/riscv/sysdep.h
@@ -107,6 +107,15 @@
# undef ret_ERRVAL
# define ret_ERRVAL ret
+/* Make a "sibling call" to DEST -- that is, transfer control to DEST
+ as-if it had been the function called by the caller of this function.
+ DEST is likely to be defined in a different shared object. Only
+ ever used immediately after ENTRY. Must not touch the stack at
+ all, and must preserve all argument and call-saved registers. */
+#undef SIBCALL
+#define SIBCALL(dest) \
+ tail JUMPTARGET(dest)
+
#endif /* __ASSEMBLER__ */
/* In order to get __set_errno() definition in INLINE_SYSCALL. */
diff --git a/sysdeps/unix/sysv/linux/s390/pt-vfork.S b/sysdeps/unix/sysv/linux/s390/pt-vfork.S
deleted file mode 100644
index 65cc3823ac..0000000000
--- a/sysdeps/unix/sysv/linux/s390/pt-vfork.S
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/alpha/pt-vfork.S>
diff --git a/sysdeps/unix/sysv/linux/sh/pt-vfork.S b/sysdeps/unix/sysv/linux/sh/pt-vfork.S
deleted file mode 100644
index 65cc3823ac..0000000000
--- a/sysdeps/unix/sysv/linux/sh/pt-vfork.S
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/alpha/pt-vfork.S>
diff --git a/sysdeps/unix/sysv/linux/sparc/pt-vfork.S b/sysdeps/unix/sysv/linux/sparc/pt-vfork.S
deleted file mode 100644
index 65cc3823ac..0000000000
--- a/sysdeps/unix/sysv/linux/sparc/pt-vfork.S
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/alpha/pt-vfork.S>
diff --git a/sysdeps/unix/sysv/linux/tile/pt-vfork.c b/sysdeps/unix/sysv/linux/tile/pt-vfork.c
deleted file mode 100644
index 5fbc6526aa..0000000000
--- a/sysdeps/unix/sysv/linux/tile/pt-vfork.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/aarch64/pt-vfork.c>
diff --git a/sysdeps/x86/sysdep.h b/sysdeps/x86/sysdep.h
index afcb7cfd76..6baf03de94 100644
--- a/sysdeps/x86/sysdep.h
+++ b/sysdeps/x86/sysdep.h
@@ -46,6 +46,15 @@
#define ENTRY_CHK(name) ENTRY (name)
#define END_CHK(name) END (name)
+/* Make a "sibling call" to DEST -- that is, transfer control to DEST
+ as-if it had been the function called by the caller of this function.
+ DEST is likely to be defined in a different shared object. Only
+ ever used immediately after ENTRY. Must not touch the stack at
+ all, and must preserve all argument and call-saved registers. */
+#undef SIBCALL
+#define SIBCALL(dest) \
+ jmp JUMPTARGET(dest)
+
/* Since C identifiers are not normally prefixed with an underscore
on this system, the asm identifier `syscall_error' intrudes on the
C name space. Make sure we use an innocuous name. */