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

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