|
@@ -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
|
|
|
-
|