]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - libexec/rtld-elf/mips/rtld_start.S
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / libexec / rtld-elf / mips / rtld_start.S
1 /*      $NetBSD: rtld_start.S,v 1.10 2009/12/14 00:41:19 matt Exp $     */
2
3 /*
4  * Copyright 1997 Michael L. Hitch <mhitch@montana.edu>
5  * Portions copyright 2002 Charles M. Hannum <root@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  * $FreeBSD$
31  */
32
33 #include <machine/asm.h>
34
35 .globl _C_LABEL(_rtld_relocate_nonplt_self)
36 .globl _C_LABEL(_rtld)
37
38 #define PTR_SIZE        (1<<PTR_SCALESHIFT)
39
40 /*
41  *      a0      stack pointer
42  *      a1      rtld cleanup (filled in by dynamic loader)
43  *      a2      rtld object (filled in by dynamic loader)
44  *      a3      ps_strings
45  */
46 LEAF(rtld_start)
47         .frame  sp, 4*PTR_SIZE, ra
48         .mask   0x10090000,-PTR_SIZE
49         .set    noreorder
50         SETUP_GP
51         PTR_SUBU sp, 4*PTR_SIZE         /* adjust stack pointer */
52         SETUP_GP64(s4, rtld_start)
53         SAVE_GP(0)
54                                         /* -> 1*PTR_SIZE(sp) for atexit */
55                                         /* -> 2*PTR_SIZE(sp) for obj_main */
56         move    s0, a0                  /* save stack pointer from a0 */
57         move    s3, a3                  /* save ps_strings pointer */
58
59         PTR_LA  a1, 1f
60         bal     1f
61         PTR_LA  t0, _C_LABEL(_rtld_relocate_nonplt_self)
62 1:      PTR_SUBU a1, ra, a1             /* relocbase */
63         PTR_LA  a0, _DYNAMIC
64         PTR_ADDU t9, a1, t0
65         jalr    t9                      /* _rtld_relocate_nonplt_self(dynp, relocabase) */
66         PTR_ADDU a0, a1, a0             /* &_DYNAMIC */
67
68         move    a0, s0                  /* sp */
69         PTR_ADDU a1, sp, 2*PTR_SIZE     /* &our atexit function */
70         PTR_ADDU a2, sp, 3*PTR_SIZE     /* obj_main entry */
71         PTR_SUBU sp, 4*SZREG            /* ABI requires to reserve memory for 4 regs */
72         PTR_LA  t9, _C_LABEL(_rtld)
73         jalr    t9                      /* v0 = _rtld(sp, cleanup, objp) */
74         nop
75         PTR_ADDU sp, 4*SZREG
76
77         PTR_L   a1, 2*PTR_SIZE(sp)      /* our atexit function */
78         PTR_L   a2, 3*PTR_SIZE(sp)      /* obj_main entry */
79         PTR_ADDU sp, 4*PTR_SIZE         /* readjust stack */
80         move    a0, s0                  /* stack pointer */
81         move    t9, v0
82         PTR_SUBU sp, 4*SZREG            /* ABI requires to reserve memory for 4 regs */
83         move    ra,t9                   /* RA == PC signals backtrace routine to stop */
84         j       t9                      /* _start(sp, cleanup, obj); */
85         move    a3, s3                  /* restore ps_strings */
86 END(rtld_start)
87
88 #define XCALLFRAME_SIZ          (12*SZREG)
89 #define XCALLFRAME_RA           (10*SZREG)
90 #define XCALLFRAME_GP           (9*SZREG)
91 #define XCALLFRAME_S0           (8*SZREG)
92 #define XCALLFRAME_A3           (7*SZREG)
93 #define XCALLFRAME_A2           (6*SZREG)
94 #define XCALLFRAME_A1           (5*SZREG)
95 #define XCALLFRAME_A0           (4*SZREG)
96 #if defined(__mips_n32) || defined(__mips_n64)
97 #define XCALLFRAME_A7           (3*SZREG)
98 #define XCALLFRAME_A6           (2*SZREG)
99 #define XCALLFRAME_A5           (1*SZREG)
100 #define XCALLFRAME_A4           (0*SZREG)
101 #endif
102
103         .globl  _rtld_bind_start
104         .ent    _rtld_bind_start
105 _rtld_bind_start:
106         .frame  sp, XCALLFRAME_SIZ, $15
107         move    v1, gp                  /* save old GP */
108 #if defined(__mips_o32) || defined(__mips_o64)
109         PTR_ADDU t9, 8                  /* modify T9 to point at .cpload */
110 #endif
111         SETUP_GP
112         PTR_SUBU sp, XCALLFRAME_SIZ     /* save arguments and sp value in stack */
113         SETUP_GP64(XCALLFRAME_GP, _rtld_bind_start)
114         SAVE_GP(XCALLFRAME_GP)
115 #if defined(__mips_n32) || defined(__mips_n64)
116         REG_S   a4,  XCALLFRAME_A4(sp)
117         REG_S   a5,  XCALLFRAME_A5(sp)
118         REG_S   a6,  XCALLFRAME_A6(sp)
119         REG_S   a7,  XCALLFRAME_A7(sp)
120 #endif
121         REG_S   a0,  XCALLFRAME_A0(sp)
122         REG_S   a1,  XCALLFRAME_A1(sp)
123         REG_S   a2,  XCALLFRAME_A2(sp)
124         REG_S   a3,  XCALLFRAME_A3(sp)
125         REG_S   $15,  XCALLFRAME_RA(sp) /* ra is in t7/t3 */
126         REG_S   s0,  XCALLFRAME_S0(sp)
127         move    s0, sp
128
129         move    a0, v1                  /* old GP */
130         PTR_SUBU        a0, a0, 0x7ff0          /* The offset of $gp from the   */
131                                         /* beginning of the .got section: */
132                                         /* $gp = .got + 0x7ff0, so      */
133                                         /* .got = $gp - 0x7ff0          */
134                                         /* Simple math as you can see.  */
135 #if defined(__mips_n64)
136         ld      a0, 8(a0)               /* object = pltgot[1] */
137         and     a0, a0, 0x7fffffffffffffff
138 #else
139         lw      a0, 4(a0)               /* object = pltgot[1] & 0x7fffffff */
140         and     a0, a0, 0x7fffffff
141 #endif
142         move    a1, t8                  /* symbol index */
143
144         PTR_LA  t9, _C_LABEL(_mips_rtld_bind)
145         jalr    t9
146         nop
147
148         move    sp, s0
149         REG_L   ra, XCALLFRAME_RA(sp)
150         REG_L   s0, XCALLFRAME_S0(sp)
151         REG_L   a0, XCALLFRAME_A0(sp)
152         REG_L   a1, XCALLFRAME_A1(sp)
153         REG_L   a2, XCALLFRAME_A2(sp)
154         REG_L   a3, XCALLFRAME_A3(sp)
155 #if defined(__mips_n32) || defined(__mips_n64)
156         REG_L   a4, XCALLFRAME_A4(sp)
157         REG_L   a5, XCALLFRAME_A5(sp)
158         REG_L   a6, XCALLFRAME_A6(sp)
159         REG_L   a7, XCALLFRAME_A7(sp)
160 #endif
161         RESTORE_GP64
162         PTR_ADDU sp, XCALLFRAME_SIZ
163         move    t9, v0
164         jr      t9
165         nop
166 END(_rtld_bind_start)