rtld_start.S revision 1.7 1 /* $NetBSD: rtld_start.S,v 1.7 2001/12/13 22:34:52 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 #if defined(OLD_GOT)
58 ldq t4, 0(t9) /* Get the address of dynamic table */
59 #else
60 lda t4, _GOT_END_ /* Get the address of the end of the GOT */
61 #endif
62 addq t8, t4, t10 /* add the displacement */
63
64 /*
65 * Step 3 -- Every entry in the global offset table needs to
66 * modified for the displacement before any code will work.
67 */
68
69 3: ldq t1, 0(t9) /* load the value */
70 addq t8, t1, t1 /* add the displacement */
71 stq t1, 0(t9) /* save the new value */
72 lda t9, 8(t9) /* point to next entry */
73 cmpult t9, t10, t1 /* are we done? */
74 bne t1, 3b /* no, do more */
75
76 /*
77 * Ya! Things are far enough so we can do some dynamic linking!
78 */
79
80 /* Squirrel away ps_strings. */
81 mov a3, s0
82
83 /*
84 * Allocate space on the stack for the cleanup and obj_main
85 * entries that _rtld() will provide for us.
86 */
87 lda sp, -16(sp)
88
89 mov sp, a0 /* v0 = _rtld(sp); */
90 CALL(_rtld)
91
92 ldq a1, 0(sp) /* cleanup */
93 ldq a2, 8(sp) /* obj_main */
94 lda sp, 16(sp) /* pop stack */
95
96 mov sp, a0 /* stack pointer */
97 mov s0, a3 /* ps_strings */
98
99 mov v0, pv /* set up PV for entry point */
100
101 jsr ra, (v0), 0 /* (*_start)(sp, cleanup, obj, ps_strings); */
102 ldgp gp, 0(ra)
103
104 CALL(exit)
105 halt
106 END(_rtld_start)
107
108 #define RTLD_BIND_START_PROLOGUE \
109 /* at_reg already used by PLT code. */ \
110 .set noat ; \
111 \
112 /* \
113 * Allocate stack frame and preserve all registers that the \
114 * caller would have normally saved themselves. \
115 */ \
116 lda sp, -168(sp) ; \
117 stq ra, 0(sp) ; \
118 stq v0, 8(sp) ; \
119 stq t0, 16(sp) ; \
120 stq t1, 24(sp) ; \
121 stq t2, 32(sp) ; \
122 stq t3, 40(sp) ; \
123 stq t4, 48(sp) ; \
124 stq t5, 56(sp) ; \
125 stq t6, 64(sp) ; \
126 stq t7, 72(sp) ; \
127 stq a0, 80(sp) ; \
128 stq a1, 88(sp) ; \
129 stq a2, 96(sp) ; \
130 stq a3, 104(sp) ; \
131 stq a4, 112(sp) ; \
132 stq a5, 120(sp) ; \
133 stq t8, 128(sp) ; \
134 stq t9, 136(sp) ; \
135 stq t10, 144(sp) ; \
136 stq t11, 152(sp) ; \
137 stq gp, 160(sp) ; \
138 \
139 /* \
140 * Load our global pointer. Note, can't use pv, since it is \
141 * already used by the PLT code. \
142 */ \
143 br t0, 1f ; \
144 1: LDGP(t0)
145
146 #define RTLD_BIND_START_EPILOGUE \
147 /* Move the destination address into position. */ \
148 mov v0, pv ; \
149 \
150 /* Restore program registers. */ \
151 ldq ra, 0(sp) ; \
152 ldq v0, 8(sp) ; \
153 ldq t0, 16(sp) ; \
154 ldq t1, 24(sp) ; \
155 ldq t2, 32(sp) ; \
156 ldq t3, 40(sp) ; \
157 ldq t4, 48(sp) ; \
158 ldq t5, 56(sp) ; \
159 ldq t6, 64(sp) ; \
160 ldq t7, 72(sp) ; \
161 ldq a0, 80(sp) ; \
162 ldq a1, 88(sp) ; \
163 ldq a2, 96(sp) ; \
164 ldq a3, 104(sp) ; \
165 ldq a4, 112(sp) ; \
166 ldq a5, 120(sp) ; \
167 ldq t8, 128(sp) ; \
168 ldq t9, 136(sp) ; \
169 ldq t10, 144(sp) ; \
170 ldq t11, 152(sp) ; \
171 ldq gp, 160(sp) ; \
172 /* XXX LDGP? */ \
173 \
174 /* \
175 * We've patched the PLT; sync the I-stream. \
176 */ \
177 imb ; \
178 \
179 /* Pop the stack frame and turn control to the destination. */ \
180 lda sp, 168(sp) ; \
181 jmp zero, (pv)
182
183 /*
184 * Lazy binding entry point, called via PLT.
185 */
186 NESTED_NOPROFILE(_rtld_bind_start, 0, 168, ra, 0, 0)
187
188 RTLD_BIND_START_PROLOGUE
189
190 /* Set up the arguments for _rtld_bind. */
191 subq at_reg, pv, a1 /* calculate offset of reloc entry */
192 ldq a0, 8(pv) /* object structure */
193 subq a1, 20, a1 /* = (at - pv - 20) / 12 * 24 */
194 addq a1, a1, a1
195
196 CALL(_rtld_bind)
197
198 RTLD_BIND_START_EPILOGUE
199
200 END(_rtld_bind_start)
201
202 /*
203 * Lazy binding entry point, called via PLT. This version is for the
204 * old PLT entry format.
205 */
206 NESTED_NOPROFILE(_rtld_bind_start_old, 0, 168, ra, 0, 0)
207
208 RTLD_BIND_START_PROLOGUE
209
210 /* Set up the arguments for _rtld_bind. */
211 ldq a0, 8(pv) /* object structure */
212 mov at_reg, a1 /* offset of reloc entry */
213
214 CALL(_rtld_bind)
215
216 RTLD_BIND_START_EPILOGUE
217
218 END(_rtld_bind_start_old)
219