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 crt1.o module is provided as the bare minimum required to build a
  29  * 64-bit progile executable with gcc -pg.  It is installed in /usr/lib/amd64
  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,8
  58         .align  8
  59 _environ:
  60         .8byte  0x0
  61 
  62         .globl  ___Argv
  63         .type   ___Argv,@object
  64         .size   ___Argv,8
  65         .align  8
  66 ___Argv:
  67         .8byte  0x0
  68 
  69         .section        .text
  70         .align  8
  71 
  72 /*
  73  *   The SVR4/i386 ABI (pages 3-29) says that when the entry
  74  *   point runs registers' %rbp, %rsp, %rdx values are specified
  75  *   the following:
  76  *
  77  *      %rbp The content of this register is unspecified at
  78  *              process initialization time, but the user code should mark
  79  *              the deepest stack frame by setting the frame pointer to zero.
  80  *              No other frame's %ebp should have a zero value.
  81  *
  82  *      %rsp Performing its usual job, the stack pointer holds the address
  83  *      of the bottom of the stack, which is guaranteed to be
  84  *      quadword aligned.
  85  *
  86  *              The stack contains the arguments and environment:
  87  *        ...
  88  *        envp[0]               (16+(8*argc))(%rsp)
  89  *        NULL                  (8+(8*argc))(%rsp)
  90  *        ...
  91  *        argv[0]               8(%rsp)
  92  *        argc                  0(%rsp)
  93  *
  94  *      %rdx In a conforming program, this register contains a function
  95  *              pointer that the application should register with atexit(BA_OS).
  96  *              This function is used for shared object termination code
  97  *              [see Dynamic Linking in Chapter 5 of the System V ABI].
  98  *
  99  */
 100 
 101         .type   _start,@function
 102 _start:
 103 /*
 104  * Allocate a NULL return address and a NULL previous %rbp as if
 105  * there was a genuine call to _start.
 106  */
 107         pushq   $0
 108         pushq   $0
 109         movq    %rsp,%rbp               /* The first stack frame */
 110 
 111 /*
 112  * The stack now is
 113  *
 114  *        envp[0]               (32+(8*argc))(%rsp)      - (A)
 115  *        NULL                  (24+(8*argc))(%rsp)
 116  *        ...
 117  *        argv[0]               24(%rbp)                 - (B)
 118  *        argc                  16(%rbp)
 119  *        0                     8(%rbp)
 120  *        0                     0(%rbp)
 121  */
 122 
 123 /*
 124  * Check to see if there is an _mcleanup() function linked in, and if so,
 125  * register it with atexit() as the last thing to be run by exit().
 126  */
 127         movq    %rdx,%r12               /* save rt_do_exit for later atexit */
 128 
 129         movq    $_mcleanup,%rdi
 130         testq   %rdi,%rdi
 131         jz      1f
 132         call    atexit
 133 1:
 134 
 135         movq    $_DYNAMIC,%rax
 136         testq   %rax,%rax
 137         jz      1f
 138         movq    %r12,%rdi               /* register rt_do_exit */
 139         call    atexit
 140 1:
 141 
 142         movq    $_fini,%rdi
 143         call    atexit
 144 
 145 /* start profiling */
 146         pushq   %rbp
 147         movq    %rsp,%rbp
 148         movq    $_start,%rdi
 149         movq    $_etext,%rsi
 150         call    monstartup
 151         popq    %rbp
 152 
 153 /*
 154  * Calculate the location of the envp array by adding the size of
 155  * the argv array to the start of the argv array.
 156  */
 157         movq    16(%rbp),%rax           /* argc */
 158         movq    _environ, %rcx
 159         testq   %rcx, %rcx              /* check if _environ==0 */
 160         jne     1f
 161         leaq    32(%rbp,%rax,8),%rcx    /* (A) */
 162         movq    %rcx,_environ           /* copy to _environ */
 163 1:
 164 
 165 /*
 166  * Force stack alignment - below here there must have been an even
 167  * number of un-popped pushq instructions whenever a call is reached
 168  */
 169         andq    $-16,%rsp
 170         pushq   %rdx
 171         leaq    24(%rbp),%rdx           /* argv (B) */
 172         movq    %rdx,___Argv
 173         pushq   %rcx
 174         pushq   %rdx
 175         pushq   %rax
 176         call    __fpstart
 177         call    _init
 178         popq    %rdi
 179         popq    %rsi
 180         popq    %rdx
 181         popq    %rcx
 182         call    main                    /* main(argc,argv,envp) */
 183         pushq   %rax
 184         pushq   %rax
 185         movq    %rax,%rdi               /* and call exit */
 186         call    exit
 187         popq    %rdi
 188         popq    %rdi
 189         call    _exit           /* if user redefined exit, call _exit */
 190         hlt
 191         .size   _start, .-_start