xref: /dragonfly/lib/csu/x86_64/crt1.c (revision c9c5aa9e)
1 /*-
2  * Copyright 1996-1998 John D. Polstra.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #ifndef __GNUC__
27 #error "GCC is needed to compile this file"
28 #endif
29 
30 #include <sys/cdefs.h>
31 #include <machine/tls.h>
32 #include <elf.h>
33 #include <stdlib.h>
34 
35 #include "libc_private.h"
36 #include "initfini.c"
37 #include "crtbrand.c"
38 
39 typedef void (*fptr)(void);
40 
41 #ifdef GCRT
42 extern void _mcleanup(void);
43 extern void monstartup(void *, void *);
44 extern int eprol;
45 extern int etext;
46 #endif
47 
48 /* static ifunc reloc support */
49 extern const Elf_Rela __rela_iplt_start[] __dso_hidden __weak_symbol;
50 extern const Elf_Rela __rela_iplt_end[] __dso_hidden __weak_symbol;
51 static void fix_iplta(void) __noinline;
52 
53 static void
54 fix_iplta(void)
55 {
56 	const Elf_Rela *rela, *relalim;
57 	Elf_Addr *where, target, *ptr;
58 
59 	rela = __rela_iplt_start;
60 	relalim = __rela_iplt_end;
61 	for (; rela < relalim; ++rela) {
62 		if (ELF_R_TYPE(rela->r_info) != R_X86_64_IRELATIVE)
63 			abort();
64 		ptr = (Elf_Addr *)rela->r_addend;
65 		where = (Elf_Addr *)rela->r_offset;
66 		target = ((Elf_Addr (*)(void))ptr)();
67 		*where = target;
68 	}
69 }
70 
71 void _start(char **, void (*)(void));
72 
73 /* The entry function. */
74 void
75 _start(char **ap, void (*cleanup)(void))
76 {
77 	int argc;
78 	char **argv;
79 	char **env;
80 
81 	argc = *(long *)(void *)ap;
82 	argv = ap + 1;
83 	env = ap + 2 + argc;
84 	handle_argv(argc, argv, env);
85 
86 	/*
87 	 * Setup the initial TLS space.  The RTLD does not set up our TLS
88 	 * (it can't, it doesn't know how our errno is declared).  It simply
89 	 * does all the groundwork required so that we can call
90 	 * _rtld_allocate_tls().
91 	 */
92 	_init_tls();
93 	_rtld_call_init();
94 
95 	if (&_DYNAMIC != NULL)
96 		atexit(cleanup);
97 	else
98 		fix_iplta();
99 
100 #ifdef GCRT
101 	atexit(_mcleanup);
102 	monstartup(&eprol, &etext);
103 #endif
104 
105 	handle_static_init(argc, argv, env);
106 #ifdef GCRT
107 	/*
108 	 * This label was previously located just after the monstartup
109 	 * function.  It was relocated after the handle_static_init function
110 	 * to avoid an alternative conditional optimization performed by
111 	 * clang.  The optimization cause the compilation to fail with a
112 	 * label redefinition error.  The impact of the label relocation is
113 	 * the loss of profiling of handle_static_init function.
114 	 */
115 __asm__("eprol:");
116 #endif
117 	exit(main(argc, argv, env));
118 }
119