summaryrefslogtreecommitdiff
path: root/libc/sysdeps/linux/i386/crt1.S
diff options
context:
space:
mode:
Diffstat (limited to 'libc/sysdeps/linux/i386/crt1.S')
-rw-r--r--libc/sysdeps/linux/i386/crt1.S202
1 files changed, 106 insertions, 96 deletions
diff --git a/libc/sysdeps/linux/i386/crt1.S b/libc/sysdeps/linux/i386/crt1.S
index 7eee8aea9..fa9174f3e 100644
--- a/libc/sysdeps/linux/i386/crt1.S
+++ b/libc/sysdeps/linux/i386/crt1.S
@@ -1,121 +1,132 @@
-/* Copyright (C) 1991, 1992 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 Library General Public License as
-published by the Free Software Foundation; either version 2 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
-Library General Public License for more details.
-
-You should have received a copy of the GNU Library General Public
-License along with the GNU C Library; see the file COPYING.LIB. If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA. */
-
-
-/* Based on the code from GNU libc, but hacked up by John Beppu and Erik Andersen */
-/* adapted by PaX Team for ET_DYN/PIE binaries */
-
-/*
- When we enter this piece of code, the program stack looks like this:
- argc argument counter (integer)
- argv[0] program name (pointer)
- argv[1...N] program args (pointers)
- argv[argc-1] end of args (integer)
- NULL
- env[0...N] environment variables (pointers)
- NULL
+/* Startup code compliant to the ELF i386 ABI.
+ Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004
+ 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.
+
+ In addition to the permissions in the GNU Lesser General Public
+ License, the Free Software Foundation gives you unlimited
+ permission to link the compiled version of this file with other
+ programs, and to distribute those programs without any restriction
+ coming from the use of this file. (The GNU Lesser General Public
+ License restrictions do apply in other respects; for example, they
+ cover modification of the file, and distribution when not linked
+ into another program.)
+
+ Note that people who make modified versions of this file are not
+ obligated to grant this special exception for their modified
+ versions; it is their choice whether to do so. The GNU Lesser
+ General Public License gives permission to release a modified
+ version without this exception; this exception also makes it
+ possible to release a modified version which carries forward this
+ exception.
+
+ 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/* This is the canonical entry point, usually the first thing in the text
+ segment. The SVR4/i386 ABI (pages 3-31, 3-32) says that when the entry
+ point runs, most registers' values are unspecified, except for:
+
+ %edx Contains a function pointer to be registered with `atexit'.
+ This is how the dynamic linker arranges to have DT_FINI
+ functions called for shared libraries that have been loaded
+ before this code runs.
+
+ %esp The stack contains the arguments and environment:
+ 0(%esp) argc
+ 4(%esp) argv[0]
+ ...
+ (4*argc)(%esp) NULL
+ (4*(argc+1))(%esp) envp[0]
+ ...
+ NULL
*/
-#include <features.h>
-
-.text
- .align 4
-
- .global _start
- .type _start,%function
+ .text
+ .globl _start
+ .type _start,@function
.type _init,%function
.type _fini,%function
.type main,%function
.type __uClibc_start_main,%function
-
_start:
- /* locate the start of the environment variables */
- popl %ecx /* Store argc into %ecx */
- movl %esp,%ebx /* Store argv into ebx */
- movl %esp,%eax /* Store argv into eax as well*/
- movl %edx,%esi /* Store edx(FINI ptr) in %esi */
- movl %ecx,%edx /* Stick argc into %edx so we can do some math in a sec */
- leal 4(%eax,%edx,4),%eax
-
- /* [ register layout ]
-
- sizeof(char*) == 4
- %ecx = argc ; 0(esp)
- %ebx = argv ; 4(esp)
- %eax = env ; argv + (argc * 4) + 4
- */
- xorl %ebp,%ebp /* NULL */
- /*
- Before pushing the arguments align the stack to a 16-byte
+ /* Clear the frame pointer. The ABI suggests this be done, to mark
+ the outermost frame obviously. */
+ xorl %ebp, %ebp
+
+ /* Extract the arguments as encoded on the stack and set up
+ the arguments for `main': argc, argv. envp will be determined
+ later in __libc_start_main. */
+ popl %esi /* Pop the argument count. */
+ movl %esp, %ecx /* argv starts just at the current stack top.*/
+
+ /* Before pushing the arguments align the stack to a 16-byte
(SSE needs 16-byte alignment) boundary to avoid penalties from
misaligned accesses. Thanks to Edward Seidl <seidl@janed.com>
- for pointing this out.
- */
+ for pointing this out. */
andl $0xfffffff0, %esp
- /* Push NULL to make sure stack ptr
- is 16 byte aligned when calling __uClibc_start_main */
- pushl %ebp
-
- /* Set up an invalid (NULL return address, NULL frame pointer)
- callers stack frame so anybody unrolling the stack knows where
- to stop */
- pushl %ebp /* callers %cs */
- pushl %ebp /* callers %eip (return address) */
- pushl %ebp /* callers %ebp (frame pointer) */
- movl %esp,%ebp /* mark callers stack frame as invalid */
+ pushl %eax /* Push garbage because we allocate
+ 28 more bytes. */
+
+ /* Provide the highest stack address to the user code (for stacks
+ which grow downwards). */
+ pushl %esp
+
+ pushl %edx /* Push address of the shared library
+ termination function. */
#if defined L_Scrt1
- call .L0
-.L0:
- pop %edx
- addl $_GLOBAL_OFFSET_TABLE_+[.-.L0],%edx
-#endif
- pushl %esp /* push stack ptr */
- pushl %esi /* Push FINI pointer */
+ /* Load PIC register. */
+ call 1f
+ addl $_GLOBAL_OFFSET_TABLE_, %ebx
+
+ /* Push address of our own entry points to .fini and .init. */
+ leal _fini@GOTOFF(%ebx), %eax
+ pushl %eax
+ leal _init@GOTOFF(%ebx), %eax
+ pushl %eax
- /* Push apps .init, .fini and main arguments to __uClibc_start_main() on the stack */
-#ifdef L_Scrt1
- pushl _fini@GOT(%edx)
- pushl _init@GOT(%edx)
+ pushl %ecx /* Push second argument: argv. */
+ pushl %esi /* Push first argument: argc. */
+
+ pushl main@GOT(%ebx)
+
+ /* Call the user's main function, and exit with its value.
+ But let the libc call main. */
+ call __uClibc_start_main@PLT
#else
+ /* Push address of our own entry points to .fini and .init. */
pushl $_fini
pushl $_init
-#endif
- /* Push envp, argc, and argc arguments to __uClibc_start_main() on the stack */
- pushl %eax /* Environment pointer */
- pushl %ebx /* Argument pointer */
- pushl %ecx /* And the argument count */
+ pushl %ecx /* Push second argument: argv. */
+ pushl %esi /* Push first argument: argc. */
- /* Ok, now run uClibc's main() -- shouldn't return */
-#ifdef L_Scrt1
- pushl main@GOT(%edx)
- call *__uClibc_start_main@GOT(%edx)
-#else
pushl $main
+
+ /* Call the user's main function, and exit with its value.
+ But let the libc call main. */
call __uClibc_start_main
#endif
- /* Crash if somehow `exit' returns anyways. */
- hlt
-.size _start,.-_start
-
+ hlt /* Crash if somehow `exit' does return. */
+#if defined L_Scrt1
+1: movl (%esp), %ebx
+ ret
+#endif
/* Define a symbol for the first piece of initialized data. */
.data
.globl __data_start
@@ -123,4 +134,3 @@ __data_start:
.long 0
.weak data_start
data_start = __data_start
-