192195Sjake/*	$NetBSD: rtld_start.S,v 1.5 2001/08/14 22:17:48 eeh Exp $	*/
292195Sjake
392195Sjake/*-
492195Sjake * Copyright (c) 2001 Jake Burkholder.
592195Sjake * Copyright (c) 2000 Eduardo Horvath.
692195Sjake * Copyright (c) 1999 The NetBSD Foundation, Inc.
792195Sjake * All rights reserved.
892195Sjake *
992195Sjake * This code is derived from software contributed to The NetBSD Foundation
1092195Sjake * by Christos Zoulas and Paul Kranenburg.
1192195Sjake *
1292195Sjake * Redistribution and use in source and binary forms, with or without
1392195Sjake * modification, are permitted provided that the following conditions
1492195Sjake * are met:
1592195Sjake * 1. Redistributions of source code must retain the above copyright
1692195Sjake *    notice, this list of conditions and the following disclaimer.
1792195Sjake * 2. Redistributions in binary form must reproduce the above copyright
1892195Sjake *    notice, this list of conditions and the following disclaimer in the
1992195Sjake *    documentation and/or other materials provided with the distribution.
2092195Sjake * 3. All advertising materials mentioning features or use of this software
2192195Sjake *    must display the following acknowledgement:
2292195Sjake *        This product includes software developed by the NetBSD
2392195Sjake *        Foundation, Inc. and its contributors.
2492195Sjake * 4. Neither the name of The NetBSD Foundation nor the names of its
2592195Sjake *    contributors may be used to endorse or promote products derived
2692195Sjake *    from this software without specific prior written permission.
2792195Sjake *
2892195Sjake * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2992195Sjake * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
3092195Sjake * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
3192195Sjake * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
3292195Sjake * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
3392195Sjake * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
3492195Sjake * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
3592195Sjake * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
3692195Sjake * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3792195Sjake * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3892195Sjake * POSSIBILITY OF SUCH DAMAGE.
3992195Sjake *
4092195Sjake * $FreeBSD$
4192195Sjake */
4292195Sjake
4392195Sjake#include <machine/asm.h>
4492195Sjake
4592195Sjake/*
4692195Sjake * ELF:
4792195Sjake *	On startup the stack should contain 16 extended word register save
4892195Sjake *	area, followed by the arg count, etc.
4992195Sjake */
5092195Sjake
5192195SjakeENTRY(.rtld_start)
5292195Sjake	clr	%fp
5392195Sjake	mov	%o0, %l0
5492195Sjake	mov	%o3, %l1
5592195Sjake
5692195Sjake	sub	%sp, 16, %sp
5792195Sjake	add	%sp, SPOFF + CCFSZ + 0x0, %o1
5892195Sjake	call	_rtld
5992195Sjake	 add	%sp, SPOFF + CCFSZ + 0x8, %o2
6092195Sjake
6192195Sjake	ldx	[%sp + SPOFF + CCFSZ + 0x0], %o1
6292195Sjake	ldx	[%sp + SPOFF + CCFSZ + 0x8], %o2
6392195Sjake	add	%sp, 16, %sp
6492195Sjake
6592195Sjake	mov	%l1, %o3
6692195Sjake	jmp	%o0
6792195Sjake	 mov	%l0, %o0
68100265SjakeEND(.rtld_start)
6992195Sjake
70117211Sjake/*
71117211Sjake * Find the address of _DYNAMIC by disassembling a call instruction to it.
72117211Sjake * Binutils may not fill in the GOT as expected on other architectures.
73117211Sjake */
74130661Stmm.weak	_DYNAMIC
75117211Sjake
76130661StmmENTRY(rtld_dynamic_addr)
77117211Sjake	save	%sp, -CCFSZ, %sp
78117211Sjake	call	1f
79117211Sjake	 nop
80117211Sjake	call	_DYNAMIC + 8
81117211Sjake1:	lduw	[%o7 + 8], %o0
82117211Sjake	sll	%o0, 2, %o0
83117211Sjake	sra	%o0, 0, %o0
84117211Sjake	ret
85117211Sjake	 restore %o0, %o7, %o0
86130661StmmEND(rtld_dynamic_addr)
87117211Sjake
8892195Sjake	/*
8992195Sjake	 * We have two separate entry points to the runtime linker.
9092195Sjake	 * I'm implementing this following the SPARC v9 ABI spec.
9192195Sjake	 *
9292195Sjake	 * _rtld_bind_start_0(x, y) is called from .PLT0, and is used for
9392195Sjake	 * PLT entries above 32768.
9492195Sjake	 *
9592195Sjake	 * _rtld_bind_start_1(x, y) is called from .PLT1, and is used for
9692195Sjake	 * PLT entries below 32768.
9792195Sjake	 *
9892195Sjake	 * The first two entries of PLT2 contain the xword object pointer.
9992195Sjake	 *
100115396Skan	 * These routines are called with two longword arguments,
10192195Sjake	 * x and y.  To calculate the address of the entry,
10292195Sjake	 * _rtld_bind_start_1(x, y) does:
10392195Sjake	 *
10492195Sjake	 *	n = x >> 15;
10592195Sjake	 *
106107071Stmm	 * and _rtld_bind_start_0(x, y) should do, according to the SCD:
10792195Sjake	 *
108107071Stmm	 *	i = x - y - 1048596;
10992195Sjake	 *	n = 32768 + (i/5120)*160 + (i%5120)/24;
11092195Sjake	 *
111107071Stmm	 * Note that the number of 1048596 from above is incorrect; rather,
112107071Stmm	 * we need to use HIPLTOFFS as defined below.
113107071Stmm	 *
11492195Sjake	 * Neither routine needs to issue a save since it's already been
11592195Sjake	 * done in the PLT entry.
11692195Sjake	 */
11792195Sjake
118107071Stmm#define	NPLTLOSLOTS	32768
119107071Stmm#define	PLTSLOTSZ	32
120107071Stmm/*
121107071Stmm * - 16 to compensate for the difference of the positions of the jumps that
122107071Stmm * generate the arguments in .PLT0 and the high plt entry.
123107071Stmm */
124107071Stmm#define	HIPLTOFFS	(NPLTLOSLOTS * PLTSLOTSZ - 16)
125107071Stmm
12692195SjakeENTRY(_rtld_bind_start_0)
127107071Stmm	sethi	%hi(HIPLTOFFS), %l1
128107071Stmm	or	%l1, %lo(HIPLTOFFS), %l1
12992195Sjake	sub	%o0, %o1, %l0		/* x - y */
130107071Stmm	sub	%l0, %l1, %l0		/* i = x - y - HIPLTOFFS */
131107071Stmm	sethi	%hi(5120), %l7
132107071Stmm	sdivx	%l0, %l7, %l1		/* Calculate i / 5120 */
133107071Stmm	mulx	%l1, %l7, %l3
134107071Stmm	sub	%l0, %l3, %l2		/* And i % 5120 */
135107071Stmm	mulx	%l1, 160, %l5		/* (i / 5120) * 160 */
136107071Stmm	sdivx	%l2, 24, %l4		/* (i % 5120) / 24 */
137107071Stmm	sethi	%hi(NPLTLOSLOTS), %l6
138107071Stmm	add	%l4, %l5, %l4		/* (i / 5120) * 160 + (i % 5120) / 24 */
139107071Stmm	add	%l4, %l6, %l4		/* + NPLTLOSLOTS */
140107071Stmm	sub	%l4, 4, %l4		/* XXX:	4 entries are reserved */
141115396Skan
142107071Stmm	sllx	%l4, 1, %l5		/* Each element is an Elf_Rela which */
143107071Stmm	add	%l5, %l4, %l4		/*  is 3 longwords or 24 bytes. */
144107071Stmm	sllx	%l4, 3, %l4		/*  So multiply by 24. */
14592195Sjake
14692195Sjake	ldx	[%o1 + (10*4)], %o0	/* Load object pointer from PLT2 */
14792195Sjake
14892195Sjake	call	_rtld_bind		/* Call _rtld_bind(obj, offset) */
149107071Stmm	 mov	%l4, %o1
15092195Sjake
15192195Sjake	jmp	%o0			/* return value == function address */
15292195Sjake	 restore			/* Dump our stack frame */
153100265SjakeEND(_rtld_bind_start_0)
154115396Skan
15592195SjakeENTRY(_rtld_bind_start_1)
15692195Sjake	srax	%o0, 15, %o2		/* %o0 is the index to our PLT slot */
15792195Sjake	sub	%o2, 4, %o2		/* XXX:	4 entries are reserved */
158115396Skan
15992195Sjake	sllx	%o2, 1, %o3		/* Each element is an Elf_Rela which */
16092195Sjake	add	%o3, %o2, %o2		/*  is 3 longwords or 24 bytes. */
16192195Sjake	sllx	%o2, 3, %o2		/*  So multiply by 24. */
162115396Skan
16392195Sjake	ldx	[%o1 + 8], %o0		/* The object pointer is at [%o1 + 8] */
164115396Skan
16592195Sjake	call	_rtld_bind		/* Call _rtld_bind(obj, offset) */
16692195Sjake	 mov	%o2, %o1
16792195Sjake
16892195Sjake	jmp	%o0			/* return value == function address */
16992195Sjake	 restore			/* Dump our stack frame */
170100265SjakeEND(_rtld_bind_start_1)
171