f87475a67070424297903f80cc326904d49dbbd7
[kopensolaris-gnu/glibc.git] / elf / dl-deps.c
1 /* Load the dependencies of a mapped object.
2 Copyright (C) 1996 Free Software Foundation, Inc.
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
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
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
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB.  If
17 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
18 Cambridge, MA 02139, USA.  */
19
20 #include <link.h>
21 #include <errno.h>
22 #include <dlfcn.h>
23 #include <stdlib.h>
24
25 void
26 _dl_map_object_deps (struct link_map *map)
27 {
28   unsigned int nlist = 1;
29   struct link_map **list = malloc (sizeof *list);
30   unsigned int done;
31
32   /* Start the search list with one element: MAP itself.  */
33   list[0] = map;
34
35   /* Process each element of the search list, loading each of its immediate
36      dependencies and appending them to the list as we step through it.
37      This produces a flat, ordered list that represents a breadth-first
38      search of the dependency tree.  */
39   for (done = 0; done < nlist; ++done)
40     {
41       struct link_map *l = list[done];
42       if (l->l_info[DT_NEEDED])
43         {
44           const char *strtab
45             = ((void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
46           const Elf32_Dyn *d;
47           for (d = l->l_ld; d->d_tag != DT_NULL; ++d)
48             if (d->d_tag == DT_NEEDED)
49               {
50                 /* Extend the list and put this object on the end.  */
51                 struct link_map **n
52                   = realloc (list, (nlist + 1) * sizeof *list);
53                 if (n)
54                   list = n;
55                 else
56                   {
57                     free (list);
58                     _dl_signal_error (ENOMEM, map->l_name,
59                                       "finding dependencies");
60                   }
61                 list[nlist++] = _dl_map_object (l, strtab + d->d_un.d_val);
62               }
63         }
64     }
65
66   map->l_searchlist = list;
67   map->l_nsearchlist = nlist;
68 }
69
70
71 struct link_map *
72 _dl_open (struct link_map *parent, const char *file, int mode)
73 {
74   struct link_map *new, *l;
75   Elf32_Addr init;
76
77   /* Load the named object.  */
78   new = _dl_map_object (parent, file);
79
80   /* Load that object's dependencies.  */
81   _dl_map_object_deps (new);
82
83   /* Relocate the objects loaded.  */
84   for (l = new; l; l = l->l_next)
85     if (! l->l_relocated)
86       _dl_relocate_object (l, (mode & RTLD_BINDING_MASK) == RTLD_LAZY);
87
88   /* Run the initializer functions of new objects.  */
89   while (init = _dl_init_next ())
90     (*(void (*) (void)) init) ();
91
92   return new;
93 }