1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20: #include <assert.h>
21: #include <stddef.h>
22: #include <setjmp.h>
23: #include <libintl.h>
24:
25: #include <dlfcn.h>
26: #include <ldsodefs.h>
27: #include <dl-hash.h>
28: #include <sysdep-cancel.h>
29: #include <dl-tls.h>
30:
31:
32: #ifdef SHARED
33:
34:
35:
36: # ifndef __TLS_GET_ADDR
37: # define __TLS_GET_ADDR __tls_get_addr
38: # endif
39:
40:
41:
42: static void *
43: internal_function
44: _dl_tls_symaddr (struct link_map *map, const ElfW(Sym) *ref)
45: {
46: # ifndef DONT_USE_TLS_INDEX
47: tls_index tmp =
48: {
49: .ti_module = map->l_tls_modid,
50: .ti_offset = ref->st_value
51: };
52:
53: return __TLS_GET_ADDR (&tmp);
54: # else
55: return __TLS_GET_ADDR (map->l_tls_modid, ref->st_value);
56: # endif
57: }
58: #endif
59:
60:
61: struct call_dl_lookup_args
62: {
63:
64: struct link_map *map;
65: const char *name;
66: struct r_found_version *vers;
67: int flags;
68:
69:
70: lookup_t loadbase;
71: const ElfW(Sym) **refp;
72: };
73:
74: static void
75: call_dl_lookup (void *ptr)
76: {
77: struct call_dl_lookup_args *args = (struct call_dl_lookup_args *) ptr;
78: args->map = GLRO(dl_lookup_symbol_x) (args->name, args->map, args->refp,
79: args->map->l_scope, args->vers, 0,
80: args->flags, NULL);
81: }
82:
83:
84: static void *
85: internal_function
86: do_sym (void *handle, const char *name, void *who,
87: struct r_found_version *vers, int flags)
88: {
89: const ElfW(Sym) *ref = NULL;
90: lookup_t result;
91: ElfW(Addr) caller = (ElfW(Addr)) who;
92:
93:
94:
95: struct link_map *match = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
96:
97:
98: for (Lmid_t ns = 0; ns < DL_NNS; ++ns)
99: for (struct link_map *l = GL(dl_ns)[ns]._ns_loaded; l != NULL;
100: l = l->l_next)
101: if (caller >= l->l_map_start && caller < l->l_map_end
102: && (l->l_contiguous || _dl_addr_inside_object (l, caller)))
103: {
104: match = l;
105: break;
106: }
107:
108: if (handle == RTLD_DEFAULT)
109: {
110:
111:
112:
113:
114:
115: if (RTLD_SINGLE_THREAD_P)
116: result = GLRO(dl_lookup_symbol_x) (name, match, &ref,
117: match->l_scope, vers, 0,
118: flags | DL_LOOKUP_ADD_DEPENDENCY,
119: NULL);
120: else
121: {
122: struct call_dl_lookup_args args;
123: args.name = name;
124: args.map = match;
125: args.vers = vers;
126: args.flags
127: = flags | DL_LOOKUP_ADD_DEPENDENCY | DL_LOOKUP_GSCOPE_LOCK;
128: args.refp = &ref;
129:
130: THREAD_GSCOPE_SET_FLAG ();
131:
132: const char *objname;
133: const char *errstring = NULL;
134: bool malloced;
135: int err = GLRO(dl_catch_error) (&objname, &errstring, &malloced,
136: call_dl_lookup, &args);
137:
138: THREAD_GSCOPE_RESET_FLAG ();
139:
140: if (__builtin_expect (errstring != NULL, 0))
141: {
142:
143: char *errstring_dup = strdupa (errstring);
144: char *objname_dup = strdupa (objname);
145: if (malloced)
146: free ((char *) errstring);
147:
148: GLRO(dl_signal_error) (err, objname_dup, NULL, errstring_dup);
149:
150: }
151:
152: result = args.map;
153: }
154: }
155: else if (handle == RTLD_NEXT)
156: {
157: if (__builtin_expect (match == GL(dl_ns)[LM_ID_BASE]._ns_loaded, 0))
158: {
159: if (match == NULL
160: || caller < match->l_map_start
161: || caller >= match->l_map_end)
162: GLRO(dl_signal_error) (0, NULL, NULL, N_("\
163: RTLD_NEXT used in code not dynamically loaded"));
164: }
165:
166: struct link_map *l = match;
167: while (l->l_loader != NULL)
168: l = l->l_loader;
169:
170: result = GLRO(dl_lookup_symbol_x) (name, match, &ref, l->l_local_scope,
171: vers, 0, 0, match);
172: }
173: else
174: {
175:
176: struct link_map *map = handle;
177: result = GLRO(dl_lookup_symbol_x) (name, map, &ref, map->l_local_scope,
178: vers, 0, flags, NULL);
179: }
180:
181: if (ref != NULL)
182: {
183: void *value;
184:
185: #ifdef SHARED
186: if (ELFW(ST_TYPE) (ref->st_info) == STT_TLS)
187:
188:
189: value = _dl_tls_symaddr (result, ref);
190: else
191: #endif
192: value = DL_SYMBOL_ADDRESS (result, ref);
193:
194: #ifdef SHARED
195:
196:
197:
198: if (__builtin_expect (GLRO(dl_naudit) > 0, 0))
199: {
200: const char *strtab = (const char *) D_PTR (result,
201: l_info[DT_STRTAB]);
202:
203:
204: unsigned int ndx = (ref - (ElfW(Sym) *) D_PTR (result,
205: l_info[DT_SYMTAB]));
206:
207: if ((match->l_audit_any_plt | result->l_audit_any_plt) != 0)
208: {
209: unsigned int altvalue = 0;
210: struct audit_ifaces *afct = GLRO(dl_audit);
211:
212:
213: ElfW(Sym) sym = *ref;
214: sym.st_value = (ElfW(Addr)) value;
215:
216: for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
217: {
218: if (afct->symbind != NULL
219: && ((match->l_audit[cnt].bindflags & LA_FLG_BINDFROM)
220: != 0
221: || ((result->l_audit[cnt].bindflags & LA_FLG_BINDTO)
222: != 0)))
223: {
224: unsigned int flags = altvalue | LA_SYMB_DLSYM;
225: uintptr_t new_value
226: = afct->symbind (&sym, ndx,
227: &match->l_audit[cnt].cookie,
228: &result->l_audit[cnt].cookie,
229: &flags, strtab + ref->st_name);
230: if (new_value != (uintptr_t) sym.st_value)
231: {
232: altvalue = LA_SYMB_ALTVALUE;
233: sym.st_value = new_value;
234: }
235: }
236:
237: afct = afct->next;
238: }
239:
240: value = (void *) sym.st_value;
241: }
242: }
243: #endif
244:
245: return value;
246: }
247:
248: return NULL;
249: }
250:
251:
252: void *
253: internal_function
254: _dl_vsym (void *handle, const char *name, const char *version, void *who)
255: {
256: struct r_found_version vers;
257:
258:
259: vers.name = version;
260: vers.hidden = 1;
261: vers.hash = _dl_elf_hash (version);
262:
263: vers.filename = NULL;
264:
265: return do_sym (handle, name, who, &vers, 0);
266: }
267:
268:
269: void *
270: internal_function
271: _dl_sym (void *handle, const char *name, void *who)
272: {
273: return do_sym (handle, name, who, NULL, DL_LOOKUP_RETURN_NEWEST);
274: }