]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/mach/hurd/dl-sysdep.c
Update.
[thirdparty/glibc.git] / sysdeps / mach / hurd / dl-sysdep.c
CommitLineData
99b306dc 1/* Operating system support for run-time dynamic linker. Hurd version.
a42195db 2 Copyright (C) 1995, 96, 97, 98, 99, 2000 Free Software Foundation, Inc.
6d52618b 3 This file is part of the GNU C Library.
99b306dc 4
6d52618b
UD
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
99b306dc 9
6d52618b
UD
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 Library General Public License for more details.
99b306dc 14
6d52618b
UD
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
99b306dc
RM
19
20#include <hurd.h>
21#include <link.h>
22#include <unistd.h>
23#include <fcntl.h>
24#include <stdlib.h>
25#include <sys/mman.h>
a42195db 26#include <ldsodefs.h>
99b306dc
RM
27#include <sys/wait.h>
28#include <assert.h>
29#include <sysdep.h>
30#include <mach/mig_support.h>
31#include "hurdstartup.h"
32#include <mach/host_info.h>
0a54e401 33#include <stdio-common/_itoa.h>
99b306dc
RM
34#include <hurd/auth.h>
35#include <hurd/term.h>
36#include <stdarg.h>
db2286f6 37#include <ctype.h>
a01680aa 38#include <sys/stat.h>
99b306dc 39
c764b9a7
UD
40#include <entry.h>
41#include <dl-machine.h>
42#include <dl-procinfo.h>
99b306dc 43
a1a9d215
RM
44extern void __mach_init (void);
45
99b306dc
RM
46extern int _dl_argc;
47extern char **_dl_argv;
48extern char **_environ;
c764b9a7 49extern void ENTRY_POINT (void);
99b306dc 50
ce7a5ef4 51int __libc_enable_secure;
c764b9a7
UD
52int __libc_multiple_libcs; /* Defining this here avoids the inclusion
53 of init-first. */
54/* This variable containts the lowest stack address ever used. */
55void *__libc_stack_end;
56unsigned long int _dl_hwcap_mask = HWCAP_IMPORTANT;
07435eb4 57
ce7a5ef4 58
99b306dc
RM
59struct hurd_startup_data *_dl_hurd_data;
60
3dc9c979
RM
61/* Defining these variables here avoids the inclusion of hurdsig.c. */
62unsigned long int __hurd_sigthread_stack_base;
63unsigned long int __hurd_sigthread_stack_end;
64unsigned long int *__hurd_sigthread_variables;
65
66/* Defining these variables here avoids the inclusion of init-first.c.
67 We need to provide temporary storage for the per-thread variables
68 of the main user thread here, since it is used for storing the
69 `errno' variable. Note that this information is lost once we
70 relocate the dynamic linker. */
5bf62f2d
RM
71static unsigned long int threadvars[_HURD_THREADVAR_MAX];
72unsigned long int __hurd_threadvar_stack_offset
73 = (unsigned long int) &threadvars;
4ca84cff 74unsigned long int __hurd_threadvar_stack_mask;
5bf62f2d 75
5bf62f2d
RM
76/* XXX loser kludge for vm_map kernel bug */
77static vm_address_t fmha;
78static vm_size_t fmhs;
4ca84cff 79static void unfmh(void){
5bf62f2d 80__vm_deallocate(__mach_task_self(),fmha,fmhs);}
4ca84cff 81static void fmh(void) {
5bf62f2d
RM
82 error_t err;int x;mach_port_t p;
83 vm_address_t a=0x08000000U,max=VM_MAX_ADDRESS;
84 while (!(err=__vm_region(__mach_task_self(),&a,&fmhs,&x,&x,&x,&x,&p,&x))){
85 __mach_port_deallocate(__mach_task_self(),p);
86 if (a+fmhs>=0x80000000U){
d819080c 87 max=a; break;}
5bf62f2d
RM
88 fmha=a+=fmhs;}
89 if (err) assert(err==KERN_NO_SPACE);
d819080c 90 if (!fmha)fmhs=0;else{
5bf62f2d
RM
91 fmhs=max-fmha;
92 err = __vm_map (__mach_task_self (),
93 &fmha, fmhs, 0, 0, MACH_PORT_NULL, 0, 1,
94 VM_PROT_NONE, VM_PROT_NONE, VM_INHERIT_COPY);
d819080c 95 assert_perror(err);}
5bf62f2d
RM
96 }
97/* XXX loser kludge for vm_map kernel bug */
98
99
100
99b306dc
RM
101Elf32_Addr
102_dl_sysdep_start (void **start_argptr,
103 void (*dl_main) (const Elf32_Phdr *phdr, Elf32_Word phent,
104 Elf32_Addr *user_entry))
105{
106 void go (int *argdata)
107 {
879bf2e6 108 extern unsigned int _dl_skip_args; /* rtld.c */
99b306dc
RM
109 char **p;
110
111 /* Cache the information in various global variables. */
a1a9d215 112 _dl_argc = *argdata;
879bf2e6 113 _dl_argv = 1 + (char **) argdata;
99b306dc 114 _environ = &_dl_argv[_dl_argc + 1];
879bf2e6
RM
115 for (p = _environ; *p++;); /* Skip environ pointers and terminator. */
116
117 if ((void *) p == _dl_argv[0])
118 {
119 static struct hurd_startup_data nodata;
120 _dl_hurd_data = &nodata;
c764b9a7 121 nodata.user_entry = (vm_address_t) &ENTRY_POINT;
879bf2e6
RM
122 }
123 else
124 _dl_hurd_data = (void *) p;
99b306dc 125
cddcfecf 126 __libc_enable_secure = _dl_hurd_data->flags & EXEC_SECURE;
99b306dc 127
ec967c06
RM
128 if (_dl_hurd_data->flags & EXEC_STACK_ARGS &&
129 _dl_hurd_data->user_entry == 0)
c764b9a7 130 _dl_hurd_data->user_entry = (vm_address_t) &ENTRY_POINT;
ec967c06 131
5bf62f2d 132unfmh(); /* XXX */
879bf2e6 133
a9ddb793 134#if 0 /* XXX make this work for real someday... */
c764b9a7 135 if (_dl_hurd_data->user_entry == (vm_address_t) &ENTRY_POINT)
879bf2e6
RM
136 /* We were invoked as a command, not as the program interpreter.
137 The generic ld.so code supports this: it will parse the args
138 as "ld.so PROGRAM [ARGS...]". For booting the Hurd, we
139 support an additional special syntax:
140 ld.so [-LIBS...] PROGRAM [ARGS...]
141 Each LIBS word consists of "FILENAME=MEMOBJ";
142 for example "-/lib/libc.so=123" says that the contents of
143 /lib/libc.so are found in a memory object whose port name
144 in our task is 123. */
6a76c115 145 while (_dl_argc > 2 && _dl_argv[1][0] == '-' && _dl_argv[1][1] != '-')
879bf2e6
RM
146 {
147 char *lastslash, *memobjname, *p;
148 struct link_map *l;
149 mach_port_t memobj;
150 error_t err;
151
152 ++_dl_skip_args;
153 --_dl_argc;
154 p = _dl_argv++[1] + 1;
155
156 memobjname = strchr (p, '=');
157 if (! memobjname)
158 _dl_sysdep_fatal ("Bogus library spec: ", p, "\n", NULL);
159 *memobjname++ = '\0';
db2286f6
RM
160 memobj = 0;
161 while (*memobjname != '\0')
162 memobj = (memobj * 10) + (*memobjname++ - '0');
ec967c06 163
879bf2e6
RM
164 /* Add a user reference on the memory object port, so we will
165 still have one after _dl_map_object_from_fd calls our
166 `close'. */
167 err = __mach_port_mod_refs (__mach_task_self (), memobj,
168 MACH_PORT_RIGHT_SEND, +1);
169 assert_perror (err);
ec967c06 170
879bf2e6
RM
171 lastslash = strrchr (p, '/');
172 l = _dl_map_object_from_fd (lastslash ? lastslash + 1 : p,
2f54c82d 173 memobj, strdup (p), 0);
879bf2e6
RM
174
175 /* Squirrel away the memory object port where it
176 can be retrieved by the program later. */
177 l->l_info[DT_NULL] = (void *) memobj;
178 }
a9ddb793 179#endif
879bf2e6 180
99b306dc
RM
181 /* Call elf/rtld.c's main program. It will set everything
182 up and leave us to transfer control to USER_ENTRY. */
183 (*dl_main) ((const Elf32_Phdr *) _dl_hurd_data->phdr,
184 _dl_hurd_data->phdrsz / sizeof (Elf32_Phdr),
185 &_dl_hurd_data->user_entry);
186
879bf2e6
RM
187 if (_dl_skip_args && _dl_argv[-_dl_skip_args] == (char *) p)
188 {
189 /* We are ignoring the first few arguments, but we have no Hurd
190 startup data. It is magical convention that ARGV[0] == P in
191 this case. The startup code in init-first.c will get confused
192 if this is not the case, so we must rearrange things to make
193 it so. Overwrite the original ARGV[0] at P with
194 ARGV[_dl_skip_args]. */
195 assert ((char *) p < _dl_argv[0]);
196 _dl_argv[0] = strcpy ((char *) p, _dl_argv[0]);
197 }
198
99b306dc
RM
199 {
200 extern void _dl_start_user (void);
201 /* Unwind the stack to ARGDATA and simulate a return from _dl_start
202 to the RTLD_START code which will run the user's entry point. */
203 RETURN_TO (argdata, &_dl_start_user, _dl_hurd_data->user_entry);
204 }
205 }
206
a1a9d215
RM
207 /* Set up so we can do RPCs. */
208 __mach_init ();
209
0a54e401
UD
210 /* Initialize frequently used global variable. */
211 _dl_pagesize = __getpagesize ();
212
5bf62f2d
RM
213fmh(); /* XXX */
214
99b306dc
RM
215 /* See hurd/hurdstartup.c; this deals with getting information
216 from the exec server and slicing up the arguments.
217 Then it will call `go', above. */
218 _hurd_startup (start_argptr, &go);
219
220 LOSE;
54da5be3 221 abort ();
99b306dc 222}
4cb20290
RM
223
224void
225_dl_sysdep_start_cleanup (void)
226{
227 /* Deallocate the reply port and task port rights acquired by
228 __mach_init. We are done with them now, and the user will
229 reacquire them for himself when he wants them. */
230 __mig_dealloc_reply_port (MACH_PORT_NULL);
231 __mach_port_deallocate (__mach_task_self (), __mach_task_self_);
232}
99b306dc 233\f
99b306dc
RM
234/* Minimal open/close/mmap implementation sufficient for initial loading of
235 shared libraries. These are weak definitions so that when the
236 dynamic linker re-relocates itself to be user-visible (for -ldl),
237 it will get the user's definition (i.e. usually libc's). */
238
eb0e1178 239/* Open FILE_NAME and return a Hurd I/O for it in *PORT, or
a01680aa
MB
240 return an error. If STAT is non-zero, stat the file into that stat buffer. */
241static error_t
242open_file (const char *file_name, int mode,
eb0e1178 243 mach_port_t *port, struct stat *stat)
99b306dc 244{
99b306dc
RM
245 enum retry_type doretry;
246 char retryname[1024]; /* XXX string_t LOSES! */
247 file_t startdir, newpt, fileport;
248 int dealloc_dir;
249 int nloops;
b122c703 250 error_t err;
99b306dc 251
e852e889 252 assert (!(mode & ~O_READ));
99b306dc 253
99b306dc
RM
254 startdir = _dl_hurd_data->portarray[file_name[0] == '/' ?
255 INIT_PORT_CRDIR : INIT_PORT_CWDIR];
256
257 while (file_name[0] == '/')
258 file_name++;
259
a01680aa 260 if (err = __dir_lookup (startdir, (char *)file_name, mode, 0,
b122c703 261 &doretry, retryname, &fileport))
a01680aa 262 return err;
99b306dc
RM
263
264 dealloc_dir = 0;
265 nloops = 0;
ec967c06 266
99b306dc
RM
267 while (1)
268 {
269 if (dealloc_dir)
270 __mach_port_deallocate (__mach_task_self (), startdir);
b122c703 271 if (err)
a01680aa 272 return err;
99b306dc
RM
273
274 switch (doretry)
275 {
276 case FS_RETRY_REAUTH:
277 {
278 mach_port_t ref = __mach_reply_port ();
b122c703
RM
279 err = __io_reauthenticate (fileport, ref, MACH_MSG_TYPE_MAKE_SEND);
280 if (! err)
281 err = __auth_user_authenticate
99b306dc 282 (_dl_hurd_data->portarray[INIT_PORT_AUTH],
99b306dc
RM
283 ref, MACH_MSG_TYPE_MAKE_SEND,
284 &newpt);
285 __mach_port_destroy (__mach_task_self (), ref);
286 }
287 __mach_port_deallocate (__mach_task_self (), fileport);
b122c703 288 if (err)
a01680aa 289 return err;
99b306dc
RM
290 fileport = newpt;
291 /* Fall through. */
292
293 case FS_RETRY_NORMAL:
294#ifdef SYMLOOP_MAX
295 if (nloops++ >= SYMLOOP_MAX)
a01680aa 296 return ELOOP;
99b306dc
RM
297#endif
298
299 /* An empty RETRYNAME indicates we have the final port. */
300 if (retryname[0] == '\0')
301 {
99b306dc 302 dealloc_dir = 1;
99b306dc
RM
303 opened:
304 /* We have the file open. Now map it. */
a01680aa
MB
305 if (stat)
306 err = __io_stat (fileport, stat);
a01680aa 307
b122c703 308 if (err)
eb0e1178
UD
309 {
310 if (dealloc_dir)
311 __mach_port_deallocate (__mach_task_self (), fileport);
312 }
313 else
314 {
315 if (!dealloc_dir)
316 __mach_port_mod_refs (__mach_task_self (), fileport,
317 MACH_PORT_RIGHT_SEND, 1);
318 *port = fileport;
319 }
99b306dc 320
eb0e1178 321 return err;
99b306dc
RM
322 }
323
324 startdir = fileport;
325 dealloc_dir = 1;
326 file_name = retryname;
327 break;
328
329 case FS_RETRY_MAGICAL:
330 switch (retryname[0])
331 {
332 case '/':
333 startdir = _dl_hurd_data->portarray[INIT_PORT_CRDIR];
334 dealloc_dir = 0;
335 if (fileport != MACH_PORT_NULL)
336 __mach_port_deallocate (__mach_task_self (), fileport);
337 file_name = &retryname[1];
338 break;
339
340 case 'f':
db2286f6
RM
341 if (retryname[1] == 'd' && retryname[2] == '/' &&
342 isdigit (retryname[3]))
99b306dc 343 {
db2286f6
RM
344 /* We can't use strtol for the decoding here
345 because it brings in hairy locale bloat. */
346 char *p;
347 int fd = 0;
348 for (p = &retryname[3]; isdigit (*p); ++p)
349 fd = (fd * 10) + (*p - '0');
350 /* Check for excess text after the number. A slash is
351 valid; it ends the component. Anything else does not
352 name a numeric file descriptor. */
353 if (*p != '/' && *p != '\0')
a01680aa 354 return ENOENT;
99b306dc
RM
355 if (fd < 0 || fd >= _dl_hurd_data->dtablesize ||
356 _dl_hurd_data->dtable[fd] == MACH_PORT_NULL)
b122c703
RM
357 /* If the name was a proper number, but the file
358 descriptor does not exist, we return EBADF instead
359 of ENOENT. */
a01680aa 360 return EBADF;
99b306dc 361 fileport = _dl_hurd_data->dtable[fd];
db2286f6 362 if (*p == '\0')
99b306dc
RM
363 {
364 /* This descriptor is the file port we want. */
365 dealloc_dir = 0;
366 goto opened;
367 }
368 else
369 {
370 /* Do a normal retry on the remaining components. */
371 startdir = fileport;
372 dealloc_dir = 1;
db2286f6 373 file_name = p + 1; /* Skip the slash. */
99b306dc
RM
374 break;
375 }
376 }
377 else
378 goto bad_magic;
379 break;
380
381 case 'm':
382 if (retryname[1] == 'a' && retryname[2] == 'c' &&
383 retryname[3] == 'h' && retryname[4] == 't' &&
384 retryname[5] == 'y' && retryname[6] == 'p' &&
385 retryname[7] == 'e')
386 {
387 error_t err;
388 struct host_basic_info hostinfo;
389 mach_msg_type_number_t hostinfocnt = HOST_BASIC_INFO_COUNT;
390 char *p;
391 if (err = __host_info (__mach_host_self (), HOST_BASIC_INFO,
392 (natural_t *) &hostinfo,
393 &hostinfocnt))
394 return err;
395 if (hostinfocnt != HOST_BASIC_INFO_COUNT)
396 return EGRATUITOUS;
397 p = _itoa (hostinfo.cpu_subtype, &retryname[8], 10, 0);
398 *--p = '/';
399 p = _itoa (hostinfo.cpu_type, &retryname[8], 10, 0);
400 if (p < retryname)
401 abort (); /* XXX write this right if this ever happens */
402 if (p > retryname)
403 strcpy (retryname, p);
404 startdir = fileport;
405 dealloc_dir = 1;
406 }
407 else
408 goto bad_magic;
409 break;
410
411 case 't':
412 if (retryname[1] == 't' && retryname[2] == 'y')
413 switch (retryname[3])
414 {
415 error_t opentty (file_t *result)
416 {
417 error_t err;
418 file_t unauth;
419 err = __termctty_open_terminal
420 (_dl_hurd_data->portarray[INIT_PORT_CTTYID],
421 mode, &unauth);
422 if (! err)
423 {
424 mach_port_t ref = __mach_reply_port ();
54da5be3 425 err = __io_reauthenticate
99b306dc
RM
426 (unauth, ref, MACH_MSG_TYPE_MAKE_SEND);
427 if (! err)
428 err = __auth_user_authenticate
429 (_dl_hurd_data->portarray[INIT_PORT_AUTH],
99b306dc
RM
430 ref, MACH_MSG_TYPE_MAKE_SEND,
431 result);
432 __mach_port_deallocate (__mach_task_self (),
433 unauth);
434 __mach_port_destroy (__mach_task_self (), ref);
435 }
436 return err;
437 }
438
439 case '\0':
b122c703 440 if (err = opentty (&fileport))
a01680aa 441 return err;
99b306dc
RM
442 dealloc_dir = 1;
443 goto opened;
444 case '/':
b122c703 445 if (err = opentty (&startdir))
a01680aa 446 return err;
99b306dc
RM
447 dealloc_dir = 1;
448 strcpy (retryname, &retryname[4]);
449 break;
450 default:
451 goto bad_magic;
452 }
453 else
454 goto bad_magic;
455 break;
456
457 default:
458 bad_magic:
a01680aa 459 return EGRATUITOUS;
99b306dc 460 }
ec967c06 461 break;
99b306dc
RM
462
463 default:
a01680aa 464 return EGRATUITOUS;
99b306dc
RM
465 }
466
a01680aa 467 err = __dir_lookup (startdir, (char *)file_name, mode, 0,
b122c703 468 &doretry, retryname, &fileport);
99b306dc
RM
469 }
470}
471
a01680aa
MB
472int weak_function
473__open (const char *file_name, int mode, ...)
474{
eb0e1178
UD
475 mach_port_t port;
476 error_t err = open_file (file_name, mode, &port, 0);
a01680aa
MB
477 if (err)
478 return __hurd_fail (err);
479 else
eb0e1178 480 return (int)port;
a01680aa
MB
481}
482
af5b3bc3 483int weak_function
266180eb 484__close (int fd)
99b306dc
RM
485{
486 if (fd != (int) MACH_PORT_NULL)
487 __mach_port_deallocate (__mach_task_self (), (mach_port_t) fd);
488 return 0;
489}
490
eb0e1178
UD
491__ssize_t weak_function
492__libc_read (int fd, void *buf, size_t nbytes)
493{
494 error_t err;
495 char *data;
496 mach_msg_type_number_t nread;
497
498 data = buf;
499 err = __io_read ((mach_port_t) fd, &data, &nread, -1, nbytes);
500 if (err)
501 return __hurd_fail (err);
502
503 if (data != buf)
504 {
505 memcpy (buf, data, nread);
506 __vm_deallocate (__mach_task_self (), (vm_address_t) data, nread);
507 }
508
509 return nread;
510}
511
3dc9c979
RM
512__ssize_t weak_function
513__libc_write (int fd, const void *buf, size_t nbytes)
514{
515 error_t err;
516 mach_msg_type_number_t nwrote;
67afae58 517
3dc9c979 518 assert (fd < _hurd_init_dtablesize);
67afae58 519
3dc9c979
RM
520 err = __io_write (_hurd_init_dtable[fd], buf, nbytes, -1, &nwrote);
521 if (err)
522 return __hurd_fail (err);
523
524 return nwrote;
525}
526
ddbf7fef
UD
527off_t weak_function
528__lseek (int fd, off_t offset, int whence)
529{
530 error_t err;
3c068816 531
ddbf7fef
UD
532 err = __io_seek ((mach_port_t) fd, offset, whence, &offset);
533 if (err)
534 return __hurd_fail (err);
3c068816 535
ddbf7fef
UD
536 return offset;
537}
538
4bca4c17
UD
539__ptr_t weak_function
540__mmap (__ptr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
99b306dc 541{
b122c703 542 error_t err;
99b306dc
RM
543 vm_prot_t vmprot;
544 vm_address_t mapaddr;
eb0e1178 545 mach_port_t memobj_rd, memobj_wr;
99b306dc
RM
546
547 vmprot = VM_PROT_NONE;
548 if (prot & PROT_READ)
549 vmprot |= VM_PROT_READ;
550 if (prot & PROT_WRITE)
551 vmprot |= VM_PROT_WRITE;
552 if (prot & PROT_EXEC)
553 vmprot |= VM_PROT_EXECUTE;
554
eb0e1178
UD
555 if (flags & MAP_ANON)
556 memobj_rd = MACH_PORT_NULL;
557 else
558 {
07435eb4 559 assert (!(flags & MAP_SHARED));
eb0e1178
UD
560 err = __io_map ((mach_port_t) fd, &memobj_rd, &memobj_wr);
561 if (err)
562 return (__ptr_t) __hurd_fail (err);
563 __mach_port_deallocate (__mach_task_self (), memobj_wr);
564 }
565
99b306dc 566 mapaddr = (vm_address_t) addr;
b122c703
RM
567 err = __vm_map (__mach_task_self (),
568 &mapaddr, (vm_size_t) len, 0 /*ELF_MACHINE_USER_ADDRESS_MASK*/,
569 !(flags & MAP_FIXED),
eb0e1178 570 memobj_rd,
2064087b 571 (vm_offset_t) offset,
b122c703
RM
572 flags & (MAP_COPY|MAP_PRIVATE),
573 vmprot, VM_PROT_ALL,
755f55b0 574 (flags & MAP_SHARED) ? VM_INHERIT_SHARE : VM_INHERIT_COPY);
22930c9b
RM
575 if (err == KERN_NO_SPACE && (flags & MAP_FIXED))
576 {
577 /* XXX this is not atomic as it is in unix! */
578 /* The region is already allocated; deallocate it first. */
579 err = __vm_deallocate (__mach_task_self (), mapaddr, len);
580 if (! err)
581 err = __vm_map (__mach_task_self (),
582 &mapaddr, (vm_size_t) len, 0 /*ELF_MACHINE_USER_ADDRESS_MASK*/,
583 !(flags & MAP_FIXED),
eb0e1178 584 memobj_rd, (vm_offset_t) offset,
22930c9b
RM
585 flags & (MAP_COPY|MAP_PRIVATE),
586 vmprot, VM_PROT_ALL,
587 (flags & MAP_SHARED)
588 ? VM_INHERIT_SHARE : VM_INHERIT_COPY);
589 }
590
eb0e1178
UD
591 if ((flags & MAP_ANON) == 0)
592 __mach_port_deallocate (__mach_task_self (), memobj_rd);
593
4bca4c17 594 return err ? (__ptr_t) __hurd_fail (err) : (__ptr_t) mapaddr;
99b306dc
RM
595}
596
e852e889
UD
597int weak_function
598__fxstat (int vers, int fd, struct stat *buf)
599{
600 error_t err;
3c068816 601
e852e889 602 assert (vers == _STAT_VER);
3c068816 603
e852e889
UD
604 err = __io_stat ((mach_port_t) fd, buf);
605 if (err)
606 return __hurd_fail (err);
607
608 return 0;
e852e889
UD
609}
610
611int weak_function
612__xstat (int vers, const char *file, struct stat *buf)
613{
614 error_t err;
615 mach_port_t port;
3c068816 616
e852e889
UD
617 assert (vers == _STAT_VER);
618
619 err = open_file (file, 0, &port, buf);
620 if (err)
621 return __hurd_fail (err);
622
623 __mach_port_deallocate (__mach_task_self (), port);
624
625 return 0;
626}
627
ddbf7fef
UD
628pid_t weak_function
629__getpid ()
630{
631 pid_t pid, ppid;
632 int orphaned;
3c068816 633
ddbf7fef
UD
634 if (__proc_getpids (_dl_hurd_data->portarray[INIT_PORT_PROC],
635 &pid, &ppid, &orphaned))
636 return -1;
637
638 return pid;
639}
640
67afae58
RM
641/* This is called only in some strange cases trying to guess a value
642 for $ORIGIN for the executable. The dynamic linker copes with
643 getcwd failing (dl-object.c), and it's too much hassle to include
644 the functionality here. (We could, it just requires duplicating or
645 reusing getcwd.c's code but using our special lookup function as in
646 `open', above.) */
3dc9c979
RM
647char *
648weak_function
649__getcwd (char *buf, size_t size)
650{
67afae58 651 errno = ENOSYS;
3dc9c979
RM
652 return NULL;
653}
654
af5b3bc3 655void weak_function
99b306dc
RM
656_exit (int status)
657{
54da5be3 658 __proc_mark_exit (_dl_hurd_data->portarray[INIT_PORT_PROC],
0e3426bb 659 W_EXITCODE (status, 0), 0);
99b306dc
RM
660 while (__task_terminate (__mach_task_self ()))
661 __mach_task_self_ = (__mach_task_self) ();
662}
ddbf7fef
UD
663
664/* Try to get a machine dependent instruction which will make the
665 program crash. This is used in case everything else fails. */
666#include <abort-instr.h>
667#ifndef ABORT_INSTRUCTION
668/* No such instruction is available. */
669# define ABORT_INSTRUCTION
670#endif
671
672void weak_function
673abort (void)
674{
675 /* Try to abort using the system specific command. */
676 ABORT_INSTRUCTION;
677
678 /* If the abort instruction failed, exit. */
679 _exit (127);
680
681 /* If even this fails, make sure we never return. */
682 while (1)
683 /* Try for ever and ever. */
684 ABORT_INSTRUCTION;
685}
3dc9c979 686\f
54da5be3
RM
687/* This function is called by interruptible RPC stubs. For initial
688 dynamic linking, just use the normal mach_msg. Since this defn is
99b306dc
RM
689 weak, the real defn in libc.so will override it if we are linked into
690 the user program (-ldl). */
54da5be3 691
af5b3bc3 692error_t weak_function
54da5be3
RM
693_hurd_intr_rpc_mach_msg (mach_msg_header_t *msg,
694 mach_msg_option_t option,
695 mach_msg_size_t send_size,
696 mach_msg_size_t rcv_size,
697 mach_port_t rcv_name,
698 mach_msg_timeout_t timeout,
699 mach_port_t notify)
700{
701 return __mach_msg (msg, option, send_size, rcv_size, rcv_name,
702 timeout, notify);
703}
ca34d7a7 704
3dc9c979 705
ca34d7a7 706void
c764b9a7 707internal_function
ca34d7a7
UD
708_dl_show_auxv (void)
709{
710 /* There is nothing to print. Hurd has no auxiliary vector. */
711}
7e7a548e 712
c764b9a7
UD
713
714/* Return an array of useful/necessary hardware capability names. */
715const struct r_strlenpair *
716internal_function
717_dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
718 size_t *max_capstrlen)
719{
720 struct r_strlenpair *result;
721
722 /* Return an empty array. Hurd has no hardware capabilities. */
723 result = (struct r_strlenpair *) malloc (sizeof (*result));
724 if (result == NULL)
725 _dl_signal_error (ENOMEM, NULL, "cannot create capability list");
726
727 result[0].str = (char *) result; /* Does not really matter. */
728 result[0].len = 0;
729
730 *sz = 1;
731 return result;
732}
5879ee9f
RM
733
734void weak_function
735_dl_init_first (int argc, ...)
736{
737 /* This no-op definition only gets used if libc is not linked in. */
738}