1*5d9d9091SRichard Lowe/* 2*5d9d9091SRichard Lowe * CDDL HEADER START 3*5d9d9091SRichard Lowe * 4*5d9d9091SRichard Lowe * The contents of this file are subject to the terms of the 5*5d9d9091SRichard Lowe * Common Development and Distribution License, Version 1.0 only 6*5d9d9091SRichard Lowe * (the "License"). You may not use this file except in compliance 7*5d9d9091SRichard Lowe * with the License. 8*5d9d9091SRichard Lowe * 9*5d9d9091SRichard Lowe * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*5d9d9091SRichard Lowe * or http://www.opensolaris.org/os/licensing. 11*5d9d9091SRichard Lowe * See the License for the specific language governing permissions 12*5d9d9091SRichard Lowe * and limitations under the License. 13*5d9d9091SRichard Lowe * 14*5d9d9091SRichard Lowe * When distributing Covered Code, include this CDDL HEADER in each 15*5d9d9091SRichard Lowe * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*5d9d9091SRichard Lowe * If applicable, add the following below this CDDL HEADER, with the 17*5d9d9091SRichard Lowe * fields enclosed by brackets "[]" replaced with your own identifying 18*5d9d9091SRichard Lowe * information: Portions Copyright [yyyy] [name of copyright owner] 19*5d9d9091SRichard Lowe * 20*5d9d9091SRichard Lowe * CDDL HEADER END 21*5d9d9091SRichard Lowe */ 22*5d9d9091SRichard Lowe/* 23*5d9d9091SRichard Lowe * Copyright (c) 1988 AT&T 24*5d9d9091SRichard Lowe * All Rights Reserved 25*5d9d9091SRichard Lowe * 26*5d9d9091SRichard Lowe * 27*5d9d9091SRichard Lowe * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 28*5d9d9091SRichard Lowe * Use is subject to license terms. 29*5d9d9091SRichard Lowe */ 30*5d9d9091SRichard Lowe 31*5d9d9091SRichard Lowe/* 32*5d9d9091SRichard Lowe * Bootstrap routine for run-time linker. 33*5d9d9091SRichard Lowe * We get control from exec which has loaded our text and 34*5d9d9091SRichard Lowe * data into the process' address space and created the process 35*5d9d9091SRichard Lowe * stack. 36*5d9d9091SRichard Lowe * 37*5d9d9091SRichard Lowe * On entry, the process stack looks like this: 38*5d9d9091SRichard Lowe * 39*5d9d9091SRichard Lowe * # # <- %esp 40*5d9d9091SRichard Lowe * #_______________________# high addresses 41*5d9d9091SRichard Lowe * # strings # 42*5d9d9091SRichard Lowe * #_______________________# 43*5d9d9091SRichard Lowe * # 0 word # 44*5d9d9091SRichard Lowe * #_______________________# 45*5d9d9091SRichard Lowe * # Auxiliary # 46*5d9d9091SRichard Lowe * # entries # 47*5d9d9091SRichard Lowe * # ... # 48*5d9d9091SRichard Lowe * # (size varies) # 49*5d9d9091SRichard Lowe * #_______________________# 50*5d9d9091SRichard Lowe * # 0 word # 51*5d9d9091SRichard Lowe * #_______________________# 52*5d9d9091SRichard Lowe * # Environment # 53*5d9d9091SRichard Lowe * # pointers # 54*5d9d9091SRichard Lowe * # ... # 55*5d9d9091SRichard Lowe * # (one word each) # 56*5d9d9091SRichard Lowe * #_______________________# 57*5d9d9091SRichard Lowe * # 0 word # 58*5d9d9091SRichard Lowe * #_______________________# 59*5d9d9091SRichard Lowe * # Argument # low addresses 60*5d9d9091SRichard Lowe * # pointers # 61*5d9d9091SRichard Lowe * # Argc words # 62*5d9d9091SRichard Lowe * #_______________________# 63*5d9d9091SRichard Lowe * # argc # 64*5d9d9091SRichard Lowe * #_______________________# <- %ebp 65*5d9d9091SRichard Lowe * 66*5d9d9091SRichard Lowe * 67*5d9d9091SRichard Lowe * We must calculate the address at which ld.so was loaded, 68*5d9d9091SRichard Lowe * find the addr of the dynamic section of ld.so, of argv[0], and of 69*5d9d9091SRichard Lowe * the process' environment pointers - and pass the thing to _setup 70*5d9d9091SRichard Lowe * to handle. We then call _rtld - on return we jump to the entry 71*5d9d9091SRichard Lowe * point for the executable. 72*5d9d9091SRichard Lowe */ 73*5d9d9091SRichard Lowe 74*5d9d9091SRichard Lowe#if defined(lint) 75*5d9d9091SRichard Lowe 76*5d9d9091SRichard Loweextern unsigned long _setup(); 77*5d9d9091SRichard Loweextern void atexit_fini(); 78*5d9d9091SRichard Lowevoid 79*5d9d9091SRichard Lowemain() 80*5d9d9091SRichard Lowe{ 81*5d9d9091SRichard Lowe (void) _setup(); 82*5d9d9091SRichard Lowe atexit_fini(); 83*5d9d9091SRichard Lowe} 84*5d9d9091SRichard Lowe 85*5d9d9091SRichard Lowe#else 86*5d9d9091SRichard Lowe 87*5d9d9091SRichard Lowe#include <link.h> 88*5d9d9091SRichard Lowe 89*5d9d9091SRichard Lowe .file "boot.s" 90*5d9d9091SRichard Lowe .text 91*5d9d9091SRichard Lowe .globl _rt_boot 92*5d9d9091SRichard Lowe .globl _setup 93*5d9d9091SRichard Lowe .globl _GLOBAL_OFFSET_TABLE_ 94*5d9d9091SRichard Lowe .type _rt_boot,@function 95*5d9d9091SRichard Lowe .align 4 96*5d9d9091SRichard Lowe 97*5d9d9091SRichard Lowe / init is called from the _init symbol in the CRT, however .init_array 98*5d9d9091SRichard Lowe / are called "naturally" from call_init. Because of that, we need the 99*5d9d9091SRichard Lowe / stack aligned here so that initializers called via _array sections may 100*5d9d9091SRichard Lowe / safely use SIMD instructions. 101*5d9d9091SRichard Lowe_rt_alias: 102*5d9d9091SRichard Lowe jmp .get_ip / in case we were invoked from libc.so 103*5d9d9091SRichard Lowe_rt_boot: 104*5d9d9091SRichard Lowe movl %esp,%ebp / save for referencing args 105*5d9d9091SRichard Lowe subl $EB_MAX_SIZE32,%esp / make room for a max sized boot vector 106*5d9d9091SRichard Lowe andl $-16,%esp 107*5d9d9091SRichard Lowe subl $8,%esp 108*5d9d9091SRichard Lowe movl %esp,%esi / use esi as a pointer to &eb[0] 109*5d9d9091SRichard Lowe movl $EB_ARGV,0(%esi) / set up tag for argv 110*5d9d9091SRichard Lowe leal 4(%ebp),%eax / get address of argv 111*5d9d9091SRichard Lowe movl %eax,4(%esi) / put after tag 112*5d9d9091SRichard Lowe movl $EB_ENVP,8(%esi) / set up tag for envp 113*5d9d9091SRichard Lowe movl (%ebp),%eax / get # of args 114*5d9d9091SRichard Lowe addl $2,%eax / one for the zero & one for argc 115*5d9d9091SRichard Lowe leal (%ebp,%eax,4),%edi / now points past args & @ envp 116*5d9d9091SRichard Lowe movl %edi,12(%esi) / set envp 117*5d9d9091SRichard Lowe.L0: addl $4,%edi / next 118*5d9d9091SRichard Lowe cmpl $0,-4(%edi) / search for 0 at end of env 119*5d9d9091SRichard Lowe jne .L0 120*5d9d9091SRichard Lowe movl $EB_AUXV,16(%esi) / set up tag for auxv 121*5d9d9091SRichard Lowe movl %edi,20(%esi) / point to auxv 122*5d9d9091SRichard Lowe movl $EB_NULL,24(%esi) / set up NULL tag 123*5d9d9091SRichard Lowe.get_ip: 124*5d9d9091SRichard Lowe call .L1 / only way to get IP into a register 125*5d9d9091SRichard Lowe.L1: 126*5d9d9091SRichard Lowe popl %ebx / pop the IP we just "pushed" 127*5d9d9091SRichard Lowe addl $_GLOBAL_OFFSET_TABLE_+[.-.L1],%ebx 128*5d9d9091SRichard Lowe pushl (%ebx) / address of dynamic structure 129*5d9d9091SRichard Lowe pushl %esi / push &eb[0] 130*5d9d9091SRichard Lowe 131*5d9d9091SRichard Lowe call _setup@PLT / _setup(&eb[0], _DYNAMIC) 132*5d9d9091SRichard Lowe movl %ebp,%esp / release stack frame 133*5d9d9091SRichard Lowe 134*5d9d9091SRichard Lowe movl atexit_fini@GOT(%ebx), %edx 135*5d9d9091SRichard Lowe jmp *%eax / transfer control to the executable 136*5d9d9091SRichard Lowe .size _rt_boot,.-_rt_boot 137*5d9d9091SRichard Lowe 138*5d9d9091SRichard Lowe#endif 139