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