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