1/* crt1.s for Solaris 2, x86 2 3 Copyright (C) 1993-2017 Free Software Foundation, Inc. 4 Written By Fred Fish, Nov 1992 5 6This file is free software; you can redistribute it and/or modify it 7under the terms of the GNU General Public License as published by the 8Free Software Foundation; either version 3, or (at your option) any 9later version. 10 11This file is distributed in the hope that it will be useful, but 12WITHOUT ANY WARRANTY; without even the implied warranty of 13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14General Public License for more details. 15 16Under Section 7 of GPL version 3, you are granted additional 17permissions described in the GCC Runtime Library Exception, version 183.1, as published by the Free Software Foundation. 19 20You should have received a copy of the GNU General Public License and 21a copy of the GCC Runtime Library Exception along with this program; 22see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23<http://www.gnu.org/licenses/>. */ 24 25 26/* This file takes control of the process from the kernel, as specified 27 in section 3 of the System V Application Binary Interface, Intel386 28 Processor Supplement. It has been constructed from information obtained 29 from the ABI, information obtained from single stepping existing 30 Solaris executables through their startup code with gdb, and from 31 information obtained by single stepping executables on other i386 SVR4 32 implementations. This file is the first thing linked into any 33 executable. */ 34 35#ifndef GCRT1 36 .ident "GNU C crt1.s" 37#define CLEANUP _cleanup 38#else 39/* This is a modified crt1.s by J.W.Hawtin <oolon@ankh.org> 15/8/96, 40 to allow program profiling, by calling monstartup on entry and _mcleanup 41 on exit. */ 42 .ident "GNU C gcrt1.s" 43#define CLEANUP _mcleanup 44#endif 45 .weak _cleanup 46 .weak _DYNAMIC 47 .text 48 49/* Start creating the initial frame by pushing a NULL value for the return 50 address of the initial frame, and mark the end of the stack frame chain 51 (the innermost stack frame) with a NULL value, per page 3-32 of the ABI. 52 Initialize the first stack frame pointer in %ebp (the contents of which 53 are unspecified at process initialization). */ 54 55 .globl _start 56_start: 57 pushl $0x0 58 pushl $0x0 59 movl %esp,%ebp 60 61/* As specified per page 3-32 of the ABI, %edx contains a function 62 pointer that should be registered with atexit(), for proper 63 shared object termination. Just push it onto the stack for now 64 to preserve it. We want to register _cleanup() first. */ 65 66 pushl %edx 67 68/* Check to see if there is an _cleanup() function linked in, and if 69 so, register it with atexit() as the last thing to be run by 70 atexit(). */ 71 72 movl $CLEANUP,%eax 73 testl %eax,%eax 74 je .L1 75 pushl $CLEANUP 76 call atexit 77 addl $0x4,%esp 78.L1: 79 80/* Now check to see if we have an _DYNAMIC table, and if so then 81 we need to register the function pointer previously in %edx, but 82 now conveniently saved on the stack as the argument to pass to 83 atexit(). */ 84 85 movl $_DYNAMIC,%eax 86 testl %eax,%eax 87 je .L2 88 call atexit 89.L2: 90 91/* Register _fini() with atexit(). We will take care of calling _init() 92 directly. */ 93 94 pushl $_fini 95 call atexit 96 97#ifdef GCRT1 98/* Start profiling. */ 99 100 pushl %ebp 101 movl %esp,%ebp 102 pushl $_etext 103 pushl $_start 104 call monstartup 105 addl $8,%esp 106 popl %ebp 107#endif 108 109/* Compute the address of the environment vector on the stack and load 110 it into the global variable _environ. Currently argc is at 8 off 111 the frame pointer. Fetch the argument count into %eax, scale by the 112 size of each arg (4 bytes) and compute the address of the environment 113 vector which is 16 bytes (the two zero words we pushed, plus argc, 114 plus the null word terminating the arg vector) further up the stack, 115 off the frame pointer (whew!). */ 116 117 movl 8(%ebp),%eax 118 leal 16(%ebp,%eax,4),%edx 119 movl %edx,_environ 120 121/* Push the environment vector pointer, the argument vector pointer, 122 and the argument count on to the stack to set up the arguments 123 for _init(), _fpstart(), and main(). Note that the environment 124 vector pointer and the arg count were previously loaded into 125 %edx and %eax respectively. The only new value we need to compute 126 is the argument vector pointer, which is at a fixed address off 127 the initial frame pointer. */ 128 129/* Make sure the stack is properly aligned. */ 130 andl $0xfffffff0,%esp 131 subl $4,%esp 132 133 pushl %edx 134 leal 12(%ebp),%edx 135 pushl %edx 136 pushl %eax 137 138/* Call _init(argc, argv, environ), _fpstart(argc, argv, environ), and 139 main(argc, argv, environ). */ 140 141 call _init 142 call __fpstart 143 call main 144 145/* Pop the argc, argv, and environ arguments off the stack, push the 146 value returned from main(), and call exit(). */ 147 148 addl $12,%esp 149 pushl %eax 150 call exit 151 152/* An inline equivalent of _exit, as specified in Figure 3-26 of the ABI. */ 153 154 pushl $0x0 155 movl $0x1,%eax 156 lcall $7,$0 157 158/* If all else fails, just try a halt! */ 159 160 hlt 161 .type _start,@function 162 .size _start,.-_start 163 164#ifndef GCRT1 165/* A dummy profiling support routine for non-profiling executables, 166 in case we link in some objects that have been compiled for profiling. */ 167 168 .weak _mcount 169_mcount: 170 ret 171 .type _mcount,@function 172 .size _mcount,.-_mcount 173#endif 174