1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22/* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27/* 28 * This gcrt1.o module is provided as the bare minimum required to build a 29 * 32-bit profile executable with gcc -pg. It is installed in /usr/lib 30 * where it will be picked up by gcc, along with crti.o and crtn.o 31 */ 32 33 .ident "%Z%%M% %I% %E% SMI" 34 35 .file "gcrt1.s" 36 37 .globl _start 38 .globl _etext 39 40/* global entities defined elsewhere but used here */ 41 .globl main 42 .globl __fpstart 43 .globl _init 44 .globl _fini 45 .globl exit 46 .globl _exit 47 .globl monstartup 48 .weak _mcleanup 49 .weak _DYNAMIC 50 51 .section .data 52 53 .weak environ 54 .set environ,_environ 55 .globl _environ 56 .type _environ,@object 57 .size _environ,4 58 .align 4 59_environ: 60 .4byte 0x0 61 62 .globl ___Argv 63 .type ___Argv,@object 64 .size ___Argv,4 65 .align 4 66___Argv: 67 .4byte 0x0 68 69 .section .text 70 .align 4 71 72/* 73 * C language startup routine. 74 * Assume that exec code has cleared the direction flag in the TSS. 75 * Assume that %esp is set to the addr after the last word pushed. 76 * The stack contains (in order): argc, argv[],envp[],... 77 * Assume that all of the segment registers are initialized. 78 * 79 * Allocate a NULL return address and a NULL previous %ebp as if 80 * there was a genuine call to _start. 81 * sdb stack trace shows _start(argc,argv[0],argv[1],...,envp[0],...) 82 */ 83 .type _start,@function 84_start: 85 pushl $0 86 pushl $0 87 movl %esp,%ebp /* The first stack frame */ 88 89/* 90 * Check to see if there is an _mcleanup() function linked in, and if so, 91 * register it with atexit() as the last thing to be run by exit(). 92 */ 93 pushl %edx /* save rt_do_exit for later atexit */ 94 95 movl $_mcleanup,%eax 96 testl %eax,%eax 97 jz 1f 98 pushl %eax 99 call atexit 100 addl $4,%esp 1011: 102 103 movl $_DYNAMIC,%eax 104 testl %eax,%eax 105 jz 1f 106 call atexit /* register rt_do_exit */ 1071: 108 addl $4,%esp 109 110 pushl $_fini 111 call atexit 112 addl $4,%esp 113 114/* start profiling */ 115 pushl %ebp 116 movl %esp,%ebp 117 pushl $_etext 118 pushl $_start 119 call monstartup 120 addl $8,%esp 121 popl %ebp 122 123/* 124 * The following code provides almost standard static destructor handling 125 * for systems that do not have the modified atexit processing in their 126 * system libraries. It checks for the existence of the new routine 127 * "_get_exit_frame_monitor()", which is in libc.so when the new exit-handling 128 * code is there. It then check for the existence of "__Crun::do_exit_code()" 129 * which will be in libCrun.so whenever the code was linked with the C++ 130 * compiler. If there is no enhanced atexit, and we do have do_exit_code, 131 * we register the latter with atexit. There are 5 extra slots in 132 * atexit, so this will still be standard conforming. Since the code 133 * is registered after the .fini section, it runs before the library 134 * cleanup code, leaving nothing for the calls to _do_exit_code_in_range 135 * to handle. 136 * 137 * Remove this code and the associated code in libCrun when the earliest 138 * system to be supported is Solaris 8. 139 */ 140 .weak _get_exit_frame_monitor 141 .weak __1cG__CrunMdo_exit_code6F_v_ 142 143 .section .data 144 .align 4 145__get_exit_frame_monitor_ptr: 146 .4byte _get_exit_frame_monitor 147 .type __get_exit_frame_monitor_ptr,@object 148 .size __get_exit_frame_monitor_ptr,4 149 150 .align 4 151__do_exit_code_ptr: 152 .4byte __1cG__CrunMdo_exit_code6F_v_ 153 .type __do_exit_code_ptr,@object 154 .size __do_exit_code_ptr,4 155 156 .section .text 157 158 lea __get_exit_frame_monitor_ptr, %eax 159 movl (%eax), %eax 160 testl %eax,%eax 161 jz 1f 162 lea __do_exit_code_ptr, %eax 163 movl (%eax), %eax 164 testl %eax, %eax 165 jz 1f 166 pushl %eax 167 call atexit /* atexit(__Crun::do_exit_code()) */ 168 addl $4,%esp 1691: 170 171/* 172 * End of destructor handling code 173 */ 174 175/* 176 * Calculate the location of the envp array by adding the size of 177 * the argv array to the start of the argv array. 178 */ 179 180 movl 8(%ebp),%eax /* argc */ 181 movl _environ, %edx /* fixed bug 4302802 */ 182 testl %edx, %edx /* check if _enviorn==0 */ 183 jne 1f /* fixed bug 4203802 */ 184 leal 16(%ebp,%eax,4),%edx /* envp */ 185 movl %edx,_environ /* copy to _environ */ 1861: 187 andl $-16,%esp /* align the stack */ 188 subl $4,%esp 189 190 pushl %edx 191 leal 12(%ebp),%edx /* argv */ 192 movl %edx,___Argv 193 pushl %edx 194 pushl %eax /* argc */ 195 call __fpstart 196 call _init 197 call main /* main(argc,argv,envp) */ 198 addl $12,%esp 199 pushl %eax /* return value from main */ 200 pushl %eax /* push it again (for _exit(), below) */ 201 call exit 202 addl $4,%esp 203 call _exit /* if user redefined exit, call _exit */ 204 addl $4,%esp 205 hlt 206 .size _start, .-_start 207