/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 1988 AT&T * All Rights Reserved * * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Bootstrap routine for ld.so. Control arrives here directly from * exec() upon invocation of a dynamically linked program specifying ld.so * as its interpreter. * * On entry, the stack appears as: * * !_______________________! high addresses * ! 0 word ! * !_______________________! * ! ! * ! Information ! * ! Block ! * ! (size varies) ! * !_______________________! * ! Auxiliary ! * ! vector ! * ! 2 word entries ! * ! ! * !_______________________! * ! 0 word ! * !_______________________! * ! Environment ! * ! pointers ! * ! ... ! * ! (one word each) ! * !_______________________! * ! 0 word ! * !_______________________! * ! Argument ! low addresses * ! pointers ! * ! Argc words ! * !_______________________! * ! ! * ! Argc ! * !_______________________! <- %sp + STACK_BIAS + WINDOWSIZE * ! ! * ! Window save area ! * !_______________________! <- %sp + STACK_BIAS */ #if defined(lint) extern unsigned long _setup(); extern void atexit_fini(); void main() { (void) _setup(); atexit_fini(); } #else #include #include #include .file "boot.s" .seg ".text" .global _rt_boot, _setup, atexit_fini .type _rt_boot, #function .align 4 ! Entry vector ! +0: normal start ! +4: normal start ! +8: alias start (frame exists) XX64 what's this for? _rt_boot: nop ba,a _elf_start ba,a _alias_start ! Start up routines _elf_start: ! Create a stack frame, perform PIC set up. We have ! to determine a bunch of things from our "environment" and ! construct an Elf64_Boot attribute value vector. save %sp, -SA(MINFRAME + (EB_MAX * 16)), %sp _alias_start: 1: ! PIC prologue call 2f sethi %hh(_GLOBAL_OFFSET_TABLE_ + (. - 1b)), %g1 2: or %g1, %hm(_GLOBAL_OFFSET_TABLE_ + (. - 1b)), %g1 sllx %g1, 32, %g5 sethi %lm(_GLOBAL_OFFSET_TABLE_ + (. - 1b)), %l7 or %l7, %lo(_GLOBAL_OFFSET_TABLE_ + (. - 1b)), %l7 or %g5, %l7, %l7 add %l7, %o7, %l7 ! finish PIC prologue ! %fp points to the root of our ELF bootstrap vector, use it to construct ! the vector and send it to _setup. ! ! The resulting Elf64_Boot vector looks like this: ! ! Offset Contents ! +0x0 EB_ARGV ! +0x8 argv[] ! +0x10 EB_ENVP ! +0x18 envp[] ! +0x20 EB_AUXV ! +0x28 auxv[] ! +0x30 EB_NULL add %sp, STACK_BIAS + SA(MINFRAME), %o0 ! &eb[0] == %sp + frame size mov EB_ARGV, %l0 ! code for this entry stx %l0, [%o0] ! store it add %fp, WINDOWSIZE + 8 + STACK_BIAS, %l0 ! argument vector stx %l0, [%o0 + 0x8] ! store that ldx [%fp + WINDOWSIZE + STACK_BIAS], %l1 ! get argument count (argc) inc %l1 ! account for last element of 0 sllx %l1, 3, %l1 ! multiply by 8 add %l0, %l1, %l0 ! and get address of first env ptr stx %l0, [%o0 + 0x18] ! store it in the vector mov EB_ENVP, %l1 ! code for environment base stx %l1, [%o0 + 0x10] ! store it mov EB_AUXV, %l1 ! get code for auxiliary vector stx %l1, [%o0 + 0x20] ! store it 3: ldx [%l0], %l1 ! get an entry brnz,pt %l1, 3b ! if not at end, go back and look again add %l0, 8, %l0 ! incrementing pointer in delay stx %l0, [%o0 + 0x28] ! store aux vector pointer mov EB_NULL, %l0 ! set up for the last pointer stx %l0, [%o0 + 0x30] ! and store it mov %g0, %g2 ! clear globals mov %g0, %g3 ! Call _setup. Two arguments, the ELF bootstrap vector and our (unrelocated) ! _DYNAMIC address. The _DYNAMIC address is located in entry 0 of the GOT call _setup ! call it ldx [%l7], %o1 ! On return, give callee the exit function in %g1, and jump to the ! target program, clearing out the reserved globals as we go. ldx [%l7 + atexit_fini], %g1! get function address restore %o0, %g0, %l1 ! release frame jmpl %l1, %g0 ! call main program mov %g0, %g4 ! clear one last global in delay .size _rt_boot, . - _rt_boot #endif