Blame sysdeps/mach/hurd/dl-sysdep.c

Packit 6c4009
/* Operating system support for run-time dynamic linker.  Hurd version.
Packit 6c4009
   Copyright (C) 1995-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
/* In the static library, this is all handled by dl-support.c
Packit 6c4009
   or by the vanilla definitions in the rest of the C library.  */
Packit 6c4009
#ifdef SHARED
Packit 6c4009
Packit 6c4009
#include <hurd.h>
Packit 6c4009
#include <link.h>
Packit 6c4009
#include <unistd.h>
Packit 6c4009
#include <fcntl.h>
Packit 6c4009
#include <stdlib.h>
Packit 6c4009
#include <sys/mman.h>
Packit 6c4009
#include <ldsodefs.h>
Packit 6c4009
#include <sys/wait.h>
Packit 6c4009
#include <assert.h>
Packit 6c4009
#include <sysdep.h>
Packit 6c4009
#include <mach/mig_support.h>
Packit 6c4009
#include <mach/machine/vm_param.h>
Packit 6c4009
#include "hurdstartup.h"
Packit 6c4009
#include <hurd/lookup.h>
Packit 6c4009
#include <hurd/auth.h>
Packit 6c4009
#include <hurd/term.h>
Packit 6c4009
#include <stdarg.h>
Packit 6c4009
#include <ctype.h>
Packit 6c4009
#include <sys/stat.h>
Packit 6c4009
#include <sys/uio.h>
Packit 6c4009
Packit 6c4009
#include <entry.h>
Packit 6c4009
#include <dl-machine.h>
Packit 6c4009
#include <dl-procinfo.h>
Packit 6c4009
Packit 6c4009
#include <dl-tunables.h>
Packit 6c4009
#include <not-errno.h>
Packit 6c4009
Packit 6c4009
extern void __mach_init (void);
Packit 6c4009
Packit 6c4009
extern int _dl_argc;
Packit 6c4009
extern char **_dl_argv;
Packit 6c4009
extern char **_environ;
Packit 6c4009
Packit 6c4009
int __libc_enable_secure = 0;
Packit 6c4009
rtld_hidden_data_def (__libc_enable_secure)
Packit 6c4009
int __libc_multiple_libcs = 0;	/* Defining this here avoids the inclusion
Packit 6c4009
				   of init-first.  */
Packit 6c4009
/* This variable contains the lowest stack address ever used.  */
Packit 6c4009
void *__libc_stack_end = NULL;
Packit 6c4009
rtld_hidden_data_def(__libc_stack_end)
Packit 6c4009
Packit 6c4009
/* TODO: Initialize.  */
Packit 6c4009
void *_dl_random attribute_relro = NULL;
Packit 6c4009
Packit 6c4009
struct hurd_startup_data *_dl_hurd_data;
Packit 6c4009
Packit 6c4009
#define FMH defined(__i386__)
Packit 6c4009
#if ! FMH
Packit 6c4009
# define fmh()		((void)0)
Packit 6c4009
# define unfmh()	((void)0)
Packit 6c4009
#else
Packit 6c4009
/* XXX loser kludge for vm_map kernel bug */
Packit 6c4009
#undef	ELF_MACHINE_USER_ADDRESS_MASK
Packit 6c4009
#define ELF_MACHINE_USER_ADDRESS_MASK	0
Packit 6c4009
static vm_address_t fmha;
Packit 6c4009
static vm_size_t fmhs;
Packit 6c4009
static void unfmh(void){
Packit 6c4009
__vm_deallocate(__mach_task_self(),fmha,fmhs);}
Packit 6c4009
static void fmh(void) {
Packit 6c4009
    error_t err;int x;vm_offset_t o;mach_port_t p;
Packit 6c4009
    vm_address_t a=0x08000000U,max=VM_MAX_ADDRESS;
Packit 6c4009
    while (!(err=__vm_region(__mach_task_self(),&a,&fmhs,&x,&x,&x,&x,&p,&o))){
Packit 6c4009
      __mach_port_deallocate(__mach_task_self(),p);
Packit 6c4009
      if (a+fmhs>=0x80000000U){
Packit 6c4009
	max=a; break;}
Packit 6c4009
      fmha=a+=fmhs;}
Packit 6c4009
    if (err) assert(err==KERN_NO_SPACE);
Packit 6c4009
    if (!fmha)fmhs=0;else{
Packit 6c4009
    fmhs=max-fmha;
Packit 6c4009
    err = __vm_map (__mach_task_self (),
Packit 6c4009
		    &fmha, fmhs, 0, 0, MACH_PORT_NULL, 0, 1,
Packit 6c4009
		    VM_PROT_NONE, VM_PROT_NONE, VM_INHERIT_COPY);
Packit 6c4009
    assert_perror(err);}
Packit 6c4009
  }
