diff options
Diffstat (limited to 'sysdeps/unix/sysv')
-rw-r--r-- | sysdeps/unix/sysv/linux/alpha/init-first.h | 12 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/i386/init-first.h | 13 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/init-first.c | 43 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/m68k/init-first.h | 12 |
4 files changed, 53 insertions, 27 deletions
diff --git a/sysdeps/unix/sysv/linux/alpha/init-first.h b/sysdeps/unix/sysv/linux/alpha/init-first.h new file mode 100644 index 0000000000..c27c589a28 --- /dev/null +++ b/sysdeps/unix/sysv/linux/alpha/init-first.h @@ -0,0 +1,12 @@ +/* This fragment is invoked in the stack context of program start. + Its job is to set up a pointer to argc as an argument, pass + control to `INIT', and, if necessary, clean up after the call + to leave the stack in the same condition it was found in. */ + +#define SYSDEP_CALL_INIT(NAME, INIT) \ + asm(".globl " #NAME "\n" \ + #NAME ":\n\t" \ + "ldgp $29, 0($27)\n\t" \ + ".prologue 1\n\t" \ + "mov $30, $16\n\t" \ + "br $31, " #INIT "..ng"); diff --git a/sysdeps/unix/sysv/linux/i386/init-first.h b/sysdeps/unix/sysv/linux/i386/init-first.h new file mode 100644 index 0000000000..f42d7f2533 --- /dev/null +++ b/sysdeps/unix/sysv/linux/i386/init-first.h @@ -0,0 +1,13 @@ +/* This fragment is invoked in the stack context of program start. + Its job is to set up a pointer to argc as an argument, pass + control to `INIT', and, if necessary, clean up after the call + to leave the stack in the same condition it was found in. */ + +#define SYSDEP_CALL_INIT(NAME, INIT) \ + asm(".globl " #NAME "\n\t" \ + #NAME ":\n\t" \ + "lea 4(%esp), %eax\n\t" \ + "pushl %eax\n\t" \ + "call " #INIT "\n\t" \ + "popl %eax\n\t" \ + "ret"); diff --git a/sysdeps/unix/sysv/linux/init-first.c b/sysdeps/unix/sysv/linux/init-first.c index 6d974ea1e6..a63200c1ae 100644 --- a/sysdeps/unix/sysv/linux/init-first.c +++ b/sysdeps/unix/sysv/linux/init-first.c @@ -19,23 +19,22 @@ Cambridge, MA 02139, USA. */ #include <unistd.h> #include <sysdep.h> -#include "fpu_control.h" - -/* This code is mostly the same for all machines. This version works at - least for i386 and m68k, and probably any CISCy machine with a normal - stack arrangement. */ +#include <fpu_control.h> +#include "init-first.h" extern void __libc_init (int, char **, char **); extern void __libc_global_ctors (void); +/* The function is called from assembly stubs the compiler can't see. */ +static void init (void *) __attribute__ ((unused)); static void -init (int *data) +init (void *data) { extern int __personality (int); - int argc = *data; - char **argv = (void *) (data + 1); + int argc = *(long *)data; + char **argv = (char **)data + 1; char **envp = &argv[argc + 1]; /* The `personality' system call takes one argument that chooses the @@ -50,33 +49,23 @@ init (int *data) __environ = envp; __libc_init (argc, argv, envp); + +#ifdef PIC + __libc_global_ctors (); +#endif } #ifdef PIC -/* This function is called to initialize the shared C library. - It is called just before the user _start code from i386/elf/start.S, - with the stack set up as that code gets it. */ -/* NOTE! The linker notices the magical name `_init' and sets the DT_INIT - pointer in the dynamic section based solely on that. It is convention - for this function to be in the `.init' section, but the symbol name is - the only thing that really matters!! */ -/*void _init (int argc, ...) __attribute__ ((unused, section (".init")));*/ +SYSDEP_CALL_INIT(_init, init); void -_init (int argc, ...) +__libc_init_first (void) { - init (&argc); - - __libc_global_ctors (); } -#endif +#else + +SYSDEP_CALL_INIT(__libc_init_first, init); -void -__libc_init_first (int argc __attribute__ ((unused)), ...) -{ -#ifndef PIC - init (&argc); #endif -} diff --git a/sysdeps/unix/sysv/linux/m68k/init-first.h b/sysdeps/unix/sysv/linux/m68k/init-first.h new file mode 100644 index 0000000000..7d8c320b0a --- /dev/null +++ b/sysdeps/unix/sysv/linux/m68k/init-first.h @@ -0,0 +1,12 @@ +/* This fragment is invoked in the stack context of program start. + Its job is to set up a pointer to argc as an argument, pass + control to `INIT', and, if necessary, clean up after the call + to leave the stack in the same condition it was found in. */ + +#define SYSDEP_CALL_INIT(NAME, INIT) \ + asm(".globl " #NAME "\n\t" \ + #NAME ":\n\t" \ + "pea %sp@(4)\n\t" \ + "jbsr " #INIT "\n\t" \ + "addq #4,%sp\n\t" \ + "rts"); |