rtld_start.S revision 1.2 1 /* $NetBSD: rtld_start.S,v 1.2 1999/04/18 23:12:59 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
34 /*
35 * Note: we can call ourselves LEAF even though we use callee-saved
36 * registers because we're the root of the call graph.
37 */
38 LEAF_NOPROFILE(_rtld_start, 0)
39 .set noreorder
40 br pv, L1
41 L1: LDGP(pv)
42
43 /*
44 * Save the stack pointer. This is what we will pass to _rtld().
45 */
46 lda s0, 0(sp)
47
48 /*
49 * Make room for the atexit and cleanup vectors that _rtld() will
50 * provide to us.
51 */
52 lda sp, -16(sp)
53
54 /* Save ps_strings pointer */
55 mov a3, s1
56
57 /* XXX Partially relocate ourself. */
58
59 /* Step 1 -- Figure out the displacement */
60
61 br t2, L2 /* get our PC */
62 L2: ldiq t3, L2 /* get where the linker thought we were */
63 subq t2, t3, t8 /* calculate the displacement */
64
65
66 /* Step 2 -- Find bounds of global offset table */
67
68 lda t5, _GLOBAL_OFFSET_TABLE_
69 addq t8, t5, t9 /* add the displacement */
70 #if defined(OLD_GOT)
71 ldq t4, 0(t9) /* Get the address of dynamic table */
72 #else
73 lda t4, _DYNAMIC
74 #endif
75 addq t8, t4, t10 /* add the displacement */
76
77 /*
78 * Step 3 -- Every entry in the global offset table needs to
79 * modified for the displacement before any code will work.
80 */
81
82 L3: ldq t1, 0(t9) /* load the value */
83 addq t8, t1, t1 /* add the displacement */
84 stq t1, 0(t9) /* save the new value */
85 lda t9, 8(t9) /* point to next entry */
86 cmpult t9, t10, t1 /* are we done? */
87 bne t1, L3 /* no, do more */
88
89 /*
90 * Ya! Things are far enough so we can do some dynamic linking!
91 */
92
93 lda a0, -16(s0)
94 CALL(_rtld) /* v0 = _rtld(sp); */
95
96 ldq a1, -16(s0) /* our atexit function */
97 ldq a2, -8(s0) /* obj_main entry */
98 lda sp, 16(sp) /* readjust our stack */
99 mov s0, a0 /* stack pointer */
100 mov s1, a3 /* ps_strings pointer */
101 mov v0, t12
102 jsr ra, (v0), 0 /* (*_start)(sp, cleanup, obj, ps_strings); */
103 ldgp gp, 0(ra)
104
105 CALL(exit)
106 halt
107 END(_rtld_start)
108
109 /*
110 * Lazy binding entry point, called via PLT.
111 */
112 NESTED_NOPROFILE(_rtld_bind_start, 0, 168, ra, 0, 0)
113 /* at_reg already used by PLT code. */
114 .set noat
115
116 /*
117 * Allocate stack frame and preserve all registers that the caller
118 * would have normally saved themselves.
119 */
120 lda sp, -168(sp)
121 stq ra, 0(sp)
122 stq v0, 8(sp)
123 stq t0, 16(sp)
124 stq t1, 24(sp)
125 stq t2, 32(sp)
126 stq t3, 40(sp)
127 stq t4, 48(sp)
128 stq t5, 56(sp)
129 stq t6, 64(sp)
130 stq t7, 72(sp)
131 stq a0, 80(sp)
132 stq a1, 88(sp)
133 stq a2, 96(sp)
134 stq a3, 104(sp)
135 stq a4, 112(sp)
136 stq a5, 120(sp)
137 stq t8, 128(sp)
138 stq t9, 136(sp)
139 stq t10, 144(sp)
140 stq t11, 152(sp)
141 stq gp, 160(sp)
142
143 /*
144 * Load our global pointer. Note, can't use pv, since it is
145 * already used by the PLT code.
146 */
147 br t0, L100
148 L100: LDGP(t0)
149
150 /* Set up the arguments for _rtld_bind. */
151 ldq a0, 8(pv) /* object structure */
152 mov at_reg, a1 /* offset of reloc entry */
153 CALL(_rtld_bind)
154
155 /* Move the destination address into position. */
156 mov v0, pv
157
158 /* Restore program registers. */
159 ldq ra, 0(sp)
160 ldq v0, 8(sp)
161 ldq t0, 16(sp)
162 ldq t1, 24(sp)
163 ldq t2, 32(sp)
164 ldq t3, 40(sp)
165 ldq t4, 48(sp)
166 ldq t5, 56(sp)
167 ldq t6, 64(sp)
168 ldq t7, 72(sp)
169 ldq a0, 80(sp)
170 ldq a1, 88(sp)
171 ldq a2, 96(sp)
172 ldq a3, 104(sp)
173 ldq a4, 112(sp)
174 ldq a5, 120(sp)
175 ldq t8, 128(sp)
176 ldq t9, 136(sp)
177 ldq t10, 144(sp)
178 ldq t11, 152(sp)
179 ldq gp, 160(sp)
180 /* XXX LDGP? */
181
182 /*
183 * We've patched the PLT; sync the I-stream.
184 */
185 imb
186
187 /* Pop the stack frame and turn control to the destination. */
188 lda sp, 168(sp)
189 jmp zero, (pv)
190 END(_rtld_bind_start)
191