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"
40 extern char **_dl_argv;
41 extern char **_environ;
43 struct hurd_startup_data *_dl_hurd_data;
46 _dl_sysdep_start (void **start_argptr,
47 void (*dl_main) (const Elf32_Phdr *phdr, Elf32_Word phent,
48 Elf32_Addr *user_entry))
50 void go (int *argdata)
54 /* Cache the information in various global variables. */
55 _dl_argc = *argdata++;
56 _dl_argv = (void *) argdata;
57 _environ = &_dl_argv[_dl_argc + 1];
58 for (p = _environ; *p; ++p);
59 _dl_hurd_data = (void *) ++p;
61 _dl_secure = _dl_hurd_data->flags & EXEC_SECURE;
63 /* Call elf/rtld.c's main program. It will set everything
64 up and leave us to transfer control to USER_ENTRY. */
65 (*dl_main) ((const Elf32_Phdr *) _dl_hurd_data->phdr,
66 _dl_hurd_data->phdrsz / sizeof (Elf32_Phdr),
67 &_dl_hurd_data->user_entry);
70 extern void _dl_start_user (void);
71 /* Unwind the stack to ARGDATA and simulate a return from _dl_start
72 to the RTLD_START code which will run the user's entry point. */
73 RETURN_TO (argdata, &_dl_start_user, _dl_hurd_data->user_entry);
77 /* See hurd/hurdstartup.c; this deals with getting information
78 from the exec server and slicing up the arguments.
79 Then it will call `go', above. */
80 _hurd_startup (start_argptr, &go);
85 /* This is called when all other dynamic linking is finished, before the
86 dynamic linker re-relocates itself when ld.so itself appears in a
87 DT_NEEDED entry. It is called whether of not ld.so is being linked in.
89 We take this opportunity to deallocate the reply port and task-self send
90 right user reference we have acquired, since they will not be used again
91 before the library and user code runs. The C library will acquire its
92 own ports in its initialization. */
95 _dl_sysdep_prepare_for_ld_reloc (void)
97 __mig_dealloc_reply_port (__mig_get_reply_port ());
98 __mach_port_deallocate (__mach_task_self (), __mach_task_self ());
102 _dl_sysdep_open_zero_fill (void)
104 return (int) MACH_PORT_NULL;
109 _dl_sysdep_fatal (const char *msg, ...)
111 extern __typeof (__io_write) __hurd_intr_rpc_io_write;
117 size_t len = strlen (msg);
118 mach_msg_type_number_t nwrote;
121 if (__hurd_intr_rpc_io_write (_hurd_init_dtable[2],
122 msg, len, -1, &nwrote))
126 } while (nwrote > 0);
127 msg = va_arg (ap, const char *);
135 /* Minimal open/close/mmap implementation sufficient for initial loading of
136 shared libraries. These are weak definitions so that when the
137 dynamic linker re-relocates itself to be user-visible (for -ldl),
138 it will get the user's definition (i.e. usually libc's). */
141 open (const char *file_name, int mode, ...)
143 extern __typeof (__dir_lookup) __hurd_intr_rpc_dir_lookup;
144 extern __typeof (__io_reauthenticate) __hurd_intr_rpc_io_reauthenticate;
145 enum retry_type doretry;
146 char retryname[1024]; /* XXX string_t LOSES! */
147 file_t startdir, newpt, fileport;
152 assert (mode == O_RDONLY);
155 startdir = _dl_hurd_data->portarray[file_name[0] == '/' ?
156 INIT_PORT_CRDIR : INIT_PORT_CWDIR];
158 while (file_name[0] == '/')
161 if (errno = __hurd_intr_rpc_dir_lookup (startdir, file_name, mode, 0,
162 &doretry, retryname, &fileport))
172 __mach_port_deallocate (__mach_task_self (), startdir);
178 case FS_RETRY_REAUTH:
180 mach_port_t ref = __mach_reply_port ();
181 errno = __hurd_intr_rpc_io_reauthenticate
182 (fileport, ref, MACH_MSG_TYPE_MAKE_SEND);
184 errno = __auth_user_authenticate
185 (_dl_hurd_data->portarray[INIT_PORT_AUTH],
187 ref, MACH_MSG_TYPE_MAKE_SEND,
189 __mach_port_destroy (__mach_task_self (), ref);
191 __mach_port_deallocate (__mach_task_self (), fileport);
197 case FS_RETRY_NORMAL:
199 if (nloops++ >= SYMLOOP_MAX)
206 /* An empty RETRYNAME indicates we have the final port. */
207 if (retryname[0] == '\0')
209 mach_port_t memobj_rd, memobj_wr;
210 extern __typeof (__io_map) __hurd_intr_rpc_io_map;
215 /* We have the file open. Now map it. */
216 errno = __hurd_intr_rpc_io_map (fileport,
217 &memobj_rd, &memobj_wr);
219 __mach_port_deallocate (__mach_task_self (), fileport);
222 if (memobj_wr != MACH_PORT_NULL)
223 __mach_port_deallocate (__mach_task_self (), memobj_wr);
225 return (int) memobj_rd;
230 file_name = retryname;
233 case FS_RETRY_MAGICAL:
234 switch (retryname[0])
237 startdir = _dl_hurd_data->portarray[INIT_PORT_CRDIR];
239 if (fileport != MACH_PORT_NULL)
240 __mach_port_deallocate (__mach_task_self (), fileport);
241 file_name = &retryname[1];
245 if (retryname[1] == 'd' && retryname[2] == '/')
250 fd = (int) strtol (retryname, &end, 10);
251 if (end == NULL || errno || /* Malformed number. */
252 /* Check for excess text after the number. A slash
253 is valid; it ends the component. Anything else
254 does not name a numeric file descriptor. */
255 (*end != '/' && *end != '\0'))
260 if (fd < 0 || fd >= _dl_hurd_data->dtablesize ||
261 _dl_hurd_data->dtable[fd] == MACH_PORT_NULL)
263 /* If the name was a proper number, but the file
264 descriptor does not exist, we return EBADF instead
269 fileport = _dl_hurd_data->dtable[fd];
272 /* This descriptor is the file port we want. */
278 /* Do a normal retry on the remaining components. */
281 file_name = end + 1; /* Skip the slash. */
290 if (retryname[1] == 'a' && retryname[2] == 'c' &&
291 retryname[3] == 'h' && retryname[4] == 't' &&
292 retryname[5] == 'y' && retryname[6] == 'p' &&
296 struct host_basic_info hostinfo;
297 mach_msg_type_number_t hostinfocnt = HOST_BASIC_INFO_COUNT;
299 if (err = __host_info (__mach_host_self (), HOST_BASIC_INFO,
300 (natural_t *) &hostinfo,
303 if (hostinfocnt != HOST_BASIC_INFO_COUNT)
305 p = _itoa (hostinfo.cpu_subtype, &retryname[8], 10, 0);
307 p = _itoa (hostinfo.cpu_type, &retryname[8], 10, 0);
309 abort (); /* XXX write this right if this ever happens */
311 strcpy (retryname, p);
320 if (retryname[1] == 't' && retryname[2] == 'y')
321 switch (retryname[3])
323 error_t opentty (file_t *result)
327 err = __termctty_open_terminal
328 (_dl_hurd_data->portarray[INIT_PORT_CTTYID],
332 mach_port_t ref = __mach_reply_port ();
333 err = __hurd_intr_rpc_io_reauthenticate
334 (unauth, ref, MACH_MSG_TYPE_MAKE_SEND);
336 err = __auth_user_authenticate
337 (_dl_hurd_data->portarray[INIT_PORT_AUTH],
339 ref, MACH_MSG_TYPE_MAKE_SEND,
341 __mach_port_deallocate (__mach_task_self (),
343 __mach_port_destroy (__mach_task_self (), ref);
349 if (errno = opentty (&fileport))
354 if (errno = opentty (&startdir))
357 strcpy (retryname, &retryname[4]);
378 errno = __hurd_intr_rpc_dir_lookup (startdir, file_name, mode, 0,
379 &doretry, retryname, &fileport);
386 if (fd != (int) MACH_PORT_NULL)
387 __mach_port_deallocate (__mach_task_self (), (mach_port_t) fd);
392 mmap (caddr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
395 vm_address_t mapaddr;
397 vmprot = VM_PROT_NONE;
398 if (prot & PROT_READ)
399 vmprot |= VM_PROT_READ;
400 if (prot & PROT_WRITE)
401 vmprot |= VM_PROT_WRITE;
402 if (prot & PROT_EXEC)
403 vmprot |= VM_PROT_EXECUTE;
405 mapaddr = (vm_address_t) addr;
406 errno = __vm_map (__mach_task_self (),
407 &mapaddr, (vm_size_t) len, (vm_address_t) 0,
408 !(flags & MAP_FIXED),
409 (mach_port_t) fd, (vm_offset_t) offset,
410 flags & (MAP_COPY|MAP_PRIVATE),
412 (flags & MAP_INHERIT) ? VM_INHERIT_COPY : VM_INHERIT_NONE);
413 return errno ? (caddr_t) -1 : (caddr_t) mapaddr;
419 extern __typeof (__proc_mark_exit) __hurd_intr_rpc_proc_mark_exit;
420 __hurd_intr_rpc_proc_mark_exit (_dl_hurd_data->portarray[INIT_PORT_PROC],
421 W_EXITCODE (status, 0));
422 while (__task_terminate (__mach_task_self ()))
423 __mach_task_self_ = (__mach_task_self) ();
431 /* Minimal `malloc' allocator for use while loading shared libraries.
432 Only small blocks are allocated, and none are ever freed. */
437 static vm_address_t ptr, end;
442 /* Consume any unused space in the last page of our data segment. */
444 ptr = (vm_address_t) &_end;
445 end = round_page (ptr);
448 /* Make sure the allocation pointer is ideally aligned. */
449 ptr += sizeof (double) - 1;
450 ptr &= ~(sizeof (double) - 1);
454 /* Insufficient space left; allocate another page. */
456 assert (n <= __vm_page_size);
457 __vm_allocate (__mach_task_self (), &page, __vm_page_size, 1);
460 end = page + __vm_page_size;
463 block = (void *) ptr;
470 /* These should never be called. */
471 void *realloc (void *ptr, size_t n) { ptr += n; abort (); }
472 void free (void *ptr) { ptr = ptr; abort (); }
473 weak_symbol (realloc)
476 /* Avoid signal frobnication in setjmp/longjmp. */
478 int __sigjmp_save (sigjmp_buf env, int savemask)
479 { env[0].__mask_was_saved = savemask; return 0; }
480 weak_symbol (__sigjmp_save)
483 longjmp (jmp_buf env, int val) { __longjmp (env[0].__jmpbuf, val); }
484 weak_symbol (longjmp)
487 /* Stub out this function that is called by interruptible RPC stubs. It
488 should never get called during initial dynamic linking, because we use
489 only the raw MiG stub functions __hurd_intr_rpc_*. Since this defn is
490 weak, the real defn in libc.so will override it if we are linked into
491 the user program (-ldl). */
492 struct hurd_sigstate *
493 _hurd_thread_sigstate (thread_t thread) { thread = thread; abort (); }
494 weak_symbol (_hurd_thread_sigstate)