]>
Commit | Line | Data |
---|---|---|
efec1d0c | 1 | /* Load the dependencies of a mapped object. |
afd4eb37 UD |
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 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 | ||
25 | void | |
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 | }; | |
2064087b | 35 | struct list head[1 + npreloads], *tailp, *scanp; |
84384f5b | 36 | struct list duphead, *duptailp; |
f68b86cc | 37 | unsigned int nlist; |
84384f5b | 38 | unsigned int nduplist; |
efec1d0c RM |
39 | |
40 | /* Start the search list with one element: MAP itself. */ | |
2064087b RM |
41 | head[0].map = map; |
42 | ||
84384f5b UD |
43 | /* We use `l_reserved' as a mark bit to detect objects we have already |
44 | put in the search list and avoid adding duplicate elements later in | |
45 | the list. */ | |
46 | map->l_reserved = 1; | |
47 | ||
2064087b RM |
48 | /* Add the preloaded items after MAP but before any of its dependencies. */ |
49 | for (nlist = 0; nlist < npreloads; ++nlist) | |
50 | { | |
51 | head[nlist].next = &head[nlist + 1]; | |
52 | head[nlist + 1].map = preloads[nlist]; | |
84384f5b | 53 | preloads[nlist]->l_reserved = 1; |
2064087b RM |
54 | } |
55 | ||
8a523922 | 56 | /* Terminate the lists. */ |
c928de79 | 57 | head[nlist].next = NULL; |
8a523922 | 58 | duphead.next = NULL; |
c928de79 RM |
59 | |
60 | /* Start here for adding dependencies to the list. */ | |
61 | tailp = &head[nlist++]; | |
f68b86cc | 62 | |
84384f5b UD |
63 | /* Until now we have the same number of libraries in the normal and |
64 | the list with duplicates. */ | |
65 | nduplist = nlist; | |
66 | duptailp = &duphead; | |
efec1d0c RM |
67 | |
68 | /* Process each element of the search list, loading each of its immediate | |
69 | dependencies and appending them to the list as we step through it. | |
70 | This produces a flat, ordered list that represents a breadth-first | |
71 | search of the dependency tree. */ | |
c928de79 | 72 | for (scanp = head; scanp; scanp = scanp->next) |
efec1d0c | 73 | { |
f68b86cc RM |
74 | struct link_map *l = scanp->map; |
75 | ||
efec1d0c RM |
76 | if (l->l_info[DT_NEEDED]) |
77 | { | |
78 | const char *strtab | |
79 | = ((void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr); | |
266180eb | 80 | const ElfW(Dyn) *d; |
efec1d0c RM |
81 | for (d = l->l_ld; d->d_tag != DT_NULL; ++d) |
82 | if (d->d_tag == DT_NEEDED) | |
83 | { | |
f68b86cc RM |
84 | /* Map in the needed object. */ |
85 | struct link_map *dep | |
ba79d61b RM |
86 | = _dl_map_object (l, strtab + d->d_un.d_val, |
87 | l->l_type == lt_executable ? lt_library : | |
46ec036d | 88 | l->l_type, trace_mode); |
f68b86cc RM |
89 | |
90 | if (dep->l_reserved) | |
91 | /* This object is already in the search list we are | |
92 | building. Don't add a duplicate pointer. Release the | |
93 | reference just added by _dl_map_object. */ | |
94 | --dep->l_opencount; | |
efec1d0c RM |
95 | else |
96 | { | |
f68b86cc RM |
97 | /* Append DEP to the search list. */ |
98 | tailp->next = alloca (sizeof *tailp); | |
99 | tailp = tailp->next; | |
100 | tailp->map = dep; | |
101 | tailp->next = NULL; | |
102 | ++nlist; | |
f9496a7b RM |
103 | /* Set the mark bit that says it's already in the list. */ |
104 | dep->l_reserved = 1; | |
efec1d0c | 105 | } |
84384f5b UD |
106 | |
107 | /* In any case Append DEP to the duplicates search list. */ | |
108 | duptailp->next = alloca (sizeof *duptailp); | |
109 | duptailp = duptailp->next; | |
110 | duptailp->map = dep; | |
111 | duptailp->next = NULL; | |
112 | ++nduplist; | |
efec1d0c RM |
113 | } |
114 | } | |
115 | } | |
116 | ||
f68b86cc RM |
117 | /* Store the search list we built in the object. It will be used for |
118 | searches in the scope of this object. */ | |
119 | map->l_searchlist = malloc (nlist * sizeof (struct link_map *)); | |
efec1d0c | 120 | map->l_nsearchlist = nlist; |
f68b86cc RM |
121 | |
122 | nlist = 0; | |
2064087b | 123 | for (scanp = head; scanp; scanp = scanp->next) |
f68b86cc RM |
124 | { |
125 | map->l_searchlist[nlist++] = scanp->map; | |
126 | ||
127 | /* Now clear all the mark bits we set in the objects on the search list | |
128 | to avoid duplicates, so the next call starts fresh. */ | |
129 | scanp->map->l_reserved = 0; | |
130 | } | |
84384f5b UD |
131 | |
132 | map->l_dupsearchlist = malloc (nduplist * sizeof (struct link_map *)); | |
133 | map->l_ndupsearchlist = nduplist; | |
134 | ||
135 | for (nlist = 0; nlist < npreloads + 1; ++nlist) | |
136 | map->l_dupsearchlist[nlist] = head[nlist].map; | |
137 | for (scanp = duphead.next; scanp; scanp = scanp->next) | |
138 | map->l_dupsearchlist[nlist++] = scanp->map; | |
efec1d0c | 139 | } |