1 /* $FreeBSD: src/libexec/rtld-elf/alpha/rtld_start.S,v 1.3.2.2 2002/09/02 02:10:20 obrien Exp $ */
2 /* $DragonFly: src/libexec/rtld-elf/alpha/Attic/rtld_start.S,v 1.2 2003/06/17 04:27:08 dillon Exp $ */
3 /* From: NetBSD: rtld_start.S,v 1.1 1996/12/16 20:38:09 cgd Exp */
6 * Copyright 1996 Matt Thomas <matt@3am-software.com>
7 * Copyright 2000 John D. Polstra
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include <machine/asm.h>
34 #include <machine/pal.h>
36 .extern _GLOBAL_OFFSET_TABLE_
39 LEAF(_rtld_start, 0) /* XXX */
44 /* save away the stack pointer */
46 lda s0, 0(sp) /* get argc from stack */
47 lda sp, -16(sp) /* space for arguments */
49 /* save ps_strings pointer */
52 /* Step 1 -- Figure out the displacement */
54 br t2, $34 /* get our PC */
55 $34: ldiq t3, $34 /* get where the linker thought we were */
56 subq t2, t3, t8 /* calculate the displacement */
59 /* Step 2 -- Find bounds of global offset table */
61 lda t5, _GLOBAL_OFFSET_TABLE_
62 addq t8, t5, t9 /* add the displacement */
64 addq t8, t4, t10 /* add the displacement */
67 * Step 3 -- Every entry in the global offset table needs to
68 * modified for the displacement before any code will work.
71 $35: ldq t1, 0(t9) /* load the value */
72 addq t8, t1, t1 /* add the displacement */
73 stq t1, 0(t9) /* save the new value */
74 lda t9, 8(t9) /* point to next entry */
75 cmpult t9, t10, t1 /* are we done? */
76 bne t1, $35 /* no, do more */
79 * Ya! Things are far enough so we can do some dynamic linking!
82 lda a0, 0(s0) /* initial sp */
83 lda a1, -16(s0) /* address for exit proc */
84 lda a2, -8(s0) /* address for obj_main */
85 CALL(_rtld) /* v0 = _rtld(sp, &exit_proc, &obj_main); */
87 ldq a1, -16(s0) /* our atexit function */
88 ldq a2, -8(s0) /* obj_main entry */
89 lda sp, 16(sp) /* readjust our stack */
90 mov s0, a0 /* stack pointer */
91 mov s1, a3 /* ps_strings pointer */
93 jsr ra, (v0), 0 /* (*_start)(sp, cleanup, obj); */
100 #define RTLD_BIND_START_PROLOGUE \
101 /* at_reg already used by PLT code. */ \
105 * Allocate stack frame and preserve all registers that the \
106 * caller would have normally saved themselves. \
132 * Load our global pointer. Note, can't use pv, since it is \
133 * already used by the PLT code. \
138 #define RTLD_BIND_START_EPILOGUE \
139 /* Move the destination address into position. */ \
142 /* Restore program registers. */ \
167 * We've patched the PLT; sync the I-stream. \
171 /* Pop the stack frame and turn control to the destination. */ \
177 * Lazy binding entry point, called via PLT.
179 NESTED_NOPROFILE(_rtld_bind_start, 0, 168, ra, 0, 0)
181 RTLD_BIND_START_PROLOGUE
183 /* Set up the arguments for _rtld_bind. */
184 subq at_reg, pv, a1 /* calculate reloc offset */
185 ldq a0, 8(pv) /* object structure */
186 subq a1, 20, a1 /* = (at - t11 - 20) / 12 * 24 */
191 RTLD_BIND_START_EPILOGUE
193 END(_rtld_bind_start)
196 * Lazy binding entry point, called via PLT. This version is for the
197 * old PLT entry format.
199 NESTED_NOPROFILE(_rtld_bind_start_old, 0, 168, ra, 0, 0)
201 RTLD_BIND_START_PROLOGUE
203 /* Set up the arguments for _rtld_bind. */
204 ldq a0, 8(pv) /* object structure */
205 mov at_reg, a1 /* offset of reloc entry */
209 RTLD_BIND_START_EPILOGUE
211 END(_rtld_bind_start_old)
214 * int cmp0_and_store_int(volatile int *p, int newval);
216 * If an int holds 0, store newval into it; else do nothing. Returns
217 * the previous value.
219 LEAF(cmp0_and_store_int, 2)
229 END(cmp0_and_store_int)
231 LEAF(atomic_add_int, 2)
241 /* Atomically increment an int. */
242 LEAF(atomic_incr_int, 1)
252 /* Atomically decrement an int. */
253 LEAF(atomic_decr_int, 1)