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