Home | History | Annotate | Line # | Download | only in hppa
rtld_start.S revision 1.13
      1 /*	$NetBSD: rtld_start.S,v 1.13 2020/05/10 06:42:38 skrll Exp $	*/
      2 
      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  */
     31 
     32 #include <machine/asm.h>
     33 #include <machine/frame.h>
     34 
     35 	.import _GLOBAL_OFFSET_TABLE_
     36 
     37 ENTRY($rtld_start,HPPA_FRAME_SIZE)
     38 
     39 	/* Start stack calling convention. */
     40 	copy	%r3, %r1
     41 	copy	%sp, %r3
     42 	stw,ma	%r1, HPPA_FRAME_SIZE(%sp)
     43 
     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)
     50 
     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 	 */
     57 
     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
     62 
     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
     70 
     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
     80 
     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
     87 
     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)
     96 
     97 	/* Call _rtld, copying relocbase into arg1. */
     98 	bl	_rtld, %rp
     99 	copy	%r4, %arg1		; %arg1 = relocbase
    100 
    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
    106 
    107 	/* End stack calling convention. */
    108 	ldo	HPPA_FRAME_SIZE(%r3), %sp
    109 	ldw,mb	-HPPA_FRAME_SIZE(%sp), %r3
    110 
    111 	/* Go for it. */
    112 	bv	%r0(%ret0)
    113 	copy	%r0, %rp
    114 EXIT($rtld_start)
    115 
    116 /*
    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)
    121 
    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)
    127 
    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 	 */
    133 
    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
    138 
    139 	stw	%arg0, -8(%arg1)
    140 	bv	%r0(%rp)
    141 	stw	%r19, -4(%arg1)
    142 EXIT(__rtld_setup_hppa_pltgot)
    143 
    144 /*
    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  */
    149 
    150 /*
    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  */
    155 
    156 	bl	_rtld_bind, %rp
    157 
    158 ENTRY(_rtld_bind_start,HPPA_FRAME_SIZE)
    159 
    160 	/* Start stack calling convention.  */
    161 	copy	%r3, %r1
    162 	copy	%sp, %r3
    163 
    164 	stw,ma	%r1, HPPA_FRAME_SIZE(%sp)
    165 
    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 */
    185 
    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
    193 
    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
    200 
    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
    207 
    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
    215 
    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 */
    225 
    226 	/* End stack calling convention. */
    227 	ldo	HPPA_FRAME_SIZE(%r3), %sp
    228 	ldw,mb	-HPPA_FRAME_SIZE(%sp), %r3
    229 
    230 	/* Transfer to the function. */
    231 	bv	%r0(%r21)
    232 	nop
    233 EXIT(_rtld_bind_start)
    234