aboutsummaryrefslogtreecommitdiff
path: root/elf/dl-init.c
diff options
context:
space:
mode:
Diffstat (limited to 'elf/dl-init.c')
-rw-r--r--elf/dl-init.c60
1 files changed, 40 insertions, 20 deletions
diff --git a/elf/dl-init.c b/elf/dl-init.c
index 64aa1ce0bf..c4b1e22152 100644
--- a/elf/dl-init.c
+++ b/elf/dl-init.c
@@ -1,5 +1,5 @@
/* Return the next shared object initializer function not yet run.
- Copyright (C) 1995, 1996, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -38,39 +38,59 @@ _dl_init_next (struct r_scope_elem *searchlist)
while (i-- > 0)
{
struct link_map *l = searchlist->r_list[i];
+ ElfW(Addr) *array;
if (l->l_init_called)
/* This object is all done. */
continue;
- if (l->l_init_running)
+ /* Check for object which constructors we do not run here.
+ XXX Maybe this should be pre-computed, but where? */
+ if (l->l_name[0] == '\0' && l->l_type == lt_executable)
{
- /* This object's initializer was just running.
- Now mark it as having run, so this object
- will be skipped in the future. */
- l->l_init_running = 0;
l->l_init_called = 1;
continue;
}
- if (l->l_info[DT_INIT]
- && (l->l_name[0] != '\0' || l->l_type != lt_executable))
- {
- /* Run this object's initializer. */
- l->l_init_running = 1;
+ /* Account for running next constructor. */
+ ++l->l_runcount;
- /* Print a debug message if wanted. */
- if (_dl_debug_impcalls)
- _dl_debug_message (1, "\ncalling init: ",
- l->l_name[0] ? l->l_name : _dl_argv[0],
- "\n\n", NULL);
+ if (l->l_runcount == 1)
+ {
+ /* Try running the DT_INIT constructor. */
+ if (l->l_info[DT_INIT])
+ {
+ /* Print a debug message if wanted. */
+ if (_dl_debug_impcalls)
+ _dl_debug_message (1, "\ncalling init: ",
+ l->l_name[0] ? l->l_name : _dl_argv[0],
+ "\n\n", NULL);
+
+ return l->l_addr + l->l_info[DT_INIT]->d_un.d_ptr;
+ }
+
+ /* No DT_INIT, so go on with the array. */
+ ++l->l_runcount;
+ }
- return l->l_addr + l->l_info[DT_INIT]->d_un.d_ptr;
+ if (l->l_runcount > l->l_initcount)
+ {
+ /* That were all of the constructors. */
+ l->l_runcount = 0;
+ l->l_init_called = 1;
+ continue;
}
- /* No initializer for this object.
- Mark it so we will skip it in the future. */
- l->l_init_called = 1;
+ /* Print a debug message if wanted. */
+ if (_dl_debug_impcalls && l->l_info[DT_INIT] == NULL
+ && l->l_runcount == 2)
+ _dl_debug_message (1, "\ncalling init: ",
+ l->l_name[0] ? l->l_name : _dl_argv[0],
+ "\n\n", NULL);
+
+ array = (ElfW(Addr) *) l->l_info[DT_INIT_ARRAY]->d_un.d_ptr;
+ return l->l_addr + array[l->l_runcount - 2];
+ /* NOTREACHED */
}