rtld_start.S revision 1.3 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
46 ENTRY($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
69 L$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
126 EXIT($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 */
132 LEAF_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
150 L$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)
156 EXIT(__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 */
163 ENTRY(_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
236 EXIT(_rtld_bind_start)
237