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