1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22/* 23 * Copyright (c) 1988 AT&T 24 * All Rights Reserved 25 * 26 * 27 * Copyright (c) 1998 by Sun Microsystems, Inc. 28 * All rights reserved. 29 */ 30 31#pragma ident "%Z%%M% %I% %E% SMI" 32 33/* 34 * Bootstrap routine for ld.so. Control arrives here directly from 35 * exec() upon invocation of a dynamically linked program specifying ld.so 36 * as its interpreter. 37 * 38 * On entry, the stack appears as: 39 * 40 * !_______________________! high addresses 41 * ! 0 word ! 42 * !_______________________! 43 * ! ! 44 * ! Information ! 45 * ! Block ! 46 * ! (size varies) ! 47 * !_______________________! 48 * ! Auxiliary ! 49 * ! vector ! 50 * ! 2 word entries ! 51 * ! ! 52 * !_______________________! 53 * ! 0 word ! 54 * !_______________________! 55 * ! Environment ! 56 * ! pointers ! 57 * ! ... ! 58 * ! (one word each) ! 59 * !_______________________! 60 * ! 0 word ! 61 * !_______________________! 62 * ! Argument ! low addresses 63 * ! pointers ! 64 * ! Argc words ! 65 * !_______________________! 66 * ! ! 67 * ! Argc ! 68 * !_______________________! <- %sp + STACK_BIAS + WINDOWSIZE 69 * ! ! 70 * ! Window save area ! 71 * !_______________________! <- %sp + STACK_BIAS 72 */ 73 74#if defined(lint) 75 76extern unsigned long _setup(); 77extern void atexit_fini(); 78 79void 80main() 81{ 82 (void) _setup(); 83 atexit_fini(); 84} 85 86#else 87 88#include <sys/asm_linkage.h> 89#include <sys/param.h> 90#include <link.h> 91 92 .file "%M%" 93 .seg ".text" 94 .global _rt_boot, _setup, atexit_fini 95 .type _rt_boot, #function 96 .align 4 97 98! Entry vector 99! +0: normal start 100! +4: normal start 101! +8: alias start (frame exists) XX64 what's this for? 102 103_rt_boot: 104 nop 105 ba,a _elf_start 106 ba,a _alias_start 107 108! Start up routines 109 110_elf_start: 111 112! Create a stack frame, perform PIC set up. We have 113! to determine a bunch of things from our "environment" and 114! construct an Elf64_Boot attribute value vector. 115 116 save %sp, -SA(MINFRAME + (EB_MAX * 16)), %sp 117 118_alias_start: 119 1201: ! PIC prologue 121 call 2f 122 sethi %hh(_GLOBAL_OFFSET_TABLE_ + (. - 1b)), %g1 1232: or %g1, %hm(_GLOBAL_OFFSET_TABLE_ + (. - 1b)), %g1 124 sllx %g1, 32, %g5 125 sethi %lm(_GLOBAL_OFFSET_TABLE_ + (. - 1b)), %l7 126 or %l7, %lo(_GLOBAL_OFFSET_TABLE_ + (. - 1b)), %l7 127 or %g5, %l7, %l7 128 add %l7, %o7, %l7 ! finish PIC prologue 129 130! %fp points to the root of our ELF bootstrap vector, use it to construct 131! the vector and send it to _setup. 132! 133! The resulting Elf64_Boot vector looks like this: 134! 135! Offset Contents 136! +0x0 EB_ARGV 137! +0x8 argv[] 138! +0x10 EB_ENVP 139! +0x18 envp[] 140! +0x20 EB_AUXV 141! +0x28 auxv[] 142! +0x30 EB_NULL 143 144 add %sp, STACK_BIAS + SA(MINFRAME), %o0 145 ! &eb[0] == %sp + frame size 146 mov EB_ARGV, %l0 ! code for this entry 147 stx %l0, [%o0] ! store it 148 add %fp, WINDOWSIZE + 8 + STACK_BIAS, %l0 149 ! argument vector 150 stx %l0, [%o0 + 0x8] ! store that 151 ldx [%fp + WINDOWSIZE + STACK_BIAS], %l1 152 ! get argument count (argc) 153 inc %l1 ! account for last element of 0 154 sllx %l1, 3, %l1 ! multiply by 8 155 add %l0, %l1, %l0 ! and get address of first env ptr 156 stx %l0, [%o0 + 0x18] ! store it in the vector 157 mov EB_ENVP, %l1 ! code for environment base 158 stx %l1, [%o0 + 0x10] ! store it 159 mov EB_AUXV, %l1 ! get code for auxiliary vector 160 stx %l1, [%o0 + 0x20] ! store it 161 1623: ldx [%l0], %l1 ! get an entry 163 brnz,pt %l1, 3b ! if not at end, go back and look again 164 add %l0, 8, %l0 ! incrementing pointer in delay 165 stx %l0, [%o0 + 0x28] ! store aux vector pointer 166 167 mov EB_NULL, %l0 ! set up for the last pointer 168 stx %l0, [%o0 + 0x30] ! and store it 169 mov %g0, %g2 ! clear globals 170 mov %g0, %g3 171 172! Call _setup. Two arguments, the ELF bootstrap vector and our (unrelocated) 173! _DYNAMIC address. The _DYNAMIC address is located in entry 0 of the GOT 174 175 176 call _setup ! call it 177 ldx [%l7], %o1 178 179! On return, give callee the exit function in %g1, and jump to the 180! target program, clearing out the reserved globals as we go. 181 182 ldx [%l7 + atexit_fini], %g1! get function address 183 restore %o0, %g0, %l1 ! release frame 184 jmpl %l1, %g0 ! call main program 185 mov %g0, %g4 ! clear one last global in delay 186 187 .size _rt_boot, . - _rt_boot 188#endif 189