rtld_start.S revision 1.18 1 1.18 matt /* $NetBSD: rtld_start.S,v 1.18 2014/03/19 02:39:22 matt Exp $ */
2 1.1 matt
3 1.1 matt /*
4 1.1 matt * Copyright 1996 Matt Thomas <matt (at) 3am-software.com>
5 1.16 mycroft * Portions copyright 2002, 2003 Charles M. Hannum <root (at) ihack.net>
6 1.1 matt * All rights reserved.
7 1.1 matt *
8 1.1 matt * Redistribution and use in source and binary forms, with or without
9 1.1 matt * modification, are permitted provided that the following conditions
10 1.1 matt * are met:
11 1.1 matt * 1. Redistributions of source code must retain the above copyright
12 1.1 matt * notice, this list of conditions and the following disclaimer.
13 1.1 matt * 2. Redistributions in binary form must reproduce the above copyright
14 1.1 matt * notice, this list of conditions and the following disclaimer in the
15 1.1 matt * documentation and/or other materials provided with the distribution.
16 1.1 matt * 3. The name of the author may not be used to endorse or promote products
17 1.1 matt * derived from this software without specific prior written permission.
18 1.1 matt *
19 1.1 matt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 1.1 matt * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 1.1 matt * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 1.1 matt * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 1.1 matt * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 1.1 matt * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 1.1 matt * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 1.1 matt * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 1.1 matt * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 1.1 matt * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 1.1 matt */
30 1.1 matt
31 1.1 matt #include <machine/asm.h>
32 1.1 matt
33 1.1 matt /* R9 contains the address of PS_STRINGS and since its caller saved,
34 1.1 matt * we can just use it. R6 has a backup copy of the stack pointer which
35 1.16 mycroft * we can use as well.
36 1.1 matt */
37 1.3 matt ENTRY(_rtld_start, 0)
38 1.1 matt /* Allocate space on the stack for the cleanup and obj_main
39 1.1 matt * entries that _rtld() will provide for us.
40 1.1 matt */
41 1.7 matt clrl %fp
42 1.7 matt subl2 $8,%sp
43 1.1 matt
44 1.9 mycroft movab _DYNAMIC,%r0
45 1.16 mycroft subl3 _GLOBAL_OFFSET_TABLE_,%r0,%r10
46 1.10 mycroft pushl %r10 /* relocbase */
47 1.9 mycroft pushl %r0 /* &_DYNAMIC */
48 1.9 mycroft calls $2,_rtld_relocate_nonplt_self
49 1.9 mycroft
50 1.10 mycroft pushl %r10 /* relocbase */
51 1.11 mycroft pushal 4(%sp) /* sp */
52 1.8 mycroft calls $2,_rtld /* entry = _rtld(sp, relocbase) */
53 1.4 matt
54 1.7 matt movq (%sp)+,%r7 /* grab cleanup and obj_main into %r7/%r8 */
55 1.7 matt jmp 2(%r0) /* jump to entry point + 2 */
56 1.17 matt END(_rtld_start)
57 1.1 matt
58 1.1 matt /*
59 1.17 matt * Lazy binding entry point, called via PLT via JMP into pltgot[1].
60 1.17 matt * SP+0: obj entry points
61 1.17 matt * SP+4: address to relocation index
62 1.13 mycroft *
63 1.13 mycroft * Note: Some functions rely on there not being an additional call frame;
64 1.13 mycroft * hence the `optimization' to avoid the callg opportunistically.
65 1.1 matt */
66 1.3 matt ALTENTRY(_rtld_bind_start)
67 1.18 matt movab -64(%sp),%sp /* reserve some space */
68 1.14 mycroft pushr $0x3f /* save R0-R5 */
69 1.18 matt movq -8(%fp),%r0 /* get addresses of plt.got & reloc index */
70 1.7 matt pushl (%r1) /* push relocation index */
71 1.7 matt pushl %r0 /* push address of obj entry */
72 1.1 matt calls $2,_rtld_bind
73 1.18 matt
74 1.18 matt movl %r0,%r3 /* save routine address */
75 1.18 matt extzv $0,$12,(%r0),%r1 /* get entry mask */
76 1.18 matt extzv $0,$12,6(%fp),%r2 /* get saved mask */
77 1.18 matt cmpw %r1,%r2 /* compare them */
78 1.18 matt bneq 12f /* if they are different, rebuild */
79 1.18 matt movl %r0,-4(%fp) /* save routine address */
80 1.18 matt popr $0x3f /* pop registers */
81 1.18 matt movab 68(%sp),%sp /* restore sp */
82 1.18 matt rsb /* and jump to it */
83 1.18 matt
84 1.18 matt /*
85 1.18 matt * We need to rebuild the callframe. Save the current one in case
86 1.18 matt * we might overwrite it.
87 1.18 matt */
88 1.18 matt 12: movq 4(%fp),-(%sp) /* save PSW and AP */
89 1.18 matt movq 12(%fp),-(%sp) /* save FP and return address */
90 1.18 matt /*
91 1.18 matt * Find out where this this call frame ends.
92 1.18 matt */
93 1.18 matt movl %ap,%r0 /* get past callframe and registers */
94 1.18 matt bbs $29,4(%fp),22f /* calls is easy, it's where AP is */
95 1.18 matt /*
96 1.18 matt * Callg not so much
97 1.18 matt */
98 1.18 matt movab 20(%fp),%r0 /* past fixed callframe */
99 1.18 matt tstw %r2 /* no saved registers? */
100 1.18 matt beql 22f /* none, so we are done. */
101 1.18 matt movl $11,%r4 /* start with register 11 */
102 1.18 matt 20: bbc %r4,%r2,21f /* save this register? */
103 1.18 matt addl2 $4,%r0 /* yes, adjust for saved register */
104 1.18 matt 21: sobgeq %r4,20b /* try next register */
105 1.18 matt
106 1.18 matt 22:
107 1.18 matt /*
108 1.18 matt * First "push" the caller saved registers (if there any that
109 1.18 matt * need to saved.)
110 1.18 matt */
111 1.18 matt tstw %r1 /* if there are no registers to save */
112 1.18 matt beql 1f /* just push the callframe */
113 1.18 matt cmpw %r1,$63 /* if there are no caller-saved registers */
114 1.18 matt blequ 5f /* skip them */
115 1.18 matt bbc $11,%r1,10f /* does it need to be saved? */
116 1.18 matt movl %r11,-(%r0)
117 1.18 matt 10: bbc $10,%r1,9f /* does it need to be saved? */
118 1.18 matt movl %r10,-(%r0)
119 1.18 matt 9: bbc $9,%r1,8f /* does it need to be saved? */
120 1.18 matt movl %r9,-(%r0)
121 1.18 matt 8: bbc $8,%r1,7f /* does it need to be saved? */
122 1.18 matt movl %r8,-(%r0)
123 1.18 matt 7: bbc $7,%r1,6f /* does it need to be saved? */
124 1.18 matt movl %r7,-(%r0)
125 1.18 matt 6: bbc $6,%r1,5f /* does it need to be saved? */
126 1.18 matt movl %r6,-(%r0)
127 1.18 matt 5:
128 1.18 matt /*
129 1.18 matt * r0-r5 are not normally preserved so we should be done.
130 1.18 matt */
131 1.18 matt cmpw %r1,$63
132 1.18 matt bgtru 1f
133 1.18 matt /*
134 1.18 matt * For some reason, we have to preserve these.
135 1.18 matt */
136 1.18 matt movab 16(%sp),%r2
137 1.18 matt bbc $5,%r1,4f /* does it need to be saved? */
138 1.18 matt movl 20(%r2),-(%r0)
139 1.18 matt 4: bbc $4,%r1,3f /* does it need to be saved? */
140 1.18 matt movl 16(%r2),-(%r0)
141 1.18 matt 3: bbc $3,%r1,2f /* does it need to be saved? */
142 1.18 matt movl 12(%r2),-(%r0)
143 1.18 matt 2: bbc $2,%r1,1f /* does it need to be saved? */
144 1.18 matt movl 8(%r2),-(%r0)
145 1.18 matt
146 1.18 matt /*
147 1.18 matt * Now we save the fixed part of the callframe.
148 1.18 matt */
149 1.18 matt 1: clrl %r4 /* clear condition handler slot */
150 1.18 matt movq (%sp)+,-(%r0) /* move FP and PC into place */
151 1.18 matt movq (%sp)+,-(%r0) /* move PSW/save-mask/etc + AP into place */
152 1.18 matt movq %r3,-(%r0) /* move routine address + cond handle slot */
153 1.18 matt addl3 $4,%r0,%fp /* get start of new callframe */
154 1.18 matt insv $0,$12,%r1,6(%fp) /* insert new saved mask */
155 1.14 mycroft popr $0x3f /* restore R0-R5 (cond flags not modified) */
156 1.18 matt subl3 $4,%fp,%sp /* sp needs to be equal to fp */
157 1.18 matt rsb /* and jmp to the routine */
158 1.17 matt END(_rtld_bind_start)
159