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