1/*        $NetBSD: rtld_start.S,v 1.12 2013/12/03 00:19:56 matt Exp $ */
2
3/*-
4 * Copyright (c) 1998, 2002 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Matt Thomas and by Charles M. Hannum.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
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 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <machine/asm.h>
33
34RCSID("$NetBSD: rtld_start.S,v 1.12 2013/12/03 00:19:56 matt Exp $")
35
36ENTRY_NP(_rtld_start)
37          sub       sp, sp, #8                    /* make room for obj_main & exit proc */
38          movs      r4, r0                        /* save ps_strings */
39
40          ldr       r6, .Lgot
41          ldr       r5, .Ldynamic
42          add       r6, r6, pc                    /* r6 = &GOT[0]; pc = &LPIC1; */
43          adds      r0, r6, r5                    /* arg0 = &_DYNAMIC */
44.LPIC1:
45          ldr       r5, [r6]            /* GOT[0] = &_DYNAMIC */
46          subs      r5, r0, r5                    /* relocbase = GOT[0] - &_DYNAMIC */
47          movs      r1, r5                        /* arg1 = relocabase */
48          bl        _rtld_relocate_nonplt_self
49
50          movs      r1, r5                        /* relocbase */
51          mov       r0, sp                        /* sp */
52          bl        _rtld                         /* call the shared loader */
53          movs      r3, r0                        /* save entry point */
54
55#ifdef __thumb__
56          ldr       r2, [sp, #0]                  /* pop r2 = cleanup */
57          ldr       r1, [sp, #4]                  /* pop r1 = obj_main */
58          add       sp, sp, #8
59#else
60          ldr       r2, [sp], #4                  /* pop r2 = cleanup */
61          ldr       r1, [sp], #4                  /* pop r1 = obj_main */
62#endif
63          movs      r0, r4                        /* restore ps_strings */
64          RETr(r3)
65
66          .align    0
67.Lgot:
68          .word     _GLOBAL_OFFSET_TABLE_ - .LPIC1
69.Ldynamic:
70          .word     _DYNAMIC(GOTOFF)
71END(_rtld_start)
72
73/*
74 *        stack[0] = RA
75 *        ip = &GOT[n+3]
76 *        lr = &GOT[2]
77 */
78ARM_ENTRY_NP(_rtld_bind_start)
79          stmdb     sp!,{r0-r4,sl,fp}   /* 8 byte aligned (lr already saved) */
80
81          sub       r1, ip, lr                    /* r1 = 4 * (n + 1) */
82          sub       r1, r1, #4                    /* r1 = 4 * n */
83          add       r1, r1, r1                    /* r1 = 8 * n */
84
85          ldr       r0, [lr, #-4]                 /* get obj ptr from GOT[1] */
86          mov       r4, ip                        /* save GOT location */
87
88          bl        _rtld_bind                    /* Call the binder */
89
90          str       r0, [r4]            /* save address in GOT */
91          mov       ip, r0                        /* save new address */
92
93          ldmia     sp!,{r0-r4,sl,fp,lr}          /* restore the stack */
94          RETr(ip)                      /* jump to the new address */
95END(_rtld_bind_start)
96