sol2-c1.asm revision 302408
1185377Ssam! crt1.s for Solaris 2, x86 2187831Ssam 3185377Ssam! Copyright (C) 1993, 1998 Free Software Foundation, Inc. 4185377Ssam! Written By Fred Fish, Nov 1992 5185377Ssam! 6185377Ssam! This file is free software; you can redistribute it and/or modify it 7185377Ssam! under the terms of the GNU General Public License as published by the 8185377Ssam! Free Software Foundation; either version 2, or (at your option) any 9185377Ssam! later version. 10185377Ssam! 11185377Ssam! In addition to the permissions in the GNU General Public License, the 12185377Ssam! Free Software Foundation gives you unlimited permission to link the 13185377Ssam! compiled version of this file with other programs, and to distribute 14185377Ssam! those programs without any restriction coming from the use of this 15185377Ssam! file. (The General Public License restrictions do apply in other 16185377Ssam! respects; for example, they cover modification of the file, and 17187611Ssam! distribution when not linked into another program.) 18185377Ssam! 19185377Ssam! This file is distributed in the hope that it will be useful, but 20185377Ssam! WITHOUT ANY WARRANTY; without even the implied warranty of 21185377Ssam! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22185377Ssam! General Public License for more details. 23185377Ssam! 24185377Ssam! You should have received a copy of the GNU General Public License 25185377Ssam! along with this program; see the file COPYING. If not, write to 26185377Ssam! the Free Software Foundation, 51 Franklin Street, Fifth Floor, 27185377Ssam! Boston, MA 02110-1301, USA. 28185377Ssam! 29185377Ssam! As a special exception, if you link this library with files 30185377Ssam! compiled with GCC to produce an executable, this does not cause 31185377Ssam! the resulting executable to be covered by the GNU General Public License. 32185377Ssam! This exception does not however invalidate any other reasons why 33185377Ssam! the executable file might be covered by the GNU General Public License. 34185377Ssam! 35185377Ssam 36185377Ssam! This file takes control of the process from the kernel, as specified 37185377Ssam! in section 3 of the System V Application Binary Interface, Intel386 38185377Ssam! Processor Supplement. It has been constructed from information obtained 39185377Ssam! from the ABI, information obtained from single stepping existing 40185377Ssam! Solaris executables through their startup code with gdb, and from 41185377Ssam! information obtained by single stepping executables on other i386 SVR4 42185377Ssam! implementations. This file is the first thing linked into any executable. 43185377Ssam 44185377Ssam .file "crt1.s" 45185377Ssam .ident "GNU C crt1.s" 46185377Ssam .weak _cleanup 47185377Ssam .weak _DYNAMIC 48185377Ssam .text 49208644Srpaulo 50185377Ssam! Start creating the initial frame by pushing a NULL value for the return 51185377Ssam! address of the initial frame, and mark the end of the stack frame chain 52185377Ssam! (the innermost stack frame) with a NULL value, per page 3-32 of the ABI. 53185377Ssam! Initialize the first stack frame pointer in %ebp (the contents of which 54185377Ssam! are unspecified at process initialization). 55185377Ssam 56185377Ssam .globl _start 57185377Ssam_start: 58185377Ssam pushl $0x0 59185377Ssam pushl $0x0 60185377Ssam movl %esp,%ebp 61185377Ssam 62185377Ssam! As specified per page 3-32 of the ABI, %edx contains a function 63185377Ssam! pointer that should be registered with atexit(), for proper 64185377Ssam! shared object termination. Just push it onto the stack for now 65185377Ssam! to preserve it. We want to register _cleanup() first. 66185377Ssam 67185377Ssam pushl %edx 68185377Ssam 69185377Ssam! Check to see if there is an _cleanup() function linked in, and if 70185377Ssam! so, register it with atexit() as the last thing to be run by 71185377Ssam! atexit(). 72185377Ssam 73185377Ssam movl $_cleanup,%eax 74185377Ssam testl %eax,%eax 75185377Ssam je .L1 76185377Ssam pushl $_cleanup 77185377Ssam call atexit 78185377Ssam addl $0x4,%esp 79185377Ssam.L1: 80185377Ssam 81185377Ssam! Now check to see if we have an _DYNAMIC table, and if so then 82185377Ssam! we need to register the function pointer previously in %edx, but 83185377Ssam! now conveniently saved on the stack as the argument to pass to 84185377Ssam! atexit(). 85185377Ssam 86185377Ssam movl $_DYNAMIC,%eax 87185377Ssam testl %eax,%eax 88185377Ssam je .L2 89185377Ssam call atexit 90185377Ssam.L2: 91185377Ssam 92185377Ssam! Register _fini() with atexit(). We will take care of calling _init() 93185377Ssam! directly. 94185377Ssam 95185377Ssam pushl $_fini 96185377Ssam call atexit 97185377Ssam 98185377Ssam! Compute the address of the environment vector on the stack and load 99185377Ssam! it into the global variable _environ. Currently argc is at 8 off 100185377Ssam! the frame pointer. Fetch the argument count into %eax, scale by the 101185377Ssam! size of each arg (4 bytes) and compute the address of the environment 102185377Ssam! vector which is 16 bytes (the two zero words we pushed, plus argc, 103185377Ssam! plus the null word terminating the arg vector) further up the stack, 104185377Ssam! off the frame pointer (whew!). 105185377Ssam 106185377Ssam movl 8(%ebp),%eax 107185377Ssam leal 16(%ebp,%eax,4),%edx 108187831Ssam movl %edx,_environ 109187831Ssam 110185377Ssam! Push the environment vector pointer, the argument vector pointer, 111185377Ssam! and the argument count on to the stack to set up the arguments 112187831Ssam! for _init(), _fpstart(), and main(). Note that the environment 113187831Ssam! vector pointer and the arg count were previously loaded into 114187831Ssam! %edx and %eax respectively. The only new value we need to compute 115187831Ssam! is the argument vector pointer, which is at a fixed address off 116187831Ssam! the initial frame pointer. 117187831Ssam 118185377Ssam! 119185377Ssam! Make sure the stack is properly aligned. 120187831Ssam! 121187831Ssam andl $0xfffffff0,%esp 122185377Ssam subl $4,%esp 123185377Ssam 124187831Ssam pushl %edx 125185377Ssam leal 12(%ebp),%edx 126185377Ssam pushl %edx 127185377Ssam pushl %eax 128185377Ssam 129185377Ssam! Call _init(argc, argv, environ), _fpstart(argc, argv, environ), and 130185377Ssam! main(argc, argv, environ). 131185377Ssam 132185377Ssam call _init 133185377Ssam call __fpstart 134185377Ssam call main 135185377Ssam 136185377Ssam! Pop the argc, argv, and environ arguments off the stack, push the 137185377Ssam! value returned from main(), and call exit(). 138185377Ssam 139201758Smbr addl $12,%esp 140185377Ssam pushl %eax 141185377Ssam call exit 142185377Ssam 143185377Ssam! An inline equivalent of _exit, as specified in Figure 3-26 of the ABI. 144185377Ssam 145185377Ssam pushl $0x0 146185377Ssam movl $0x1,%eax 147185377Ssam lcall $7,$0 148185377Ssam 149185377Ssam! If all else fails, just try a halt! 150185377Ssam 151185377Ssam hlt 152185377Ssam .type _start,@function 153185377Ssam .size _start,.-_start 154185377Ssam 155185377Ssam! A dummy profiling support routine for non-profiling executables, 156187831Ssam! in case we link in some objects that have been compiled for profiling. 157187831Ssam 158185377Ssam .weak _mcount 159185377Ssam_mcount: 160185377Ssam ret 161185377Ssam .type _mcount,@function 162185377Ssam .size _mcount,.-_mcount 163185377Ssam