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