]>
Commit | Line | Data |
---|---|---|
d66e34cd | 1 | /* Storage management for the chain of loaded shared objects. |
c1d32f33 | 2 | Copyright (C) 1995,96,97,98,99,2000,2001 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. */ | |
d66e34cd | 19 | |
a853022c | 20 | #include <errno.h> |
d66e34cd RM |
21 | #include <string.h> |
22 | #include <stdlib.h> | |
f787edde | 23 | #include <unistd.h> |
a42195db | 24 | #include <ldsodefs.h> |
d66e34cd | 25 | |
a853022c | 26 | #include <assert.h> |
d66e34cd | 27 | |
d66e34cd RM |
28 | |
29 | /* Allocate a `struct link_map' for a new object being loaded, | |
30 | and enter it into the _dl_loaded list. */ | |
31 | ||
32 | struct link_map * | |
d0fc4041 | 33 | internal_function |
be935610 UD |
34 | _dl_new_object (char *realname, const char *libname, int type, |
35 | struct link_map *loader) | |
d66e34cd | 36 | { |
be935610 UD |
37 | struct link_map *l; |
38 | int idx; | |
76156ea1 UD |
39 | size_t libname_len = strlen (libname) + 1; |
40 | struct link_map *new = calloc (sizeof *new, 1); | |
41 | struct libname_list *newname = malloc (sizeof *newname + libname_len); | |
c84142e8 | 42 | if (! new || ! newname) |
ba79d61b | 43 | return NULL; |
d66e34cd | 44 | |
d66e34cd | 45 | new->l_name = realname; |
76156ea1 | 46 | newname->name = memcpy (newname + 1, libname, libname_len); |
c84142e8 UD |
47 | newname->next = NULL; |
48 | new->l_libname = newname; | |
d66e34cd | 49 | new->l_type = type; |
be935610 | 50 | new->l_loader = loader; |
b25d4ff0 | 51 | /* new->l_global = 0; We use calloc therefore not necessary. */ |
d66e34cd | 52 | |
be935610 UD |
53 | /* Counter for the scopes we have to handle. */ |
54 | idx = 0; | |
55 | ||
56 | if (_dl_loaded != NULL) | |
d66e34cd | 57 | { |
be935610 | 58 | l = _dl_loaded; |
d66e34cd RM |
59 | while (l->l_next) |
60 | l = l->l_next; | |
61 | new->l_prev = l; | |
49c091e5 | 62 | /* new->l_next = NULL; Would be necessary but we use calloc. */ |
d66e34cd | 63 | l->l_next = new; |
d66e34cd | 64 | |
be935610 UD |
65 | /* Add the global scope. */ |
66 | new->l_scope[idx++] = &_dl_loaded->l_searchlist; | |
67 | } | |
e4d50917 UD |
68 | else |
69 | _dl_loaded = new; | |
1ebba33e | 70 | ++_dl_nloaded; |
be935610 UD |
71 | /* This is our local scope. */ |
72 | if (loader != NULL) | |
73 | { | |
74 | while (loader->l_loader != NULL) | |
75 | loader = loader->l_loader; | |
c1d32f33 UD |
76 | if (idx == 0 || &loader->l_searchlist != new->l_scope[0]) |
77 | new->l_scope[idx] = &loader->l_searchlist; | |
be935610 | 78 | } |
c1d32f33 | 79 | else if (idx == 0 || &new->l_searchlist != new->l_scope[0]) |
be935610 UD |
80 | new->l_scope[idx] = &new->l_searchlist; |
81 | ||
df4d2898 | 82 | new->l_local_scope[0] = &new->l_searchlist; |
be935610 UD |
83 | |
84 | /* Don't try to find the origin for the main map which has the name "". */ | |
85 | if (realname[0] != '\0') | |
f787edde UD |
86 | { |
87 | char *origin; | |
88 | ||
89 | if (realname[0] == '/') | |
90 | { | |
91 | /* It an absolute path. Use it. But we have to make a copy since | |
92 | we strip out the trailing slash. */ | |
93 | size_t len = strlen (realname) + 1; | |
94 | origin = malloc (len); | |
95 | if (origin == NULL) | |
96 | origin = (char *) -1; | |
97 | else | |
98 | memcpy (origin, realname, len); | |
99 | } | |
100 | else | |
101 | { | |
102 | size_t realname_len = strlen (realname) + 1; | |
103 | size_t len = 128 + realname_len; | |
104 | char *result = NULL; | |
105 | ||
106 | /* Get the current directory name. */ | |
107 | origin = malloc (len); | |
108 | ||
109 | while (origin != NULL | |
110 | && (result = __getcwd (origin, len - realname_len)) == NULL | |
111 | && errno == ERANGE) | |
112 | { | |
113 | len += 128; | |
114 | origin = (char *) realloc (origin, len); | |
115 | } | |
116 | ||
117 | if (result == NULL) | |
118 | { | |
119 | /* We were not able to determine the current directory. */ | |
120 | if (origin != NULL) | |
121 | free (origin); | |
122 | origin = (char *) -1; | |
123 | } | |
124 | else | |
125 | { | |
126 | /* Now append the filename. */ | |
127 | char *cp = strchr (origin, '\0'); | |
128 | ||
129 | if (cp [-1] != '/') | |
130 | *cp++ = '/'; | |
131 | ||
132 | memcpy (cp, realname, realname_len); | |
133 | } | |
134 | } | |
135 | ||
136 | if (origin != (char *) -1) | |
143e2b96 UD |
137 | { |
138 | /* Now remove the filename and the slash. Do this even if the | |
139 | string is something like "/foo" which leaves an empty string. */ | |
140 | char *last = strrchr (origin, '/'); | |
141 | ||
142 | if (last == origin) | |
143 | origin[1] = '\0'; | |
144 | else | |
145 | *last = '\0'; | |
146 | } | |
f787edde UD |
147 | |
148 | new->l_origin = origin; | |
149 | } | |
150 | ||
d66e34cd RM |
151 | return new; |
152 | } |