Back to index

glibc  2.9
dl-init.c
Go to the documentation of this file.
00001 /* Return the next shared object initializer function not yet run.
00002    Copyright (C) 1995, 1996, 1998-2002, 2004 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <stddef.h>
00021 #include <ldsodefs.h>
00022 
00023 
00024 /* Type of the initializer.  */
00025 typedef void (*init_t) (int, char **, char **);
00026 
00027 #ifndef HAVE_INLINED_SYSCALLS
00028 /* Flag, nonzero during startup phase.  */
00029 extern int _dl_starting_up;
00030 extern int _dl_starting_up_internal attribute_hidden;
00031 #endif
00032 
00033 
00034 static void
00035 call_init (struct link_map *l, int argc, char **argv, char **env)
00036 {
00037   if (l->l_init_called)
00038     /* This object is all done.  */
00039     return;
00040 
00041   /* Avoid handling this constructor again in case we have a circular
00042      dependency.  */
00043   l->l_init_called = 1;
00044 
00045   /* Check for object which constructors we do not run here.  */
00046   if (__builtin_expect (l->l_name[0], 'a') == '\0'
00047       && l->l_type == lt_executable)
00048     return;
00049 
00050   /* Are there any constructors?  */
00051   if (l->l_info[DT_INIT] == NULL
00052       && __builtin_expect (l->l_info[DT_INIT_ARRAY] == NULL, 1))
00053     return;
00054 
00055   /* Print a debug message if wanted.  */
00056   if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
00057     _dl_debug_printf ("\ncalling init: %s\n\n",
00058                     l->l_name[0] ? l->l_name : rtld_progname);
00059 
00060   /* Now run the local constructors.  There are two forms of them:
00061      - the one named by DT_INIT
00062      - the others in the DT_INIT_ARRAY.
00063   */
00064   if (l->l_info[DT_INIT] != NULL)
00065     {
00066       init_t init = (init_t) DL_DT_INIT_ADDRESS
00067        (l, l->l_addr + l->l_info[DT_INIT]->d_un.d_ptr);
00068 
00069       /* Call the function.  */
00070       init (argc, argv, env);
00071     }
00072 
00073   /* Next see whether there is an array with initialization functions.  */
00074   ElfW(Dyn) *init_array = l->l_info[DT_INIT_ARRAY];
00075   if (init_array != NULL)
00076     {
00077       unsigned int j;
00078       unsigned int jm;
00079       ElfW(Addr) *addrs;
00080 
00081       jm = l->l_info[DT_INIT_ARRAYSZ]->d_un.d_val / sizeof (ElfW(Addr));
00082 
00083       addrs = (ElfW(Addr) *) (init_array->d_un.d_ptr + l->l_addr);
00084       for (j = 0; j < jm; ++j)
00085        ((init_t) addrs[j]) (argc, argv, env);
00086     }
00087 }
00088 
00089 
00090 void
00091 internal_function
00092 _dl_init (struct link_map *main_map, int argc, char **argv, char **env)
00093 {
00094   ElfW(Dyn) *preinit_array = main_map->l_info[DT_PREINIT_ARRAY];
00095   ElfW(Dyn) *preinit_array_size = main_map->l_info[DT_PREINIT_ARRAYSZ];
00096   unsigned int i;
00097 
00098   if (__builtin_expect (GL(dl_initfirst) != NULL, 0))
00099     {
00100       call_init (GL(dl_initfirst), argc, argv, env);
00101       GL(dl_initfirst) = NULL;
00102     }
00103 
00104   /* Don't do anything if there is no preinit array.  */
00105   if (__builtin_expect (preinit_array != NULL, 0)
00106       && preinit_array_size != NULL
00107       && (i = preinit_array_size->d_un.d_val / sizeof (ElfW(Addr))) > 0)
00108     {
00109       ElfW(Addr) *addrs;
00110       unsigned int cnt;
00111 
00112       if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
00113        _dl_debug_printf ("\ncalling preinit: %s\n\n",
00114                        main_map->l_name[0]
00115                        ? main_map->l_name : rtld_progname);
00116 
00117       addrs = (ElfW(Addr) *) (preinit_array->d_un.d_ptr + main_map->l_addr);
00118       for (cnt = 0; cnt < i; ++cnt)
00119        ((init_t) addrs[cnt]) (argc, argv, env);
00120     }
00121 
00122   /* Stupid users forced the ELF specification to be changed.  It now
00123      says that the dynamic loader is responsible for determining the
00124      order in which the constructors have to run.  The constructors
00125      for all dependencies of an object must run before the constructor
00126      for the object itself.  Circular dependencies are left unspecified.
00127 
00128      This is highly questionable since it puts the burden on the dynamic
00129      loader which has to find the dependencies at runtime instead of
00130      letting the user do it right.  Stupidity rules!  */
00131 
00132   i = main_map->l_searchlist.r_nlist;
00133   while (i-- > 0)
00134     call_init (main_map->l_initfini[i], argc, argv, env);
00135 
00136 #ifndef HAVE_INLINED_SYSCALLS
00137   /* Finished starting up.  */
00138   INTUSE(_dl_starting_up) = 0;
00139 #endif
00140 }
00141 INTDEF (_dl_init)