xref: /netbsd-src/libexec/ld.elf_so/arch/hppa/rtld_start.S (revision e5548b402ae4c44fb816de42c7bba9581ce23ef5)
1/*	$NetBSD: rtld_start.S,v 1.3 2004/05/17 13:16:02 skrll Exp $	*/
2
3/*-
4 * Copyright (c) 2002 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Matt Fredette.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 *    must display the following acknowledgement:
20 *        This product includes software developed by the NetBSD
21 *        Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 *    contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39#include <machine/asm.h>
40#define _LOCORE /* XXX fredette we MUST get rid of this */
41#include <machine/frame.h>
42#undef _LOCORE
43
44	.import _GLOBAL_OFFSET_TABLE_
45
46ENTRY($rtld_start,32)
47
48	/* Start stack calling convention. */
49	copy	%r3, %r1
50	copy	%sp, %r3
51	stw,ma	%r1, HPPA_FRAME_SIZE(%sp)
52
53	/*
54	 * Save our single argument, the ps_strings pointer.
55	 * We'll need this twice later: once to call _rtld,
56	 * and again to transfer to the program's entry point.
57	 */
58        stw     %arg0, HPPA_FRAME_ARG(0)(%r3)
59
60	/*
61	 * We can't move to C until we relocate at least the
62	 * Global Offset Table.  Even finding the GOT is tricky
63	 * without inadvertently causing the linker to make
64	 * relocations for this part of the text segment.
65	 */
66
67	bl	L$lpc1, %r19
68	depi	0, 31, 2, %r19
69L$lpc1:	addil	L'_DYNAMIC - ($PIC_pcrel$0 - 8), %r19
70	ldo	R'_DYNAMIC - ($PIC_pcrel$0 - 12)(%r1),%arg0
71
72	/*
73	 * Load the absolute address of the beginning of the
74	 * GOT into %r19, the shared library linkage table
75	 * register, leaving it ready-to-use by the dynamic
76	 * linker C code.
77	 */
78	addil	L'_GLOBAL_OFFSET_TABLE_ - ($PIC_pcrel$0 - 16), %r19
79	ldo	R'_GLOBAL_OFFSET_TABLE_ - ($PIC_pcrel$0 - 20)(%r1),%r19
80
81	/*
82	 * The linker sets the first entry in the GOT to the
83	 * unrelocated address of _DYNAMIC.  Subtract this
84	 * from the absolute address of _DYNAMIC to get our
85	 * relocbase.
86	 */
87	ldw	0(%r19), %arg1
88	sub	%arg0, %arg1, %arg1	; %arg1 = relocbase
89	bl	_rtld_relocate_nonplt_self, %rp
90	copy	%arg1, %r4		; save for later
91
92	/*
93	 * Recover the ps_strings pointer, and take out the
94	 * ps_argvstr member.
95	 */
96	ldw	HPPA_FRAME_ARG(0)(%r3), %arg0	; ps_strings
97	ldw	0(%arg0), %arg0		; ps_argvstr member first in struct
98
99	/*
100	 * ps_argvstr - 4 would get us a pointer to argc,
101	 * comparable to the initial stack pointer on
102	 * architectures where the stack grows down.
103	 * Subtracting an additional eight creates the
104	 * storage for obj and cleanup that _rtld needs.
105	 */
106	ldo	-12(%arg0), %arg0
107	stw	%arg0, HPPA_FRAME_ARG(1)(%r3)
108
109	/* Call _rtld, copying relocbase into arg1. */
110	bl	_rtld, %rp
111	copy	%r4, %arg1		; %arg1 = relocbase
112
113	/* Prepare the arguments for the entry point. */
114	ldw	HPPA_FRAME_ARG(1)(%r3), %r1
115	ldw	HPPA_FRAME_ARG(0)(%r3), %arg0	; ps_strings
116	ldw	0(%r1), %arg1			; cleanup
117	ldw	4(%r1), %arg2			; obj
118
119	/* End stack calling convention. */
120	ldo	HPPA_FRAME_SIZE(%r3), %sp
121	ldw,mb	-HPPA_FRAME_SIZE(%sp), %r3
122
123	/* Go for it. */
124	bv	%r0(%ret0)
125	copy	%r0, %rp
126EXIT($rtld_start)
127
128/*
129 * This does our setup for an object's GOT.  %arg0 is the
130 * Obj_Entry * for the object, and %arg1 is its GOT pointer.
131 */
132LEAF_ENTRY(__rtld_setup_hppa_pltgot)
133
134	/*
135	 * The second entry of the GOT is reserved for
136	 * the dynamic linker.  We put the Obj_Entry *
137	 * for the object in there.
138	 */
139	stw	%arg0, 4(%arg1)
140
141	/*
142	 * Fill the fixup_func and fixup_ltp members of
143	 * the PLT stub.  This stub is inserted by the
144	 * linker immediately before the GOT.  We use
145	 * this stub to enter our binder.
146	 */
147
148	bl	L$lpc2, %arg0
149	depi	0, 31, 2, %arg0
150L$lpc2:	addil	L'_rtld_bind_start - ($PIC_pcrel$0 - 8), %arg0
151	ldo	R'_rtld_bind_start - ($PIC_pcrel$0 - 12)(%r1),%arg0
152
153	stw	%arg0, -8(%arg1)
154	bv	%r0(%rp)
155	stw	%r19, -4(%arg1)
156EXIT(__rtld_hppa_setup_pltgot)
157
158/*
159 * In order to support lazy binding, this implementation of
160 * _rtld_bind_start is very closely tied to the shared-library
161 * call stub and the PLT stub, both inserted by the linker.
162 */
163ENTRY(_rtld_bind_start,32)
164
165	/* Start stack calling convention.  */
166	copy	%r3, %r1
167	copy	%sp, %r3
168
169	stw,ma	%r1, HPPA_FRAME_SIZE(%sp)
170
171	/*
172	 * We have to save all calling convention registers
173	 * that are set by the caller, because we have to
174	 * restore them before transferring to the bound
175	 * function.  Note that this includes %ret0 and %ret1,
176	 * because they can have meaning on entry to a function.
177	 */
178	stw	%rp, HPPA_FRAME_CRP(%r3)
179	stw	%arg0, HPPA_FRAME_ARG(0)(%r3)
180	stw	%arg1, HPPA_FRAME_ARG(1)(%r3)
181	stw	%arg2, HPPA_FRAME_ARG(2)(%r3)
182	stw	%arg3, HPPA_FRAME_ARG(3)(%r3)
183	/* 0(%r3) is filled with the saved %r3 above */
184	stw	%ret0, 4(%r3)
185	stw	%ret1, 8(%r3)
186
187	/*
188	 * The linker PLT stub loads %r20 with (GOT - 8) for
189	 * the object that needs binding done.  The second entry
190	 * of the GOT is reserved for the dynamic linker's use,
191	 * and we previously stashed the object's Obj_Entry *
192	 * there.
193	 */
194	ldw	12(%r20), %arg0
195
196	/*
197	 * The linker shared-library call stub loads %r19 from
198	 * the shared linkage member of the PLT entry.  We
199	 * previously stashed the reloff of the relocation there.
200	 */
201	copy	%r19, %arg1
202
203	/*
204	 * The linker PLT stub loads %r21 with the fixup_ltp
205	 * word in itself.  We previously stashed our %r19
206	 * value there.
207	 */
208	bl	_rtld_bind, %rp
209	copy	%r21, %r19
210
211	/*
212	 * Our hppa version of _rtld_bind
213	 * returns to us the address of the PLT entry that
214	 * it fixed up.  Load the function address and
215	 * shared linkage for the newly bound function.
216	 */
217	ldw	0(%ret0), %r21
218	ldw	4(%ret0), %r19
219
220	/* Restore registers saved above. */
221	ldw	HPPA_FRAME_CRP(%r3), %rp
222	ldw	HPPA_FRAME_ARG(0)(%r3), %arg0
223	ldw	HPPA_FRAME_ARG(1)(%r3), %arg1
224	ldw	HPPA_FRAME_ARG(2)(%r3), %arg2
225	ldw	HPPA_FRAME_ARG(3)(%r3), %arg3
226	ldw	4(%r3), %ret0
227	ldw	8(%r3), %ret1
228
229	/* End stack calling convention. */
230	ldo	HPPA_FRAME_SIZE(%r3), %sp
231	ldw,mb	-HPPA_FRAME_SIZE(%sp), %r3
232
233	/* Transfer to the function. */
234	bv	%r0(%r21)
235	nop
236EXIT(_rtld_bind_start)
237