etc/services - sync with NetBSD-8
[minix.git] / libexec / ld.elf_so / arch / hppa / rtld_start.S
blob230fc427183f9904b1d9a4c167c4dbf390ccc03a
1 /*      $NetBSD: rtld_start.S,v 1.12 2012/01/06 10:38:57 skrll Exp $    */
3 /*-
4  * Copyright (c) 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 Fredette.
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  */
32 #include <machine/asm.h>
33 #include <machine/frame.h>
35         .import _GLOBAL_OFFSET_TABLE_
37 ENTRY($rtld_start,HPPA_FRAME_SIZE)
39         /* Start stack calling convention. */
40         copy    %r3, %r1 
41         copy    %sp, %r3
42         stw,ma  %r1, HPPA_FRAME_SIZE(%sp)
44         /*
45          * Save our single argument, the ps_strings pointer. We'll need this
46          * twice later: once to call _rtld, and again to transfer to the
47          * program's entry point.
48          */
49         stw     %arg0, HPPA_FRAME_ARG(0)(%r3)
51         /*
52          * We can't move to C until we relocate at least the 
53          * Global Offset Table.  Even finding the GOT is tricky
54          * without inadvertently causing the linker to make
55          * relocations for this part of the text segment.
56          */
58         bl      L$lpc1, %r19
59         depi    0, 31, 2, %r19
60 L$lpc1: addil   L'_DYNAMIC - ($PIC_pcrel$0 - 8), %r19
61         ldo     R'_DYNAMIC - ($PIC_pcrel$0 - 12)(%r1),%arg0
63         /*
64          * Load the absolute address of the beginning of the GOT into %r19, the
65          * shared library linkage table register, leaving it ready-to-use by
66          * the dynamic linker C code.
67          */
68         addil   L'_GLOBAL_OFFSET_TABLE_ - ($PIC_pcrel$0 - 16), %r19
69         ldo     R'_GLOBAL_OFFSET_TABLE_ - ($PIC_pcrel$0 - 20)(%r1),%r19
71         /*
72          * The linker sets the first entry in the GOT to the unrelocated
73          *  address of _DYNAMIC.  Subtract this from the absolute address of
74          * _DYNAMIC to get our relocbase.
75          */
76         ldw     0(%r19), %arg1
77         sub     %arg0, %arg1, %arg1     ; %arg1 = relocbase
78         bl      _rtld_relocate_nonplt_self, %rp
79         copy    %arg1, %r4              ; save for later
81         /*
82          * Recover the ps_strings pointer, and take out the
83          * ps_argvstr member.
84          */
85         ldw     HPPA_FRAME_ARG(0)(%r3), %arg0   ; ps_strings
86         ldw     0(%arg0), %arg0         ; ps_argvstr member first in struct
88         /*
89          * ps_argvstr - 4 would get us a pointer to argc, comparable to the
90          * initial stack pointer on architectures where the stack grows down.
91          * Subtracting an additional eight creates the storage for obj and
92          * cleanup that _rtld needs.
93          */
94         ldo     -12(%arg0), %arg0
95         stw     %arg0, HPPA_FRAME_ARG(1)(%r3)
97         /* Call _rtld, copying relocbase into arg1. */
98         bl      _rtld, %rp
99         copy    %r4, %arg1              ; %arg1 = relocbase
101         /* Prepare the arguments for the entry point. */
102         ldw     HPPA_FRAME_ARG(1)(%r3), %r1
103         ldw     HPPA_FRAME_ARG(0)(%r3), %arg0   ; ps_strings
104         ldw     0(%r1), %arg1                   ; cleanup
105         ldw     4(%r1), %arg2                   ; obj
107         /* End stack calling convention. */
108         ldo     HPPA_FRAME_SIZE(%r3), %sp
109         ldw,mb  -HPPA_FRAME_SIZE(%sp), %r3
111         /* Go for it. */
112         bv      %r0(%ret0)
113         copy    %r0, %rp
114 EXIT($rtld_start)
117  * This does our setup for an object's GOT.  %arg0 is the Obj_Entry * for the
118  * object, and %arg1 is its GOT pointer.
119  */
120 LEAF_ENTRY(__rtld_setup_hppa_pltgot)
122         /*
123          * The second entry of the GOT is reserved for the dynamic linker.  We
124          * put the Obj_Entry * for the object in there.
125          */
126         stw     %arg0, 4(%arg1)
128         /*
129          * Fill the fixup_func and fixup_ltp members of the PLT stub.  This
130          * stub is inserted by the linker immediately before the GOT.  We use
131          * this stub to enter our binder.
132          */
134         bl      L$lpc2, %arg0
135         depi    0, 31, 2, %arg0
136 L$lpc2: addil   L'_rtld_bind_start - ($PIC_pcrel$0 - 8), %arg0
137         ldo     R'_rtld_bind_start - ($PIC_pcrel$0 - 12)(%r1),%arg0
139         stw     %arg0, -8(%arg1)
140         bv      %r0(%rp)
141         stw     %r19, -4(%arg1)
142 EXIT(__rtld_setup_hppa_pltgot)
145  * In order to support lazy binding, this implementation of _rtld_bind_start is
146  * very closely tied to the shared-library call stub and the PLT stub, both
147  * inserted by the linker.
148  */
151  * This is a magic branch instruction that is used by GCC's
152  * __canonicalize_funcptr_for_compare() function to fixup relocations
153  * in order to do function pointer comparisons.
154  */
156         bl      _rtld_bind, %rp
158 ENTRY(_rtld_bind_start,HPPA_FRAME_SIZE)
160         /* Start stack calling convention.  */
161         copy    %r3, %r1 
162         copy    %sp, %r3
164         stw,ma  %r1, HPPA_FRAME_SIZE(%sp)
166         /*
167          * We have to save all calling convention registers that are set by the
168          * caller, because we have to restore them before transferring to the
169          * bound function.  Note that this includes %ret0, %ret1, and %t1.
170          *
171          * %ret0 and %ret1 because they can have meaning on entry to a
172          * function.
173          *
174          * %t1 because it's used by libc to pass on errno values to cerror.
175          */
176         stw     %rp, HPPA_FRAME_CRP(%r3)
177         stw     %arg0, HPPA_FRAME_ARG(0)(%r3)
178         stw     %arg1, HPPA_FRAME_ARG(1)(%r3)
179         stw     %arg2, HPPA_FRAME_ARG(2)(%r3)
180         stw     %arg3, HPPA_FRAME_ARG(3)(%r3)
181         /* 0(%r3) is filled with the saved %r3 above */
182         stw     %ret0, 4(%r3)
183         stw     %ret1, 8(%r3)
184         stw     %t1, 12(%r3)            /* %r22 */
186         /*
187          * The linker PLT stub loads %r20 with (GOT - 8) for the object that
188          * needs binding done.  The second entry of the GOT is reserved for the
189          * dynamic linker's use, and we previously stashed the object's
190          * Obj_Entry * there.
191          */
192         ldw     12(%r20), %arg0
194         /*
195          * The linker shared-library call stub loads %r19 from the shared
196          * linkage member of the PLT entry.  We previously stashed the reloff
197          * of the relocation there.
198          */
199         copy    %r19, %arg1
201         /*
202          * The linker PLT stub loads %r21 with the fixup_ltp word in itself.
203          * We previously stashed our %r19 value there.
204          */
205         bl      _rtld_bind, %rp
206         copy    %r21, %r19
208         /*
209          * Our hppa version of _rtld_bind returns to us the address of the PLT
210          * entry that it fixed up.  Load the function address and shared
211          * linkage for the newly bound function.
212          */
213         ldw     0(%ret0), %r21
214         ldw     4(%ret0), %r19
216         /* Restore registers saved above. */
217         ldw     HPPA_FRAME_CRP(%r3), %rp
218         ldw     HPPA_FRAME_ARG(0)(%r3), %arg0
219         ldw     HPPA_FRAME_ARG(1)(%r3), %arg1
220         ldw     HPPA_FRAME_ARG(2)(%r3), %arg2
221         ldw     HPPA_FRAME_ARG(3)(%r3), %arg3
222         ldw     4(%r3), %ret0
223         ldw     8(%r3), %ret1
224         ldw     12(%r3), %t1            /* %r22 */
226         /* End stack calling convention. */
227         ldo     HPPA_FRAME_SIZE(%r3), %sp
228         ldw,mb  -HPPA_FRAME_SIZE(%sp), %r3
230         /* Transfer to the function. */
231         bv      %r0(%r21)
232         nop
233 EXIT(_rtld_bind_start)