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