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