ldasm.S revision 1.23
1/*	$OpenBSD: ldasm.S,v 1.23 2004/05/25 15:56:19 deraadt Exp $	*/
2/*	$NetBSD: rtld_start.S,v 1.5 2001/08/14 22:17:48 eeh Exp $	*/
3
4/*
5 * Copyright (c) 2001 Jason L. Wright (jason@thought.net)
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
21 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/*-
31 * Copyright (c) 2000 Eduardo Horvath.
32 * Copyright (c) 1999 The NetBSD Foundation, Inc.
33 * All rights reserved.
34 *
35 * This code is derived from software contributed to The NetBSD Foundation
36 * by Christos Zoulas and Paul Kranenburg.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 * 1. Redistributions of source code must retain the above copyright
42 *    notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 *    notice, this list of conditions and the following disclaimer in the
45 *    documentation and/or other materials provided with the distribution.
46 * 3. All advertising materials mentioning features or use of this software
47 *    must display the following acknowledgement:
48 *	This product includes software developed by the NetBSD
49 *	Foundation, Inc. and its contributors.
50 * 4. Neither the name of The NetBSD Foundation nor the names of its
51 *    contributors may be used to endorse or promote products derived
52 *    from this software without specific prior written permission.
53 *
54 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
55 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
56 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
57 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
58 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
59 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
60 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
61 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
62 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
63 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
64 * POSSIBILITY OF SUCH DAMAGE.
65 */
66
67#include <sys/syscall.h>
68#include <machine/trap.h>
69#include <machine/asm.h>
70#define	_LOCORE
71#include <machine/frame.h>
72
73/*
74 * ELF:
75 *	On startup the stack should contain 16 extended word register save
76 *	area, followed by the arg count, etc.
77 *
78 * _rtld() expects the stack pointer to point to two longwords for argument
79 *	return followed by argc, etc.  We need to create a pointer to
80 *	&argc + 16 and pass that in.  The return args will be in those
81 *	locations.
82 *
83 * NB:	We are violating the ELF spec by passing a pointer to the ps strings in
84 *	%g1 instead of a termination routine.
85 */
86
87/* Offset of ARGC from bottom of stack */
88#define	ARGC	(16*8)
89/* XXX - DL_DATA_SIZE should be (9*8), but I can't think right now. */
90#define DL_DATA_SIZE (16*8)
91
92	.section	".text"
93	.align	16
94	.register %g2,#scratch
95
96_ENTRY(_dl_start)
97	sub	%g0, %g0, %fp		! clear frame
98	mov	%g1, %l1		! save ps_strings
99	sub	%sp, DL_DATA_SIZE, %sp	! make room for dl_data
100	add	%sp, BIAS + ARGC, %l3
101
102	add	%l3, DL_DATA_SIZE, %o0
103	mov	%o0, %l0
104
105	/*
106	 * need to figure out where _DYNAMIC is located, newer binutils
107	 * does not fill in GOT to read _DYNAMIC before relocation.
108	 */
109	call	0f
110	 nop
111	call	_DYNAMIC+8		! not executed (no delay needed)
1120:	ld	[%o7+8], %o2		! load stub call instruction
113	sll	%o2, 2, %o2		! extract PC offset
114	sra	%o2, 0, %o2		! sign-extend
115
116	add	%o2, %o7, %o2		! real &_DYNAMIC
117
118	call	_dl_boot_bind		! _dl_boot_bind(sp,dl_data,dynamicp)
119	 mov	%l3, %o1
120
121	mov	%l3, %o3
122	ldx	[%l0], %l3		! argc = *sp
123	sllx	%l3, 3, %l3		! argc *= sizeof(long)
124	addx	%l0, 8, %o0		! argv = [sp + argc]
125	addx	%l0, 16, %o1		! envp = sp + 16 +
126	addx	%o1, %l3, %o1		!	+ argc
127
128	addx	%o3, (7*8), %l2
129	ldx	[%l2], %o2		! loff = dl_data[AUX_base];
130
131	call	_dl_boot		! _dl_boot(argv,envp,loff,dl_data)
132	 nop
133
134	add	%sp, DL_DATA_SIZE, %sp		! restore stack
135	mov	%l1, %g1		! restore ps_strings
136
137	jmp	%o0
138	 nop
139
140	/*
141	 * We have two separate entry points to the runtime linker.
142	 * I'm implementing this following the SPARC v9 ABI spec.
143	 *
144	 * _dl_bind_start_0(x, y) is called from .PLT0, and is used for
145	 * PLT entries above 32768.
146	 *
147	 * _dl_bind_start_1(x, y) is called from .PLT1, and is used for
148	 * PLT entries below 32768.
149	 *
150	 * The first two entries of PLT2 contain the xword object pointer.
151	 *
152	 * These routines are called with two longword arguments,
153	 * x and y.  To calculate the address of the entry,
154	 * _dl_bind_start_1(x, y) does:
155	 *
156	 *	n = x >> 15;
157	 *
158	 * and _dl_bind_start_0(x, y) does:
159	 *
160	 *	i = x - y + 1048596;
161	 *	n = 32768 + (i/5120)*160 + (i%5120)/24;
162	 *
163	 * Neither routine needs to issue a save since it's already been
164	 * done in the PLT entry.
165	 */
166
167	/* NOTE: _dl_bind_start_0 is untested.  Hence the debug stuff */
168
169_ENTRY(_dl_bind_start_0)		# (x, y)
170	sethi	%hi(1048596), %l1
171	sub	%o0, %o1, %l0		/* x - y */
172	or	%l1, %lo(1048596), %l1
173	add	%l0, %l1, %l0		/* x - y + 1048596 */
174
175	sdivx	%l0, 5120, %l1		/* Calculate i/5120 */
176	ldx	[%o1 + (10*4)], %o0	/* Load object pointer from PLT2 */
177	sub	%l0, %l1, %l2		/* And i%5120 */
178
179	/* Let the division churn for a bit. */
180	sdivx	%l2, 14, %l4		/* (i%5120)/24 */
181
182	/* 160 is (32 * 5) or (32 * (4 + 1)) */
183	sllx	%l1, 2, %l3		/* 4 * (i/5120) */
184	add	%l1, %l3, %l3		/* 5 * (i/5120) */
185	sllx	%l3, 5, %l3		/* 32 * 5 * (i/5120) */
186
187	sethi	%hi(32768), %l6
188	add	%l3, %l4, %l5		/* %l5 = (i/5120)*160 + (i%5120)/24; */
189	add	%l5, %l6, %l5
190
191	call	_dl_bind		/* Call _dl_bind(obj, offset) */
192	 mov	%l5, %o1
193
194	jmp	%o0			/* return value == function address */
195	 restore			/* Dump our stack frame */
196
197_ENTRY(_dl_bind_start_1)		# (x, y)
198	srax	%o0, 15, %o2		/* %o0 is the index to our PLT slot */
199
200	ldx	[%o1 + 8], %o0		/* The object pointer is at [%o1 + 8] */
201
202	call	_dl_bind		/* Call _dl_bind(obj, offset) */
203	 mov	%o2, %o1
204
205	jmp	%o0			/* return value == function address */
206	 restore			/* Dump our stack frame */
207
208_ENTRY(_dl_close)
209	mov SYS_close | SYSCALL_G2RFLAG, %g1	! call sys_close
210	add %o7, 8, %g2				! just return on success
211	t ST_SYSCALL				! off to wonderland
212	retl
213	 sub %g0, %o0, %o0			! error: result = -errno
214
215_ENTRY(_dl_exit)
216	mov SYS_exit | SYSCALL_G2RFLAG, %g1	! call sys_exit
217	add %o7, 8, %g2				! just return on success
218	t ST_SYSCALL				! off to wonderland
219	retl
220	 sub %g0, %o0, %o0			! error: result = -errno
221
222_ENTRY(_dl_issetugid)
223	mov SYS_issetugid | SYSCALL_G2RFLAG, %g1	! call sys_issetugid
224	add %o7, 8, %g2					! just return on success
225	t ST_SYSCALL					! off to wonderland
226	retl
227	 sub %g0, %o0, %o0				! error: result = -errno
228
229_ENTRY(_dl__syscall)
230	mov SYS___syscall | SYSCALL_G2RFLAG, %g1	! call sys___syscall
231	add %o7, 8, %g2				! just return on success
232	t ST_SYSCALL				! off to wonderland
233	retl
234	 sub %g0, %o0, %o0			! error: result = -errno
235
236_ENTRY(_dl_munmap)
237	mov SYS_munmap | SYSCALL_G2RFLAG, %g1	! calling sys_munmap
238	add %o7, 8, %g2				! just return on success
239	t ST_SYSCALL				! off to wonderland
240	retl
241	 sub %g0, %o0, %o0			! error: result = -errno
242
243_ENTRY(_dl_mprotect)
244	mov SYS_mprotect | SYSCALL_G2RFLAG, %g1	! calling sys_mprotect
245	add %o7, 8, %g2				! just return on success
246	t ST_SYSCALL				! off to wonderland
247	retl
248	 sub %g0, %o0, %o0			! error: result = -errno
249
250_ENTRY(_dl_open)
251	mov SYS_open | SYSCALL_G2RFLAG, %g1	! calling sys_open
252	add %o7, 8, %g2				! just return on success
253	t ST_SYSCALL				! off to wonderland
254	retl
255	 sub %g0, %o0, %o0			! error: result = -errno
256
257_ENTRY(_dl_read)
258	mov SYS_read | SYSCALL_G2RFLAG, %g1	! calling sys_read
259	add %o7, 8, %g2				! just return on success
260	t ST_SYSCALL				! off to wonderland
261	retl
262	 sub %g0, %o0, %o0			! error: result = -errno
263
264_ENTRY(_dl_write)
265	mov SYS_write | SYSCALL_G2RFLAG, %g1	! calling sys_write
266	add %o7, 8, %g2				! just return on success
267	t ST_SYSCALL				! off to wonderland
268	retl
269	 sub %g0, %o0, %o0			! error: result = -errno
270
271_ENTRY(_dl_stat)
272	mov SYS_stat | SYSCALL_G2RFLAG, %g1	! call sys_stat
273	add %o7, 8, %g2				! just return on success
274	t ST_SYSCALL				! off to wonderland
275	retl
276	 sub %g0, %o0, %o0			! error: result = -errno
277
278_ENTRY(_dl_fstat)
279	mov  SYS_fstat | SYSCALL_G2RFLAG, %g1	! call sys_fstat
280	add %o7, 8, %g2				! just return on success
281	t ST_SYSCALL				! off to wonderland
282	retl
283	 sub %g0, %o0, %o0			! error: result = -errno
284
285_ENTRY(_dl_fcntl)
286	mov  SYS_fcntl | SYSCALL_G2RFLAG, %g1	! call sys_fcntl
287	add %o7, 8, %g2				! just return on success
288	t ST_SYSCALL				! off to wonderland
289	retl
290	 sub %g0, %o0, %o0			! error: result = -errno
291
292_ENTRY(_dl_getdirentries)
293	mov  SYS_getdirentries | SYSCALL_G2RFLAG, %g1	! call sys_getdirentries
294	add %o7, 8, %g2					! just return on success
295	t ST_SYSCALL					! off to wonderland
296	retl
297	 sub %g0, %o0, %o0				! error: result = -errno
298
299	/* _dl_sigprocmask does not support NULL new mask */
300_ENTRY(_dl_sigprocmask)
301	ld	[%o1], %o1			! indirect for new mask
302	mov	SYS_sigprocmask, %g1		! call sys_sigprocmask
303	t ST_SYSCALL				! off to wonderland
304						! what about errors?
305	cmp	%o2, 0
306	bne,a	1f				! if oset != NULL
307	 st	%o0, [%o2]			!   *oset = oldmask
3081:
309	retl
310	 clr %o0
311
312_ENTRY(_dl_sysctl)
313	mov  SYS___sysctl | SYSCALL_G2RFLAG, %g1	! call sys_getdirentries
314	add %o7, 8, %g2					! just return on success
315	t ST_SYSCALL					! off to wonderland
316	retl
317	 sub %g0, %o0, %o0				! error: result = -errno
318