]> git.ipfire.org Git - thirdparty/glibc.git/blame - elf/dl-object.c
Update copyright dates with scripts/update-copyrights
[thirdparty/glibc.git] / elf / dl-object.c
CommitLineData
d66e34cd 1/* Storage management for the chain of loaded shared objects.
2b778ceb 2 Copyright (C) 1995-2021 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
41bdb6e2
AJ
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
afd4eb37
UD
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
41bdb6e2 13 Lesser General Public License for more details.
afd4eb37 14
41bdb6e2 15 You should have received a copy of the GNU Lesser General Public
59ba27a6 16 License along with the GNU C Library; if not, see
5a82c748 17 <https://www.gnu.org/licenses/>. */
d66e34cd 18
a853022c 19#include <errno.h>
d66e34cd
RM
20#include <string.h>
21#include <stdlib.h>
f787edde 22#include <unistd.h>
a42195db 23#include <ldsodefs.h>
d66e34cd 24
a853022c 25#include <assert.h>
d66e34cd 26
d66e34cd 27
f0967738
AK
28/* Add the new link_map NEW to the end of the namespace list. */
29void
f0967738
AK
30_dl_add_to_namespace_list (struct link_map *new, Lmid_t nsid)
31{
32 /* We modify the list of loaded objects. */
33 __rtld_lock_lock_recursive (GL(dl_load_write_lock));
34
35 if (GL(dl_ns)[nsid]._ns_loaded != NULL)
36 {
37 struct link_map *l = GL(dl_ns)[nsid]._ns_loaded;
38 while (l->l_next != NULL)
39 l = l->l_next;
40 new->l_prev = l;
41 /* new->l_next = NULL; Would be necessary but we use calloc. */
42 l->l_next = new;
43 }
44 else
45 GL(dl_ns)[nsid]._ns_loaded = new;
46 ++GL(dl_ns)[nsid]._ns_nloaded;
47 new->l_serial = GL(dl_load_adds);
48 ++GL(dl_load_adds);
49
50 __rtld_lock_unlock_recursive (GL(dl_load_write_lock));
51}
52
53
d66e34cd
RM
54/* Allocate a `struct link_map' for a new object being loaded,
55 and enter it into the _dl_loaded list. */
d66e34cd 56struct link_map *
be935610 57_dl_new_object (char *realname, const char *libname, int type,
c0f62c56 58 struct link_map *loader, int mode, Lmid_t nsid)
d66e34cd 59{
23d2e5fa
FW
60#ifdef SHARED
61 unsigned int naudit;
62 if (__glibc_unlikely ((mode & __RTLD_OPENEXEC) != 0))
63 {
64 assert (type == lt_executable);
65 assert (nsid == LM_ID_BASE);
66
67 /* Ignore the specified libname for the main executable. It is
68 only known with an explicit loader invocation. */
69 libname = "";
70
71 /* We create the map for the executable before we know whether
72 we have auditing libraries and if yes, how many. Assume the
73 worst. */
74 naudit = DL_NNS;
75 }
76 else
77 naudit = GLRO (dl_naudit);
78#endif
79
76156ea1 80 size_t libname_len = strlen (libname) + 1;
c4bb124a
UD
81 struct link_map *new;
82 struct libname_list *newname;
9dcafc55 83#ifdef SHARED
e1d559f3 84 size_t audit_space = naudit * sizeof (struct auditstate);
9dcafc55
UD
85#else
86# define audit_space 0
87#endif
c4bb124a 88
9dcafc55 89 new = (struct link_map *) calloc (sizeof (*new) + audit_space
7b91359b 90 + sizeof (struct link_map *)
9dcafc55 91 + sizeof (*newname) + libname_len, 1);
11810621 92 if (new == NULL)
ba79d61b 93 return NULL;
d66e34cd 94
c0f62c56 95 new->l_real = new;
ff0bf753
UD
96 new->l_symbolic_searchlist.r_list = (struct link_map **) ((char *) (new + 1)
97 + audit_space);
98
99 new->l_libname = newname
100 = (struct libname_list *) (new->l_symbolic_searchlist.r_list + 1);
c4bb124a 101 newname->name = (char *) memcpy (newname + 1, libname, libname_len);
455e8060 102 /* newname->next = NULL; We use calloc therefore not necessary. */
11810621
UD
103 newname->dont_free = 1;
104
9182aa67
JK
105 /* When we create the executable link map, or a VDSO link map, we start
106 with "" for the l_name. In these cases "" points to ld.so rodata
107 and won't get dumped during core file generation. Therefore to assist
108 gdb and to create more self-contained core files we adjust l_name to
109 point at the newly allocated copy (which will get dumped) instead of
23d2e5fa
FW
110 the ld.so rodata copy.
111
112 Furthermore, in case of explicit loader invocation, discard the
113 name of the main executable, to match the regular behavior, where
114 name of the executable is not known. */
115#ifdef SHARED
116 if (*realname != '\0' && (mode & __RTLD_OPENEXEC) == 0)
117#else
118 if (*realname != '\0')
119#endif
120 new->l_name = realname;
121 else
122 new->l_name = (char *) newname->name + libname_len - 1;
123
d66e34cd 124 new->l_type = type;
2af63968
UD
125 /* If we set the bit now since we know it is never used we avoid
126 dirtying the cache line later. */
127 if ((GLRO(dl_debug_mask) & DL_DEBUG_UNUSED) == 0)
128 new->l_used = 1;
be935610 129 new->l_loader = loader;
11bf311e 130#if NO_TLS_OFFSET != 0
299601a1
UD
131 new->l_tls_offset = NO_TLS_OFFSET;
132#endif
c0f62c56 133 new->l_ns = nsid;
299601a1 134
9dcafc55
UD
135#ifdef SHARED
136 for (unsigned int cnt = 0; cnt < naudit; ++cnt)
e1d559f3
FW
137 /* No need to initialize bindflags due to calloc. */
138 link_map_audit_state (new, cnt)->cookie = (uintptr_t) new;
9dcafc55
UD
139#endif
140
b25d4ff0 141 /* new->l_global = 0; We use calloc therefore not necessary. */
d66e34cd 142
ded5b9b7 143 /* Use the 'l_scope_mem' array by default for the 'l_scope'
5a21d307
UD
144 information. If we need more entries we will allocate a large
145 array dynamically. */
c0a777e8
UD
146 new->l_scope = new->l_scope_mem;
147 new->l_scope_max = sizeof (new->l_scope_mem) / sizeof (new->l_scope_mem[0]);
1100f849 148
be935610 149 /* Counter for the scopes we have to handle. */
f0967738 150 int idx = 0;
be935610 151
c0f62c56 152 if (GL(dl_ns)[nsid]._ns_loaded != NULL)
f0967738
AK
153 /* Add the global scope. */
154 new->l_scope[idx++] = &GL(dl_ns)[nsid]._ns_loaded->l_searchlist;
5a2a1d75 155
7bccbc05
UD
156 /* If we have no loader the new object acts as it. */
157 if (loader == NULL)
158 loader = new;
159 else
160 /* Determine the local scope. */
161 while (loader->l_loader != NULL)
162 loader = loader->l_loader;
163
164 /* Insert the scope if it isn't the global scope we already added. */
c0a777e8 165 if (idx == 0 || &loader->l_searchlist != new->l_scope[0])
1fc07491
UD
166 {
167 if ((mode & RTLD_DEEPBIND) != 0 && idx != 0)
168 {
c0a777e8 169 new->l_scope[1] = new->l_scope[0];
1fc07491
UD
170 idx = 0;
171 }
172
c0a777e8 173 new->l_scope[idx] = &loader->l_searchlist;
1fc07491 174 }
be935610 175
df4d2898 176 new->l_local_scope[0] = &new->l_searchlist;
be935610 177
23d2e5fa
FW
178 /* Determine the origin. If allocating the link map for the main
179 executable, the realname is not known and "". In this case, the
180 origin needs to be determined by other means. However, in case
181 of an explicit loader invocation, the pathname of the main
182 executable is known and needs to be processed here: From the
183 point of view of the kernel, the main executable is the
184 dynamic loader, and this would lead to a computation of the wrong
185 origin. */
be935610 186 if (realname[0] != '\0')
f787edde 187 {
7bccbc05 188 size_t realname_len = strlen (realname) + 1;
f787edde 189 char *origin;
7bccbc05 190 char *cp;
f787edde
UD
191
192 if (realname[0] == '/')
193 {
7bccbc05
UD
194 /* It is an absolute path. Use it. But we have to make a
195 copy since we strip out the trailing slash. */
196 cp = origin = (char *) malloc (realname_len);
f787edde 197 if (origin == NULL)
7bccbc05
UD
198 {
199 origin = (char *) -1;
200 goto out;
201 }
f787edde
UD
202 }
203 else
204 {
7bccbc05 205 size_t len = realname_len;
f787edde
UD
206 char *result = NULL;
207
208 /* Get the current directory name. */
7bccbc05
UD
209 origin = NULL;
210 do
f787edde 211 {
d1dddedf
UD
212 char *new_origin;
213
f787edde 214 len += 128;
d1dddedf
UD
215 new_origin = (char *) realloc (origin, len);
216 if (new_origin == NULL)
217 /* We exit the loop. Note that result == NULL. */
218 break;
219 origin = new_origin;
f787edde 220 }
d1dddedf 221 while ((result = __getcwd (origin, len - realname_len)) == NULL
7bccbc05 222 && errno == ERANGE);
f787edde
UD
223
224 if (result == NULL)
225 {
7bccbc05 226 /* We were not able to determine the current directory.
2af63968 227 Note that free(origin) is OK if origin == NULL. */
903244ac 228 free (origin);
f787edde 229 origin = (char *) -1;
7bccbc05 230 goto out;
f787edde 231 }
f787edde 232
9710f75d
UD
233 /* Find the end of the path and see whether we have to add a
234 slash. We could use rawmemchr but this need not be
235 fast. */
236 cp = (strchr) (origin, '\0');
7bccbc05
UD
237 if (cp[-1] != '/')
238 *cp++ = '/';
f787edde
UD
239 }
240
7bccbc05 241 /* Add the real file name. */
88794e30 242 cp = __mempcpy (cp, realname, realname_len);
7bccbc05 243
88794e30 244 /* Now remove the filename and the slash. Leave the slash if
7bccbc05 245 the name is something like "/foo". */
88794e30
UD
246 do
247 --cp;
248 while (*cp != '/');
249
7bccbc05 250 if (cp == origin)
88794e30
UD
251 /* Keep the only slash which is the first character. */
252 ++cp;
253 *cp = '\0';
f787edde 254
7bccbc05 255 out:
f787edde
UD
256 new->l_origin = origin;
257 }
258
d66e34cd
RM
259 return new;
260}