rtld_start.S revision 1.11 1 /* $NetBSD: rtld_start.S,v 1.11 2002/09/11 18:18:37 mycroft 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, 1f
41 1: LDGP(pv)
42
43 /*
44 * Relocate ourself.
45 */
46 br t2, 2f /* get our PC */
47 2: ldiq t3, 2b /* get where the linker thought we were */
48 subq t2, t3, a1 /* calculate the displacement */
49
50 lda t5, _DYNAMIC
51 addq a1, t5, a0 /* add the displacement */
52
53 bsr ra, _rtld_relocate_nonplt_self
54 LDGP(ra)
55
56 /*
57 * Allocate space on the stack for the cleanup and obj_main
58 * entries that _rtld() will provide for us.
59 */
60 lda sp, -16(sp)
61
62 mov sp, a0 /* v0 = _rtld(sp); */
63 CALL(_rtld)
64
65 ldq a1, 0(sp) /* cleanup */
66 ldq a2, 8(sp) /* obj_main */
67 lda sp, 16(sp) /* pop stack */
68
69 mov sp, a0 /* stack pointer */
70 mov s0, a3 /* ps_strings */
71
72 mov v0, pv /* set up PV for entry point */
73
74 jsr ra, (v0), 0 /* (*_start)(sp, cleanup, obj, ps_strings); */
75 ldgp gp, 0(ra)
76
77 CALL(exit)
78 halt
79 END(_rtld_start)
80
81 #define RTLD_BIND_START_PROLOGUE \
82 /* at_reg already used by PLT code. */ \
83 .set noat ; \
84 \
85 /* \
86 * Allocate stack frame and preserve all registers that the \
87 * caller would have normally saved themselves. \
88 */ \
89 lda sp, -168(sp) ; \
90 stq ra, 0(sp) ; \
91 stq v0, 8(sp) ; \
92 stq t0, 16(sp) ; \
93 stq t1, 24(sp) ; \
94 stq t2, 32(sp) ; \
95 stq t3, 40(sp) ; \
96 stq t4, 48(sp) ; \
97 stq t5, 56(sp) ; \
98 stq t6, 64(sp) ; \
99 stq t7, 72(sp) ; \
100 stq a0, 80(sp) ; \
101 stq a1, 88(sp) ; \
102 stq a2, 96(sp) ; \
103 stq a3, 104(sp) ; \
104 stq a4, 112(sp) ; \
105 stq a5, 120(sp) ; \
106 stq t8, 128(sp) ; \
107 stq t9, 136(sp) ; \
108 stq t10, 144(sp) ; \
109 stq t11, 152(sp) ; \
110 stq gp, 160(sp) ; \
111 \
112 /* \
113 * Load our global pointer. Note, can't use pv, since it is \
114 * already used by the PLT code. \
115 */ \
116 br t0, 1f ; \
117 1: LDGP(t0)
118
119 #define RTLD_BIND_START_EPILOGUE \
120 /* Move the destination address into position. */ \
121 mov v0, pv ; \
122 \
123 /* Restore program registers. */ \
124 ldq ra, 0(sp) ; \
125 ldq v0, 8(sp) ; \
126 ldq t0, 16(sp) ; \
127 ldq t1, 24(sp) ; \
128 ldq t2, 32(sp) ; \
129 ldq t3, 40(sp) ; \
130 ldq t4, 48(sp) ; \
131 ldq t5, 56(sp) ; \
132 ldq t6, 64(sp) ; \
133 ldq t7, 72(sp) ; \
134 ldq a0, 80(sp) ; \
135 ldq a1, 88(sp) ; \
136 ldq a2, 96(sp) ; \
137 ldq a3, 104(sp) ; \
138 ldq a4, 112(sp) ; \
139 ldq a5, 120(sp) ; \
140 ldq t8, 128(sp) ; \
141 ldq t9, 136(sp) ; \
142 ldq t10, 144(sp) ; \
143 ldq t11, 152(sp) ; \
144 ldq gp, 160(sp) ; \
145 /* XXX LDGP? */ \
146 \
147 /* \
148 * We've patched the PLT; sync the I-stream. \
149 */ \
150 imb ; \
151 \
152 /* Pop the stack frame and turn control to the destination. */ \
153 lda sp, 168(sp) ; \
154 jmp zero, (pv)
155
156 /*
157 * Lazy binding entry point, called via PLT.
158 */
159 NESTED_NOPROFILE(_rtld_bind_start, 0, 168, ra, 0, 0)
160
161 RTLD_BIND_START_PROLOGUE
162
163 /* Set up the arguments for _rtld_bind. */
164 subq at_reg, pv, a1 /* calculate offset of reloc entry */
165 ldq a0, 8(pv) /* object structure */
166 subq a1, 20, a1 /* = (at - pv - 20) / 12 * 24 */
167 addq a1, a1, a1
168
169 CALL(_rtld_bind)
170
171 RTLD_BIND_START_EPILOGUE
172
173 END(_rtld_bind_start)
174
175 /*
176 * Lazy binding entry point, called via PLT. This version is for the
177 * old PLT entry format.
178 */
179 NESTED_NOPROFILE(_rtld_bind_start_old, 0, 168, ra, 0, 0)
180
181 RTLD_BIND_START_PROLOGUE
182
183 /* Set up the arguments for _rtld_bind. */
184 ldq a0, 8(pv) /* object structure */
185 mov at_reg, a1 /* offset of reloc entry */
186
187 CALL(_rtld_bind)
188
189 RTLD_BIND_START_EPILOGUE
190
191 END(_rtld_bind_start_old)
192