rtld_start.S revision 1.5 1 /* $NetBSD: rtld_start.S,v 1.5 2001/12/13 20:30:48 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, L1
42 L1: LDGP(pv)
43
44 /* XXX Partially relocate ourself. */
45
46 /* Step 1 -- Figure out the displacement */
47
48 br t2, L2 /* get our PC */
49 L2: ldiq t3, L2 /* 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 L3: 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, L3 /* 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 /*
109 * Lazy binding entry point, called via PLT.
110 */
111 NESTED_NOPROFILE(_rtld_bind_start, 0, 168, ra, 0, 0)
112 /* at_reg already used by PLT code. */
113 .set noat
114
115 /*
116 * Allocate stack frame and preserve all registers that the caller
117 * would have normally saved themselves.
118 */
119 lda sp, -168(sp)
120 stq ra, 0(sp)
121 stq v0, 8(sp)
122 stq t0, 16(sp)
123 stq t1, 24(sp)
124 stq t2, 32(sp)
125 stq t3, 40(sp)
126 stq t4, 48(sp)
127 stq t5, 56(sp)
128 stq t6, 64(sp)
129 stq t7, 72(sp)
130 stq a0, 80(sp)
131 stq a1, 88(sp)
132 stq a2, 96(sp)
133 stq a3, 104(sp)
134 stq a4, 112(sp)
135 stq a5, 120(sp)
136 stq t8, 128(sp)
137 stq t9, 136(sp)
138 stq t10, 144(sp)
139 stq t11, 152(sp)
140 stq gp, 160(sp)
141
142 /*
143 * Load our global pointer. Note, can't use pv, since it is
144 * already used by the PLT code.
145 */
146 br t0, L100
147 L100: LDGP(t0)
148
149 /* Set up the arguments for _rtld_bind. */
150 #ifdef NEW_PLT_FORMAT
151 subq at_reg, pv, a1 /* calculate offset of reloc entry */
152 ldq a0, 8(pv) /* object structure */
153 subq a1, 20, a1 /* = (at - pv - 20) / 12 * 24 */
154 addq a1, a1, a1
155 #else
156 ldq a0, 8(pv) /* object structure */
157 mov at_reg, a1 /* offset of reloc entry */
158 #endif /* NEW_PLT_FORMAT */
159 CALL(_rtld_bind)
160
161 /* Move the destination address into position. */
162 mov v0, pv
163
164 /* Restore program registers. */
165 ldq ra, 0(sp)
166 ldq v0, 8(sp)
167 ldq t0, 16(sp)
168 ldq t1, 24(sp)
169 ldq t2, 32(sp)
170 ldq t3, 40(sp)
171 ldq t4, 48(sp)
172 ldq t5, 56(sp)
173 ldq t6, 64(sp)
174 ldq t7, 72(sp)
175 ldq a0, 80(sp)
176 ldq a1, 88(sp)
177 ldq a2, 96(sp)
178 ldq a3, 104(sp)
179 ldq a4, 112(sp)
180 ldq a5, 120(sp)
181 ldq t8, 128(sp)
182 ldq t9, 136(sp)
183 ldq t10, 144(sp)
184 ldq t11, 152(sp)
185 ldq gp, 160(sp)
186 /* XXX LDGP? */
187
188 /*
189 * We've patched the PLT; sync the I-stream.
190 */
191 imb
192
193 /* Pop the stack frame and turn control to the destination. */
194 lda sp, 168(sp)
195 jmp zero, (pv)
196 END(_rtld_bind_start)
197