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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22/* 23 * Copyright (c) 1988 AT&T 24 * All Rights Reserved 25 * 26 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 27 * Use is subject to license terms. 28 */ 29#pragma ident "%Z%%M% %I% %E% SMI" 30 31/* 32 * Bootstrap routine for ld.so. Control arrives here either directly from 33 * exec() upon invocation of a dynamically linked program specifying ld.so 34 * as its interpreter, or from the "a.out compatibility ld.so". Entry 35 * vector at "_rt_boot" used to discriminate between the two. 36 * 37 * On entry, the stack appears as: 38 * 39 * !_______________________! high addresses 40 * ! ! 41 * ! Information ! 42 * ! Block ! 43 * ! (size varies) ! 44 * !_______________________! 45 * ! 0 word ! 46 * !_______________________! 47 * ! Auxiliary ! 48 * ! vector ! 49 * ! 2 word entries ! 50 * ! ! 51 * !_______________________! 52 * ! 0 word ! 53 * !_______________________! 54 * ! Environment ! 55 * ! pointers ! 56 * ! ... ! 57 * ! (one word each) ! 58 * !_______________________! 59 * ! 0 word ! 60 * !_______________________! 61 * ! Argument ! low addresses 62 * ! pointers ! 63 * ! Argc words ! 64 * !_______________________! 65 * ! ! 66 * ! Argc ! 67 * !_______________________! <- %sp + 64 68 * ! ! 69 * ! Window save area ! 70 * !_______________________! <- %sp 71 * 72 * In the case of being invoked from the a.out compatibility ld.so, the stack 73 * has the appearance above but also several frames pushed by the compatibility 74 * routine. An "elf_boot" structure is available in %o1 on entry, which 75 * has been "pre-evaluated" to hold much of the information needed from the 76 * original stack frame -- we pass this directly into the main portion of the 77 * ld.so bootstrap. 78 */ 79 80#if defined(lint) 81 82extern unsigned long _setup(); 83extern void atexit_fini(); 84 85void 86main() 87{ 88 (void) _setup(); 89 atexit_fini(); 90} 91 92#else 93 94#include <sys/asm_linkage.h> 95#include <sys/param.h> 96#include <link.h> 97 98 .file "boot.s" 99 .seg ".text" 100 .global _rt_boot, _setup, atexit_fini 101 .type _rt_boot, #function 102 .align 4 103 104! Entry vector 105! +0: normal start 106! +4: compatibility start 107! +8: alias start (frame exists) 108 109_rt_boot: 110 ba,a _elf_start 111 ba,a _aout_start 112 ba,a _alias_start 113 114! Start up routines -- the aout_start will have a pointer in %o0 that we'll 115! want to save -- the elf can be zeroed. 116 117_elf_start: 118 clr %o0 ! 0 in %o0 == ELF 119_aout_start: ! (falls through) 120 121! Create a stack frame, perform PIC set up. If we're a "normal" start, we have 122! to determine a bunch of things from our "environment" and construct an ELF 123! boot attribute value vector. Otherwise, it's already been done and we can 124! skip it. 125 126 save %sp, -SA(MINFRAME + (EB_MAX * 8)), %sp 127_alias_start: 1281: ! PIC prologue 129 call 2f 130 sethi %hi(_GLOBAL_OFFSET_TABLE_ + (. - 1b)), %l7 1312: 132 or %l7, %lo(_GLOBAL_OFFSET_TABLE_ + (. - 1b)), %l7 133 134! If %i0 (was %o0) is non-zero, we're in compatibility and we can 135! skip construction of the ELF boot attribute vector. 136 137 addcc %i0, %g0, %o0 ! set condition codes 138 bne 1f ! if non-zero, skip setup 139 add %l7, %o7, %l7 ! finish PIC prologue 140 141! %fp points to the root of our ELF bootstrap vector, use it to construct 142! the vector and send it to _setup. 143 144 add %sp, SA(MINFRAME), %o0 ! &eb[0] == %sp + frame size 145 set EB_ARGV, %l0 ! code for this entry 146 st %l0, [%o0] ! store it 147 add %fp, 68, %l0 ! argument vector is at %fp+68 148 st %l0, [%o0 + 4] ! store that 149 ld [%fp + 64], %l1 ! get argument count 150 inc %l1 ! account for last element of 0 151 sll %l1, 2, %l1 ! multiply by 4 152 add %l0, %l1, %l0 ! and get address of first env ptr 153 st %l0, [%o0 + 12] ! store it in the vector 154 set EB_ENVP, %l1 ! code for environment base 155 st %l1, [%o0 + 8] ! store it 156 set EB_AUXV, %l1 ! get code for auxiliary vector 157 st %l1, [%o0 + 16] ! store it 1582: 159 ld [%l0], %l1 ! get an entry 160 tst %l1 ! are we at a "0" entry in environment? 161 bne 2b ! no, go back and look again 162 add %l0, 4, %l0 ! incrementing pointer in delay 163 st %l0, [%o0 + 20] ! store aux vector pointer 164 set EB_NULL, %l0 ! set up for the last pointer 165 st %l0, [%o0 + 24] ! and store it 166 167! Call _setup. Two arguments, the ELF bootstrap vector and our (unrelocated) 168! _DYNAMIC address. The _DYNAMIC address is located in entry 0 of the GOT 169 1701: 171 mov %g0, %g2 ! clear globals 172 mov %g0, %g3 173 call _setup ! call it 174 ld [%l7], %o1 ! 2nd parameter 175 176! On return, give callee the exit function in %g1, and either jump to the 177! target program (normal), or if return value of _setup is "0" we have 178! to return to the compatibility bootstrap. In either case, clear out 179! reserved globals. 180 181 ld [%l7 + atexit_fini], %g1! get function address 182 restore %o0, %g0, %l1 ! release frame 183 tst %l1 ! compatibility return? 184 be 1f ! yes, 185 mov %g0, %g4 ! but clear one last global in delay 186 jmpl %l1, %g0 ! call main program 187 nop 1881: 189 retl ! compatibility return 190 nop 191 192 .size _rt_boot, . - _rt_boot 193#endif 194