1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2016, Richard Lowe.
  14  */
  15 
  16 /*
  17  * That of the CRT startup routine which itself may be implemented in C.
  18  */
  19 
  20 #include <sys/feature_tests.h>
  21 #include <sys/types.h>
  22 
  23 #include <stdlib.h>
  24 #include <synch.h>
  25 #include <unistd.h>
  26 
  27 #pragma weak _DYNAMIC
  28 extern uintptr_t _DYNAMIC;
  29 
  30 #pragma weak environ = _environ
  31 char **_environ = NULL;
  32 char **___Argv = NULL;
  33 
  34 extern int main(int argc, char **argv, char **envp);
  35 extern void _init(void);
  36 extern void _fini(void);
  37 
  38 #pragma weak _start_crt_compiler
  39 extern void _start_crt_compiler(int argc, char **argv);
  40 
  41 #if defined(__x86)
  42 int __longdouble_used = 0;
  43 extern void __fpstart(void);
  44 #endif
  45 
  46 #if defined(__i386)             /* Not amd64 */
  47 #pragma weak __fsr_init_value
  48 extern long __fsr_init_value;
  49 extern void __fsr(uintptr_t);
  50 #endif
  51 
  52 
  53 /*
  54  * Defined here for ABI reasons, must match the definition in libc.
  55  * If it cannot, a new symbol must be created.
  56  */
  57 mutex_t __environ_lock = DEFAULTMUTEX;
  58 
  59 void
  60 _start_crt(int argc, char **argv, void (*exit_handler)(void))
  61 {
  62         int ret = 0;
  63 
  64         /*
  65          * On x86, we check whether we're a dynamic executable to see whether
  66          * we'll receive an exit_handler.
  67          *
  68          * On SPARC, we just need to check whether the handler was NULL.
  69          */
  70 #if defined(__x86)
  71         if (&_DYNAMIC != NULL)
  72                 (void) atexit(exit_handler);
  73 #elif defined(__sparc)
  74         if (exit_handler != NULL)
  75                 (void) atexit(exit_handler);
  76 #endif
  77 
  78         (void) atexit(_fini);
  79 
  80         _environ = argv + (argc + 1);
  81         ___Argv = argv;
  82 
  83         if (&_start_crt_compiler != NULL)
  84                 _start_crt_compiler(argc, argv);
  85 
  86 #if defined(__x86)
  87         __fpstart();
  88 #endif
  89 #if defined(__i386)             /* Not amd64 */
  90         /*
  91          * Note that Studio cc(1) sets the _value of the symbol_, that is, its
  92          * address.  Not the value _at_ that address.
  93          */
  94         __fsr((uintptr_t)&__fsr_init_value);
  95 #endif
  96         _init();
  97         ret = main(argc, argv, _environ);
  98         exit(ret);
  99         _exit(ret);
 100 }