Blame elf/setup-vdso.h

Packit Service 82fcde
/* Set up the data structures for the system-supplied DSO.
Packit Service 82fcde
   Copyright (C) 2012-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
static inline void __attribute__ ((always_inline))
Packit Service 82fcde
setup_vdso (struct link_map *main_map __attribute__ ((unused)),
Packit Service 82fcde
	    struct link_map ***first_preload __attribute__ ((unused)))
Packit Service 82fcde
{
Packit Service 82fcde
#ifdef NEED_DL_SYSINFO_DSO
Packit Service 82fcde
  if (GLRO(dl_sysinfo_dso) == NULL)
Packit Service 82fcde
    return;
Packit Service 82fcde
Packit Service 82fcde
  /* Do an abridged version of the work _dl_map_object_from_fd would do
Packit Service 82fcde
     to map in the object.  It's already mapped and prelinked (and
Packit Service 82fcde
     better be, since it's read-only and so we couldn't relocate it).
Packit Service 82fcde
     We just want our data structures to describe it as if we had just
Packit Service 82fcde
     mapped and relocated it normally.  */
Packit Service 82fcde
  struct link_map *l = _dl_new_object ((char *) "", "", lt_library, NULL,
Packit Service 82fcde
				       0, LM_ID_BASE);
Packit Service 82fcde
  if (__glibc_likely (l != NULL))
Packit Service 82fcde
    {
Packit Service 82fcde
      static ElfW(Dyn) dyn_temp[DL_RO_DYN_TEMP_CNT] attribute_relro;
Packit Service 82fcde
Packit Service 82fcde
      l->l_phdr = ((const void *) GLRO(dl_sysinfo_dso)
Packit Service 82fcde
		   + GLRO(dl_sysinfo_dso)->e_phoff);
Packit Service 82fcde
      l->l_phnum = GLRO(dl_sysinfo_dso)->e_phnum;
Packit Service 82fcde
      for (uint_fast16_t i = 0; i < l->l_phnum; ++i)
Packit Service 82fcde
	{
Packit Service 82fcde
	  const ElfW(Phdr) *const ph = &l->l_phdr[i];
Packit Service 82fcde
	  if (ph->p_type == PT_DYNAMIC)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      l->l_ld = (void *) ph->p_vaddr;
Packit Service 82fcde
	      l->l_ldnum = ph->p_memsz / sizeof (ElfW(Dyn));
Packit Service 82fcde
	    }
Packit Service 82fcde
	  else if (ph->p_type == PT_LOAD)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      if (! l->l_addr)
Packit Service 82fcde
		l->l_addr = ph->p_vaddr;
Packit Service 82fcde
	      if (ph->p_vaddr + ph->p_memsz >= l->l_map_end)
Packit Service 82fcde
		l->l_map_end = ph->p_vaddr + ph->p_memsz;
Packit Service 82fcde
	      if ((ph->p_flags & PF_X)
Packit Service 82fcde
		  && ph->p_vaddr + ph->p_memsz >= l->l_text_end)
Packit Service 82fcde
		l->l_text_end = ph->p_vaddr + ph->p_memsz;
Packit Service 82fcde
	    }
Packit Service 82fcde
	  else
Packit Service 82fcde
	    /* There must be no TLS segment.  */
Packit Service 82fcde
	    assert (ph->p_type != PT_TLS);
Packit Service 82fcde
	}
Packit Service 82fcde
      l->l_map_start = (ElfW(Addr)) GLRO(dl_sysinfo_dso);
Packit Service 82fcde
      l->l_addr = l->l_map_start - l->l_addr;
Packit Service 82fcde
      l->l_map_end += l->l_addr;
Packit Service 82fcde
      l->l_text_end += l->l_addr;
Packit Service 82fcde
      l->l_ld = (void *) ((ElfW(Addr)) l->l_ld + l->l_addr);
Packit Service 82fcde
      elf_get_dynamic_info (l, dyn_temp);
Packit Service 82fcde
      _dl_setup_hash (l);
Packit Service 82fcde
      l->l_relocated = 1;
Packit Service 82fcde
Packit Service 82fcde
      /* The vDSO is always used.  */
Packit Service 82fcde
      l->l_used = 1;
Packit Service 82fcde
Packit Service 82fcde
      /* Initialize l_local_scope to contain just this map.  This allows
Packit Service 82fcde
	 the use of dl_lookup_symbol_x to resolve symbols within the vdso.
Packit Service 82fcde
	 So we create a single entry list pointing to l_real as its only
Packit Service 82fcde
	 element */
Packit Service 82fcde
      l->l_local_scope[0]->r_nlist = 1;
Packit Service 82fcde
      l->l_local_scope[0]->r_list = &l->l_real;
Packit Service 82fcde
Packit Service 82fcde
      /* Now that we have the info handy, use the DSO image's soname
Packit Service 82fcde
	 so this object can be looked up by name.  Note that we do not
Packit Service 82fcde
	 set l_name here.  That field gives the file name of the DSO,
Packit Service 82fcde
	 and this DSO is not associated with any file.  */
Packit Service 82fcde
      if (l->l_info[DT_SONAME] != NULL)
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* Work around a kernel problem.  The kernel cannot handle
Packit Service 82fcde
	     addresses in the vsyscall DSO pages in writev() calls.  */
Packit Service 82fcde
	  const char *dsoname = ((char *) D_PTR (l, l_info[DT_STRTAB])
Packit Service 82fcde
				 + l->l_info[DT_SONAME]->d_un.d_val);
Packit Service 82fcde
	  size_t len = strlen (dsoname) + 1;
Packit Service 82fcde
	  char *copy = malloc (len);
Packit Service 82fcde
	  if (copy == NULL)
Packit Service 82fcde
	    _dl_fatal_printf ("out of memory\n");
Packit Service 82fcde
	  l->l_libname->name = l->l_name = memcpy (copy, dsoname, len);
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      /* Add the vDSO to the object list.  */
Packit Service 82fcde
      _dl_add_to_namespace_list (l, LM_ID_BASE);
Packit Service 82fcde
Packit Service 82fcde
# if IS_IN (rtld)
Packit Service 82fcde
      /* Rearrange the list so this DSO appears after rtld_map.  */
Packit Service 82fcde
      assert (l->l_next == NULL);
Packit Service 82fcde
      assert (l->l_prev == main_map);
Packit Service 82fcde
      GL(dl_rtld_map).l_next = l;
Packit Service 82fcde
      l->l_prev = &GL(dl_rtld_map);
Packit Service 82fcde
      *first_preload = &l->l_next;
Packit Service 82fcde
# else
Packit Service 82fcde
      GL(dl_nns) = 1;
Packit Service 82fcde
# endif
Packit Service 82fcde
Packit Service 82fcde
      /* We have a prelinked DSO preloaded by the system.  */
Packit Service 82fcde
      GLRO(dl_sysinfo_map) = l;
Packit Service 82fcde
# ifdef NEED_DL_SYSINFO
Packit Service 82fcde
      if (GLRO(dl_sysinfo) == DL_SYSINFO_DEFAULT)
Packit Service 82fcde
	GLRO(dl_sysinfo) = GLRO(dl_sysinfo_dso)->e_entry + l->l_addr;
Packit Service 82fcde
# endif
Packit Service 82fcde
    }
Packit Service 82fcde
#endif
Packit Service 82fcde
}