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