]> git.ipfire.org Git - thirdparty/glibc.git/blame - elf/dl-sym.c
Update copyright dates with scripts/update-copyrights
[thirdparty/glibc.git] / elf / dl-sym.c
CommitLineData
94e365c6 1/* Look up a symbol in a shared object loaded by `dlopen'.
2b778ceb 2 Copyright (C) 1999-2021 Free Software Foundation, Inc.
94e365c6
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.
94e365c6
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.
94e365c6 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/>. */
94e365c6 18
1100f849 19#include <assert.h>
94e365c6
UD
20#include <stddef.h>
21#include <setjmp.h>
176790a7 22#include <stdlib.h>
94e365c6
UD
23#include <libintl.h>
24
25#include <dlfcn.h>
26#include <ldsodefs.h>
27#include <dl-hash.h>
609cf614 28#include <sysdep-cancel.h>
11bf311e 29#include <dl-tls.h>
42675c6f 30#include <dl-irel.h>
c76147af 31#include <dl-sym-post.h>
154d10bd
UD
32
33
11bf311e 34#ifdef SHARED
154d10bd
UD
35/* Systems which do not have tls_index also probably have to define
36 DONT_USE_TLS_INDEX. */
37
38# ifndef __TLS_GET_ADDR
39# define __TLS_GET_ADDR __tls_get_addr
40# endif
41
42/* Return the symbol address given the map of the module it is in and
43 the symbol record. This is used in dl-sym.c. */
44static void *
154d10bd
UD
45_dl_tls_symaddr (struct link_map *map, const ElfW(Sym) *ref)
46{
47# ifndef DONT_USE_TLS_INDEX
48 tls_index tmp =
49 {
50 .ti_module = map->l_tls_modid,
51 .ti_offset = ref->st_value
52 };
53
54 return __TLS_GET_ADDR (&tmp);
55# else
56 return __TLS_GET_ADDR (map->l_tls_modid, ref->st_value);
57# endif
58}
59#endif
60
94e365c6 61
1100f849
UD
62struct call_dl_lookup_args
63{
64 /* Arguments to do_dlsym. */
65 struct link_map *map;
66 const char *name;
1100f849
UD
67 struct r_found_version *vers;
68 int flags;
69
70 /* Return values of do_dlsym. */
71 lookup_t loadbase;
72 const ElfW(Sym) **refp;
73};
74
75static void
76call_dl_lookup (void *ptr)
77{
78 struct call_dl_lookup_args *args = (struct call_dl_lookup_args *) ptr;
79 args->map = GLRO(dl_lookup_symbol_x) (args->name, args->map, args->refp,
c0a777e8 80 args->map->l_scope, args->vers, 0,
1100f849
UD
81 args->flags, NULL);
82}
83
53761a8b 84static void *
f0323886
UD
85do_sym (void *handle, const char *name, void *who,
86 struct r_found_version *vers, int flags)
94e365c6 87{
94e365c6 88 const ElfW(Sym) *ref = NULL;
c0282c06 89 lookup_t result;
2b7238dd 90 ElfW(Addr) caller = (ElfW(Addr)) who;
94e365c6 91
4a2ab584
FW
92 /* Link map of the caller if needed. */
93 struct link_map *match = NULL;
2b7238dd 94
94e365c6 95 if (handle == RTLD_DEFAULT)
1100f849 96 {
c76147af 97 match = _dl_sym_find_caller_link_map (caller);
4a2ab584 98
1100f849
UD
99 /* Search the global scope. We have the simple case where
100 we look up in the scope of an object which was part of
101 the initial binary. And then the more complex part
102 where the object is dynamically loaded and the scope
103 array can change. */
e4eb675d 104 if (RTLD_SINGLE_THREAD_P)
1100f849 105 result = GLRO(dl_lookup_symbol_x) (name, match, &ref,
c0a777e8 106 match->l_scope, vers, 0,
1100f849
UD
107 flags | DL_LOOKUP_ADD_DEPENDENCY,
108 NULL);
109 else
110 {
1100f849
UD
111 struct call_dl_lookup_args args;
112 args.name = name;
113 args.map = match;
1100f849 114 args.vers = vers;
b90395e6
UD
115 args.flags
116 = flags | DL_LOOKUP_ADD_DEPENDENCY | DL_LOOKUP_GSCOPE_LOCK;
1100f849
UD
117 args.refp = &ref;
118
e4eb675d 119 THREAD_GSCOPE_SET_FLAG ();
2449ae7b
FW
120 struct dl_exception exception;
121 int err = _dl_catch_exception (&exception, call_dl_lookup, &args);
e4eb675d 122 THREAD_GSCOPE_RESET_FLAG ();
2449ae7b
FW
123 if (__glibc_unlikely (exception.errstring != NULL))
124 _dl_signal_exception (err, &exception, NULL);
1100f849
UD
125
126 result = args.map;
127 }
128 }
94e365c6
UD
129 else if (handle == RTLD_NEXT)
130 {
c76147af 131 match = _dl_sym_find_caller_link_map (caller);
4a2ab584 132
a1ffb40e 133 if (__glibc_unlikely (match == GL(dl_ns)[LM_ID_BASE]._ns_loaded))
2373b30e 134 {
173a06ec
UD
135 if (match == NULL
136 || caller < match->l_map_start
137 || caller >= match->l_map_end)
9e78f6f6 138 _dl_signal_error (0, NULL, NULL, N_("\
94e365c6 139RTLD_NEXT used in code not dynamically loaded"));
2373b30e 140 }
94e365c6 141
53761a8b 142 struct link_map *l = match;
f92338be 143 while (l->l_loader != NULL)
94e365c6
UD
144 l = l->l_loader;
145
74c5693b 146 result = GLRO(dl_lookup_symbol_x) (name, match, &ref, l->l_local_scope,
53761a8b 147 vers, 0, 0, match);
94e365c6
UD
148 }
149 else
150 {
151 /* Search the scope of the given object. */
152 struct link_map *map = handle;
021723ab 153 result = GLRO(dl_lookup_symbol_x) (name, map, &ref, map->l_local_scope,
53761a8b 154 vers, 0, flags, NULL);
94e365c6
UD
155 }
156
f92338be 157 if (ref != NULL)
aed283dd 158 {
9dcafc55
UD
159 void *value;
160
11bf311e 161#ifdef SHARED
aed283dd
UD
162 if (ELFW(ST_TYPE) (ref->st_info) == STT_TLS)
163 /* The found symbol is a thread-local storage variable.
164 Return the address for to the current thread. */
9dcafc55
UD
165 value = _dl_tls_symaddr (result, ref);
166 else
167#endif
168 value = DL_SYMBOL_ADDRESS (result, ref);
169
c76147af 170 return _dl_sym_post (result, ref, value, caller, match);
aed283dd 171 }
5e76a346 172
94e365c6
UD
173 return NULL;
174}
53761a8b
UD
175
176
53761a8b 177void *
53761a8b
UD
178_dl_vsym (void *handle, const char *name, const char *version, void *who)
179{
180 struct r_found_version vers;
181
182 /* Compute hash value to the version string. */
183 vers.name = version;
184 vers.hidden = 1;
185 vers.hash = _dl_elf_hash (version);
186 /* We don't have a specific file where the symbol can be found. */
187 vers.filename = NULL;
188
f0323886 189 return do_sym (handle, name, who, &vers, 0);
53761a8b
UD
190}
191
192
193void *
53761a8b
UD
194_dl_sym (void *handle, const char *name, void *who)
195{
f0323886 196 return do_sym (handle, name, who, NULL, DL_LOOKUP_RETURN_NEWEST);
53761a8b 197}