192195Sjake/* $NetBSD: rtld_start.S,v 1.5 2001/08/14 22:17:48 eeh Exp $ */ 292195Sjake 392195Sjake/*- 492195Sjake * Copyright (c) 2001 Jake Burkholder. 592195Sjake * Copyright (c) 2000 Eduardo Horvath. 692195Sjake * Copyright (c) 1999 The NetBSD Foundation, Inc. 792195Sjake * All rights reserved. 892195Sjake * 992195Sjake * This code is derived from software contributed to The NetBSD Foundation 1092195Sjake * by Christos Zoulas and Paul Kranenburg. 1192195Sjake * 1292195Sjake * Redistribution and use in source and binary forms, with or without 1392195Sjake * modification, are permitted provided that the following conditions 1492195Sjake * are met: 1592195Sjake * 1. Redistributions of source code must retain the above copyright 1692195Sjake * notice, this list of conditions and the following disclaimer. 1792195Sjake * 2. Redistributions in binary form must reproduce the above copyright 1892195Sjake * notice, this list of conditions and the following disclaimer in the 1992195Sjake * documentation and/or other materials provided with the distribution. 2092195Sjake * 3. All advertising materials mentioning features or use of this software 2192195Sjake * must display the following acknowledgement: 2292195Sjake * This product includes software developed by the NetBSD 2392195Sjake * Foundation, Inc. and its contributors. 2492195Sjake * 4. Neither the name of The NetBSD Foundation nor the names of its 2592195Sjake * contributors may be used to endorse or promote products derived 2692195Sjake * from this software without specific prior written permission. 2792195Sjake * 2892195Sjake * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 2992195Sjake * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 3092195Sjake * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 3192195Sjake * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 3292195Sjake * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 3392195Sjake * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 3492195Sjake * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 3592195Sjake * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 3692195Sjake * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 3792195Sjake * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3892195Sjake * POSSIBILITY OF SUCH DAMAGE. 3992195Sjake * 4092195Sjake * $FreeBSD$ 4192195Sjake */ 4292195Sjake 4392195Sjake#include <machine/asm.h> 4492195Sjake 4592195Sjake/* 4692195Sjake * ELF: 4792195Sjake * On startup the stack should contain 16 extended word register save 4892195Sjake * area, followed by the arg count, etc. 4992195Sjake */ 5092195Sjake 5192195SjakeENTRY(.rtld_start) 5292195Sjake clr %fp 5392195Sjake mov %o0, %l0 5492195Sjake mov %o3, %l1 5592195Sjake 5692195Sjake sub %sp, 16, %sp 5792195Sjake add %sp, SPOFF + CCFSZ + 0x0, %o1 5892195Sjake call _rtld 5992195Sjake add %sp, SPOFF + CCFSZ + 0x8, %o2 6092195Sjake 6192195Sjake ldx [%sp + SPOFF + CCFSZ + 0x0], %o1 6292195Sjake ldx [%sp + SPOFF + CCFSZ + 0x8], %o2 6392195Sjake add %sp, 16, %sp 6492195Sjake 6592195Sjake mov %l1, %o3 6692195Sjake jmp %o0 6792195Sjake mov %l0, %o0 68100265SjakeEND(.rtld_start) 6992195Sjake 70117211Sjake/* 71117211Sjake * Find the address of _DYNAMIC by disassembling a call instruction to it. 72117211Sjake * Binutils may not fill in the GOT as expected on other architectures. 73117211Sjake */ 74130661Stmm.weak _DYNAMIC 75117211Sjake 76130661StmmENTRY(rtld_dynamic_addr) 77117211Sjake save %sp, -CCFSZ, %sp 78117211Sjake call 1f 79117211Sjake nop 80117211Sjake call _DYNAMIC + 8 81117211Sjake1: lduw [%o7 + 8], %o0 82117211Sjake sll %o0, 2, %o0 83117211Sjake sra %o0, 0, %o0 84117211Sjake ret 85117211Sjake restore %o0, %o7, %o0 86130661StmmEND(rtld_dynamic_addr) 87117211Sjake 8892195Sjake /* 8992195Sjake * We have two separate entry points to the runtime linker. 9092195Sjake * I'm implementing this following the SPARC v9 ABI spec. 9192195Sjake * 9292195Sjake * _rtld_bind_start_0(x, y) is called from .PLT0, and is used for 9392195Sjake * PLT entries above 32768. 9492195Sjake * 9592195Sjake * _rtld_bind_start_1(x, y) is called from .PLT1, and is used for 9692195Sjake * PLT entries below 32768. 9792195Sjake * 9892195Sjake * The first two entries of PLT2 contain the xword object pointer. 9992195Sjake * 100115396Skan * These routines are called with two longword arguments, 10192195Sjake * x and y. To calculate the address of the entry, 10292195Sjake * _rtld_bind_start_1(x, y) does: 10392195Sjake * 10492195Sjake * n = x >> 15; 10592195Sjake * 106107071Stmm * and _rtld_bind_start_0(x, y) should do, according to the SCD: 10792195Sjake * 108107071Stmm * i = x - y - 1048596; 10992195Sjake * n = 32768 + (i/5120)*160 + (i%5120)/24; 11092195Sjake * 111107071Stmm * Note that the number of 1048596 from above is incorrect; rather, 112107071Stmm * we need to use HIPLTOFFS as defined below. 113107071Stmm * 11492195Sjake * Neither routine needs to issue a save since it's already been 11592195Sjake * done in the PLT entry. 11692195Sjake */ 11792195Sjake 118107071Stmm#define NPLTLOSLOTS 32768 119107071Stmm#define PLTSLOTSZ 32 120107071Stmm/* 121107071Stmm * - 16 to compensate for the difference of the positions of the jumps that 122107071Stmm * generate the arguments in .PLT0 and the high plt entry. 123107071Stmm */ 124107071Stmm#define HIPLTOFFS (NPLTLOSLOTS * PLTSLOTSZ - 16) 125107071Stmm 12692195SjakeENTRY(_rtld_bind_start_0) 127107071Stmm sethi %hi(HIPLTOFFS), %l1 128107071Stmm or %l1, %lo(HIPLTOFFS), %l1 12992195Sjake sub %o0, %o1, %l0 /* x - y */ 130107071Stmm sub %l0, %l1, %l0 /* i = x - y - HIPLTOFFS */ 131107071Stmm sethi %hi(5120), %l7 132107071Stmm sdivx %l0, %l7, %l1 /* Calculate i / 5120 */ 133107071Stmm mulx %l1, %l7, %l3 134107071Stmm sub %l0, %l3, %l2 /* And i % 5120 */ 135107071Stmm mulx %l1, 160, %l5 /* (i / 5120) * 160 */ 136107071Stmm sdivx %l2, 24, %l4 /* (i % 5120) / 24 */ 137107071Stmm sethi %hi(NPLTLOSLOTS), %l6 138107071Stmm add %l4, %l5, %l4 /* (i / 5120) * 160 + (i % 5120) / 24 */ 139107071Stmm add %l4, %l6, %l4 /* + NPLTLOSLOTS */ 140107071Stmm sub %l4, 4, %l4 /* XXX: 4 entries are reserved */ 141115396Skan 142107071Stmm sllx %l4, 1, %l5 /* Each element is an Elf_Rela which */ 143107071Stmm add %l5, %l4, %l4 /* is 3 longwords or 24 bytes. */ 144107071Stmm sllx %l4, 3, %l4 /* So multiply by 24. */ 14592195Sjake 14692195Sjake ldx [%o1 + (10*4)], %o0 /* Load object pointer from PLT2 */ 14792195Sjake 14892195Sjake call _rtld_bind /* Call _rtld_bind(obj, offset) */ 149107071Stmm mov %l4, %o1 15092195Sjake 15192195Sjake jmp %o0 /* return value == function address */ 15292195Sjake restore /* Dump our stack frame */ 153100265SjakeEND(_rtld_bind_start_0) 154115396Skan 15592195SjakeENTRY(_rtld_bind_start_1) 15692195Sjake srax %o0, 15, %o2 /* %o0 is the index to our PLT slot */ 15792195Sjake sub %o2, 4, %o2 /* XXX: 4 entries are reserved */ 158115396Skan 15992195Sjake sllx %o2, 1, %o3 /* Each element is an Elf_Rela which */ 16092195Sjake add %o3, %o2, %o2 /* is 3 longwords or 24 bytes. */ 16192195Sjake sllx %o2, 3, %o2 /* So multiply by 24. */ 162115396Skan 16392195Sjake ldx [%o1 + 8], %o0 /* The object pointer is at [%o1 + 8] */ 164115396Skan 16592195Sjake call _rtld_bind /* Call _rtld_bind(obj, offset) */ 16692195Sjake mov %o2, %o1 16792195Sjake 16892195Sjake jmp %o0 /* return value == function address */ 16992195Sjake restore /* Dump our stack frame */ 170100265SjakeEND(_rtld_bind_start_1) 171