Blame elf/dl-init.c

Packit Service 82fcde
/* Run initializers for newly loaded objects.
Packit Service 82fcde
   Copyright (C) 1995-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
#include <stddef.h>
Packit Service 82fcde
#include <ldsodefs.h>
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Type of the initializer.  */
Packit Service 82fcde
typedef void (*init_t) (int, char **, char **);
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
static void
Packit Service 82fcde
call_init (struct link_map *l, int argc, char **argv, char **env)
Packit Service 82fcde
{
Packit Service 82fcde
  if (l->l_init_called)
Packit Service 82fcde
    /* This object is all done.  */
Packit Service 82fcde
    return;
Packit Service 82fcde
Packit Service 82fcde
  /* Avoid handling this constructor again in case we have a circular
Packit Service 82fcde
     dependency.  */
Packit Service 82fcde
  l->l_init_called = 1;
Packit Service 82fcde
Packit Service 82fcde
  /* Check for object which constructors we do not run here.  */
Packit Service 82fcde
  if (__builtin_expect (l->l_name[0], 'a') == '\0'
Packit Service 82fcde
      && l->l_type == lt_executable)
Packit Service 82fcde
    return;
Packit Service 82fcde
Packit Service 82fcde
  /* Are there any constructors?  */
Packit Service 82fcde
  if (l->l_info[DT_INIT] == NULL
Packit Service 82fcde
      && __builtin_expect (l->l_info[DT_INIT_ARRAY] == NULL, 1))
Packit Service 82fcde
    return;
Packit Service 82fcde
Packit Service 82fcde
  /* Print a debug message if wanted.  */
Packit Service 82fcde
  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS))
Packit Service 82fcde
    _dl_debug_printf ("\ncalling init: %s\n\n",
Packit Service 82fcde
		      DSO_FILENAME (l->l_name));
Packit Service 82fcde
Packit Service 82fcde
  /* Now run the local constructors.  There are two forms of them:
Packit Service 82fcde
     - the one named by DT_INIT
Packit Service 82fcde
     - the others in the DT_INIT_ARRAY.
Packit Service 82fcde
  */
Packit Service 82fcde
  if (l->l_info[DT_INIT] != NULL)
Packit Service 82fcde
    DL_CALL_DT_INIT(l, l->l_addr + l->l_info[DT_INIT]->d_un.d_ptr, argc, argv, env);
Packit Service 82fcde
Packit Service 82fcde
  /* Next see whether there is an array with initialization functions.  */
Packit Service 82fcde
  ElfW(Dyn) *init_array = l->l_info[DT_INIT_ARRAY];
Packit Service 82fcde
  if (init_array != NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      unsigned int j;
Packit Service 82fcde
      unsigned int jm;
Packit Service 82fcde
      ElfW(Addr) *addrs;
Packit Service 82fcde
Packit Service 82fcde
      jm = l->l_info[DT_INIT_ARRAYSZ]->d_un.d_val / sizeof (ElfW(Addr));
Packit Service 82fcde
Packit Service 82fcde
      addrs = (ElfW(Addr) *) (init_array->d_un.d_ptr + l->l_addr);
Packit Service 82fcde
      for (j = 0; j < jm; ++j)
Packit Service 82fcde
	((init_t) addrs[j]) (argc, argv, env);
Packit Service 82fcde
    }
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
void
Packit Service 82fcde
_dl_init (struct link_map *main_map, int argc, char **argv, char **env)
Packit Service 82fcde
{
Packit Service 82fcde
  ElfW(Dyn) *preinit_array = main_map->l_info[DT_PREINIT_ARRAY];
Packit Service 82fcde
  ElfW(Dyn) *preinit_array_size = main_map->l_info[DT_PREINIT_ARRAYSZ];
Packit Service 82fcde
  unsigned int i;
Packit Service 82fcde
Packit Service 82fcde
  if (__glibc_unlikely (GL(dl_initfirst) != NULL))
Packit Service 82fcde
    {
Packit Service 82fcde
      call_init (GL(dl_initfirst), argc, argv, env);
Packit Service 82fcde
      GL(dl_initfirst) = NULL;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Don't do anything if there is no preinit array.  */
Packit Service 82fcde
  if (__builtin_expect (preinit_array != NULL, 0)
Packit Service 82fcde
      && preinit_array_size != NULL
Packit Service 82fcde
      && (i = preinit_array_size->d_un.d_val / sizeof (ElfW(Addr))) > 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      ElfW(Addr) *addrs;
Packit Service 82fcde
      unsigned int cnt;
Packit Service 82fcde
Packit Service 82fcde
      if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS))
Packit Service 82fcde
	_dl_debug_printf ("\ncalling preinit: %s\n\n",
Packit Service 82fcde
			  DSO_FILENAME (main_map->l_name));
Packit Service 82fcde
Packit Service 82fcde
      addrs = (ElfW(Addr) *) (preinit_array->d_un.d_ptr + main_map->l_addr);
Packit Service 82fcde
      for (cnt = 0; cnt < i; ++cnt)
Packit Service 82fcde
	((init_t) addrs[cnt]) (argc, argv, env);
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Stupid users forced the ELF specification to be changed.  It now
Packit Service 82fcde
     says that the dynamic loader is responsible for determining the
Packit Service 82fcde
     order in which the constructors have to run.  The constructors
Packit Service 82fcde
     for all dependencies of an object must run before the constructor
Packit Service 82fcde
     for the object itself.  Circular dependencies are left unspecified.
Packit Service 82fcde
Packit Service 82fcde
     This is highly questionable since it puts the burden on the dynamic
Packit Service 82fcde
     loader which has to find the dependencies at runtime instead of
Packit Service 82fcde
     letting the user do it right.  Stupidity rules!  */
Packit Service 82fcde
Packit Service 82fcde
  i = main_map->l_searchlist.r_nlist;
Packit Service 82fcde
  while (i-- > 0)
Packit Service 82fcde
    call_init (main_map->l_initfini[i], argc, argv, env);
Packit Service 82fcde
Packit Service 1c5418
#ifndef HAVE_INLINED_SYSCALLS
Packit Service 82fcde
  /* Finished starting up.  */
Packit Service 82fcde
  _dl_starting_up = 0;
Packit Service 1c5418
#endif
Packit Service 82fcde
}