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