xref: /titanic_41/usr/src/lib/common/i386/gcrt1.s (revision 4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6)
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