rtld_start.S revision 1.10 1 /* $NetBSD: rtld_start.S,v 1.10 2002/09/08 02:48:28 thorpej Exp $ */
2
3 /*
4 * Copyright 1996 Matt Thomas <matt (at) 3am-software.com>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include <machine/asm.h>
31
32 .extern _GLOBAL_OFFSET_TABLE_
33 .extern _GOT_END_
34
35 /*
36 * Note: we can call ourselves LEAF even though we use callee-saved
37 * registers because we're the root of the call graph.
38 */
39 LEAF_NOPROFILE(_rtld_start, 0)
40 .set noreorder
41 br pv, 1f
42 1: LDGP(pv)
43
44 /* XXX Partially relocate ourself. */
45
46 /* Step 1 -- Figure out the displacement */
47
48 br t2, 2f /* get our PC */
49 2: ldiq t3, 2b /* get where the linker thought we were */
50 subq t2, t3, t8 /* calculate the displacement */
51
52
53 /* Step 2 -- Find bounds of global offset table */
54
55 lda t5, _GLOBAL_OFFSET_TABLE_
56 addq t8, t5, t9 /* add the displacement */
57 lda t4, _GOT_END_ /* Get the address of the end of the GOT */
58 addq t8, t4, t10 /* add the displacement */
59
60 /*
61 * Step 3 -- Every entry in the global offset table needs to
62 * modified for the displacement before any code will work.
63 */
64
65 3: ldq t1, 0(t9) /* load the value */
66 addq t8, t1, t1 /* add the displacement */
67 stq t1, 0(t9) /* save the new value */
68 lda t9, 8(t9) /* point to next entry */
69 cmpult t9, t10, t1 /* are we done? */
70 bne t1, 3b /* no, do more */
71
72 /*
73 * Ya! Things are far enough so we can do some dynamic linking!
74 */
75
76 /* Squirrel away ps_strings. */
77 mov a3, s0
78
79 /*
80 * Allocate space on the stack for the cleanup and obj_main
81 * entries that _rtld() will provide for us.
82 */
83 lda sp, -16(sp)
84
85 mov sp, a0 /* v0 = _rtld(sp); */
86 CALL(_rtld)
87
88 ldq a1, 0(sp) /* cleanup */
89 ldq a2, 8(sp) /* obj_main */
90 lda sp, 16(sp) /* pop stack */
91
92 mov sp, a0 /* stack pointer */
93 mov s0, a3 /* ps_strings */
94
95 mov v0, pv /* set up PV for entry point */
96
97 jsr ra, (v0), 0 /* (*_start)(sp, cleanup, obj, ps_strings); */
98 ldgp gp, 0(ra)
99
100 CALL(exit)
101 halt
102 END(_rtld_start)
103
104 #define RTLD_BIND_START_PROLOGUE \
105 /* at_reg already used by PLT code. */ \
106 .set noat ; \
107 \
108 /* \
109 * Allocate stack frame and preserve all registers that the \
110 * caller would have normally saved themselves. \
111 */ \
112 lda sp, -168(sp) ; \
113 stq ra, 0(sp) ; \
114 stq v0, 8(sp) ; \
115 stq t0, 16(sp) ; \
116 stq t1, 24(sp) ; \
117 stq t2, 32(sp) ; \
118 stq t3, 40(sp) ; \
119 stq t4, 48(sp) ; \
120 stq t5, 56(sp) ; \
121 stq t6, 64(sp) ; \
122 stq t7, 72(sp) ; \
123 stq a0, 80(sp) ; \
124 stq a1, 88(sp) ; \
125 stq a2, 96(sp) ; \
126 stq a3, 104(sp) ; \
127 stq a4, 112(sp) ; \
128 stq a5, 120(sp) ; \
129 stq t8, 128(sp) ; \
130 stq t9, 136(sp) ; \
131 stq t10, 144(sp) ; \
132 stq t11, 152(sp) ; \
133 stq gp, 160(sp) ; \
134 \
135 /* \
136 * Load our global pointer. Note, can't use pv, since it is \
137 * already used by the PLT code. \
138 */ \
139 br t0, 1f ; \
140 1: LDGP(t0)
141
142 #define RTLD_BIND_START_EPILOGUE \
143 /* Move the destination address into position. */ \
144 mov v0, pv ; \
145 \
146 /* Restore program registers. */ \
147 ldq ra, 0(sp) ; \
148 ldq v0, 8(sp) ; \
149 ldq t0, 16(sp) ; \
150 ldq t1, 24(sp) ; \
151 ldq t2, 32(sp) ; \
152 ldq t3, 40(sp) ; \
153 ldq t4, 48(sp) ; \
154 ldq t5, 56(sp) ; \
155 ldq t6, 64(sp) ; \
156 ldq t7, 72(sp) ; \
157 ldq a0, 80(sp) ; \
158 ldq a1, 88(sp) ; \
159 ldq a2, 96(sp) ; \
160 ldq a3, 104(sp) ; \
161 ldq a4, 112(sp) ; \
162 ldq a5, 120(sp) ; \
163 ldq t8, 128(sp) ; \
164 ldq t9, 136(sp) ; \
165 ldq t10, 144(sp) ; \
166 ldq t11, 152(sp) ; \
167 ldq gp, 160(sp) ; \
168 /* XXX LDGP? */ \
169 \
170 /* \
171 * We've patched the PLT; sync the I-stream. \
172 */ \
173 imb ; \
174 \
175 /* Pop the stack frame and turn control to the destination. */ \
176 lda sp, 168(sp) ; \
177 jmp zero, (pv)
178
179 /*
180 * Lazy binding entry point, called via PLT.
181 */
182 NESTED_NOPROFILE(_rtld_bind_start, 0, 168, ra, 0, 0)
183
184 RTLD_BIND_START_PROLOGUE
185
186 /* Set up the arguments for _rtld_bind. */
187 subq at_reg, pv, a1 /* calculate offset of reloc entry */
188 ldq a0, 8(pv) /* object structure */
189 subq a1, 20, a1 /* = (at - pv - 20) / 12 * 24 */
190 addq a1, a1, a1
191
192 CALL(_rtld_bind)
193
194 RTLD_BIND_START_EPILOGUE
195
196 END(_rtld_bind_start)
197
198 /*
199 * Lazy binding entry point, called via PLT. This version is for the
200 * old PLT entry format.
201 */
202 NESTED_NOPROFILE(_rtld_bind_start_old, 0, 168, ra, 0, 0)
203
204 RTLD_BIND_START_PROLOGUE
205
206 /* Set up the arguments for _rtld_bind. */
207 ldq a0, 8(pv) /* object structure */
208 mov at_reg, a1 /* offset of reloc entry */
209
210 CALL(_rtld_bind)
211
212 RTLD_BIND_START_EPILOGUE
213
214 END(_rtld_bind_start_old)
215