rtld_start.S revision 1.15 1 /* $NetBSD: rtld_start.S,v 1.15 2002/10/05 11:59:05 mycroft Exp $ */
2
3 /*
4 * Copyright 1996 Matt Thomas <matt (at) 3am-software.com>
5 * Portions copyright 2002 Charles M. Hannum <root (at) ihack.net>
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include <machine/asm.h>
32
33 /*
34 * Note: we can call ourselves LEAF even though we use callee-saved
35 * registers because we're the root of the call graph.
36 */
37 LEAF_NOPROFILE(_rtld_start, 0)
38 .set noreorder
39 br pv, 1f
40 1: LDGP(pv)
41
42 /*
43 * Relocate ourself.
44 */
45 br s2, 2f /* get our PC */
46 2: ldiq s3, 2b /* get where the linker thought we were */
47
48 subq s2, s3, a1 /* relocbase */
49 lda t5, _DYNAMIC
50 addq a1, t5, a0 /* &_DYNAMIC */
51
52 bsr ra, _rtld_relocate_nonplt_self
53 LDGP(ra)
54
55 /*
56 * Allocate space on the stack for the cleanup and obj_main
57 * entries that _rtld() will provide for us.
58 */
59 lda sp, -16(sp)
60
61 subq s2, s3, a1 /* relocbase */
62 mov sp, a0 /* sp */
63 CALL(_rtld) /* v0 = _rtld(sp, relocbase); */
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