Blame elf/dl-init.c

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