]> git.ipfire.org Git - thirdparty/glibc.git/blame - elf/dl-runtime.c
nptl/tst-cancel25 needs to be an internal test
[thirdparty/glibc.git] / elf / dl-runtime.c
CommitLineData
38334018 1/* On-demand PLT fixup for shared objects.
04277e02 2 Copyright (C) 1995-2019 Free Software Foundation, Inc.
afd4eb37 3 This file is part of the GNU C Library.
d66e34cd 4
afd4eb37 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.
d66e34cd 9
afd4eb37
UD
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.
d66e34cd 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
868b78c8
RM
19#define IN_DL_RUNTIME 1 /* This can be tested in dl-machine.h. */
20
53308042 21#include <alloca.h>
101edd3f 22#include <stdlib.h>
3db52d94 23#include <unistd.h>
9fbdeb41 24#include <sys/param.h>
a42195db 25#include <ldsodefs.h>
609cf614 26#include <sysdep-cancel.h>
f51d1dfd 27#include "dynamic-link.h"
df94b641 28#include <tls.h>
42675c6f 29#include <dl-irel.h>
df94b641 30
f51d1dfd 31
4cf5b6d0 32#if (!ELF_MACHINE_NO_RELA && !defined ELF_MACHINE_PLT_REL) \
32e6df36 33 || ELF_MACHINE_NO_REL
a2b08ee5 34# define PLTREL ElfW(Rela)
38334018 35#else
a2b08ee5 36# define PLTREL ElfW(Rel)
38334018 37#endif
38334018 38
1e5f1d86
UD
39/* The fixup functions might have need special attributes. If none
40 are provided define the macro as empty. */
41#ifndef ARCH_FIXUP_ATTRIBUTE
42# define ARCH_FIXUP_ATTRIBUTE
43#endif
44
a42ad61b
UD
45#ifndef reloc_offset
46# define reloc_offset reloc_arg
47# define reloc_index reloc_arg / sizeof (PLTREL)
48#endif
49
50
38334018
RM
51
52/* This function is called through a special trampoline from the PLT the
53 first time each PLT entry is called. We must perform the relocation
54 specified in the PLT of the given shared object, and return the resolved
55 function address to the trampoline, which will restart the original call
56 to that address. Future calls will bounce directly from the PLT to the
57 function. */
58
028dca77 59DL_FIXUP_VALUE_TYPE
58c9ff1b 60attribute_hidden __attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE
9dcafc55 61_dl_fixup (
cb0509a8 62# ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
9dcafc55 63 ELF_MACHINE_RUNTIME_FIXUP_ARGS,
cb0509a8 64# endif
70d9946a 65 struct link_map *l, ElfW(Word) reloc_arg)
d66e34cd 66{
266180eb 67 const ElfW(Sym) *const symtab
a42195db
UD
68 = (const void *) D_PTR (l, l_info[DT_SYMTAB]);
69 const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
d66e34cd 70
38334018 71 const PLTREL *const reloc
a42195db 72 = (const void *) (D_PTR (l, l_info[DT_JMPREL]) + reloc_offset);
a2b08ee5 73 const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
0572433b 74 const ElfW(Sym) *refsym = sym;
a2b08ee5 75 void *const rel_addr = (void *)(l->l_addr + reloc->r_offset);
c0282c06 76 lookup_t result;
028dca77 77 DL_FIXUP_VALUE_TYPE value;
d66e34cd 78
a2b08ee5
UD
79 /* Sanity check that we're really looking at a PLT relocation. */
80 assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);
f51d1dfd 81
736d0841
UD
82 /* Look up the target symbol. If the normal lookup rules are not
83 used don't look in the global scope. */
84 if (__builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0)
a2b08ee5 85 {
021723ab 86 const struct r_found_version *version = NULL;
021723ab
UD
87
88 if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
06535ae9 89 {
021723ab
UD
90 const ElfW(Half) *vernum =
91 (const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]);
92 ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)] & 0x7fff;
93 version = &l->l_versions[ndx];
94 if (version->hash == 0)
95 version = NULL;
06535ae9 96 }
a2b08ee5 97
4e35ef2c
UD
98 /* We need to keep the scope around so do some locking. This is
99 not necessary for objects which cannot be unloaded or when
100 we are not using any threads (yet). */
101 int flags = DL_LOOKUP_ADD_DEPENDENCY;
df94b641 102 if (!RTLD_SINGLE_THREAD_P)
b90395e6
UD
103 {
104 THREAD_GSCOPE_SET_FLAG ();
105 flags |= DL_LOOKUP_GSCOPE_LOCK;
106 }
1100f849 107
b48a267b
UD
108#ifdef RTLD_ENABLE_FOREIGN_CALL
109 RTLD_ENABLE_FOREIGN_CALL;
110#endif
111
4e35ef2c
UD
112 result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym, l->l_scope,
113 version, ELF_RTYPE_CLASS_PLT, flags, NULL);
021723ab 114
df94b641
UD
115 /* We are done with the global scope. */
116 if (!RTLD_SINGLE_THREAD_P)
117 THREAD_GSCOPE_RESET_FLAG ();
118
b48a267b
UD
119#ifdef RTLD_FINALIZE_FOREIGN_CALL
120 RTLD_FINALIZE_FOREIGN_CALL;
121#endif
122
c0282c06
UD
123 /* Currently result contains the base load address (or link map)
124 of the object that defines sym. Now add in the symbol
125 offset. */
028dca77 126 value = DL_FIXUP_MAKE_VALUE (result,
10a446dd 127 SYMBOL_ADDRESS (result, sym, false));
06535ae9
UD
128 }
129 else
c0282c06 130 {
6ed623f8
UD
131 /* We already found the symbol. The module (and therefore its load
132 address) is also known. */
10a446dd 133 value = DL_FIXUP_MAKE_VALUE (l, SYMBOL_ADDRESS (l, sym, true));
c0282c06 134 result = l;
c0282c06 135 }
a2b08ee5 136
dfd2257a
UD
137 /* And now perhaps the relocation addend. */
138 value = elf_machine_plt_value (l, reloc, value);
650425ce 139
9acbe24d
AS
140 if (sym != NULL
141 && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0))
42675c6f 142 value = elf_ifunc_invoke (DL_FIXUP_VALUE_ADDR (value));
425ce2ed 143
a2b08ee5 144 /* Finally, fix up the plt itself. */
a1ffb40e 145 if (__glibc_unlikely (GLRO(dl_bind_not)))
f53c03c2
UD
146 return value;
147
0572433b 148 return elf_machine_fixup_plt (l, result, refsym, sym, reloc, rel_addr, value);
38334018 149}
d66e34cd 150
2bdd4ca6 151#ifndef PROF
028dca77 152DL_FIXUP_VALUE_TYPE
9dcafc55
UD
153__attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE
154_dl_profile_fixup (
3996f34b 155#ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
9dcafc55 156 ELF_MACHINE_RUNTIME_FIXUP_ARGS,
3996f34b 157#endif
a42ad61b 158 struct link_map *l, ElfW(Word) reloc_arg,
91bf35de 159 ElfW(Addr) retaddr, void *regs, long int *framesizep)
3996f34b 160{
ab97ee8f 161 void (*mcount_fct) (ElfW(Addr), ElfW(Addr)) = _dl_mcount;
3996f34b 162
2e64d265
L
163 if (l->l_reloc_result == NULL)
164 {
165 /* BZ #14843: ELF_DYNAMIC_RELOCATE is called before l_reloc_result
166 is allocated. We will get here if ELF_DYNAMIC_RELOCATE calls a
167 resolver function to resolve an IRELATIVE relocation and that
168 resolver calls a function that is not yet resolved (lazy). For
169 example, the resolver in x86-64 libm.so calls __get_cpu_features
170 defined in libc.so. Skip audit and resolve the external function
171 in this case. */
172 *framesizep = -1;
173 return _dl_fixup (
174# ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
175# ifndef ELF_MACHINE_RUNTIME_FIXUP_PARAMS
176# error Please define ELF_MACHINE_RUNTIME_FIXUP_PARAMS.
177# endif
178 ELF_MACHINE_RUNTIME_FIXUP_PARAMS,
179# endif
180 l, reloc_arg);
181 }
182
ea7eb7e3
UD
183 /* This is the address in the array where we store the result of previous
184 relocations. */
a42ad61b 185 struct reloc_result *reloc_result = &l->l_reloc_result[reloc_index];
3996f34b 186
e5d262ef
TMQMF
187 /* CONCURRENCY NOTES:
188
189 Multiple threads may be calling the same PLT sequence and with
190 LD_AUDIT enabled they will be calling into _dl_profile_fixup to
191 update the reloc_result with the result of the lazy resolution.
192 The reloc_result guard variable is reloc_init, and we use
193 acquire/release loads and store to it to ensure that the results of
194 the structure are consistent with the loaded value of the guard.
195 This does not fix all of the data races that occur when two or more
196 threads read reloc_result->reloc_init with a value of zero and read
197 and write to that reloc_result concurrently. The expectation is
198 generally that while this is a data race it works because the
199 threads write the same values. Until the data races are fixed
200 there is a potential for problems to arise from these data races.
201 The reloc result updates should happen in parallel but there should
202 be an atomic RMW which does the final update to the real result
203 entry (see bug 23790).
204
205 The following code uses reloc_result->init set to 0 to indicate if it is
206 the first time this object is being relocated, otherwise 1 which
207 indicates the object has already been relocated.
208
209 Reading/Writing from/to reloc_result->reloc_init must not happen
210 before previous writes to reloc_result complete as they could
211 end-up with an incomplete struct. */
212 DL_FIXUP_VALUE_TYPE value;
213 unsigned int init = atomic_load_acquire (&reloc_result->init);
214
215 if (init == 0)
a2b08ee5 216 {
ea7eb7e3
UD
217 /* This is the first time we have to relocate this object. */
218 const ElfW(Sym) *const symtab
a42195db 219 = (const void *) D_PTR (l, l_info[DT_SYMTAB]);
9dcafc55 220 const char *strtab = (const char *) D_PTR (l, l_info[DT_STRTAB]);
ea7eb7e3
UD
221
222 const PLTREL *const reloc
a42195db 223 = (const void *) (D_PTR (l, l_info[DT_JMPREL]) + reloc_offset);
9dcafc55
UD
224 const ElfW(Sym) *refsym = &symtab[ELFW(R_SYM) (reloc->r_info)];
225 const ElfW(Sym) *defsym = refsym;
226 lookup_t result;
ea7eb7e3 227
ea7eb7e3
UD
228 /* Sanity check that we're really looking at a PLT relocation. */
229 assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);
230
6aa29abe 231 /* Look up the target symbol. If the symbol is marked STV_PROTECTED
06535ae9 232 don't look in the global scope. */
9dcafc55 233 if (__builtin_expect (ELFW(ST_VISIBILITY) (refsym->st_other), 0) == 0)
ea7eb7e3 234 {
021723ab 235 const struct r_found_version *version = NULL;
021723ab
UD
236
237 if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
06535ae9 238 {
021723ab
UD
239 const ElfW(Half) *vernum =
240 (const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]);
241 ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)] & 0x7fff;
242 version = &l->l_versions[ndx];
243 if (version->hash == 0)
244 version = NULL;
06535ae9
UD
245 }
246
4e35ef2c
UD
247 /* We need to keep the scope around so do some locking. This is
248 not necessary for objects which cannot be unloaded or when
249 we are not using any threads (yet). */
250 int flags = DL_LOOKUP_ADD_DEPENDENCY;
df94b641 251 if (!RTLD_SINGLE_THREAD_P)
b90395e6
UD
252 {
253 THREAD_GSCOPE_SET_FLAG ();
254 flags |= DL_LOOKUP_GSCOPE_LOCK;
255 }
1100f849 256
4e35ef2c
UD
257 result = _dl_lookup_symbol_x (strtab + refsym->st_name, l,
258 &defsym, l->l_scope, version,
259 ELF_RTYPE_CLASS_PLT, flags, NULL);
021723ab 260
df94b641
UD
261 /* We are done with the global scope. */
262 if (!RTLD_SINGLE_THREAD_P)
263 THREAD_GSCOPE_RESET_FLAG ();
264
c0282c06
UD
265 /* Currently result contains the base load address (or link map)
266 of the object that defines sym. Now add in the symbol
267 offset. */
028dca77 268 value = DL_FIXUP_MAKE_VALUE (result,
10a446dd 269 SYMBOL_ADDRESS (result, defsym, false));
425ce2ed 270
b32b8b45
UD
271 if (defsym != NULL
272 && __builtin_expect (ELFW(ST_TYPE) (defsym->st_info)
273 == STT_GNU_IFUNC, 0))
42675c6f 274 value = elf_ifunc_invoke (DL_FIXUP_VALUE_ADDR (value));
ea7eb7e3 275 }
06535ae9 276 else
c0282c06 277 {
6ed623f8
UD
278 /* We already found the symbol. The module (and therefore its load
279 address) is also known. */
10a446dd 280 value = DL_FIXUP_MAKE_VALUE (l, SYMBOL_ADDRESS (l, refsym, true));
425ce2ed
UD
281
282 if (__builtin_expect (ELFW(ST_TYPE) (refsym->st_info)
283 == STT_GNU_IFUNC, 0))
42675c6f 284 value = elf_ifunc_invoke (DL_FIXUP_VALUE_ADDR (value));
425ce2ed 285
6ed623f8 286 result = l;
c0282c06 287 }
ea7eb7e3
UD
288 /* And now perhaps the relocation addend. */
289 value = elf_machine_plt_value (l, reloc, value);
290
9dcafc55
UD
291#ifdef SHARED
292 /* Auditing checkpoint: we have a new binding. Provide the
293 auditing libraries the possibility to change the value and
294 tell us whether further auditing is wanted. */
295 if (defsym != NULL && GLRO(dl_naudit) > 0)
296 {
297 reloc_result->bound = result;
298 /* Compute index of the symbol entry in the symbol table of
299 the DSO with the definition. */
300 reloc_result->boundndx = (defsym
301 - (ElfW(Sym) *) D_PTR (result,
302 l_info[DT_SYMTAB]));
303
304 /* Determine whether any of the two participating DSOs is
305 interested in auditing. */
306 if ((l->l_audit_any_plt | result->l_audit_any_plt) != 0)
307 {
de7ce8f1 308 unsigned int flags = 0;
9dcafc55
UD
309 struct audit_ifaces *afct = GLRO(dl_audit);
310 /* Synthesize a symbol record where the st_value field is
311 the result. */
312 ElfW(Sym) sym = *defsym;
028dca77 313 sym.st_value = DL_FIXUP_VALUE_ADDR (value);
9dcafc55
UD
314
315 /* Keep track whether there is any interest in tracing
316 the call in the lower two bits. */
317 assert (DL_NNS * 2 <= sizeof (reloc_result->flags) * 8);
318 assert ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) == 3);
319 reloc_result->enterexit = LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT;
320
321 const char *strtab2 = (const void *) D_PTR (result,
322 l_info[DT_STRTAB]);
323
324 for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
325 {
326 /* XXX Check whether both DSOs must request action or
327 only one */
328 if ((l->l_audit[cnt].bindflags & LA_FLG_BINDFROM) != 0
329 && (result->l_audit[cnt].bindflags & LA_FLG_BINDTO) != 0)
330 {
9dcafc55
UD
331 if (afct->symbind != NULL)
332 {
333 uintptr_t new_value
334 = afct->symbind (&sym, reloc_result->boundndx,
335 &l->l_audit[cnt].cookie,
336 &result->l_audit[cnt].cookie,
337 &flags,
338 strtab2 + defsym->st_name);
339 if (new_value != (uintptr_t) sym.st_value)
340 {
de7ce8f1 341 flags |= LA_SYMB_ALTVALUE;
9dcafc55
UD
342 sym.st_value = new_value;
343 }
344 }
345
346 /* Remember the results for every audit library and
347 store a summary in the first two bits. */
348 reloc_result->enterexit
349 &= flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT);
350 reloc_result->enterexit
351 |= ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT))
352 << ((cnt + 1) * 2));
353 }
354 else
355 /* If the bind flags say this auditor is not interested,
356 set the bits manually. */
357 reloc_result->enterexit
358 |= ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)
359 << ((cnt + 1) * 2));
360
361 afct = afct->next;
362 }
363
de7ce8f1 364 reloc_result->flags = flags;
028dca77 365 value = DL_FIXUP_ADDR_VALUE (sym.st_value);
9dcafc55
UD
366 }
367 else
368 /* Set all bits since this symbol binding is not interesting. */
369 reloc_result->enterexit = (1u << DL_NNS) - 1;
370 }
371#endif
372
ea7eb7e3 373 /* Store the result for later runs. */
a1ffb40e 374 if (__glibc_likely (! GLRO(dl_bind_not)))
e5d262ef
TMQMF
375 {
376 reloc_result->addr = value;
377 /* Guarantee all previous writes complete before
378 init is updated. See CONCURRENCY NOTES earlier */
379 atomic_store_release (&reloc_result->init, 1);
380 }
381 init = 1;
ea7eb7e3 382 }
e5d262ef
TMQMF
383 else
384 value = reloc_result->addr;
3996f34b 385
9dcafc55
UD
386 /* By default we do not call the pltexit function. */
387 long int framesize = -1;
388
e5d262ef 389
9dcafc55
UD
390#ifdef SHARED
391 /* Auditing checkpoint: report the PLT entering and allow the
392 auditors to change the value. */
e5d262ef 393 if (GLRO(dl_naudit) > 0
9dcafc55
UD
394 /* Don't do anything if no auditor wants to intercept this call. */
395 && (reloc_result->enterexit & LA_SYMB_NOPLTENTER) == 0)
396 {
e5d262ef
TMQMF
397 /* Sanity check: DL_FIXUP_VALUE_CODE_ADDR (value) should have been
398 initialized earlier in this function or in another thread. */
399 assert (DL_FIXUP_VALUE_CODE_ADDR (value) != 0);
9dcafc55
UD
400 ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,
401 l_info[DT_SYMTAB])
402 + reloc_result->boundndx);
403
404 /* Set up the sym parameter. */
405 ElfW(Sym) sym = *defsym;
028dca77 406 sym.st_value = DL_FIXUP_VALUE_ADDR (value);
9dcafc55
UD
407
408 /* Get the symbol name. */
409 const char *strtab = (const void *) D_PTR (reloc_result->bound,
410 l_info[DT_STRTAB]);
411 const char *symname = strtab + sym.st_name;
412
413 /* Keep track of overwritten addresses. */
de7ce8f1 414 unsigned int flags = reloc_result->flags;
9dcafc55
UD
415
416 struct audit_ifaces *afct = GLRO(dl_audit);
417 for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
418 {
9acbe24d 419 if (afct->ARCH_LA_PLTENTER != NULL
9dcafc55
UD
420 && (reloc_result->enterexit
421 & (LA_SYMB_NOPLTENTER << (2 * (cnt + 1)))) == 0)
422 {
9dcafc55
UD
423 long int new_framesize = -1;
424 uintptr_t new_value
425 = afct->ARCH_LA_PLTENTER (&sym, reloc_result->boundndx,
426 &l->l_audit[cnt].cookie,
427 &reloc_result->bound->l_audit[cnt].cookie,
428 regs, &flags, symname,
429 &new_framesize);
430 if (new_value != (uintptr_t) sym.st_value)
431 {
de7ce8f1 432 flags |= LA_SYMB_ALTVALUE;
9dcafc55
UD
433 sym.st_value = new_value;
434 }
435
436 /* Remember the results for every audit library and
437 store a summary in the first two bits. */
438 reloc_result->enterexit
439 |= ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT))
440 << (2 * (cnt + 1)));
441
442 if ((reloc_result->enterexit & (LA_SYMB_NOPLTEXIT
443 << (2 * (cnt + 1))))
444 == 0 && new_framesize != -1 && framesize != -2)
445 {
446 /* If this is the first call providing information,
447 use it. */
448 if (framesize == -1)
449 framesize = new_framesize;
450 /* If two pltenter calls provide conflicting information,
451 use the larger value. */
452 else if (new_framesize != framesize)
453 framesize = MAX (new_framesize, framesize);
454 }
455 }
456
457 afct = afct->next;
458 }
459
028dca77 460 value = DL_FIXUP_ADDR_VALUE (sym.st_value);
9dcafc55
UD
461 }
462#endif
463
464 /* Store the frame size information. */
465 *framesizep = framesize;
466
028dca77 467 (*mcount_fct) (retaddr, DL_FIXUP_VALUE_CODE_ADDR (value));
3996f34b 468
a2b08ee5 469 return value;
3996f34b 470}
a2b08ee5 471
150dc1a0 472#endif /* PROF */
3996f34b
UD
473
474
9dcafc55
UD
475#include <stdio.h>
476void
477ARCH_FIXUP_ATTRIBUTE
a42ad61b 478_dl_call_pltexit (struct link_map *l, ElfW(Word) reloc_arg,
9dcafc55
UD
479 const void *inregs, void *outregs)
480{
481#ifdef SHARED
482 /* This is the address in the array where we store the result of previous
483 relocations. */
484 // XXX Maybe the bound information must be stored on the stack since
485 // XXX with bind_not a new value could have been stored in the meantime.
a42ad61b 486 struct reloc_result *reloc_result = &l->l_reloc_result[reloc_index];
9dcafc55
UD
487 ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,
488 l_info[DT_SYMTAB])
489 + reloc_result->boundndx);
490
491 /* Set up the sym parameter. */
492 ElfW(Sym) sym = *defsym;
8517b15e 493 sym.st_value = DL_FIXUP_VALUE_ADDR (reloc_result->addr);
9dcafc55
UD
494
495 /* Get the symbol name. */
496 const char *strtab = (const void *) D_PTR (reloc_result->bound,
497 l_info[DT_STRTAB]);
498 const char *symname = strtab + sym.st_name;
499
500 struct audit_ifaces *afct = GLRO(dl_audit);
501 for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
502 {
503 if (afct->ARCH_LA_PLTEXIT != NULL
504 && (reloc_result->enterexit
505 & (LA_SYMB_NOPLTEXIT >> (2 * cnt))) == 0)
506 {
507 afct->ARCH_LA_PLTEXIT (&sym, reloc_result->boundndx,
508 &l->l_audit[cnt].cookie,
509 &reloc_result->bound->l_audit[cnt].cookie,
510 inregs, outregs, symname);
511 }
d66e34cd 512
9dcafc55
UD
513 afct = afct->next;
514 }
515#endif
516}