]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
RFC: Introduce pt-compat-stubs and use it to replace pt-vfork.
authorZack Weinberg <zackw@panix.com>
Sun, 18 Mar 2018 21:12:42 +0000 (17:12 -0400)
committerZack Weinberg <zackw@panix.com>
Mon, 26 Mar 2018 12:27:47 +0000 (08:27 -0400)
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.

37 files changed:
nptl/Makefile
nptl/pt-vfork.c [deleted file]
posix/vfork.c
sysdeps/aarch64/sysdep.h
sysdeps/arm/sysdep.h
sysdeps/generic/pt-compat-stubs.S [new file with mode: 0644]
sysdeps/generic/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/sh/sysdep.h
sysdeps/sparc/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/aarch64/pt-vfork.c [deleted file]
sysdeps/unix/sysv/linux/alpha/pt-vfork.S [deleted file]
sysdeps/unix/sysv/linux/hppa/pt-vfork.S [deleted file]
sysdeps/unix/sysv/linux/ia64/pt-vfork.S [deleted file]
sysdeps/unix/sysv/linux/m68k/pt-vfork.c [deleted file]
sysdeps/unix/sysv/linux/microblaze/pt-vfork.S [deleted file]
sysdeps/unix/sysv/linux/mips/pt-vfork.S [deleted file]
sysdeps/unix/sysv/linux/riscv/pt-vfork.S [deleted file]
sysdeps/unix/sysv/linux/riscv/sysdep.h
sysdeps/unix/sysv/linux/s390/pt-vfork.S [deleted file]
sysdeps/unix/sysv/linux/sh/pt-vfork.S [deleted file]
sysdeps/unix/sysv/linux/sparc/pt-vfork.S [deleted file]
sysdeps/unix/sysv/linux/tile/pt-vfork.c [deleted file]
sysdeps/x86/sysdep.h

index 94be92c78962a3b47fbc0e06371a7b173c36e6e8..18fbdfbee7cb6bd647f38895ec107c2e01262a4f 100644 (file)
@@ -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 (file)
index 2f890d3..0000000
+++ /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
index d4e76ad21e21552651cb8d74e6062c0ec1364e8a..07cfca1885cc100f945f0f0f2289704e04543ade 100644 (file)
 /* 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)
index 5b30709436d3acea7440bc5e44893a089abb3aad..a790e3b4ead6f6fa2cfdf2f182ee24bf7ddc7d53 100644 (file)
        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.  */
index 21673feea217751b54befab5edce37d85feff8e8..b3a233bff515daac05a9ef99c3482f6813af1415 100644 (file)
 #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 (file)
index 0000000..3055cfe
--- /dev/null
@@ -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
index 934d4da839f8955a33a692b6157805e6568349d9..59e8ec237aaf85dca52c21e2a35514df64ca04f7 100644 (file)
 # 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
index 4b139228a1fa9b7ea66f3fa74c63e7e0ad593fa9..12cfe51dc3d9a678345a3d2295567596336d948f 100644 (file)
 #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.  */
index 6066ebd1d3a135d3519b5d2474fc524f9e2d614c..ba0e4a5ed28974bdfa97004a5b878deee2b2b723 100644 (file)
 #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 */
index 0ecb3eae9ffe0cf7d114a7325bfb2859af02c18c..ae085ed9f19463e86d9135e996062206a76960b0 100644 (file)
 #  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__ */
index 86cd827a09c4b4d619df0b5faf6ce07e04c2f34b..091986d2212d9f7284e57617d072bf6fd0032a88 100644 (file)
 # 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
index 38ea9456afad65c8ba442a6a35d89b67624f55e9..97a3e2eb24638fd8eaf0bad027a9618d62603346 100644 (file)
@@ -53,7 +53,7 @@
 # else
 #  define CALL_MCOUNT                          \
   mov r8, ra;                                  \
-  call _mount;                                 \
+  call _mcount;                                        \
   mov ra, r8;                                  \
   ret;
 # endif
 # 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__ */
index 5f1294ead3071db9f787049ef0960e8221d469ff..da67bf0e91e5b5f858778c02ea45e25ca8323ccc 100644 (file)
@@ -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;              \
index 2df1d9b6e6749da4a1a0ccc9d78881326cd99f71..596c40af9ee7644961b35778c725ae94990d653b 100644 (file)
@@ -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
index 7e2763fe9296eb91de50b45458f9e2659d2363ad..6ba1496735ca9b3457827619b9bdd612b769d999 100644 (file)
 #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.  */
index a573e08e92f64c65d1aa0ecf40802136434003c1..67f8f09542ed583f7478f98b2c988b7cd30b389d 100644 (file)
 #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.  */
index 37889fb0ccda21b5cccfca89b22df66dbc5fce2f..63eab89001e7b520c2e4399867fd014b9619e267 100644 (file)
 #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.  */
index 487852c7ec5aa691d87b32e4b1455fff1023b785..130d782b11ad1b3aef3686ef633e2badd1bb3e08 100644 (file)
@@ -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__ */
index bb82d3ca6c605cc48812d1e83f2dcfb5c2398544..aee98932333b827dbf6b03554acfe58cfdd89ef4 100644 (file)
 #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
 
index 104aa8e48bbe43bb2b6b2d4abb1977e83b35423c..263117f805008070319a7a1b152b29ba9ca99e7b 100644 (file)
@@ -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
index 825d0074894bf83d2768018f7b560bde631fa037..a45eba743048829212c26b554065c06df6cbc44f 100644 (file)
@@ -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
index 78c1eca872716407c0fa1cec6c0699b0a51a17d4..caae9a4b4d0963d2dd81a8879aee3c1d88f7ea96 100644 (file)
@@ -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__ */
index a559917e64be38dfeedb7278174df2a77aaeddec..167f3300203682132fd87dc8a181cd2ef0f8b6d6 100644 (file)
@@ -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 (file)
index 2b277f2..0000000
+++ /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 (file)
index 7ecaa78..0000000
+++ /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 (file)
index 45f7620..0000000
+++ /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 (file)
index 61f3e38..0000000
+++ /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 (file)
index 5fbc652..0000000
+++ /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 (file)
index 74bc1cd..0000000
+++ /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 (file)
index 65cc382..0000000
+++ /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 (file)
index 1cc8931..0000000
+++ /dev/null
@@ -1 +0,0 @@
-/* Not needed.  */
index 5470ea3d2a6882ad34e5fc924517fd6fc98add2b..0a2c2f86964fad39153f155b97323fffc0f799d9 100644 (file)
 # 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 (file)
index 65cc382..0000000
+++ /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 (file)
index 65cc382..0000000
+++ /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 (file)
index 65cc382..0000000
+++ /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 (file)
index 5fbc652..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/aarch64/pt-vfork.c>
index afcb7cfd76b22f925da54710e5cccb155f620208..6baf03de94756b1ae849e13ce0f3b86ad761259d 100644 (file)
 #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.  */