]> git.ipfire.org Git - thirdparty/glibc.git/blame - elf/dl-deps.c
Update.
[thirdparty/glibc.git] / elf / dl-deps.c
CommitLineData
efec1d0c 1/* Load the dependencies of a mapped object.
df4ef2ab 2 Copyright (C) 1996, 1997 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
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 not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
efec1d0c
RM
19
20#include <link.h>
21#include <errno.h>
22#include <dlfcn.h>
23#include <stdlib.h>
24
25void
2064087b 26_dl_map_object_deps (struct link_map *map,
46ec036d
UD
27 struct link_map **preloads, unsigned int npreloads,
28 int trace_mode)
efec1d0c 29{
f68b86cc
RM
30 struct list
31 {
32 struct link_map *map;
33 struct list *next;
34 };
1228ed5c 35 struct list *head, *tailp, *scanp;
84384f5b 36 struct list duphead, *duptailp;
84384f5b 37 unsigned int nduplist;
df4ef2ab
UD
38 unsigned int nlist, naux, i;
39 inline void preload (struct link_map *map)
40 {
41 head[nlist].next = &head[nlist + 1];
42 head[nlist++].map = map;
efec1d0c 43
df4ef2ab
UD
44 /* We use `l_reserved' as a mark bit to detect objects we have
45 already put in the search list and avoid adding duplicate
46 elements later in the list. */
47 map->l_reserved = 1;
48 }
2064087b 49
df4ef2ab 50 naux = nlist = 0;
84384f5b 51
1228ed5c
UD
52 /* XXX The AUXILIARY implementation isn't correct in the moment. XXX
53 XXX The problem is that we currently do not handle auxiliary XXX
54 XXX entries in the loaded objects. XXX */
df4ef2ab 55
1228ed5c
UD
56#define AUXTAG (DT_NUM + DT_PROCNUM + DT_VERSIONTAGNUM \
57 + DT_EXTRATAGIDX (DT_AUXILIARY))
58
59 /* First determine the number of auxiliary objects we have to load. */
df4ef2ab 60 if (map->l_info[AUXTAG])
2064087b 61 {
1228ed5c
UD
62 ElfW(Dyn) *d;
63 for (d = map->l_ld; d->d_tag != DT_NULL; ++d)
64 if (d->d_tag == DT_AUXILIARY)
65 ++naux;
66 }
67
68 /* Now we can allocate the array for the linker maps. */
69 head = (struct list *) alloca (sizeof (struct list)
70 * (naux + npreloads + 2));
71
72 /* Load the auxiliary objects, even before the object itself. */
73 if (map->l_info[AUXTAG])
74 {
75 /* There is at least one auxiliary library specified. We try to
76 load it, and if we can, use its symbols in preference to our
77 own. But if we can't load it, we just silently ignore it. */
78 const char *strtab
79 = ((void *) map->l_addr + map->l_info[DT_STRTAB]->d_un.d_ptr);
80 ElfW(Dyn) *d;
81
82 for (d = map->l_ld; d->d_tag != DT_NULL; ++d)
83 if (d->d_tag == DT_AUXILIARY)
84 {
85 struct link_map *aux;
86 void openaux (void)
87 {
88 aux = _dl_map_object (map, strtab + d->d_un.d_val,
89 (map->l_type == lt_executable
90 ? lt_library : map->l_type),
91 trace_mode);
92 }
93 char *errstring;
94 const char *objname;
95 if (! _dl_catch_error (&errstring, &objname, openaux))
96 /* The auxiliary object is actually there. Use it as
97 the first search element, even before MAP itself. */
98 preload (aux);
99 }
2064087b
RM
100 }
101
1228ed5c 102 /* Next load MAP itself. */
df4ef2ab
UD
103 preload (map);
104
105 /* Add the preloaded items after MAP but before any of its dependencies. */
106 for (i = 0; i < npreloads; ++i)
107 preload (preloads[i]);
108
8a523922 109 /* Terminate the lists. */
df4ef2ab 110 head[nlist - 1].next = NULL;
8a523922 111 duphead.next = NULL;
c928de79
RM
112
113 /* Start here for adding dependencies to the list. */
df4ef2ab 114 tailp = &head[nlist - 1];
f68b86cc 115
84384f5b
UD
116 /* Until now we have the same number of libraries in the normal and
117 the list with duplicates. */
118 nduplist = nlist;
119 duptailp = &duphead;
efec1d0c
RM
120
121 /* Process each element of the search list, loading each of its immediate
122 dependencies and appending them to the list as we step through it.
123 This produces a flat, ordered list that represents a breadth-first
124 search of the dependency tree. */
c928de79 125 for (scanp = head; scanp; scanp = scanp->next)
efec1d0c 126 {
f68b86cc
RM
127 struct link_map *l = scanp->map;
128
efec1d0c
RM
129 if (l->l_info[DT_NEEDED])
130 {
131 const char *strtab
132 = ((void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
266180eb 133 const ElfW(Dyn) *d;
efec1d0c
RM
134 for (d = l->l_ld; d->d_tag != DT_NULL; ++d)
135 if (d->d_tag == DT_NEEDED)
136 {
f68b86cc
RM
137 /* Map in the needed object. */
138 struct link_map *dep
ba79d61b
RM
139 = _dl_map_object (l, strtab + d->d_un.d_val,
140 l->l_type == lt_executable ? lt_library :
46ec036d 141 l->l_type, trace_mode);
f68b86cc
RM
142
143 if (dep->l_reserved)
144 /* This object is already in the search list we are
145 building. Don't add a duplicate pointer. Release the
146 reference just added by _dl_map_object. */
147 --dep->l_opencount;
efec1d0c
RM
148 else
149 {
f68b86cc
RM
150 /* Append DEP to the search list. */
151 tailp->next = alloca (sizeof *tailp);
152 tailp = tailp->next;
153 tailp->map = dep;
154 tailp->next = NULL;
155 ++nlist;
f9496a7b
RM
156 /* Set the mark bit that says it's already in the list. */
157 dep->l_reserved = 1;
efec1d0c 158 }
84384f5b 159
df4ef2ab 160 /* In any case append DEP to the duplicates search list. */
84384f5b
UD
161 duptailp->next = alloca (sizeof *duptailp);
162 duptailp = duptailp->next;
163 duptailp->map = dep;
164 duptailp->next = NULL;
165 ++nduplist;
efec1d0c
RM
166 }
167 }
168 }
169
f68b86cc
RM
170 /* Store the search list we built in the object. It will be used for
171 searches in the scope of this object. */
172 map->l_searchlist = malloc (nlist * sizeof (struct link_map *));
df4ef2ab
UD
173 if (map->l_searchlist == NULL)
174 _dl_signal_error (ENOMEM, map->l_name,
175 "cannot allocate symbol search list");
efec1d0c 176 map->l_nsearchlist = nlist;
f68b86cc
RM
177
178 nlist = 0;
2064087b 179 for (scanp = head; scanp; scanp = scanp->next)
f68b86cc
RM
180 {
181 map->l_searchlist[nlist++] = scanp->map;
182
183 /* Now clear all the mark bits we set in the objects on the search list
184 to avoid duplicates, so the next call starts fresh. */
185 scanp->map->l_reserved = 0;
186 }
84384f5b
UD
187
188 map->l_dupsearchlist = malloc (nduplist * sizeof (struct link_map *));
df4ef2ab
UD
189 if (map->l_dupsearchlist == NULL)
190 _dl_signal_error (ENOMEM, map->l_name,
191 "cannot allocate symbol search list");
84384f5b
UD
192 map->l_ndupsearchlist = nduplist;
193
df4ef2ab 194 for (nlist = 0; nlist < naux + 1 + npreloads; ++nlist)
84384f5b
UD
195 map->l_dupsearchlist[nlist] = head[nlist].map;
196 for (scanp = duphead.next; scanp; scanp = scanp->next)
197 map->l_dupsearchlist[nlist++] = scanp->map;
efec1d0c 198}