1 /* Operating system support for run-time dynamic linker. Hurd version.
2 Copyright (C) 1995 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
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
17 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
18 Cambridge, MA 02139, USA. */
29 #include <mach/mig_support.h>
30 #include "hurdstartup.h"
31 #include <mach/host_info.h>
32 #include "../stdio/_itoa.h"
33 #include <hurd/auth.h>
34 #include <hurd/term.h>
37 #include "dl-machine.h"
39 extern void __mach_init (void);
42 extern char **_dl_argv;
43 extern char **_environ;
45 struct hurd_startup_data *_dl_hurd_data;
48 _dl_sysdep_start (void **start_argptr,
49 void (*dl_main) (const Elf32_Phdr *phdr, Elf32_Word phent,
50 Elf32_Addr *user_entry))
52 void go (int *argdata)
56 /* Cache the information in various global variables. */
58 _dl_argv = (void *) &argdata[1];
59 _environ = &_dl_argv[_dl_argc + 1];
60 for (p = _environ; *p; ++p);
61 _dl_hurd_data = (void *) ++p;
63 _dl_secure = _dl_hurd_data->flags & EXEC_SECURE;
65 /* Call elf/rtld.c's main program. It will set everything
66 up and leave us to transfer control to USER_ENTRY. */
67 (*dl_main) ((const Elf32_Phdr *) _dl_hurd_data->phdr,
68 _dl_hurd_data->phdrsz / sizeof (Elf32_Phdr),
69 &_dl_hurd_data->user_entry);
71 /* Deallocate the reply port and task port rights acquired by
72 __mach_init. We are done with them now, and the user will
73 reacquire them for himself when he wants them. */
74 __mig_dealloc_reply_port (MACH_PORT_NULL);
75 __mach_port_deallocate (__mach_task_self (), __mach_task_self_);
78 extern void _dl_start_user (void);
79 /* Unwind the stack to ARGDATA and simulate a return from _dl_start
80 to the RTLD_START code which will run the user's entry point. */
81 RETURN_TO (argdata, &_dl_start_user, _dl_hurd_data->user_entry);
85 /* Set up so we can do RPCs. */
88 /* See hurd/hurdstartup.c; this deals with getting information
89 from the exec server and slicing up the arguments.
90 Then it will call `go', above. */
91 _hurd_startup (start_argptr, &go);
96 /* This is called when all other dynamic linking is finished, before the
97 dynamic linker re-relocates itself when ld.so itself appears in a
98 DT_NEEDED entry. It is called whether of not ld.so is being linked in.
100 We take this opportunity to deallocate the reply port and task-self send
101 right user reference we have acquired, since they will not be used again
102 before the library and user code runs. The C library will acquire its
103 own ports in its initialization. */
106 _dl_sysdep_prepare_for_ld_reloc (void)
108 __mig_dealloc_reply_port (__mig_get_reply_port ());
109 __mach_port_deallocate (__mach_task_self (), __mach_task_self ());
113 _dl_sysdep_open_zero_fill (void)
115 return (int) MACH_PORT_NULL;
120 _dl_sysdep_fatal (const char *msg, ...)
122 extern __typeof (__io_write) __hurd_intr_rpc_io_write;
128 size_t len = strlen (msg);
129 mach_msg_type_number_t nwrote;
132 if (__hurd_intr_rpc_io_write (_hurd_init_dtable[2],
133 msg, len, -1, &nwrote))
137 } while (nwrote > 0);
138 msg = va_arg (ap, const char *);
146 /* Minimal open/close/mmap implementation sufficient for initial loading of
147 shared libraries. These are weak definitions so that when the
148 dynamic linker re-relocates itself to be user-visible (for -ldl),
149 it will get the user's definition (i.e. usually libc's). */
152 open (const char *file_name, int mode, ...)
154 extern __typeof (__dir_lookup) __hurd_intr_rpc_dir_lookup;
155 extern __typeof (__io_reauthenticate) __hurd_intr_rpc_io_reauthenticate;
156 enum retry_type doretry;
157 char retryname[1024]; /* XXX string_t LOSES! */
158 file_t startdir, newpt, fileport;
163 assert (mode == O_RDONLY);
166 startdir = _dl_hurd_data->portarray[file_name[0] == '/' ?
167 INIT_PORT_CRDIR : INIT_PORT_CWDIR];
169 while (file_name[0] == '/')
172 if (errno = __hurd_intr_rpc_dir_lookup (startdir, file_name, mode, 0,
173 &doretry, retryname, &fileport))
183 __mach_port_deallocate (__mach_task_self (), startdir);
189 case FS_RETRY_REAUTH:
191 mach_port_t ref = __mach_reply_port ();
192 errno = __hurd_intr_rpc_io_reauthenticate
193 (fileport, ref, MACH_MSG_TYPE_MAKE_SEND);
195 errno = __auth_user_authenticate
196 (_dl_hurd_data->portarray[INIT_PORT_AUTH],
198 ref, MACH_MSG_TYPE_MAKE_SEND,
200 __mach_port_destroy (__mach_task_self (), ref);
202 __mach_port_deallocate (__mach_task_self (), fileport);
208 case FS_RETRY_NORMAL:
210 if (nloops++ >= SYMLOOP_MAX)
217 /* An empty RETRYNAME indicates we have the final port. */
218 if (retryname[0] == '\0')
220 mach_port_t memobj_rd, memobj_wr;
221 extern __typeof (__io_map) __hurd_intr_rpc_io_map;
226 /* We have the file open. Now map it. */
227 errno = __hurd_intr_rpc_io_map (fileport,
228 &memobj_rd, &memobj_wr);
230 __mach_port_deallocate (__mach_task_self (), fileport);
233 if (memobj_wr != MACH_PORT_NULL)
234 __mach_port_deallocate (__mach_task_self (), memobj_wr);
236 return (int) memobj_rd;
241 file_name = retryname;
244 case FS_RETRY_MAGICAL:
245 switch (retryname[0])
248 startdir = _dl_hurd_data->portarray[INIT_PORT_CRDIR];
250 if (fileport != MACH_PORT_NULL)
251 __mach_port_deallocate (__mach_task_self (), fileport);
252 file_name = &retryname[1];
256 if (retryname[1] == 'd' && retryname[2] == '/')
261 fd = (int) strtol (retryname, &end, 10);
262 if (end == NULL || errno || /* Malformed number. */
263 /* Check for excess text after the number. A slash
264 is valid; it ends the component. Anything else
265 does not name a numeric file descriptor. */
266 (*end != '/' && *end != '\0'))
271 if (fd < 0 || fd >= _dl_hurd_data->dtablesize ||
272 _dl_hurd_data->dtable[fd] == MACH_PORT_NULL)
274 /* If the name was a proper number, but the file
275 descriptor does not exist, we return EBADF instead
280 fileport = _dl_hurd_data->dtable[fd];
283 /* This descriptor is the file port we want. */
289 /* Do a normal retry on the remaining components. */
292 file_name = end + 1; /* Skip the slash. */
301 if (retryname[1] == 'a' && retryname[2] == 'c' &&
302 retryname[3] == 'h' && retryname[4] == 't' &&
303 retryname[5] == 'y' && retryname[6] == 'p' &&
307 struct host_basic_info hostinfo;
308 mach_msg_type_number_t hostinfocnt = HOST_BASIC_INFO_COUNT;
310 if (err = __host_info (__mach_host_self (), HOST_BASIC_INFO,
311 (natural_t *) &hostinfo,
314 if (hostinfocnt != HOST_BASIC_INFO_COUNT)
316 p = _itoa (hostinfo.cpu_subtype, &retryname[8], 10, 0);
318 p = _itoa (hostinfo.cpu_type, &retryname[8], 10, 0);
320 abort (); /* XXX write this right if this ever happens */
322 strcpy (retryname, p);
331 if (retryname[1] == 't' && retryname[2] == 'y')
332 switch (retryname[3])
334 error_t opentty (file_t *result)
338 err = __termctty_open_terminal
339 (_dl_hurd_data->portarray[INIT_PORT_CTTYID],
343 mach_port_t ref = __mach_reply_port ();
344 err = __hurd_intr_rpc_io_reauthenticate
345 (unauth, ref, MACH_MSG_TYPE_MAKE_SEND);
347 err = __auth_user_authenticate
348 (_dl_hurd_data->portarray[INIT_PORT_AUTH],
350 ref, MACH_MSG_TYPE_MAKE_SEND,
352 __mach_port_deallocate (__mach_task_self (),
354 __mach_port_destroy (__mach_task_self (), ref);
360 if (errno = opentty (&fileport))
365 if (errno = opentty (&startdir))
368 strcpy (retryname, &retryname[4]);
389 errno = __hurd_intr_rpc_dir_lookup (startdir, file_name, mode, 0,
390 &doretry, retryname, &fileport);
397 if (fd != (int) MACH_PORT_NULL)
398 __mach_port_deallocate (__mach_task_self (), (mach_port_t) fd);
403 mmap (caddr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
406 vm_address_t mapaddr;
408 vmprot = VM_PROT_NONE;
409 if (prot & PROT_READ)
410 vmprot |= VM_PROT_READ;
411 if (prot & PROT_WRITE)
412 vmprot |= VM_PROT_WRITE;
413 if (prot & PROT_EXEC)
414 vmprot |= VM_PROT_EXECUTE;
416 mapaddr = (vm_address_t) addr;
417 errno = __vm_map (__mach_task_self (),
418 &mapaddr, (vm_size_t) len, (vm_address_t) 0,
419 !(flags & MAP_FIXED),
420 (mach_port_t) fd, (vm_offset_t) offset,
421 flags & (MAP_COPY|MAP_PRIVATE),
423 (flags & MAP_INHERIT) ? VM_INHERIT_COPY : VM_INHERIT_NONE);
424 return errno ? (caddr_t) -1 : (caddr_t) mapaddr;
430 extern __typeof (__proc_mark_exit) __hurd_intr_rpc_proc_mark_exit;
431 __hurd_intr_rpc_proc_mark_exit (_dl_hurd_data->portarray[INIT_PORT_PROC],
432 W_EXITCODE (status, 0));
433 while (__task_terminate (__mach_task_self ()))
434 __mach_task_self_ = (__mach_task_self) ();
442 /* Minimal `malloc' allocator for use while loading shared libraries.
443 Only small blocks are allocated, and none are ever freed. */
448 static vm_address_t ptr, end;
453 /* Consume any unused space in the last page of our data segment. */
455 ptr = (vm_address_t) &_end;
456 end = round_page (ptr);
459 /* Make sure the allocation pointer is ideally aligned. */
460 ptr += sizeof (double) - 1;
461 ptr &= ~(sizeof (double) - 1);
465 /* Insufficient space left; allocate another page. */
467 assert (n <= __vm_page_size);
468 __vm_allocate (__mach_task_self (), &page, __vm_page_size, 1);
471 end = page + __vm_page_size;
474 block = (void *) ptr;
481 /* These should never be called. */
482 void *realloc (void *ptr, size_t n) { ptr += n; abort (); }
483 void free (void *ptr) { ptr = ptr; abort (); }
484 weak_symbol (realloc)
487 /* Avoid signal frobnication in setjmp/longjmp. */
489 int __sigjmp_save (sigjmp_buf env, int savemask)
490 { env[0].__mask_was_saved = savemask; return 0; }
491 weak_symbol (__sigjmp_save)
494 longjmp (jmp_buf env, int val) { __longjmp (env[0].__jmpbuf, val); }
495 weak_symbol (longjmp)
498 /* Stub out this function that is called by interruptible RPC stubs. It
499 should never get called during initial dynamic linking, because we use
500 only the raw MiG stub functions __hurd_intr_rpc_*. Since this defn is
501 weak, the real defn in libc.so will override it if we are linked into
502 the user program (-ldl). */
503 struct hurd_sigstate *
504 _hurd_thread_sigstate (thread_t thread) { thread = thread; abort (); }
505 weak_symbol (_hurd_thread_sigstate)