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 directly from 33 * exec() upon invocation of a dynamically linked program specifying ld.so 34 * as its interpreter. 35 * 36 * On entry, the stack appears as: 37 * 38 * !_______________________! high addresses 39 * ! 0 word ! 40 * !_______________________! 41 * ! ! 42 * ! Information ! 43 * ! Block ! 44 * ! (size varies) ! 45 * !_______________________! 46 * ! Auxiliary ! 47 * ! vector ! 48 * ! 2 word entries ! 49 * ! ! 50 * !_______________________! 51 * ! 0 word ! 52 * !_______________________! 53 * ! Environment ! 54 * ! pointers ! 55 * ! ... ! 56 * ! (one word each) ! 57 * !_______________________! 58 * ! 0 word ! 59 * !_______________________! 60 * ! Argument ! low addresses 61 * ! pointers ! 62 * ! Argc words ! 63 * !_______________________! 64 * ! ! 65 * ! Argc ! 66 * !_______________________! <- %sp + STACK_BIAS + WINDOWSIZE 67 * ! ! 68 * ! Window save area ! 69 * !_______________________! <- %sp + STACK_BIAS 70 */ 71 72#if defined(lint) 73 74extern unsigned long _setup(); 75extern void atexit_fini(); 76 77void 78main() 79{ 80 (void) _setup(); 81 atexit_fini(); 82} 83 84#else 85 86#include <sys/asm_linkage.h> 87#include <sys/param.h> 88#include <link.h> 89 90 .file "boot.s" 91 .seg ".text" 92 .global _rt_boot, _setup, atexit_fini 93 .type _rt_boot, #function 94 .align 4 95 96! Entry vector 97! +0: normal start 98! +4: normal start 99! +8: alias start (frame exists) XX64 what's this for? 100 101_rt_boot: 102 nop 103 ba,a _elf_start 104 ba,a _alias_start 105 106! Start up routines 107 108_elf_start: 109 110! Create a stack frame, perform PIC set up. We have 111! to determine a bunch of things from our "environment" and 112! construct an Elf64_Boot attribute value vector. 113 114 save %sp, -SA(MINFRAME + (EB_MAX * 16)), %sp 115 116_alias_start: 117 1181: ! PIC prologue 119 call 2f 120 sethi %hh(_GLOBAL_OFFSET_TABLE_ + (. - 1b)), %g1 1212: or %g1, %hm(_GLOBAL_OFFSET_TABLE_ + (. - 1b)), %g1 122 sllx %g1, 32, %g5 123 sethi %lm(_GLOBAL_OFFSET_TABLE_ + (. - 1b)), %l7 124 or %l7, %lo(_GLOBAL_OFFSET_TABLE_ + (. - 1b)), %l7 125 or %g5, %l7, %l7 126 add %l7, %o7, %l7 ! finish PIC prologue 127 128! %fp points to the root of our ELF bootstrap vector, use it to construct 129! the vector and send it to _setup. 130! 131! The resulting Elf64_Boot vector looks like this: 132! 133! Offset Contents 134! +0x0 EB_ARGV 135! +0x8 argv[] 136! +0x10 EB_ENVP 137! +0x18 envp[] 138! +0x20 EB_AUXV 139! +0x28 auxv[] 140! +0x30 EB_NULL 141 142 add %sp, STACK_BIAS + SA(MINFRAME), %o0 143 ! &eb[0] == %sp + frame size 144 mov EB_ARGV, %l0 ! code for this entry 145 stx %l0, [%o0] ! store it 146 add %fp, WINDOWSIZE + 8 + STACK_BIAS, %l0 147 ! argument vector 148 stx %l0, [%o0 + 0x8] ! store that 149 ldx [%fp + WINDOWSIZE + STACK_BIAS], %l1 150 ! get argument count (argc) 151 inc %l1 ! account for last element of 0 152 sllx %l1, 3, %l1 ! multiply by 8 153 add %l0, %l1, %l0 ! and get address of first env ptr 154 stx %l0, [%o0 + 0x18] ! store it in the vector 155 mov EB_ENVP, %l1 ! code for environment base 156 stx %l1, [%o0 + 0x10] ! store it 157 mov EB_AUXV, %l1 ! get code for auxiliary vector 158 stx %l1, [%o0 + 0x20] ! store it 159 1603: ldx [%l0], %l1 ! get an entry 161 brnz,pt %l1, 3b ! if not at end, go back and look again 162 add %l0, 8, %l0 ! incrementing pointer in delay 163 stx %l0, [%o0 + 0x28] ! store aux vector pointer 164 165 mov EB_NULL, %l0 ! set up for the last pointer 166 stx %l0, [%o0 + 0x30] ! and store it 167 mov %g0, %g2 ! clear globals 168 mov %g0, %g3 169 170! Call _setup. Two arguments, the ELF bootstrap vector and our (unrelocated) 171! _DYNAMIC address. The _DYNAMIC address is located in entry 0 of the GOT 172 173 174 call _setup ! call it 175 ldx [%l7], %o1 176 177! On return, give callee the exit function in %g1, and jump to the 178! target program, clearing out the reserved globals as we go. 179 180 ldx [%l7 + atexit_fini], %g1! get function address 181 restore %o0, %g0, %l1 ! release frame 182 jmpl %l1, %g0 ! call main program 183 mov %g0, %g4 ! clear one last global in delay 184 185 .size _rt_boot, . - _rt_boot 186#endif 187