Packit 6c4009
/* XXX loser kludge for vm_map kernel bug */
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
Packit 6c4009
ElfW(Addr)
Packit 6c4009
_dl_sysdep_start (void **start_argptr,
Packit 6c4009
		  void (*dl_main) (const ElfW(Phdr) *phdr, ElfW(Word) phent,
Packit 6c4009
				   ElfW(Addr) *user_entry,
Packit 6c4009
				   ElfW(auxv_t) *auxv))
Packit 6c4009
{
Packit 6c4009
  void go (intptr_t *argdata)
Packit 6c4009
    {
Packit 6c4009
      char **p;
Packit 6c4009
Packit 6c4009
      /* Cache the information in various global variables.  */
Packit 6c4009
      _dl_argc = *argdata;
Packit 6c4009
      _dl_argv = 1 + (char **) argdata;
Packit 6c4009
      _environ = &_dl_argv[_dl_argc + 1];
Packit 6c4009
      for (p = _environ; *p++;); /* Skip environ pointers and terminator.  */
Packit 6c4009
Packit 6c4009
      if ((void *) p == _dl_argv[0])
Packit 6c4009
	{
Packit 6c4009
	  static struct hurd_startup_data nodata;
Packit 6c4009
	  _dl_hurd_data = &nodata;
Packit 6c4009
	  nodata.user_entry = (vm_address_t) ENTRY_POINT;
Packit 6c4009
	}
Packit 6c4009
      else
Packit 6c4009
	_dl_hurd_data = (void *) p;
Packit 6c4009
Packit 6c4009
      __libc_enable_secure = _dl_hurd_data->flags & EXEC_SECURE;
Packit 6c4009
Packit 6c4009
      __tunables_init (_environ);
Packit 6c4009
Packit 6c4009
      if (_dl_hurd_data->flags & EXEC_STACK_ARGS &&
Packit 6c4009
	  _dl_hurd_data->user_entry == 0)
Packit 6c4009
	_dl_hurd_data->user_entry = (vm_address_t) ENTRY_POINT;
Packit 6c4009
Packit 6c4009
unfmh();			/* XXX */
Packit 6c4009
Packit 6c4009
#if 0				/* XXX make this work for real someday... */
Packit 6c4009
      if (_dl_hurd_data->user_entry == (vm_address_t) ENTRY_POINT)
Packit 6c4009
	/* We were invoked as a command, not as the program interpreter.
Packit 6c4009
	   The generic ld.so code supports this: it will parse the args
Packit 6c4009
	   as "ld.so PROGRAM [ARGS...]".  For booting the Hurd, we
Packit 6c4009
	   support an additional special syntax:
Packit 6c4009
	     ld.so [-LIBS...] PROGRAM [ARGS...]
Packit 6c4009
	   Each LIBS word consists of "FILENAME=MEMOBJ";
Packit 6c4009
	   for example "-/lib/libc.so=123" says that the contents of
Packit 6c4009
	   /lib/libc.so are found in a memory object whose port name
Packit 6c4009
	   in our task is 123.  */
Packit 6c4009
	while (_dl_argc > 2 && _dl_argv[1][0] == '-' && _dl_argv[1][1] != '-')
Packit 6c4009
	  {
Packit 6c4009
	    char *lastslash, *memobjname, *p;
Packit 6c4009
	    struct link_map *l;
Packit 6c4009
	    mach_port_t memobj;
Packit 6c4009
	    error_t err;
Packit 6c4009
Packit 6c4009
	    ++_dl_skip_args;
Packit 6c4009
	    --_dl_argc;
Packit 6c4009
	    p = _dl_argv++[1] + 1;
Packit 6c4009
Packit 6c4009
	    memobjname = strchr (p, '=');
Packit 6c4009
	    if (! memobjname)
Packit 6c4009
	      _dl_sysdep_fatal ("Bogus library spec: ", p, "\n", NULL);
Packit 6c4009
	    *memobjname++ = '\0';
Packit 6c4009
	    memobj = 0;
Packit 6c4009
	    while (*memobjname != '\0')
Packit 6c4009
	      memobj = (memobj * 10) + (*memobjname++ - '0');
Packit 6c4009
Packit 6c4009
	    /* Add a user reference on the memory object port, so we will
Packit 6c4009
	       still have one after _dl_map_object_from_fd calls our
Packit 6c4009
	       `close'.  */
Packit 6c4009
	    err = __mach_port_mod_refs (__mach_task_self (), memobj,
Packit 6c4009
					MACH_PORT_RIGHT_SEND, +1);
Packit 6c4009
	    assert_perror (err);
Packit 6c4009
Packit 6c4009
	    lastslash = strrchr (p, '/');
Packit 6c4009
	    l = _dl_map_object_from_fd (lastslash ? lastslash + 1 : p, NULL,
Packit 6c4009
					memobj, strdup (p), 0);
Packit 6c4009
Packit 6c4009
	    /* Squirrel away the memory object port where it
Packit 6c4009
	       can be retrieved by the program later.  */
Packit 6c4009
	    l->l_info[DT_NULL] = (void *) memobj;
Packit 6c4009
	  }
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
      /* Call elf/rtld.c's main program.  It will set everything
Packit 6c4009
	 up and leave us to transfer control to USER_ENTRY.  */
Packit 6c4009
      (*dl_main) ((const ElfW(Phdr) *) _dl_hurd_data->phdr,
Packit 6c4009
		  _dl_hurd_data->phdrsz / sizeof (ElfW(Phdr)),
Packit 6c4009
		  (ElfW(Addr) *) &_dl_hurd_data->user_entry, NULL);
Packit 6c4009
Packit 6c4009
      /* The call above might screw a few things up.
Packit 6c4009
Packit 6c4009
	 First of all, if _dl_skip_args is nonzero, we are ignoring
Packit 6c4009
	 the first few arguments.  However, if we have no Hurd startup
Packit 6c4009
	 data, it is the magical convention that ARGV[0] == P.  The
Packit 6c4009
	 startup code in init-first.c will get confused if this is not
Packit 6c4009
	 the case, so we must rearrange things to make it so.  We'll
Packit 6c4009
	 overwrite the origional ARGV[0] at P with ARGV[_dl_skip_args].
Packit 6c4009
Packit 6c4009
	 Secondly, if we need to be secure, it removes some dangerous
Packit 6c4009
	 environment variables.  If we have no Hurd startup date this
Packit 6c4009
	 changes P (since that's the location after the terminating
Packit 6c4009
	 NULL in the list of environment variables).  We do the same
Packit 6c4009
	 thing as in the first case but make sure we recalculate P.
Packit 6c4009
	 If we do have Hurd startup data, we have to move the data
Packit 6c4009
	 such that it starts just after the terminating NULL in the
Packit 6c4009
	 environment list.
Packit 6c4009
Packit 6c4009
	 We use memmove, since the locations might overlap.  */
Packit 6c4009
      if (__libc_enable_secure || _dl_skip_args)
Packit 6c4009
	{
Packit 6c4009
	  char **newp;
Packit 6c4009
Packit 6c4009
	  for (newp = _environ; *newp++;);
Packit 6c4009
Packit 6c4009
	  if (_dl_argv[-_dl_skip_args] == (char *) p)
Packit 6c4009
	    {
Packit 6c4009
	      if ((char *) newp != _dl_argv[0])
Packit 6c4009
		{
Packit 6c4009
		  assert ((char *) newp < _dl_argv[0]);
Packit 6c4009
		  _dl_argv[0] = memmove ((char *) newp, _dl_argv[0],
Packit 6c4009
					 strlen (_dl_argv[0]) + 1);
Packit 6c4009
		}
Packit 6c4009
	    }
Packit 6c4009
	  else
Packit 6c4009
	    {
Packit 6c4009
	      if ((void *) newp != _dl_hurd_data)
Packit 6c4009
		memmove (newp, _dl_hurd_data, sizeof (*_dl_hurd_data));
Packit 6c4009
	    }
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
      {
Packit 6c4009
	extern void _dl_start_user (void);
Packit 6c4009
	/* Unwind the stack to ARGDATA and simulate a return from _dl_start
Packit 6c4009
	   to the RTLD_START code which will run the user's entry point.  */
Packit 6c4009
	RETURN_TO (argdata, &_dl_start_user, _dl_hurd_data->user_entry);
Packit 6c4009
      }
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* Set up so we can do RPCs.  */
Packit 6c4009
  __mach_init ();
Packit 6c4009
Packit 6c4009
  /* Initialize frequently used global variable.  */
Packit 6c4009
  GLRO(dl_pagesize) = __getpagesize ();
Packit 6c4009
Packit 6c4009
fmh();				/* XXX */
Packit 6c4009
Packit 6c4009
  /* See hurd/hurdstartup.c; this deals with getting information
Packit 6c4009
     from the exec server and slicing up the arguments.
Packit 6c4009
     Then it will call `go', above.  */
Packit 6c4009
  _hurd_startup (start_argptr, &go);
Packit 6c4009
Packit 6c4009
  LOSE;
Packit 6c4009
  abort ();
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
void
Packit 6c4009
_dl_sysdep_start_cleanup (void)
Packit 6c4009
{
Packit 6c4009
  /* Deallocate the reply port and task port rights acquired by
Packit 6c4009
     __mach_init.  We are done with them now, and the user will
Packit 6c4009
     reacquire them for himself when he wants them.  */
Packit 6c4009
  __mig_dealloc_reply_port (MACH_PORT_NULL);
Packit 6c4009
  __mach_port_deallocate (__mach_task_self (), __mach_host_self_);
Packit 6c4009
  __mach_port_deallocate (__mach_task_self (), __mach_task_self_);
Packit 6c4009
}
Packit 6c4009

Packit 6c4009
/* Minimal open/close/mmap implementation sufficient for initial loading of
Packit 6c4009
   shared libraries.  These are weak definitions so that when the
Packit 6c4009
   dynamic linker re-relocates itself to be user-visible (for -ldl),
Packit 6c4009
   it will get the user's definition (i.e. usually libc's).
Packit 6c4009
Packit 6c4009
   They also need to be set in the ld section of sysdeps/mach/hurd/Versions, to
Packit 6c4009
   be overridable, and in libc.abilist and ld.abilist to be checked. */
Packit 6c4009
Packit 6c4009
/* This macro checks that the function does not get renamed to be hidden: we do
Packit 6c4009
   need these to be overridable by libc's.  */
Packit 6c4009
#define check_no_hidden(name)				\
Packit 6c4009
  static __typeof (name) __check_##name##_no_hidden	\
Packit 6c4009
       __attribute__ ((alias (#name)));
Packit 6c4009
Packit 6c4009
/* Open FILE_NAME and return a Hurd I/O for it in *PORT, or return an
Packit 6c4009
   error.  If STAT is non-zero, stat the file into that stat buffer.  */
Packit 6c4009
static error_t
Packit 6c4009
open_file (const char *file_name, int flags,
Packit 6c4009
	   mach_port_t *port, struct stat64 *stat)
Packit 6c4009
{
Packit 6c4009
  enum retry_type doretry;
Packit 6c4009
  char retryname[1024];		/* XXX string_t LOSES! */
Packit 6c4009
  file_t startdir;
Packit 6c4009
  error_t err;
Packit 6c4009
Packit 6c4009
  error_t use_init_port (int which, error_t (*operate) (file_t))
Packit 6c4009
    {
Packit 6c4009
      return (which < _dl_hurd_data->portarraysize
Packit 6c4009
	      ? ((*operate) (_dl_hurd_data->portarray[which]))
Packit 6c4009
	      : EGRATUITOUS);
Packit 6c4009
    }
Packit 6c4009
  file_t get_dtable_port (int fd)
Packit 6c4009
    {
Packit 6c4009
      if ((unsigned int) fd < _dl_hurd_data->dtablesize
Packit 6c4009
	  && _dl_hurd_data->dtable[fd] != MACH_PORT_NULL)
Packit 6c4009
	{
Packit 6c4009
	  __mach_port_mod_refs (__mach_task_self (), _dl_hurd_data->dtable[fd],
Packit 6c4009
				MACH_PORT_RIGHT_SEND, +1);
Packit 6c4009
	  return _dl_hurd_data->dtable[fd];
Packit 6c4009
	}
Packit 6c4009
      errno = EBADF;
Packit 6c4009
      return MACH_PORT_NULL;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  assert (!(flags & ~(O_READ | O_CLOEXEC)));
Packit 6c4009
Packit 6c4009
  startdir = _dl_hurd_data->portarray[file_name[0] == '/' ?
Packit 6c4009
				      INIT_PORT_CRDIR : INIT_PORT_CWDIR];
Packit 6c4009
Packit 6c4009
  while (file_name[0] == '/')
Packit 6c4009
    file_name++;
Packit 6c4009
Packit 6c4009
  err = __dir_lookup (startdir, (char *)file_name, O_RDONLY, 0,
Packit 6c4009
		      &doretry, retryname, port);
Packit 6c4009
Packit 6c4009
  if (!err)
Packit 6c4009
    err = __hurd_file_name_lookup_retry (use_init_port, get_dtable_port,
Packit 6c4009
					 __dir_lookup, doretry, retryname,
Packit 6c4009
					 O_RDONLY, 0, port);
Packit 6c4009
  if (!err && stat)
Packit 6c4009
    {
Packit 6c4009
      err = __io_stat (*port, stat);
Packit 6c4009
      if (err)
Packit 6c4009
	__mach_port_deallocate (__mach_task_self (), *port);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  return err;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
check_no_hidden(__open);
Packit 6c4009
check_no_hidden (__open64);
Packit 6c4009
int weak_function
Packit 6c4009
__open (const char *file_name, int mode, ...)
Packit 6c4009
{
Packit 6c4009
  mach_port_t port;
Packit 6c4009
  error_t err = open_file (file_name, mode, &port, 0);
Packit 6c4009
  if (err)
Packit 6c4009
    return __hurd_fail (err);
Packit 6c4009
  else
Packit 6c4009
    return (int)port;
Packit 6c4009
}
Packit 6c4009
weak_alias (__open, __open64)
Packit 6c4009
Packit 6c4009
check_no_hidden(__close);
Packit 6c4009
int weak_function
Packit 6c4009
__close (int fd)
Packit 6c4009
{
Packit 6c4009
  if (fd != (int) MACH_PORT_NULL)
Packit 6c4009
    __mach_port_deallocate (__mach_task_self (), (mach_port_t) fd);
Packit 6c4009
  return 0;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
check_no_hidden(__read);
Packit 6c4009
__ssize_t weak_function
Packit 6c4009
__read (int fd, void *buf, size_t nbytes)
Packit 6c4009
{
Packit 6c4009
  error_t err;
Packit 6c4009
  char *data;
Packit 6c4009
  mach_msg_type_number_t nread;
Packit 6c4009
Packit 6c4009
  data = buf;
Packit 6c4009
  nread = nbytes;
Packit 6c4009
  err = __io_read ((mach_port_t) fd, &data, &nread, -1, nbytes);
Packit 6c4009
  if (err)
Packit 6c4009
    return __hurd_fail (err);
Packit 6c4009
Packit 6c4009
  if (data != buf)
Packit 6c4009
    {
Packit 6c4009
      memcpy (buf, data, nread);
Packit 6c4009
      __vm_deallocate (__mach_task_self (), (vm_address_t) data, nread);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  return nread;
Packit 6c4009
}
Packit 6c4009
libc_hidden_weak (__read)
Packit 6c4009
Packit 6c4009
check_no_hidden(__write);
Packit 6c4009
__ssize_t weak_function
Packit 6c4009
__write (int fd, const void *buf, size_t nbytes)
Packit 6c4009
{
Packit 6c4009
  error_t err;
Packit 6c4009
  mach_msg_type_number_t nwrote;
Packit 6c4009
Packit 6c4009
  assert (fd < _hurd_init_dtablesize);
Packit 6c4009
Packit 6c4009
  err = __io_write (_hurd_init_dtable[fd], buf, nbytes, -1, &nwrote);
Packit 6c4009
  if (err)
Packit 6c4009
    return __hurd_fail (err);
Packit 6c4009
Packit 6c4009
  return nwrote;
Packit 6c4009
}
Packit 6c4009
libc_hidden_weak (__write)
Packit 6c4009
Packit 6c4009
/* This is only used for printing messages (see dl-misc.c).  */
Packit 6c4009
check_no_hidden(__writev);
Packit 6c4009
__ssize_t weak_function
Packit 6c4009
__writev (int fd, const struct iovec *iov, int niov)
Packit 6c4009
{
Packit 6c4009
  if (fd >= _hurd_init_dtablesize)
Packit 6c4009
    {
Packit 6c4009
      errno = EBADF;
Packit 6c4009
      return -1;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  int i;
Packit 6c4009
  size_t total = 0;
Packit 6c4009
  for (i = 0; i < niov; ++i)
Packit 6c4009
    total += iov[i].iov_len;
Packit 6c4009
Packit 6c4009
  if (total != 0)
Packit 6c4009
    {
Packit 6c4009
      char buf[total], *bufp = buf;
Packit 6c4009
      error_t err;
Packit 6c4009
      mach_msg_type_number_t nwrote;
Packit 6c4009
Packit 6c4009
      for (i = 0; i < niov; ++i)
Packit 6c4009
	bufp = (memcpy (bufp, iov[i].iov_base, iov[i].iov_len)
Packit 6c4009
		+ iov[i].iov_len);
Packit 6c4009
Packit 6c4009
      err = __io_write (_hurd_init_dtable[fd], buf, total, -1, &nwrote);
Packit 6c4009
      if (err)
Packit 6c4009
	return __hurd_fail (err);
Packit 6c4009
Packit 6c4009
      return nwrote;
Packit 6c4009
    }
Packit 6c4009
  return 0;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
check_no_hidden(__libc_lseek64);
Packit 6c4009
off64_t weak_function
Packit 6c4009
__libc_lseek64 (int fd, off64_t offset, int whence)
Packit 6c4009
{
Packit 6c4009
  error_t err;
Packit 6c4009
Packit 6c4009
  err = __io_seek ((mach_port_t) fd, offset, whence, &offset);
Packit 6c4009
  if (err)
Packit 6c4009
    return __hurd_fail (err);
Packit 6c4009
Packit 6c4009
  return offset;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
check_no_hidden(__mmap);
Packit 6c4009
void *weak_function
Packit 6c4009
__mmap (void *addr, size_t len, int prot, int flags, int fd, off_t offset)
Packit 6c4009
{
Packit 6c4009
  error_t err;
Packit 6c4009
  vm_prot_t vmprot;
Packit 6c4009
  vm_address_t mapaddr;
Packit 6c4009
  mach_port_t memobj_rd, memobj_wr;
Packit 6c4009
Packit 6c4009
  vmprot = VM_PROT_NONE;
Packit 6c4009
  if (prot & PROT_READ)
Packit 6c4009
    vmprot |= VM_PROT_READ;
Packit 6c4009
  if (prot & PROT_WRITE)
Packit 6c4009
    vmprot |= VM_PROT_WRITE;
Packit 6c4009
  if (prot & PROT_EXEC)
Packit 6c4009
    vmprot |= VM_PROT_EXECUTE;
Packit 6c4009
Packit 6c4009
  if (flags & MAP_ANON)
Packit 6c4009
    memobj_rd = MACH_PORT_NULL;
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      assert (!(flags & MAP_SHARED));
Packit 6c4009
      err = __io_map ((mach_port_t) fd, &memobj_rd, &memobj_wr);
Packit 6c4009
      if (err)
Packit 6c4009
	return __hurd_fail (err), MAP_FAILED;
Packit 6c4009
      if (memobj_wr != MACH_PORT_NULL)
Packit 6c4009
	__mach_port_deallocate (__mach_task_self (), memobj_wr);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  mapaddr = (vm_address_t) addr;
Packit 6c4009
  err = __vm_map (__mach_task_self (),
Packit 6c4009
		  &mapaddr, (vm_size_t) len, ELF_MACHINE_USER_ADDRESS_MASK,
Packit 6c4009
		  !(flags & MAP_FIXED),
Packit 6c4009
		  memobj_rd,
Packit 6c4009
		  (vm_offset_t) offset,
Packit 6c4009
		  flags & (MAP_COPY|MAP_PRIVATE),
Packit 6c4009
		  vmprot, VM_PROT_ALL,
Packit 6c4009
		  (flags & MAP_SHARED) ? VM_INHERIT_SHARE : VM_INHERIT_COPY);
Packit 6c4009
  if (err == KERN_NO_SPACE && (flags & MAP_FIXED))
Packit 6c4009
    {
Packit 6c4009
      /* XXX this is not atomic as it is in unix! */
Packit 6c4009
      /* The region is already allocated; deallocate it first.  */
Packit 6c4009
      err = __vm_deallocate (__mach_task_self (), mapaddr, len);
Packit 6c4009
      if (! err)
Packit 6c4009
	err = __vm_map (__mach_task_self (),
Packit 6c4009
			&mapaddr, (vm_size_t) len,
Packit 6c4009
			ELF_MACHINE_USER_ADDRESS_MASK,
Packit 6c4009
			!(flags & MAP_FIXED),
Packit 6c4009
			memobj_rd, (vm_offset_t) offset,
Packit 6c4009
			flags & (MAP_COPY|MAP_PRIVATE),
Packit 6c4009
			vmprot, VM_PROT_ALL,
Packit 6c4009
			(flags & MAP_SHARED)
Packit 6c4009
			? VM_INHERIT_SHARE : VM_INHERIT_COPY);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  if ((flags & MAP_ANON) == 0)
Packit 6c4009
    __mach_port_deallocate (__mach_task_self (), memobj_rd);
Packit 6c4009
Packit 6c4009
  if (err)
Packit 6c4009
    return __hurd_fail (err), MAP_FAILED;
Packit 6c4009
  return (void *) mapaddr;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
check_no_hidden(__fxstat64);
Packit 6c4009
int weak_function
Packit 6c4009
__fxstat64 (int vers, int fd, struct stat64 *buf)
Packit 6c4009
{
Packit 6c4009
  error_t err;
Packit 6c4009
Packit 6c4009
  assert (vers == _STAT_VER);
Packit 6c4009
Packit 6c4009
  err = __io_stat ((mach_port_t) fd, buf);
Packit 6c4009
  if (err)
Packit 6c4009
    return __hurd_fail (err);
Packit 6c4009
Packit 6c4009
  return 0;
Packit 6c4009
}
Packit 6c4009
libc_hidden_def (__fxstat64)
Packit 6c4009
Packit 6c4009
check_no_hidden(__xstat64);
Packit 6c4009
int weak_function
Packit 6c4009
__xstat64 (int vers, const char *file, struct stat64 *buf)
Packit 6c4009
{
Packit 6c4009
  error_t err;
Packit 6c4009
  mach_port_t port;
Packit 6c4009
Packit 6c4009
  assert (vers == _STAT_VER);
Packit 6c4009
Packit 6c4009
  err = open_file (file, 0, &port, buf);
Packit 6c4009
  if (err)
Packit 6c4009
    return __hurd_fail (err);
Packit 6c4009
Packit 6c4009
  __mach_port_deallocate (__mach_task_self (), port);
Packit 6c4009
Packit 6c4009
  return 0;
Packit 6c4009
}
Packit 6c4009
libc_hidden_def (__xstat64)
Packit 6c4009
Packit 6c4009
/* This function is called by the dynamic linker (rtld.c) to check
Packit 6c4009
   whether debugging malloc is allowed even for SUID binaries.  This
Packit 6c4009
   stub will always fail, which means that malloc-debugging is always
Packit 6c4009
   disabled for SUID binaries.  */
Packit 6c4009
check_no_hidden(__access);
Packit 6c4009
int weak_function
Packit 6c4009
__access (const char *file, int type)
Packit 6c4009
{
Packit 6c4009
  errno = ENOSYS;
Packit 6c4009
  return -1;
Packit 6c4009
}
Packit 6c4009
check_no_hidden(__access_noerrno);
Packit 6c4009
int weak_function
Packit 6c4009
__access_noerrno (const char *file, int type)
Packit 6c4009
{
Packit 6c4009
  return -1;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
check_no_hidden(__getpid);
Packit 6c4009
pid_t weak_function
Packit 6c4009
__getpid (void)
Packit 6c4009
{
Packit 6c4009
  pid_t pid, ppid;
Packit 6c4009
  int orphaned;
Packit 6c4009
Packit 6c4009
  if (__proc_getpids (_dl_hurd_data->portarray[INIT_PORT_PROC],
Packit 6c4009
		      &pid, &ppid, &orphaned))
Packit 6c4009
    return -1;
Packit 6c4009
Packit 6c4009
  return pid;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* We need this alias to satisfy references from libc_pic.a objects
Packit 6c4009
   that were affected by the libc_hidden_proto declaration for __getpid.  */
Packit 6c4009
strong_alias (__getpid, __GI___getpid)
Packit 6c4009
Packit 6c4009
/* This is called only in some strange cases trying to guess a value
Packit 6c4009
   for $ORIGIN for the executable.  The dynamic linker copes with
Packit 6c4009
   getcwd failing (dl-object.c), and it's too much hassle to include
Packit 6c4009
   the functionality here.  (We could, it just requires duplicating or
Packit 6c4009
   reusing getcwd.c's code but using our special lookup function as in
Packit 6c4009
   `open', above.)  */
Packit 6c4009
check_no_hidden(__getcwd);
Packit 6c4009
char *weak_function
Packit 6c4009
__getcwd (char *buf, size_t size)
Packit 6c4009
{
Packit 6c4009
  errno = ENOSYS;
Packit 6c4009
  return NULL;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* This is used by dl-tunables.c to strdup strings.  We can just make this a
Packit 6c4009
   mere allocation.  */
Packit 6c4009
check_no_hidden(__sbrk);
Packit 6c4009
void *weak_function
Packit 6c4009
__sbrk (intptr_t increment)
Packit 6c4009
{
Packit 6c4009
  vm_address_t addr;
Packit 6c4009
  __vm_allocate (__mach_task_self (), &addr, increment, 1);
Packit 6c4009
  return (void *) addr;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
check_no_hidden(__strtoul_internal);
Packit 6c4009
unsigned long int weak_function
Packit 6c4009
__strtoul_internal (const char *nptr, char **endptr, int base, int group)
Packit 6c4009
{
Packit 6c4009
  assert (base == 0 || base == 10);
Packit 6c4009
  assert (group == 0);
Packit 6c4009
  return _dl_strtoul (nptr, endptr);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* We need this alias to satisfy references from libc_pic.a objects
Packit 6c4009
   that were affected by the libc_hidden_proto declaration for __strtoul_internal.  */
Packit 6c4009
strong_alias (__strtoul_internal, __GI___strtoul_internal)
Packit 6c4009
strong_alias (__strtoul_internal, __GI_____strtoul_internal)
Packit 6c4009
Packit 6c4009
check_no_hidden(_exit);
Packit 6c4009
void weak_function attribute_hidden
Packit 6c4009
_exit (int status)
Packit 6c4009
{
Packit 6c4009
  __proc_mark_exit (_dl_hurd_data->portarray[INIT_PORT_PROC],
Packit 6c4009
		    W_EXITCODE (status, 0), 0);
Packit 6c4009
  while (__task_terminate (__mach_task_self ()))
Packit 6c4009
    __mach_task_self_ = (__mach_task_self) ();
Packit 6c4009
Packit 6c4009
  LOSE;
Packit 6c4009
  abort ();
Packit 6c4009
}
Packit 6c4009
/* We need this alias to satisfy references from libc_pic.a objects
Packit 6c4009
   that were affected by the libc_hidden_proto declaration for _exit.  */
Packit 6c4009
strong_alias (_exit, __GI__exit)
Packit 6c4009
Packit 6c4009
/* Try to get a machine dependent instruction which will make the
Packit 6c4009
   program crash.  This is used in case everything else fails.  */
Packit 6c4009
#include <abort-instr.h>
Packit 6c4009
#ifndef ABORT_INSTRUCTION
Packit 6c4009
/* No such instruction is available.  */
Packit 6c4009
# define ABORT_INSTRUCTION
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
check_no_hidden(abort);
Packit 6c4009
void weak_function
Packit 6c4009
abort (void)
Packit 6c4009
{
Packit 6c4009
  /* Try to abort using the system specific command.  */
Packit 6c4009
  ABORT_INSTRUCTION;
Packit 6c4009
Packit 6c4009
  /* If the abort instruction failed, exit.  */
Packit 6c4009
  _exit (127);
Packit 6c4009
Packit 6c4009
  /* If even this fails, make sure we never return.  */
Packit 6c4009
  while (1)
Packit 6c4009
    /* Try for ever and ever.  */
Packit 6c4009
    ABORT_INSTRUCTION;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* We need this alias to satisfy references from libc_pic.a objects
Packit 6c4009
   that were affected by the libc_hidden_proto declaration for abort.  */
Packit 6c4009
strong_alias (abort, __GI_abort)
Packit 6c4009
strong_alias (abort, __GI___chk_fail)
Packit 6c4009
strong_alias (abort, __GI___fortify_fail)
Packit 6c4009
strong_alias (abort, __GI___assert_fail)
Packit 6c4009
strong_alias (abort, __GI___assert_perror_fail)
Packit 6c4009

Packit 6c4009
/* This function is called by interruptible RPC stubs.  For initial
Packit 6c4009
   dynamic linking, just use the normal mach_msg.  Since this defn is
Packit 6c4009
   weak, the real defn in libc.so will override it if we are linked into
Packit 6c4009
   the user program (-ldl).  */
Packit 6c4009
Packit 6c4009
error_t weak_function
Packit 6c4009
_hurd_intr_rpc_mach_msg (mach_msg_header_t *msg,
Packit 6c4009
			 mach_msg_option_t option,
Packit 6c4009
			 mach_msg_size_t send_size,
Packit 6c4009
			 mach_msg_size_t rcv_size,
Packit 6c4009
			 mach_port_t rcv_name,
Packit 6c4009
			 mach_msg_timeout_t timeout,
Packit 6c4009
			 mach_port_t notify)
Packit 6c4009
{
Packit 6c4009
  return __mach_msg (msg, option, send_size, rcv_size, rcv_name,
Packit 6c4009
		     timeout, notify);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
void
Packit 6c4009
_dl_show_auxv (void)
Packit 6c4009
{
Packit 6c4009
  /* There is nothing to print.  Hurd has no auxiliary vector.  */
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
void weak_function
Packit 6c4009
_dl_init_first (int argc, ...)
Packit 6c4009
{
Packit 6c4009
  /* This no-op definition only gets used if libc is not linked in.  */
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
#endif /* SHARED */