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