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