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 2004 Sun Microsystems, Inc.  All rights reserved.
  28  * Use is subject to license terms.
  29  */
  30 
  31 /*
  32  * Bootstrap routine for run-time linker.
  33  * We get control from exec which has loaded our text and
  34  * data into the process' address space and created the process
  35  * stack.
  36  *
  37  * On entry, the process stack looks like this:
  38  *
  39  *      #                       # <- %esp
  40  *      #_______________________#  high addresses
  41  *      #       strings         #
  42  *      #_______________________#
  43  *      #       0 word          #
  44  *      #_______________________#
  45  *      #       Auxiliary       #
  46  *      #       entries         #
  47  *      #       ...             #
  48  *      #       (size varies)   #
  49  *      #_______________________#
  50  *      #       0 word          #
  51  *      #_______________________#
  52  *      #       Environment     #
  53  *      #       pointers        #
  54  *      #       ...             #
  55  *      #       (one word each) #
  56  *      #_______________________#
  57  *      #       0 word          #
  58  *      #_______________________#
  59  *      #       Argument        # low addresses
  60  *      #       pointers        #
  61  *      #       Argc words      #
  62  *      #_______________________#
  63  *      #       argc            #
  64  *      #_______________________# <- %ebp
  65  *
  66  *
  67  * We must calculate the address at which ld.so was loaded,
  68  * find the addr of the dynamic section of ld.so, of argv[0], and  of
  69  * the process' environment pointers - and pass the thing to _setup
  70  * to handle.  We then call _rtld - on return we jump to the entry
  71  * point for the a.out.
  72  */
  73 
  74 #if     defined(lint)
  75 
  76 extern  unsigned long   _setup();
  77 extern  void            atexit_fini();
  78 void
  79 main()
  80 {
  81         (void) _setup();
  82         atexit_fini();
  83 }
  84 
  85 #else
  86 
  87 #include        <link.h>
  88 
  89         .file   "boot.s"
  90         .text
  91         .globl  _rt_boot
  92         .globl  _setup
  93         .globl  _GLOBAL_OFFSET_TABLE_
  94         .type   _rt_boot,@function
  95         .align  4
  96 
  97         / init is called from the _init symbol in the CRT, however .init_array
  98         / are called "naturally" from call_init.  Because of that, we need the
  99         / stack aligned here so that initializers called via _array sections may
 100         / safely use SIMD instructions.
 101 _rt_alias:
 102         jmp     .get_ip                 / in case we were invoked from libc.so
 103 _rt_boot:
 104         movl    %esp,%ebp               / save for referencing args
 105         subl    $EB_MAX_SIZE32,%esp     / make room for a max sized boot vector
 106         andl    $-16,%esp
 107         subl    $8,%esp
 108         movl    %esp,%esi               / use esi as a pointer to &eb[0]
 109         movl    $EB_ARGV,0(%esi)        / set up tag for argv
 110         leal    4(%ebp),%eax            / get address of argv
 111         movl    %eax,4(%esi)            / put after tag
 112         movl    $EB_ENVP,8(%esi)        / set up tag for envp
 113         movl    (%ebp),%eax             / get # of args
 114         addl    $2,%eax                 / one for the zero & one for argc
 115         leal    (%ebp,%eax,4),%edi      / now points past args & @ envp
 116         movl    %edi,12(%esi)           / set envp
 117 .L0:    addl    $4,%edi                 / next
 118         cmpl    $0,-4(%edi)             / search for 0 at end of env
 119         jne     .L0
 120         movl    $EB_AUXV,16(%esi)       / set up tag for auxv
 121         movl    %edi,20(%esi)           / point to auxv
 122         movl    $EB_NULL,24(%esi)       / set up NULL tag
 123 .get_ip:
 124         call    .L1                     / only way to get IP into a register
 125 .L1:
 126         popl    %ebx                    / pop the IP we just "pushed"
 127         addl    $_GLOBAL_OFFSET_TABLE_+[.-.L1],%ebx
 128         pushl   (%ebx)                  / address of dynamic structure
 129         pushl   %esi                    / push &eb[0]
 130 
 131         call    _setup@PLT              / _setup(&eb[0], _DYNAMIC)
 132         movl    %ebp,%esp               / release stack frame
 133 
 134         movl    atexit_fini@GOT(%ebx), %edx
 135         jmp     *%eax                   / transfer control to a.out
 136         .size   _rt_boot,.-_rt_boot
 137 
 138 #endif