__libc_start_main.c 2.5 KB

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