github.com/afumu/libc@v0.0.6/musl/src/env/__libc_start_main.c (about)

     1  #include <elf.h>
     2  #include <poll.h>
     3  #include <fcntl.h>
     4  #include <signal.h>
     5  #include <unistd.h>
     6  #include "syscall.h"
     7  #include "atomic.h"
     8  #include "libc.h"
     9  
    10  static void dummy(void) {}
    11  weak_alias(dummy, _init);
    12  
    13  extern weak hidden void (*const __init_array_start)(void), (*const __init_array_end)(void);
    14  
    15  static void dummy1(void *p) {}
    16  weak_alias(dummy1, __init_ssp);
    17  
    18  #define AUX_CNT 38
    19  
    20  #ifdef __GNUC__
    21  __attribute__((__noinline__))
    22  #endif
    23  void __init_libc(char **envp, char *pn)
    24  {
    25  	size_t i, *auxv, aux[AUX_CNT] = { 0 };
    26  	__environ = envp;
    27  	for (i=0; envp[i]; i++);
    28  	libc.auxv = auxv = (void *)(envp+i+1);
    29  	for (i=0; auxv[i]; i+=2) if (auxv[i]<AUX_CNT) aux[auxv[i]] = auxv[i+1];
    30  	__hwcap = aux[AT_HWCAP];
    31  	if (aux[AT_SYSINFO]) __sysinfo = aux[AT_SYSINFO];
    32  	libc.page_size = aux[AT_PAGESZ];
    33  
    34  	if (!pn) pn = (void*)aux[AT_EXECFN];
    35  	if (!pn) pn = "";
    36  	__progname = __progname_full = pn;
    37  	for (i=0; pn[i]; i++) if (pn[i]=='/') __progname = pn+i+1;
    38  
    39  	__init_tls(aux);
    40  	__init_ssp((void *)aux[AT_RANDOM]);
    41  
    42  	if (aux[AT_UID]==aux[AT_EUID] && aux[AT_GID]==aux[AT_EGID]
    43  		&& !aux[AT_SECURE]) return;
    44  
    45  	struct pollfd pfd[3] = { {.fd=0}, {.fd=1}, {.fd=2} };
    46  	int r =
    47  #ifdef SYS_poll
    48  	__syscall(SYS_poll, pfd, 3, 0);
    49  #else
    50  	__syscall(SYS_ppoll, pfd, 3, &(struct timespec){0}, 0, _NSIG/8);
    51  #endif
    52  	if (r<0) a_crash();
    53  	for (i=0; i<3; i++) if (pfd[i].revents&POLLNVAL)
    54  		if (__sys_open("/dev/null", O_RDWR)<0)
    55  			a_crash();
    56  	libc.secure = 1;
    57  }
    58  
    59  static void libc_start_init(void)
    60  {
    61  	_init();
    62  	uintptr_t a = (uintptr_t)&__init_array_start;
    63  	for (; a<(uintptr_t)&__init_array_end; a+=sizeof(void(*)()))
    64  		(*(void (**)(void))a)();
    65  }
    66  
    67  weak_alias(libc_start_init, __libc_start_init);
    68  
    69  typedef int lsm2_fn(int (*)(int,char **,char **), int, char **);
    70  static lsm2_fn libc_start_main_stage2;
    71  
    72  int __libc_start_main(int (*main)(int,char **,char **), int argc, char **argv)
    73  {
    74  	char **envp = argv+argc+1;
    75  
    76  	/* External linkage, and explicit noinline attribute if available,
    77  	 * are used to prevent the stack frame used during init from
    78  	 * persisting for the entire process lifetime. */
    79  	__init_libc(envp, argv[0]);
    80  
    81  	/* Barrier against hoisting application code or anything using ssp
    82  	 * or thread pointer prior to its initialization above. */
    83  	lsm2_fn *stage2 = libc_start_main_stage2;
    84  	__asm__ ( "" : "+r"(stage2) : : "memory" );
    85  	return stage2(main, argc, argv);
    86  }
    87  
    88  static int libc_start_main_stage2(int (*main)(int,char **,char **), int argc, char **argv)
    89  {
    90  	char **envp = argv+argc+1;
    91  	__libc_start_init();
    92  
    93  	/* Pass control to the application */
    94  	exit(main(argc, argv, envp));
    95  	return 0;
    96  }