1/* Operating system support for run-time dynamic linker. Hurd version.
2 Copyright (C) 1995-2024 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
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.
9
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.
14
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/>. */
18
19/* In the static library, this is all handled by dl-support.c
20 or by the vanilla definitions in the rest of the C library. */
21#ifdef SHARED
22
23#include <hurd.h>
24#include <link.h>
25#include <unistd.h>
26#include <fcntl.h>
27#include <stdlib.h>
28#include <sys/mman.h>
29#include <ldsodefs.h>
30#include <sys/wait.h>
31#include <assert.h>
32#include <sysdep.h>
33#include <argz.h>
34#include <mach/mig_support.h>
35#include "hurdstartup.h"
36#include <hurd/lookup.h>
37#include <hurd/auth.h>
38#include <hurd/term.h>
39#include <stdarg.h>
40#include <ctype.h>
41#include <sys/stat.h>
42#include <sys/uio.h>
43
44#include <entry.h>
45#include <dl-machine.h>
46#include <dl-procinfo.h>
47
48#include <dl-tunables.h>
49#include <not-errno.h>
50#include <not-cancel.h>
51
52extern void __mach_init (void);
53
54extern int _dl_argc;
55extern char **_dl_argv;
56extern char **_environ;
57
58int __libc_enable_secure = 0;
59rtld_hidden_data_def (__libc_enable_secure)
60/* This variable contains the lowest stack address ever used. */
61void *__libc_stack_end = NULL;
62rtld_hidden_data_def(__libc_stack_end)
63
64/* TODO: Initialize. */
65void *_dl_random attribute_relro = NULL;
66
67struct hurd_startup_data *_dl_hurd_data;
68
69
70ElfW(Addr)
71_dl_sysdep_start (void **start_argptr,
72 void (*dl_main) (const ElfW(Phdr) *phdr, ElfW(Word) phent,
73 ElfW(Addr) *user_entry,
74 ElfW(auxv_t) *auxv))
75{
76 void go (intptr_t *argdata)
77 {
78 char *orig_argv0;
79 char **p;
80
81 /* Cache the information in various global variables. */
82 _dl_argc = *argdata;
83 _dl_argv = 1 + (char **) argdata;
84 _environ = &_dl_argv[_dl_argc + 1];
85 for (p = _environ; *p++;); /* Skip environ pointers and terminator. */
86
87 orig_argv0 = _dl_argv[0];
88
89 if ((void *) p == _dl_argv[0])
90 {
91 static struct hurd_startup_data nodata;
92 _dl_hurd_data = &nodata;
93 nodata.user_entry = (vm_address_t) ENTRY_POINT;
94 }
95 else
96 _dl_hurd_data = (void *) p;
97
98 GLRO(dl_platform) = NULL; /* Default to nothing known about the platform. */
99
100 __libc_enable_secure = _dl_hurd_data->flags & EXEC_SECURE;
101
102 __tunables_init (_environ);
103
104 /* Initialize DSO sorting algorithm after tunables. */
105 _dl_sort_maps_init ();
106
107#ifdef DL_SYSDEP_INIT
108 DL_SYSDEP_INIT;
109#endif
110
111#ifdef DL_PLATFORM_INIT
112 DL_PLATFORM_INIT;
113#endif
114
115 /* Determine the length of the platform name. */
116 if (GLRO(dl_platform) != NULL)
117 GLRO(dl_platformlen) = strlen (GLRO(dl_platform));
118
119 if (_dl_hurd_data->flags & EXEC_STACK_ARGS
120 && _dl_hurd_data->user_entry == 0)
121 _dl_hurd_data->user_entry = (vm_address_t) ENTRY_POINT;
122
123#if 0 /* XXX make this work for real someday... */
124 if (_dl_hurd_data->user_entry == (vm_address_t) ENTRY_POINT)
125 /* We were invoked as a command, not as the program interpreter.
126 The generic ld.so code supports this: it will parse the args
127 as "ld.so PROGRAM [ARGS...]". For booting the Hurd, we
128 support an additional special syntax:
129 ld.so [-LIBS...] PROGRAM [ARGS...]
130 Each LIBS word consists of "FILENAME=MEMOBJ";
131 for example "-/lib/libc.so=123" says that the contents of
132 /lib/libc.so are found in a memory object whose port name
133 in our task is 123. */
134 while (_dl_argc > 2 && _dl_argv[1][0] == '-' && _dl_argv[1][1] != '-')
135 {
136 char *lastslash, *memobjname, *p;
137 struct link_map *l;
138 mach_port_t memobj;
139 error_t err;
140
141 --_dl_argc;
142 p = _dl_argv++[1] + 1;
143
144 memobjname = strchr (p, '=');
145 if (! memobjname)
146 _dl_sysdep_fatal ("Bogus library spec: ", p, "\n", NULL);
147 *memobjname++ = '\0';
148 memobj = 0;
149 while (*memobjname != '\0')
150 memobj = (memobj * 10) + (*memobjname++ - '0');
151
152 /* Add a user reference on the memory object port, so we will
153 still have one after _dl_map_object_from_fd calls our
154 `close'. */
155 err = __mach_port_mod_refs (__mach_task_self (), memobj,
156 MACH_PORT_RIGHT_SEND, +1);
157 assert_perror (err);
158
159 lastslash = strrchr (p, '/');
160 l = _dl_map_object_from_fd (lastslash ? lastslash + 1 : p, NULL,
161 memobj, strdup (p), 0);
162
163 /* Squirrel away the memory object port where it
164 can be retrieved by the program later. */
165 l->l_info[DT_NULL] = (void *) memobj;
166 }
167#endif
168
169 /* Call elf/rtld.c's main program. It will set everything
170 up and leave us to transfer control to USER_ENTRY. */
171 (*dl_main) ((const ElfW(Phdr) *) _dl_hurd_data->phdr,
172 _dl_hurd_data->phdrsz / sizeof (ElfW(Phdr)),
173 (ElfW(Addr) *) &_dl_hurd_data->user_entry, NULL);
174
175 /* The call above might screw a few things up.
176
177 P is the location after the terminating NULL of the list of
178 environment variables. It has to point to the Hurd startup
179 data or if that's missing then P == ARGV[0] must hold. The
180 startup code in init-first.c will get confused if this is not
181 the case, so we must rearrange things to make it so. We'll
182 recompute P and move the Hurd data or the new ARGV[0] there.
183
184 Note: directly invoked ld.so can move arguments and env vars.
185
186 We use memmove, since the locations might overlap. */
187
188 char **newp;
189 for (newp = _environ; *newp++;);
190
191 if (newp != p || _dl_argv[0] != orig_argv0)
192 {
193 if (orig_argv0 == (char *) p)
194 {
195 if ((char *) newp != _dl_argv[0])
196 {
197 assert ((char *) newp < _dl_argv[0]);
198 _dl_argv[0] = memmove ((char *) newp, _dl_argv[0],
199 strlen (_dl_argv[0]) + 1);
200 }
201 }
202 else
203 {
204 if ((void *) newp != _dl_hurd_data)
205 memmove (newp, _dl_hurd_data, sizeof (*_dl_hurd_data));
206 }
207 }
208
209 _dl_init_first (argdata);
210
211 {
212 extern void _dl_start_user (void);
213 /* Unwind the stack to ARGDATA and simulate a return from _dl_start
214 to the RTLD_START code which will run the user's entry point. */
215 RETURN_TO (argdata, &_dl_start_user, _dl_hurd_data->user_entry);
216 }
217 }
218
219 /* Set up so we can do RPCs. */
220 __mach_init ();
221
222 /* Initialize frequently used global variable. */
223 GLRO(dl_pagesize) = __getpagesize ();
224
225 /* See hurd/hurdstartup.c; this deals with getting information
226 from the exec server and slicing up the arguments.
227 Then it will call `go', above. */
228 _hurd_startup (start_argptr, &go);
229
230 LOSE;
231 abort ();
232}
233
234void
235_dl_sysdep_start_cleanup (void)
236{
237 /* Deallocate the reply port and task port rights acquired by
238 __mach_init. We are done with them now, and the user will
239 reacquire them for himself when he wants them. */
240 __mig_dealloc_reply_port (__mig_get_reply_port ());
241 __mach_port_deallocate (__mach_task_self (), __mach_host_self_);
242 __mach_port_deallocate (__mach_task_self (), __mach_task_self_);
243}
244
245/* Minimal open/close/mmap/etc. implementation sufficient for initial loading of
246 shared libraries. These are weak definitions so that when the
247 dynamic linker re-relocates itself to be user-visible (for -ldl),
248 it will get the user's definition (i.e. usually libc's).
249
250 They also need to be set in the libc and ld section of
251 sysdeps/mach/hurd/Versions, to be overridable, and in libc.abilist and
252 ld.abilist to be checked. */
253
254/* This macro checks that the function does not get renamed to be hidden: we do
255 need these to be overridable by libc's. */
256#define check_no_hidden(name) \
257 __typeof (name) __check_##name##_no_hidden \
258 __attribute__ ((alias (#name))) \
259 __attribute_copy__ (name);
260
261/* Open FILE_NAME and return a Hurd I/O for it in *PORT, or return an
262 error. If STAT is non-zero, stat the file into that stat buffer. */
263static error_t
264open_file (const char *file_name, int flags,
265 mach_port_t *port, struct stat64 *stat)
266{
267 enum retry_type doretry;
268 char retryname[1024]; /* XXX string_t LOSES! */
269 file_t startdir;
270 error_t err;
271
272 error_t use_init_port (int which, error_t (*operate) (file_t))
273 {
274 return (which < _dl_hurd_data->portarraysize
275 ? ((*operate) (_dl_hurd_data->portarray[which]))
276 : EGRATUITOUS);
277 }
278 file_t get_dtable_port (int fd)
279 {
280 if ((unsigned int) fd < _dl_hurd_data->dtablesize
281 && _dl_hurd_data->dtable[fd] != MACH_PORT_NULL)
282 {
283 __mach_port_mod_refs (__mach_task_self (), _dl_hurd_data->dtable[fd],
284 MACH_PORT_RIGHT_SEND, +1);
285 return _dl_hurd_data->dtable[fd];
286 }
287 return __hurd_fail (EBADF), MACH_PORT_NULL;
288 }
289
290 assert (!(flags & ~(O_READ | O_EXEC | O_CLOEXEC | O_IGNORE_CTTY)));
291 flags &= ~(O_CLOEXEC | O_IGNORE_CTTY);
292
293 startdir = _dl_hurd_data->portarray[file_name[0] == '/'
294 ? INIT_PORT_CRDIR : INIT_PORT_CWDIR];
295
296 while (file_name[0] == '/')
297 file_name++;
298
299 err = __dir_lookup (startdir, (char *)file_name, flags, 0,
300 &doretry, retryname, port);
301
302 if (!err)
303 err = __hurd_file_name_lookup_retry (use_init_port, get_dtable_port,
304 __dir_lookup, doretry, retryname,
305 flags, 0, port);
306 if (!err && stat)
307 {
308 err = __io_stat (*port, stat);
309 if (err)
310 __mach_port_deallocate (__mach_task_self (), *port);
311 }
312
313 return err;
314}
315
316check_no_hidden(__open);
317check_no_hidden (__open64);
318check_no_hidden (__open_nocancel);
319int weak_function
320__open (const char *file_name, int mode, ...)
321{
322 mach_port_t port;
323 error_t err = open_file (file_name, mode, &port, 0);
324 if (err)
325 return __hurd_fail (err);
326 else
327 return (int)port;
328}
329weak_alias (__open, __open64)
330weak_alias (__open, __open_nocancel)
331
332check_no_hidden(__close);
333check_no_hidden(__close_nocancel);
334int weak_function
335__close (int fd)
336{
337 if (fd != (int) MACH_PORT_NULL)
338 __mach_port_deallocate (__mach_task_self (), (mach_port_t) fd);
339 return 0;
340}
341weak_alias (__close, __close_nocancel)
342
343check_no_hidden(__pread64);
344check_no_hidden(__pread64_nocancel);
345__ssize_t weak_function
346__pread64 (int fd, void *buf, size_t nbytes, off64_t offset)
347{
348 error_t err;
349 char *data;
350 mach_msg_type_number_t nread;
351
352 data = buf;
353 nread = nbytes;
354 err = __io_read ((mach_port_t) fd, &data, &nread, offset, nbytes);
355 if (err)
356 return __hurd_fail (err);
357
358 if (data != buf)
359 {
360 memcpy (buf, data, nread);
361 __vm_deallocate (__mach_task_self (), (vm_address_t) data, nread);
362 }
363
364 return nread;
365}
366libc_hidden_weak (__pread64)
367weak_alias (__pread64, __pread64_nocancel)
368
369check_no_hidden(__read);
370check_no_hidden(__read_nocancel);
371__ssize_t weak_function
372__read (int fd, void *buf, size_t nbytes)
373{
374 return __pread64 (fd, buf, nbytes, -1);
375}
376libc_hidden_weak (__read)
377weak_alias (__read, __read_nocancel)
378
379check_no_hidden(__write);
380check_no_hidden(__write_nocancel);
381__ssize_t weak_function
382__write (int fd, const void *buf, size_t nbytes)
383{
384 error_t err;
385 vm_size_t nwrote;
386
387 assert (fd < _hurd_init_dtablesize);
388
389 err = __io_write (_hurd_init_dtable[fd], buf, nbytes, -1, &nwrote);
390 if (err)
391 return __hurd_fail (err);
392
393 return nwrote;
394}
395libc_hidden_weak (__write)
396 weak_alias (__write, __write_nocancel)
397
398/* This is only used for printing messages (see dl-misc.c). */
399check_no_hidden(__writev);
400__ssize_t weak_function
401__writev (int fd, const struct iovec *iov, int niov)
402{
403 if (fd >= _hurd_init_dtablesize)
404 return __hurd_fail (EBADF);
405
406 int i;
407 size_t total = 0;
408 for (i = 0; i < niov; ++i)
409 total += iov[i].iov_len;
410
411 if (total != 0)
412 {
413 char buf[total], *bufp = buf;
414 error_t err;
415 vm_size_t nwrote;
416
417 for (i = 0; i < niov; ++i)
418 bufp = (memcpy (bufp, iov[i].iov_base, iov[i].iov_len)
419 + iov[i].iov_len);
420
421 err = __io_write (_hurd_init_dtable[fd], buf, total, -1, &nwrote);
422 if (err)
423 return __hurd_fail (err);
424
425 return nwrote;
426 }
427 return 0;
428}
429
430check_no_hidden(__libc_lseek64);
431off64_t weak_function
432__libc_lseek64 (int fd, off64_t offset, int whence)
433{
434 error_t err;
435
436 err = __io_seek ((mach_port_t) fd, offset, whence, &offset);
437 if (err)
438 return __hurd_fail (err);
439
440 return offset;
441}
442
443check_no_hidden(__mmap);
444void *weak_function
445__mmap (void *addr, size_t len, int prot, int flags, int fd, off_t offset)
446{
447 error_t err;
448 vm_prot_t vmprot;
449 vm_address_t mapaddr, mask;
450 mach_port_t memobj_rd, memobj_wr;
451
452 vmprot = VM_PROT_NONE;
453 if (prot & PROT_READ)
454 vmprot |= VM_PROT_READ;
455 if (prot & PROT_WRITE)
456 vmprot |= VM_PROT_WRITE;
457 if (prot & PROT_EXEC)
458 vmprot |= VM_PROT_EXECUTE;
459
460#ifdef __LP64__
461 if ((addr == NULL) && (prot & PROT_EXEC)
462 && HAS_ARCH_FEATURE (Prefer_MAP_32BIT_EXEC))
463 flags |= MAP_32BIT;
464#endif
465 mask = (flags & MAP_32BIT) ? ~(vm_address_t) 0x7FFFFFFF : 0;
466
467 if (flags & MAP_ANON)
468 memobj_rd = MACH_PORT_NULL;
469 else
470 {
471 assert (!(flags & MAP_SHARED));
472 err = __io_map ((mach_port_t) fd, &memobj_rd, &memobj_wr);
473 if (err)
474 return __hurd_fail (err), MAP_FAILED;
475 if (MACH_PORT_VALID (memobj_wr))
476 __mach_port_deallocate (__mach_task_self (), memobj_wr);
477 }
478
479 mapaddr = (vm_address_t) addr;
480 err = __vm_map (__mach_task_self (),
481 &mapaddr, (vm_size_t) len, mask,
482 !(flags & MAP_FIXED),
483 memobj_rd,
484 (vm_offset_t) offset,
485 flags & (MAP_COPY|MAP_PRIVATE),
486 vmprot, VM_PROT_ALL,
487 (flags & MAP_SHARED) ? VM_INHERIT_SHARE : VM_INHERIT_COPY);
488 if (err == KERN_NO_SPACE && (flags & MAP_FIXED))
489 {
490 /* XXX this is not atomic as it is in unix! */
491 /* The region is already allocated; deallocate it first. */
492 err = __vm_deallocate (__mach_task_self (), mapaddr, len);
493 if (! err)
494 err = __vm_map (__mach_task_self (),
495 &mapaddr, (vm_size_t) len,
496 mask,
497 !(flags & MAP_FIXED),
498 memobj_rd, (vm_offset_t) offset,
499 flags & (MAP_COPY|MAP_PRIVATE),
500 vmprot, VM_PROT_ALL,
501 (flags & MAP_SHARED)
502 ? VM_INHERIT_SHARE : VM_INHERIT_COPY);
503 }
504
505 if ((flags & MAP_ANON) == 0)
506 __mach_port_deallocate (__mach_task_self (), memobj_rd);
507
508 if (err)
509 return __hurd_fail (err), MAP_FAILED;
510 return (void *) mapaddr;
511}
512
513check_no_hidden(__fstat64);
514int weak_function
515__fstat64 (int fd, struct stat64 *buf)
516{
517 error_t err;
518
519 err = __io_stat ((mach_port_t) fd, buf);
520 if (err)
521 return __hurd_fail (err);
522
523 return 0;
524}
525libc_hidden_def (__fstat64)
526
527check_no_hidden(__stat64);
528int weak_function
529__stat64 (const char *file, struct stat64 *buf)
530{
531 error_t err;
532 mach_port_t port;
533
534 err = open_file (file, 0, &port, buf);
535 if (err)
536 return __hurd_fail (err);
537
538 __mach_port_deallocate (__mach_task_self (), port);
539
540 return 0;
541}
542libc_hidden_def (__stat64)
543
544/* This function is called by the dynamic linker (rtld.c) to check for
545 existence of /etc/ld.so.preload. This stub will always fail, which
546 means that /etc/ld.so.preload is unsupported. */
547check_no_hidden(__access);
548int weak_function
549__access (const char *file, int type)
550{
551 return __hurd_fail (ENOSYS);
552}
553
554int
555__rtld_execve (const char *file_name, char *const argv[],
556 char *const envp[])
557{
558 file_t file;
559 error_t err;
560 char *args, *env;
561 size_t argslen, envlen;
562 mach_port_t *ports = _dl_hurd_data->portarray;
563 unsigned int portarraysize = _dl_hurd_data->portarraysize;
564 file_t *dtable = _dl_hurd_data->dtable;
565 unsigned int dtablesize = _dl_hurd_data->dtablesize;
566 int *intarray = _dl_hurd_data->intarray;
567 unsigned int i, j;
568 mach_port_t *please_dealloc, *pdp;
569 mach_port_t *portnames = NULL;
570 mach_msg_type_number_t nportnames = 0;
571 mach_port_type_t *porttypes = NULL;
572 mach_msg_type_number_t nporttypes = 0;
573 int flags;
574
575 err = open_file (file_name, O_EXEC, &file, NULL);
576 if (err)
577 goto out;
578
579 if (argv == NULL)
580 args = NULL, argslen = 0;
581 else if (err = __argz_create (argv, &args, &argslen))
582 goto outfile;
583 if (envp == NULL)
584 env = NULL, envlen = 0;
585 else if (err = __argz_create (envp, &env, &envlen))
586 goto outargs;
587
588 please_dealloc = __alloca ((portarraysize + dtablesize)
589 * sizeof (mach_port_t));
590 pdp = please_dealloc;
591
592 /* Get all ports that we may not know about and we should thus destroy. */
593 err = __mach_port_names (__mach_task_self (),
594 &portnames, &nportnames,
595 &porttypes, &nporttypes);
596 if (err)
597 goto outenv;
598 if (nportnames != nporttypes)
599 {
600 err = EGRATUITOUS;
601 goto outenv;
602 }
603
604 for (i = 0; i < portarraysize; ++i)
605 if (ports[i] != MACH_PORT_NULL)
606 {
607 *pdp++ = ports[i];
608 for (j = 0; j < nportnames; j++)
609 if (portnames[j] == ports[i])
610 portnames[j] = MACH_PORT_NULL;
611 }
612 for (i = 0; i < dtablesize; ++i)
613 if (dtable[i] != MACH_PORT_NULL)
614 {
615 *pdp++ = dtable[i];
616 for (j = 0; j < nportnames; j++)
617 if (portnames[j] == dtable[i])
618 portnames[j] = MACH_PORT_NULL;
619 }
620
621 /* Pack ports to be destroyed together. */
622 for (i = 0, j = 0; i < nportnames; i++)
623 {
624 if (portnames[i] == MACH_PORT_NULL)
625 continue;
626 if (j != i)
627 portnames[j] = portnames[i];
628 j++;
629 }
630 nportnames = j;
631
632 flags = 0;
633#ifdef EXEC_SIGTRAP
634 if (__sigismember (&intarray[INIT_TRACEMASK], SIGKILL))
635 flags |= EXEC_SIGTRAP;
636#endif
637
638 err = __file_exec_paths (file, __mach_task_self (), flags,
639 file_name, file_name[0] == '/' ? file_name : "",
640 args, argslen,
641 env, envlen,
642 dtable, MACH_MSG_TYPE_COPY_SEND, dtablesize,
643 ports, MACH_MSG_TYPE_COPY_SEND, portarraysize,
644 intarray, INIT_INT_MAX,
645 please_dealloc, pdp - please_dealloc,
646 portnames, nportnames);
647
648 /* Oh well. Might as well be tidy. */
649outenv:
650 free (env);
651outargs:
652 free (args);
653outfile:
654 __mach_port_deallocate (__mach_task_self (), file);
655out:
656 return err;
657}
658
659check_no_hidden(__getpid);
660pid_t weak_function
661__getpid (void)
662{
663 pid_t pid, ppid;
664 int orphaned;
665
666 if (__proc_getpids (_dl_hurd_data->portarray[INIT_PORT_PROC],
667 &pid, &ppid, &orphaned))
668 return -1;
669
670 return pid;
671}
672
673/* We need this alias to satisfy references from libc_pic.a objects
674 that were affected by the libc_hidden_proto declaration for __getpid. */
675strong_alias (__getpid, __GI___getpid)
676
677/* This is called only in some strange cases trying to guess a value
678 for $ORIGIN for the executable. The dynamic linker copes with
679 getcwd failing (dl-object.c), and it's too much hassle to include
680 the functionality here. (We could, it just requires duplicating or
681 reusing getcwd.c's code but using our special lookup function as in
682 `open', above.) */
683check_no_hidden(__getcwd);
684char *weak_function
685__getcwd (char *buf, size_t size)
686{
687 return __hurd_fail (ENOSYS), NULL;
688}
689
690/* This is used by dl-tunables.c to strdup strings. We can just make this a
691 mere allocation. */
692check_no_hidden(__sbrk);
693void *weak_function
694__sbrk (intptr_t increment)
695{
696 vm_address_t addr;
697 if (__vm_allocate (__mach_task_self (), &addr, increment, 1))
698 return NULL;
699 return (void *) addr;
700}
701
702/* This is only used by hurdlookup for the /dev/fd/nnn magic.
703 * We avoid pulling the whole libc implementation, and we can keep this hidden. */
704unsigned long int weak_function
705__strtoul_internal (const char *nptr, char **endptr, int base, int group)
706{
707 assert (base == 0 || base == 10);
708 assert (group == 0);
709 return _dl_strtoul (nptr, endptr);
710}
711
712/* We need this alias to satisfy references from libc_pic.a objects
713 that were affected by the libc_hidden_proto declaration for __strtoul_internal. */
714strong_alias (__strtoul_internal, __GI___strtoul_internal)
715strong_alias (__strtoul_internal, __GI_____strtoul_internal)
716
717check_no_hidden(_exit);
718void weak_function attribute_hidden
719_exit (int status)
720{
721 __proc_mark_exit (_dl_hurd_data->portarray[INIT_PORT_PROC],
722 W_EXITCODE (status, 0), 0);
723 while (__task_terminate (__mach_task_self ()))
724 __mach_task_self_ = (__mach_task_self) ();
725
726 LOSE;
727 abort ();
728}
729/* We need this alias to satisfy references from libc_pic.a objects
730 that were affected by the libc_hidden_proto declaration for _exit. */
731strong_alias (_exit, __GI__exit)
732
733/* Try to get a machine dependent instruction which will make the
734 program crash. This is used in case everything else fails. */
735#include <abort-instr.h>
736#ifndef ABORT_INSTRUCTION
737/* No such instruction is available. */
738# define ABORT_INSTRUCTION
739#endif
740
741check_no_hidden(abort);
742void weak_function
743abort (void)
744{
745 /* Try to abort using the system specific command. */
746 ABORT_INSTRUCTION;
747
748 /* If the abort instruction failed, exit. */
749 _exit (127);
750
751 /* If even this fails, make sure we never return. */
752 while (1)
753 /* Try for ever and ever. */
754 ABORT_INSTRUCTION;
755}
756
757/* We need this alias to satisfy references from libc_pic.a objects
758 that were affected by the libc_hidden_proto declaration for abort. */
759strong_alias (abort, __GI_abort)
760strong_alias (abort, __GI___fortify_fail)
761strong_alias (abort, __GI___assert_fail)
762strong_alias (abort, __GI___assert_perror_fail)
763
764/* This function is called by interruptible RPC stubs. For initial
765 dynamic linking, just use the normal mach_msg. Since this defn is
766 weak, the real defn in libc.so will override it if we are linked into
767 the user program (-ldl). */
768
769error_t weak_function
770_hurd_intr_rpc_mach_msg (mach_msg_header_t *msg,
771 mach_msg_option_t option,
772 mach_msg_size_t send_size,
773 mach_msg_size_t rcv_size,
774 mach_port_t rcv_name,
775 mach_msg_timeout_t timeout,
776 mach_port_t notify)
777{
778 return __mach_msg (msg, option, send_size, rcv_size, rcv_name,
779 timeout, notify);
780}
781
782
783void
784_dl_show_auxv (void)
785{
786 /* There is nothing to print. Hurd has no auxiliary vector. */
787}
788
789
790void weak_function
791_dl_init_first (void *p)
792{
793 /* This no-op definition only gets used if libc is not linked in. */
794}
795
796#endif /* SHARED */
797

source code of glibc/sysdeps/mach/hurd/dl-sysdep.c