summaryrefslogtreecommitdiff
path: root/elf/dl-runtime.c
diff options
context:
space:
mode:
Diffstat (limited to 'elf/dl-runtime.c')
-rw-r--r--elf/dl-runtime.c35
1 files changed, 27 insertions, 8 deletions
diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c
index 088ff64c6e..08c605cd0f 100644
--- a/elf/dl-runtime.c
+++ b/elf/dl-runtime.c
@@ -1,5 +1,5 @@
/* On-demand PLT fixup for shared objects.
- Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -74,15 +74,19 @@ _dl_object_relocation_scope (struct link_map *l)
#define elf_machine_rel 1
#define elf_machine_rela 2
#if elf_machine_relplt == elf_machine_rel
-#define PLTREL ElfW(Rel)
+# define PLTREL ElfW(Rel)
#elif elf_machine_relplt == elf_machine_rela
-#define PLTREL ElfW(Rela)
+# define PLTREL ElfW(Rela)
#else
-#error "dl-machine.h bug: elf_machine_relplt not rel or rela"
+# error "dl-machine.h bug: elf_machine_relplt not rel or rela"
#endif
#undef elf_machine_rel
#undef elf_machine_rela
+#ifndef VERSYMIDX
+# define VERSYMIDX(sym) (DT_NUM + DT_PROCNUM + DT_VERSIONTAGIDX (sym))
+#endif
+
/* We need to define the function as a local symbol so that the reference
in the trampoline code will be a local PC-relative call. Tell the
compiler not to worry that the function appears not to be called. */
@@ -122,13 +126,28 @@ fixup (
{
/* This macro is used as a callback from the elf_machine_relplt code. */
-#define RESOLVE(ref, flags) \
- (_dl_lookup_symbol (strtab + (*ref)->st_name, ref, scope, \
- l->l_name, flags))
+#define RESOLVE(ref, version, flags) \
+ ((version) != NULL && (version)->hash != 0 \
+ ? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name, (ref), scope, \
+ l->l_name, (version), (flags)) \
+ : _dl_lookup_symbol (strtab + (*ref)->st_name, (ref), scope, \
+ l->l_name, (flags)))
#include "dynamic-link.h"
/* Perform the specified relocation. */
- elf_machine_relplt (l, reloc, &symtab[ELFW(R_SYM) (reloc->r_info)]);
+ if (l->l_info[VERSYMIDX (DT_VERNEEDNUM)])
+ {
+ const ElfW(Half) * version =
+ (const ElfW(Half) *) (l->l_addr +
+ l->l_info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr);
+ ElfW(Half) ndx = version[ELFW(R_SYM) (reloc->r_info)];
+
+ elf_machine_relplt (l, reloc, &symtab[ELFW(R_SYM) (reloc->r_info)],
+ &l->l_versions[ndx]);
+ }
+ else
+ elf_machine_relplt (l, reloc, &symtab[ELFW(R_SYM) (reloc->r_info)],
+ NULL);
}
*_dl_global_scope_end = NULL;