1 /* Initialization code run first thing by the ELF startup code. For Hurd.
2 Copyright (C) 1995-2024 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
25 #include <dl-sysdep.h>
26 #include <set-hooks.h>
27 #include "hurdstartup.h"
30 #include <fpu_control.h>
31 #include <libc-diag.h>
32 #include <libc-internal.h>
34 extern void __mach_init (void);
35 extern void __init_misc (int, char **, char **);
37 extern int __libc_argc attribute_hidden
;
38 extern char **__libc_argv attribute_hidden
;
39 extern char **_dl_argv
;
41 #if !defined (SHARED) && (defined (THREAD_SET_STACK_GUARD) || defined (THREAD_SET_POINTER_GUARD))
42 /* In the static case, we need to set up TLS early so that the stack
43 protection guard can be read at from TLS by the GCC-generated snippets,
44 on architectures that store the guard in TLS and not globally. */
45 # define USE_INIT1_TCBHEAD 1
47 # define USE_INIT1_TCBHEAD 0
51 static tcbhead_t __init1_tcbhead
;
54 /* Things that want to be run before _hurd_init or much anything else.
55 Importantly, these are called before anything tries to use malloc. */
56 DEFINE_HOOK (_hurd_preinit_hook
, (void));
59 /* We call this once the Hurd magic is all set up and we are ready to be a
60 Posixoid program. This does the same things the generic version does. */
62 posixland_init (int argc
, char **argv
, char **envp
)
64 /* Now we have relocations etc. we can start signals etc. */
65 _hurd_libc_proc_init (argv
);
68 /* Make sure we don't initialize twice. */
71 /* Set the FPU control word to the proper default value. */
72 __setfpucw (__fpu_control
);
76 /* Initialize data structures so the additional libc can do RPCs. */
80 __setfpucw (__fpu_control
);
83 /* Save the command-line arguments. */
89 _dl_non_dynamic_init ();
91 __init_misc (argc
, argv
, envp
);
97 int argc
= (int) (uintptr_t) *data
;
98 char **argv
= (void *) (data
+ 1);
99 char **envp
= &argv
[argc
+ 1];
100 struct hurd_startup_data
*d
;
102 /* Since the cthreads initialization code uses malloc, and the
103 malloc initialization code needs to get at the environment, make
104 sure we can find it. We'll need to do this again later on since
105 switching stacks changes the location where the environment is
115 /* If we are the bootstrap task started by the kernel,
116 then after the environment pointers there is no Hurd
117 data block; the argument strings start there. */
118 if ((void *) d
== argv
[0] || d
->phdr
== 0)
120 __libc_enable_secure
= 0;
121 /* With a new enough linker (binutils-2.23 or better),
122 the magic __ehdr_start symbol will be available and
123 __libc_start_main will have done this that way already. */
124 if (_dl_phdr
== NULL
)
126 /* We may need to see our own phdrs, e.g. for TLS setup.
127 Try the usual kludge to find the headers without help from
129 extern const void __executable_start
;
130 const ElfW(Ehdr
) *const ehdr
= &__executable_start
;
131 _dl_phdr
= (const void *) ehdr
+ ehdr
->e_phoff
;
132 _dl_phnum
= ehdr
->e_phnum
;
133 assert (ehdr
->e_phentsize
== sizeof (ElfW(Phdr
)));
138 __libc_enable_secure
= d
->flags
& EXEC_SECURE
;
139 _dl_phdr
= (ElfW(Phdr
) *) d
->phdr
;
140 _dl_phnum
= d
->phdrsz
/ sizeof (ElfW(Phdr
));
141 assert (d
->phdrsz
% sizeof (ElfW(Phdr
)) == 0);
145 if ((void *) d
== argv
[0])
148 _hurd_init_dtable
= d
->dtable
;
149 _hurd_init_dtablesize
= d
->dtablesize
;
151 if (d
->portarray
|| d
->intarray
)
152 /* Initialize library data structures, start signal processing, etc. */
153 _hurd_init (d
->flags
, argv
,
154 d
->portarray
, d
->portarraysize
,
155 d
->intarray
, d
->intarraysize
);
158 /* Do the first essential initializations that must precede all else. */
162 /* Initialize data structures so we can do RPCs. */
166 GLRO(dl_pagesize
) = __vm_page_size
;
169 #if USE_INIT1_TCBHEAD
170 _hurd_tls_init (&__init1_tcbhead
, 0);
173 RUN_RELHOOK (_hurd_preinit_hook
, ());
177 /* This function is called specially by the dynamic linker to do early
178 initialization of the shared C library before normal initializers
179 expecting a Posixoid environment can run. */
182 _dl_init_first (void *data
)
188 /* The regular posixland initialization is what goes into libc's
189 normal initializer. */
190 /* NOTE! The linker notices the magical name `_init' and sets the DT_INIT
191 pointer in the dynamic section based solely on that. It is convention
192 for this function to be in the `.init' section, but the symbol name is
193 the only thing that really matters!! */
194 strong_alias (posixland_init
, _init
);
197 __libc_init_first (int argc
, char **argv
, char **envp
)
199 /* Everything was done in the shared library initializer, _init. */
204 strong_alias (posixland_init
, __libc_init_first
);
206 /* XXX This is all a crock and I am not happy with it.
207 This poorly-named function is called by static-start.S,
208 which should not exist at all. */
210 inhibit_stack_protector
211 _hurd_stack_setup (void **argptr
)
213 /* This is the very first C code that runs in a statically linked
214 executable -- calling this function is the first thing that _start in
215 static-start.S does. Once this function returns, the unusual way that it
216 does (see below), _start jumps to _start1, the regular start-up code.
218 _start1 expects the arguments, environment, and a Hurd data block to be
219 located at the top of the stack. The data may already be located there,
220 or we may need to receive it from the exec server. If the data is located
221 on the stack (just above our call frame), argptr points to it. Note that
222 this may not be a valid pointer in case we're supposed to receive the
223 arguments from the exec server, so we can not dereference it yet. */
225 void *caller
= RETURN_ADDRESS (0);
226 /* Init the essential things. */
229 void doinit (intptr_t *data
)
231 init ((void **) data
);
232 RETURN_TO (data
, caller
, 0);
233 __builtin_unreachable ();
236 /* _hurd_startup () will attempt to receive the data block from the exec
237 server; or if that is not possible, will take the data from the pointer
238 we pass it here. The important point here is that the data
239 _hurd_startup () collects may be allocated in its stack frame (with
240 alloca), which is why _hurd_startup () does not return the normal way.
241 Instead, it invokes a callback (which is not expected to return normally
244 Our callback not only passes the data pointer to init (), but also jumps
245 out of the call stack back to our caller (i.e. to _start1), while setting
246 the stack pointer to the data (which is somewhere on the current stack
247 anyway). This way, _start1 find the data on the top of the stack, just as
249 _hurd_startup (argptr
, &doinit
);
250 __builtin_unreachable ();
255 /* This function is defined here so that if this file ever gets into
256 ld.so we will get a link error. Having this file silently included
257 in ld.so causes disaster, because the _init definition above will
258 cause ld.so to gain an init function, which is not a cool thing. */