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#pragma ident "%Z%%M% %I% %E% SMI" 31 32/* 33 * Bootstrap routine for ld.so. Control arrives here either directly from 34 * exec() upon invocation of a dynamically linked program specifying ld.so 35 * as its interpreter, or from the "a.out compatibility ld.so". Entry 36 * vector at "_rt_boot" used to discriminate between the two. 37 * 38 * On entry, the stack appears as: 39 * 40 * !_______________________! high addresses 41 * ! ! 42 * ! Information ! 43 * ! Block ! 44 * ! (size varies) ! 45 * !_______________________! 46 * ! 0 word ! 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 +64 69 * ! ! 70 * ! Window save area ! 71 * !_______________________! <- %sp 72 * 73 * In the case of being invoked from the a.out compatibility ld.so, the stack 74 * has the appearance above but also several frames pushed by the compatibility 75 * routine. An "elf_boot" structure is available in %o1 on entry, which 76 * has been "pre-evaluated" to hold much of the information needed from the 77 * original stack frame -- we pass this directly into the main portion of the 78 * ld.so bootstrap. 79 */ 80 81#if defined(lint) 82 83extern unsigned long _setup(); 84extern void atexit_fini(); 85 86void 87main() 88{ 89 (void) _setup(); 90 atexit_fini(); 91} 92 93#else 94 95#include <sys/asm_linkage.h> 96#include <sys/param.h> 97#include <link.h> 98 99 .file "boot.s" 100 .seg ".text" 101 .global _rt_boot, _setup, atexit_fini 102 .type _rt_boot, #function 103 .align 4 104 105! Entry vector 106! +0: normal start 107! +4: compatibility start 108! +8: alias start (frame exists) 109 110_rt_boot: 111 ba,a _elf_start 112 ba,a _aout_start 113 ba,a _alias_start 114 115! Start up routines -- the aout_start will have a pointer in %o0 that we'll 116! want to save -- the elf can be zeroed. 117 118_elf_start: 119 clr %o0 ! 0 in %o0 == ELF 120_aout_start: ! (falls through) 121 122! Create a stack frame, perform PIC set up. If we're a "normal" start, we have 123! to determine a bunch of things from our "environment" and construct an ELF 124! boot attribute value vector. Otherwise, it's already been done and we can 125! skip it. 126 127 save %sp, -SA(MINFRAME + (EB_MAX * 8)), %sp 128_alias_start: 1291: ! PIC prologue 130 call 2f 131 sethi %hi(_GLOBAL_OFFSET_TABLE_ + (. - 1b)), %l7 1322: 133 or %l7, %lo(_GLOBAL_OFFSET_TABLE_ + (. - 1b)), %l7 134 135! If %i0 (was %o0) is non-zero, we're in compatibility and we can 136! skip construction of the ELF boot attribute vector. 137 138 addcc %i0, %g0, %o0 ! set condition codes 139 bne 1f ! if non-zero, skip setup 140 add %l7, %o7, %l7 ! finish PIC prologue 141 142! %fp points to the root of our ELF bootstrap vector, use it to construct 143! the vector and send it to _setup. 144 145 add %sp, SA(MINFRAME), %o0 ! &eb[0] == %sp + frame size 146 set EB_ARGV, %l0 ! code for this entry 147 st %l0, [%o0] ! store it 148 add %fp, 68, %l0 ! argument vector is at %fp+68 149 st %l0, [%o0 + 4] ! store that 150 ld [%fp + 64], %l1 ! get argument count 151 inc %l1 ! account for last element of 0 152 sll %l1, 2, %l1 ! multiply by 4 153 add %l0, %l1, %l0 ! and get address of first env ptr 154 st %l0, [%o0 + 12] ! store it in the vector 155 set EB_ENVP, %l1 ! code for environment base 156 st %l1, [%o0 + 8] ! store it 157 set EB_AUXV, %l1 ! get code for auxiliary vector 158 st %l1, [%o0 + 16] ! store it 1592: 160 ld [%l0], %l1 ! get an entry 161 tst %l1 ! are we at a "0" entry in environment? 162 bne 2b ! no, go back and look again 163 add %l0, 4, %l0 ! incrementing pointer in delay 164 st %l0, [%o0 + 20] ! store aux vector pointer 165 set EB_NULL, %l0 ! set up for the last pointer 166 st %l0, [%o0 + 24] ! and store it 167 168! Call _setup. Two arguments, the ELF bootstrap vector and our (unrelocated) 169! _DYNAMIC address. The _DYNAMIC address is located in entry 0 of the GOT 170 1711: 172 mov %g0, %g2 ! clear globals 173 mov %g0, %g3 174 call _setup ! call it 175 ld [%l7], %o1 ! 2nd parameter 176 177! On return, give callee the exit function in %g1, and either jump to the 178! target program (normal), or if return value of _setup is "0" we have 179! to return to the compatibility bootstrap. In either case, clear out 180! reserved globals. 181 182 ld [%l7 + atexit_fini], %g1! get function address 183 restore %o0, %g0, %l1 ! release frame 184 tst %l1 ! compatibility return? 185 be 1f ! yes, 186 mov %g0, %g4 ! but clear one last global in delay 187 jmpl %l1, %g0 ! call main program 188 nop 1891: 190 retl ! compatibility return 191 nop 192 193 .size _rt_boot, . - _rt_boot 194#endif 195