]> sourceware.org Git - glibc.git/blame - elf/dl-init.c
(_dl_init): Fix test of the size of the preinit_array section. (call_init): Optimize...
[glibc.git] / elf / dl-init.c
CommitLineData
d66e34cd 1/* Return the next shared object initializer function not yet run.
d6b5d570 2 Copyright (C) 1995, 1996, 1998-2001, 2002 Free Software Foundation, Inc.
afd4eb37
UD
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
afd4eb37
UD
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 13 Lesser General Public License for more details.
afd4eb37 14
41bdb6e2
AJ
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
d66e34cd
RM
19
20#include <stddef.h>
a42195db 21#include <ldsodefs.h>
d66e34cd
RM
22
23
dacc8ffa
UD
24/* Type of the initializer. */
25typedef void (*init_t) (int, char **, char **);
f68b86cc 26
7688db91
UD
27/* Flag, nonzero during startup phase. */
28extern int _dl_starting_up;
e6caf4e1 29extern int _dl_starting_up_internal attribute_hidden;
7688db91 30
5d916713
UD
31
32static void
33call_init (struct link_map *l, int argc, char **argv, char **env)
34{
35 if (l->l_init_called)
36 /* This object is all done. */
37 return;
38
39 /* Avoid handling this constructor again in case we have a circular
40 dependency. */
41 l->l_init_called = 1;
42
43 /* Check for object which constructors we do not run here. */
bd929413
UD
44 if (__builtin_expect (l->l_name[0], 'a') == '\0'
45 && l->l_type == lt_executable)
5d916713
UD
46 return;
47
48 /* Are there any constructors? */
bd929413
UD
49 if (l->l_info[DT_INIT] == NULL
50 && __builtin_expect (l->l_info[DT_INIT_ARRAY] == NULL, 1))
5d916713
UD
51 return;
52
53 /* Print a debug message if wanted. */
d6b5d570 54 if (__builtin_expect (GL(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
cff26a3e 55 INTUSE(_dl_debug_printf) ("\ncalling init: %s\n\n",
e6caf4e1 56 l->l_name[0] ? l->l_name : rtld_progname);
5d916713
UD
57
58 /* Now run the local constructors. There are two forms of them:
59 - the one named by DT_INIT
60 - the others in the DT_INIT_ARRAY.
61 */
62 if (l->l_info[DT_INIT] != NULL)
63 {
64 init_t init = (init_t) DL_DT_INIT_ADDRESS
65 (l, l->l_addr + l->l_info[DT_INIT]->d_un.d_ptr);
66
67 /* Call the function. */
68 init (argc, argv, env);
69 }
70
71 /* Next see whether there is an array with initialization functions. */
53fe2758
UD
72 ElfW(Dyn) *init_array = l->l_info[DT_INIT_ARRAY];
73 if (init_array != NULL)
5d916713
UD
74 {
75 unsigned int j;
76 unsigned int jm;
77 ElfW(Addr) *addrs;
78
79 jm = l->l_info[DT_INIT_ARRAYSZ]->d_un.d_val / sizeof (ElfW(Addr));
80
53fe2758 81 addrs = (ElfW(Addr) *) (init_array->d_un.d_ptr + l->l_addr);
5d916713
UD
82 for (j = 0; j < jm; ++j)
83 ((init_t) addrs[j]) (argc, argv, env);
84 }
85}
86
dacc8ffa 87
841288ec 88void
d0fc4041 89internal_function
841288ec 90_dl_init (struct link_map *main_map, int argc, char **argv, char **env)
d66e34cd 91{
a7f91846 92 ElfW(Dyn) *preinit_array = main_map->l_info[DT_PREINIT_ARRAY];
53fe2758 93 ElfW(Dyn) *preinit_array_size = main_map->l_info[DT_PREINIT_ARRAYSZ];
841288ec 94 struct r_debug *r;
f68b86cc
RM
95 unsigned int i;
96
d6b5d570 97 if (__builtin_expect (GL(dl_initfirst) != NULL, 0))
5d916713 98 {
d6b5d570
UD
99 call_init (GL(dl_initfirst), argc, argv, env);
100 GL(dl_initfirst) = NULL;
5d916713
UD
101 }
102
d7926ed9 103 /* Don't do anything if there is no preinit array. */
bd929413 104 if (__builtin_expect (preinit_array != NULL, 0)
53fe2758
UD
105 && preinit_array_size != NULL
106 && (i = preinit_array_size->d_un.d_val / sizeof (ElfW(Addr))) > 0)
d7926ed9
UD
107 {
108 ElfW(Addr) *addrs;
109 unsigned int cnt;
110
d6b5d570 111 if (__builtin_expect (GL(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
cff26a3e
AJ
112 INTUSE(_dl_debug_printf) ("\ncalling preinit: %s\n\n",
113 main_map->l_name[0]
e6caf4e1 114 ? main_map->l_name : rtld_progname);
d7926ed9 115
53fe2758 116 addrs = (ElfW(Addr) *) (preinit_array->d_un.d_ptr + main_map->l_addr);
d7926ed9
UD
117 for (cnt = 0; cnt < i; ++cnt)
118 ((init_t) addrs[cnt]) (argc, argv, env);
119 }
120
841288ec
UD
121 /* Notify the debugger we have added some objects. We need to call
122 _dl_debug_initialize in a static program in case dynamic linking has
123 not been used before. */
124 r = _dl_debug_initialize (0);
125 r->r_state = RT_ADD;
cff26a3e 126 INTUSE(_dl_debug_state) ();
841288ec 127
bd929413 128 /* Stupid users forced the ELF specification to be changed. It now
dacc8ffa
UD
129 says that the dynamic loader is responsible for determining the
130 order in which the constructors have to run. The constructors
131 for all dependencies of an object must run before the constructor
132 for the object itself. Circular dependencies are left unspecified.
133
134 This is highly questionable since it puts the burden on the dynamic
135 loader which has to find the dependencies at runtime instead of
136 letting the user do it right. Stupidity rules! */
d66e34cd 137
841288ec 138 i = main_map->l_searchlist.r_nlist;
f68b86cc 139 while (i-- > 0)
5d916713 140 call_init (main_map->l_initfini[i], argc, argv, env);
dacc8ffa
UD
141
142 /* Notify the debugger all new objects are now ready to go. */
143 r->r_state = RT_CONSISTENT;
cff26a3e 144 INTUSE(_dl_debug_state) ();
7688db91
UD
145
146 /* Finished starting up. */
e6caf4e1 147 INTUSE(_dl_starting_up) = 0;
d66e34cd 148}
7969407a 149INTDEF (_dl_init)
This page took 0.174752 seconds and 5 git commands to generate.