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