No empty .Rs/.Re
[netbsd-mini2440.git] / libexec / ld.elf_so / arch / hppa / rtld_start.S
blob7ced23aa7e875e1cd6c916852678beeac65b3582
1 /*      $NetBSD: rtld_start.S,v 1.5 2006/10/16 13:53:09 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 #define _LOCORE /* XXX fredette we MUST get rid of this */
34 #include <machine/frame.h>
35 #undef _LOCORE
37         .import _GLOBAL_OFFSET_TABLE_
39 ENTRY($rtld_start,HPPA_FRAME_SIZE)
41         /* Start stack calling convention. */
42         copy    %r3, %r1 
43         copy    %sp, %r3
44         stw,ma  %r1, HPPA_FRAME_SIZE(%sp)
46         /*
47          * Save our single argument, the ps_strings pointer.
48          * We'll need this twice later: once to call _rtld,
49          * and again to transfer to the program's entry point.
50          */
51         stw     %arg0, HPPA_FRAME_ARG(0)(%r3)
53         /*
54          * We can't move to C until we relocate at least the 
55          * Global Offset Table.  Even finding the GOT is tricky
56          * without inadvertently causing the linker to make
57          * relocations for this part of the text segment.
58          */
60         bl      L$lpc1, %r19
61         depi    0, 31, 2, %r19
62 L$lpc1: addil   L'_DYNAMIC - ($PIC_pcrel$0 - 8), %r19
63         ldo     R'_DYNAMIC - ($PIC_pcrel$0 - 12)(%r1),%arg0
65         /*
66          * Load the absolute address of the beginning of the
67          * GOT into %r19, the shared library linkage table
68          * register, leaving it ready-to-use by the dynamic
69          * linker C code.
70          */
71         addil   L'_GLOBAL_OFFSET_TABLE_ - ($PIC_pcrel$0 - 16), %r19
72         ldo     R'_GLOBAL_OFFSET_TABLE_ - ($PIC_pcrel$0 - 20)(%r1),%r19
74         /*
75          * The linker sets the first entry in the GOT to the 
76          * unrelocated address of _DYNAMIC.  Subtract this
77          * from the absolute address of _DYNAMIC to get our
78          * relocbase.
79          */
80         ldw     0(%r19), %arg1
81         sub     %arg0, %arg1, %arg1     ; %arg1 = relocbase
82         bl      _rtld_relocate_nonplt_self, %rp
83         copy    %arg1, %r4              ; save for later
85         /*
86          * Recover the ps_strings pointer, and take out the
87          * ps_argvstr member.
88          */
89         ldw     HPPA_FRAME_ARG(0)(%r3), %arg0   ; ps_strings
90         ldw     0(%arg0), %arg0         ; ps_argvstr member first in struct
92         /* 
93          * ps_argvstr - 4 would get us a pointer to argc,
94          * comparable to the initial stack pointer on
95          * architectures where the stack grows down.
96          * Subtracting an additional eight creates the 
97          * storage for obj and cleanup that _rtld needs.
98          */
99         ldo     -12(%arg0), %arg0
100         stw     %arg0, HPPA_FRAME_ARG(1)(%r3)
102         /* Call _rtld, copying relocbase into arg1. */
103         bl      _rtld, %rp
104         copy    %r4, %arg1              ; %arg1 = relocbase
106         /* Prepare the arguments for the entry point. */
107         ldw     HPPA_FRAME_ARG(1)(%r3), %r1
108         ldw     HPPA_FRAME_ARG(0)(%r3), %arg0   ; ps_strings
109         ldw     0(%r1), %arg1                   ; cleanup
110         ldw     4(%r1), %arg2                   ; obj
112         /* End stack calling convention. */
113         ldo     HPPA_FRAME_SIZE(%r3), %sp
114         ldw,mb  -HPPA_FRAME_SIZE(%sp), %r3
116         /* Go for it. */
117         bv      %r0(%ret0)
118         copy    %r0, %rp
119 EXIT($rtld_start)
122  * This does our setup for an object's GOT.  %arg0 is the 
123  * Obj_Entry * for the object, and %arg1 is its GOT pointer.
124  */
125 LEAF_ENTRY(__rtld_setup_hppa_pltgot)
127         /*
128          * The second entry of the GOT is reserved for
129          * the dynamic linker.  We put the Obj_Entry *
130          * for the object in there.
131          */
132         stw     %arg0, 4(%arg1)
134         /*
135          * Fill the fixup_func and fixup_ltp members of 
136          * the PLT stub.  This stub is inserted by the
137          * linker immediately before the GOT.  We use 
138          * this stub to enter our binder.
139          */
141         bl      L$lpc2, %arg0
142         depi    0, 31, 2, %arg0
143 L$lpc2: addil   L'_rtld_bind_start - ($PIC_pcrel$0 - 8), %arg0
144         ldo     R'_rtld_bind_start - ($PIC_pcrel$0 - 12)(%r1),%arg0
146         stw     %arg0, -8(%arg1)
147         bv      %r0(%rp)
148         stw     %r19, -4(%arg1)
149 EXIT(__rtld_hppa_setup_pltgot)
152  * In order to support lazy binding, this implementation of
153  * _rtld_bind_start is very closely tied to the shared-library
154  * call stub and the PLT stub, both inserted by the linker.  
155  */
156 ENTRY(_rtld_bind_start,HPPA_FRAME_SIZE)
158         /* Start stack calling convention.  */
159         copy    %r3, %r1 
160         copy    %sp, %r3
162         stw,ma  %r1, HPPA_FRAME_SIZE(%sp)
164         /*
165          * We have to save all calling convention registers 
166          * that are set by the caller, because we have to 
167          * restore them before transferring to the bound 
168          * function.  Note that this includes %ret0 and %ret1, 
169          * because they can have meaning on entry to a function.
170          */
171         stw     %rp, HPPA_FRAME_CRP(%r3)
172         stw     %arg0, HPPA_FRAME_ARG(0)(%r3)
173         stw     %arg1, HPPA_FRAME_ARG(1)(%r3)
174         stw     %arg2, HPPA_FRAME_ARG(2)(%r3)
175         stw     %arg3, HPPA_FRAME_ARG(3)(%r3)
176         /* 0(%r3) is filled with the saved %r3 above */
177         stw     %ret0, 4(%r3)
178         stw     %ret1, 8(%r3)
180         /*
181          * The linker PLT stub loads %r20 with (GOT - 8) for
182          * the object that needs binding done.  The second entry
183          * of the GOT is reserved for the dynamic linker's use,
184          * and we previously stashed the object's Obj_Entry *
185          * there.
186          */
187         ldw     12(%r20), %arg0
189         /*
190          * The linker shared-library call stub loads %r19 from
191          * the shared linkage member of the PLT entry.  We 
192          * previously stashed the reloff of the relocation there.
193          */
194         copy    %r19, %arg1
196         /*
197          * The linker PLT stub loads %r21 with the fixup_ltp
198          * word in itself.  We previously stashed our %r19
199          * value there.
200          */
201         bl      _rtld_bind, %rp
202         copy    %r21, %r19
204         /*
205          * Our hppa version of _rtld_bind returns to us the
206          * address of the PLT entry that it fixed up.  Load
207          * the function address and shared linkage for the
208          * newly bound function.
209          */
210         ldw     0(%ret0), %r21
211         ldw     4(%ret0), %r19
213         /* Restore registers saved above. */
214         ldw     HPPA_FRAME_CRP(%r3), %rp
215         ldw     HPPA_FRAME_ARG(0)(%r3), %arg0
216         ldw     HPPA_FRAME_ARG(1)(%r3), %arg1
217         ldw     HPPA_FRAME_ARG(2)(%r3), %arg2
218         ldw     HPPA_FRAME_ARG(3)(%r3), %arg3
219         ldw     4(%r3), %ret0
220         ldw     8(%r3), %ret1
222         /* End stack calling convention. */
223         ldo     HPPA_FRAME_SIZE(%r3), %sp
224         ldw,mb  -HPPA_FRAME_SIZE(%sp), %r3
226         /* Transfer to the function. */
227         bv      %r0(%r21)
228         nop
229 EXIT(_rtld_bind_start)