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 2004 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 /*
  28  * This gcrt1.o module is provided as the bare minimum required to build a
  29  * 32-bit profile executable with gcc -pg.  It is installed in /usr/lib
  30  * where it will be picked up by gcc, along with crti.o and crtn.o
  31  */
  32 
  33         .ident  "%Z%%M% %I%     %E% SMI"
  34 
  35         .file   "gcrt1.s"
  36 
  37         .globl  _start
  38         .globl  _etext
  39 
  40 /* global entities defined elsewhere but used here */
  41         .globl  main
  42         .globl  __fpstart
  43         .globl  _init
  44         .globl  _fini
  45         .globl  exit
  46         .globl  _exit
  47         .globl  monstartup
  48         .weak   _mcleanup
  49         .weak   _DYNAMIC
  50 
  51         .section        .data
  52 
  53         .weak   environ
  54         .set    environ,_environ
  55         .globl  _environ
  56         .type   _environ,@object
  57         .size   _environ,4
  58         .align  4
  59 _environ:
  60         .4byte  0x0
  61 
  62         .globl  ___Argv
  63         .type   ___Argv,@object
  64         .size   ___Argv,4
  65         .align  4
  66 ___Argv:
  67         .4byte  0x0
  68 
  69         .section        .text
  70         .align  4
  71 
  72 /*
  73  * C language startup routine.
  74  * Assume that exec code has cleared the direction flag in the TSS.
  75  * Assume that %esp is set to the addr after the last word pushed.
  76  * The stack contains (in order): argc, argv[],envp[],...
  77  * Assume that all of the segment registers are initialized.
  78  *
  79  * Allocate a NULL return address and a NULL previous %ebp as if
  80  * there was a genuine call to _start.
  81  * sdb stack trace shows _start(argc,argv[0],argv[1],...,envp[0],...)
  82  */
  83         .type   _start,@function
  84 _start:
  85         pushl   $0
  86         pushl   $0
  87         movl    %esp,%ebp               /* The first stack frame */
  88 
  89 /*
  90  * Check to see if there is an _mcleanup() function linked in, and if so,
  91  * register it with atexit() as the last thing to be run by exit().
  92  */
  93         pushl   %edx                    /* save rt_do_exit for later atexit */
  94 
  95         movl    $_mcleanup,%eax
  96         testl   %eax,%eax
  97         jz      1f
  98         pushl   %eax
  99         call    atexit
 100         addl    $4,%esp
 101 1:
 102 
 103         movl    $_DYNAMIC,%eax
 104         testl   %eax,%eax
 105         jz      1f
 106         call    atexit                  /* register rt_do_exit */
 107 1:
 108         addl    $4,%esp
 109 
 110         pushl   $_fini
 111         call    atexit
 112         addl    $4,%esp
 113 
 114 /* start profiling */
 115         pushl   %ebp
 116         movl    %esp,%ebp
 117         pushl   $_etext
 118         pushl   $_start
 119         call    monstartup
 120         addl    $8,%esp
 121         popl    %ebp
 122 
 123 /*
 124  * The following code provides almost standard static destructor handling
 125  * for systems that do not have the modified atexit processing in their
 126  * system libraries.  It checks for the existence of the new routine
 127  * "_get_exit_frame_monitor()", which is in libc.so when the new exit-handling
 128  * code is there.  It then check for the existence of "__Crun::do_exit_code()"
 129  * which will be in libCrun.so whenever the code was linked with the C++
 130  * compiler.  If there is no enhanced atexit, and we do have do_exit_code,
 131  * we register the latter with atexit.  There are 5 extra slots in
 132  * atexit, so this will still be standard conforming.  Since the code
 133  * is registered after the .fini section, it runs before the library
 134  * cleanup code, leaving nothing for the calls to _do_exit_code_in_range
 135  * to handle.
 136  *
 137  * Remove this code and the associated code in libCrun when the earliest
 138  * system to be supported is Solaris 8.
 139  */
 140         .weak   _get_exit_frame_monitor
 141         .weak   __1cG__CrunMdo_exit_code6F_v_
 142 
 143         .section        .data
 144         .align  4
 145 __get_exit_frame_monitor_ptr:
 146         .4byte  _get_exit_frame_monitor
 147         .type   __get_exit_frame_monitor_ptr,@object
 148         .size   __get_exit_frame_monitor_ptr,4
 149 
 150         .align  4
 151 __do_exit_code_ptr:
 152         .4byte  __1cG__CrunMdo_exit_code6F_v_
 153         .type   __do_exit_code_ptr,@object
 154         .size   __do_exit_code_ptr,4
 155 
 156         .section        .text
 157 
 158         lea     __get_exit_frame_monitor_ptr, %eax
 159         movl    (%eax), %eax
 160         testl   %eax,%eax
 161         jz      1f
 162         lea     __do_exit_code_ptr, %eax
 163         movl    (%eax), %eax
 164         testl   %eax, %eax
 165         jz      1f
 166         pushl   %eax
 167         call    atexit          /* atexit(__Crun::do_exit_code()) */
 168         addl    $4,%esp
 169 1:
 170 
 171 /*
 172  * End of destructor handling code
 173  */
 174 
 175 /*
 176  * Calculate the location of the envp array by adding the size of
 177  * the argv array to the start of the argv array.
 178  */
 179 
 180         movl    8(%ebp),%eax            /* argc */
 181         movl    _environ, %edx          /* fixed bug 4302802 */
 182         testl   %edx, %edx              /* check if _enviorn==0 */
 183         jne     1f                      /* fixed bug 4203802 */
 184         leal    16(%ebp,%eax,4),%edx    /* envp */
 185         movl    %edx,_environ           /* copy to _environ */
 186 1:
 187         andl    $-16,%esp       /* align the stack */
 188         subl    $4,%esp
 189 
 190         pushl   %edx
 191         leal    12(%ebp),%edx   /* argv */
 192         movl    %edx,___Argv
 193         pushl   %edx
 194         pushl   %eax            /* argc */
 195         call    __fpstart
 196         call    _init
 197         call    main            /* main(argc,argv,envp) */
 198         addl    $12,%esp
 199         pushl   %eax            /* return value from main */
 200         pushl   %eax            /* push it again (for _exit(), below) */
 201         call    exit
 202         addl    $4,%esp
 203         call    _exit           /* if user redefined exit, call _exit */
 204         addl    $4,%esp
 205         hlt
 206         .size   _start, .-_start