1 /*- 2 * SPDX-License-Identifier: BSD-1-Clause 3 * 4 * Copyright 2012 Konstantin Belousov <kib@FreeBSD.org> 5 * Copyright (c) 2018, 2023 The FreeBSD Foundation 6 * 7 * Parts of this software was developed by Konstantin Belousov 8 * <kib@FreeBSD.org> under sponsorship from the FreeBSD Foundation. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <sys/param.h> 29 #include <sys/elf.h> 30 #include <sys/elf_common.h> 31 #include <stdlib.h> 32 #include "libc_private.h" 33 34 extern void (*__preinit_array_start[])(int, char **, char **) __hidden; 35 extern void (*__preinit_array_end[])(int, char **, char **) __hidden; 36 extern void (*__init_array_start[])(int, char **, char **) __hidden; 37 extern void (*__init_array_end[])(int, char **, char **) __hidden; 38 extern void (*__fini_array_start[])(void) __hidden; 39 extern void (*__fini_array_end[])(void) __hidden; 40 extern void _fini(void) __hidden; 41 extern void _init(void) __hidden; 42 43 extern int _DYNAMIC; 44 #pragma weak _DYNAMIC 45 46 #if defined(CRT_IRELOC_RELA) 47 extern const Elf_Rela __rela_iplt_start[] __weak_symbol __hidden; 48 extern const Elf_Rela __rela_iplt_end[] __weak_symbol __hidden; 49 50 #include "reloc.c" 51 52 static void 53 process_irelocs(void) 54 { 55 const Elf_Rela *r; 56 57 for (r = &__rela_iplt_start[0]; r < &__rela_iplt_end[0]; r++) 58 crt1_handle_rela(r); 59 } 60 #elif defined(CRT_IRELOC_REL) 61 extern const Elf_Rel __rel_iplt_start[] __weak_symbol __hidden; 62 extern const Elf_Rel __rel_iplt_end[] __weak_symbol __hidden; 63 64 #include "reloc.c" 65 66 static void 67 process_irelocs(void) 68 { 69 const Elf_Rel *r; 70 71 for (r = &__rel_iplt_start[0]; r < &__rel_iplt_end[0]; r++) 72 crt1_handle_rel(r); 73 } 74 #elif defined(CRT_IRELOC_SUPPRESS) 75 #else 76 #error "Define platform reloc type" 77 #endif 78 79 static void 80 finalizer(void) 81 { 82 void (*fn)(void); 83 size_t array_size, n; 84 85 array_size = __fini_array_end - __fini_array_start; 86 for (n = array_size; n > 0; n--) { 87 fn = __fini_array_start[n - 1]; 88 if ((uintptr_t)fn != 0 && (uintptr_t)fn != 1) 89 (fn)(); 90 } 91 _fini(); 92 } 93 94 static void 95 handle_static_init(int argc, char **argv, char **env) 96 { 97 #ifndef PIC 98 void (*fn)(int, char **, char **); 99 size_t array_size, n; 100 101 if (&_DYNAMIC != NULL) 102 return; 103 104 atexit(finalizer); 105 106 array_size = __preinit_array_end - __preinit_array_start; 107 for (n = 0; n < array_size; n++) { 108 fn = __preinit_array_start[n]; 109 if ((uintptr_t)fn != 0 && (uintptr_t)fn != 1) 110 fn(argc, argv, env); 111 } 112 _init(); 113 array_size = __init_array_end - __init_array_start; 114 for (n = 0; n < array_size; n++) { 115 fn = __init_array_start[n]; 116 if ((uintptr_t)fn != 0 && (uintptr_t)fn != 1) 117 fn(argc, argv, env); 118 } 119 #endif 120 } 121 122 static void 123 handle_argv(int argc, char *argv[], char **env) 124 { 125 const char *s; 126 127 if (environ == NULL) 128 environ = env; 129 if (argc > 0 && argv[0] != NULL) { 130 __progname = argv[0]; 131 for (s = __progname; *s != '\0'; s++) { 132 if (*s == '/') 133 __progname = s + 1; 134 } 135 } 136 } 137 138 void 139 __libc_start1(int argc, char *argv[], char *env[], void (*cleanup)(void), 140 int (*mainX)(int, char *[], char *[])) 141 { 142 handle_argv(argc, argv, env); 143 144 if (&_DYNAMIC != NULL) { 145 atexit(cleanup); 146 } else { 147 #ifndef CRT_IRELOC_SUPPRESS 148 INIT_IRELOCS; 149 process_irelocs(); 150 #endif 151 _init_tls(); 152 } 153 154 handle_static_init(argc, argv, env); 155 exit(mainX(argc, argv, env)); 156 } 157 158 /* XXXKIB _mcleanup and monstartup defs */ 159 extern void _mcleanup(void); 160 extern void monstartup(void *, void *); 161 162 void 163 __libc_start1_gcrt(int argc, char *argv[], char *env[], 164 void (*cleanup)(void), int (*mainX)(int, char *[], char *[]), 165 int *eprolp, int *etextp) 166 { 167 handle_argv(argc, argv, env); 168 169 if (&_DYNAMIC != NULL) { 170 atexit(cleanup); 171 } else { 172 #ifndef CRT_IRELOC_SUPPRESS 173 INIT_IRELOCS; 174 process_irelocs(); 175 #endif 176 _init_tls(); 177 } 178 179 atexit(_mcleanup); 180 monstartup(eprolp, etextp); 181 182 handle_static_init(argc, argv, env); 183 exit(mainX(argc, argv, env)); 184 } 185