diff options
author | Ulrich Drepper <drepper@redhat.com> | 2001-12-12 00:21:26 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2001-12-12 00:21:26 +0000 |
commit | 32e6df3621edc5067dfd6e87a387e1751f67f708 (patch) | |
tree | 957300a92ed16417fb46ce240d19f965fe773181 /elf/dl-lookup.c | |
parent | 4be601a15e63d03adf55c48c19dda2d2e7377d8a (diff) | |
download | glibc-32e6df3621edc5067dfd6e87a387e1751f67f708.zip glibc-32e6df3621edc5067dfd6e87a387e1751f67f708.tar.gz glibc-32e6df3621edc5067dfd6e87a387e1751f67f708.tar.bz2 |
Update.
2001-12-11 Jakub Jelinek <jakub@redhat.com>
* elf/Makefile (dl-routines): Add conflict.
(rtld-ldscript-in, rtld-ldscript, rtld-parms): Remove.
(ld.so): Add _begin local symbol.
* elf/elf.h (DT_VALTAGIDX, DT_VALNUM, DT_ADDRTAGIDX, DT_ADDRNUM):
Define.
* elf/dl-deps.c (_dl_build_local_scope): New.
(_dl_map_object_deps): If LD_TRACE_PRELINKING, compute local scopes
of all libraries.
* elf/do-rel.h (VALIDX): Define.
(elf_dynamic_do_rel): If ELF_MACHINE_PLT_REL is defined, don't do
lazy binding for RELA. If DT_GNU_PRELINKED, DT_RELACOUNT relocations
can be skipped.
* elf/dl-conflict.c: New file.
* elf/dl-lookup.c (_dl_debug_bindings): New.
(_dl_lookup_symbol): Use _dl_debug_bindings. Reference_name is always
non-NULL.
(_dl_lookup_symbol_skip): Likewise.
(_dl_lookup_versioned_symbol): Likewise.
(_dl_lookup_versioned_symbol_skip): Likewise.
* elf/dl-runtime.c (PLTREL): If ELF_MACHINE_PLT_REL is defined,
define to ElfW(Rel).
* elf/dynamic-link.h (elf_get_dynamic_info): Record selected dynamic
tags in the DT_VALRNGLO..DT_VALRNGHI and DT_ADDRRNGLO..DT_ADDRRNGHI
ranges.
Don't adjust address dynamic tags if l_addr is 0.
* elf/rtld.c (_dl_trace_prelink, _dl_trace_prelink_map): New variables.
(_dl_start): Skip ELF_DYNAMIC_RELOCATE if ld.so is prelinked.
(VALIDX, ADDRIDX): Define.
(_dl_start_final): Initialize _dl_rtld_map's l_map_start and l_map_end.
(dl_main): Print library list for LD_TRACE_PRELINKING.
If prelinking information can be used, skip relocating libraries and
call _dl_resolve_conflicts instead.
(process_envvars): Handle LD_TRACE_PRELINKING envvar.
* elf/dl-load.c (_dl_map_object): Don't create fake libs
if LD_TRACE_PRELINKING.
* include/link.h (struct link_map) [l_info]: Add DT_VALNUM
+ DT_ADDRNUM.
* sysdeps/generic/ldsodefs.h (_dl_trace_prelink_map): New declaration.
(DL_DEBUG_PRELINK): Define.
(_dl_resolve_conflicts): Add prototype.
* sysdeps/alpha/dl-machine.h (elf_machine_runtime_setup): Reinitialize
.plt for prelinked libraries where prelinking info cannot be used.
(elf_machine_rela): If relocating R_ALPHA_JMP_SLOT in .gnu.conflict
section, use RESOLVE_CONFLICT_FIND_MAP to find out reloc's link_map.
* sysdeps/arm/bits/link.h: New file.
* sysdeps/arm/dl-machine.h (elf_machine_runtime_setup): Save original
content of .got[1].
(ELF_MACHINE_NO_RELA): Only define if RTLD_BOOTSTRAP.
(ELF_MACHINE_PLT_REL): Define.
(elf_machine_rela, elf_machine_rela_relative): New.
(elf_machine_lazy_rel): Reinitialize R_ARM_JUMP_SLOT address instead
of adjusting it if prelinked and prelinking cannot be used.
* sysdeps/i386/bits/link.h: New file.
* sysdeps/i386/dl-machine.h (elf_machine_runtime_setup): Save original
content of .got[1].
(ELF_MACHINE_NO_RELA): Only define if RTLD_BOOTSTRAP.
(ELF_MACHINE_PLT_REL): Define.
(elf_machine_rela, elf_machine_rela_relative): New.
(elf_machine_lazy_rel): Reinitialize R_386_JUMP_SLOT address instead
of adjusting it if prelinked and prelinking cannot be used.
* sysdeps/powerpc/dl-machine.h (elf_machine_rela): If relocating
conflicts, skip finaladdr computation. Use RESOLVE_CONFLICT_FIND_MAP
to find out map for R_PPC_JMP_SLOT relocs.
* sysdeps/sparc/sparc32/dl-machine.h (VALIDX): Define.
(OPCODE_BA): Define.
(elf_machine_runtime_setup): Reinitialize .plt for prelinked
libraries where prelinking info cannot be used.
(sparc_fixup_plt): Renamed from elf_machine_fixup_plt.
(elf_machine_fixup_plt): Call sparc_fixup_plt.
(elf_machine_rela): Set value to 0 if relocating conflicts.
Call sparc_fixup_plt for R_SPARC_JMP_SLOT.
* sysdeps/sparc/sparc64/dl-machine.h (VALIDX): Define.
(sparc64_fixup_plt): Fix a typo.
(elf_machine_rela): Set value to 0 if relocating conflicts.
Handle R_SPARC_JMP_SLOT relocs when relocating conflicts.
(elf_machine_runtime_setup): Reinitialize .plt for prelinked
libraries where prelinking info cannot be used.
* sysdeps/sh/bits/link.h: New file.
* sysdeps/sh/dl-machine.h (elf_machine_runtime_setup): Save original
content of .got[1].
(elf_machine_lazy_rel): Reinitialize R_SH_JMP_SLOT address instead
of adjusting it if prelinked and prelinking cannot be used.
* sysdeps/s390/s390-32/bits/link.h: New file.
* sysdeps/s390/s390-32/dl-machine.h (elf_machine_runtime_setup):
Save original content of .got[1].
(elf_machine_lazy_rel): Reinitialize R_390_JMP_SLOT address instead
of adjusting it if prelinked and prelinking cannot be used.
* sysdeps/s390/s390-64/bits/link.h: New file.
* sysdeps/s390/s390-64/dl-machine.h (elf_machine_runtime_setup):
Save original content of .got[1].
(elf_machine_lazy_rel): Reinitialize R_390_JMP_SLOT address instead
of adjusting it if prelinked and prelinking cannot be used.
* sysdeps/x86_64/bits/link.h: New file.
* sysdeps/x86_64/dl-machine.h (elf_machine_runtime_setup):
Save original content of .got[1].
(elf_machine_lazy_rel): Reinitialize R_X86_64_JMP_SLOT address instead
of adjusting it if prelinked and prelinking cannot be used.
Diffstat (limited to 'elf/dl-lookup.c')
-rw-r--r-- | elf/dl-lookup.c | 229 |
1 files changed, 134 insertions, 95 deletions
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c index 5fa50fc..ae3f0b1 100644 --- a/elf/dl-lookup.c +++ b/elf/dl-lookup.c @@ -194,6 +194,12 @@ _dl_do_lookup_versioned (const char *undef_name, unsigned long int hash, const struct r_found_version *const version, struct link_map *skip, int type_class); +static void +internal_function +_dl_debug_bindings (const char *undef_name, struct link_map *undef_map, + const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[], + struct sym_val *value, const struct r_found_version *version, + int type_class, int protected); /* Search loaded objects' symbol tables for a definition of the symbol UNDEF_NAME. */ @@ -204,7 +210,7 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map, const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[], int type_class, int explicit) { - unsigned long int hash = _dl_elf_hash (undef_name); + const unsigned long int hash = _dl_elf_hash (undef_name); struct sym_val current_value = { NULL, NULL }; struct r_scope_elem **scope; int protected; @@ -241,7 +247,7 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map, if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK) /* We could find no value for a strong reference. */ /* XXX We cannot translate the messages. */ - _dl_signal_cerror (0, (reference_name && reference_name[0] + _dl_signal_cerror (0, (reference_name[0] ? reference_name : (_dl_argv[0] ?: "<main program>")), N_("relocation error"), @@ -251,25 +257,7 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map, } protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED; - - if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 0)) - { - const char *reference_name = undef_map ? undef_map->l_name : NULL; - - _dl_debug_printf ("binding file %s to %s: %s symbol `%s'\n", - (reference_name && reference_name[0] - ? reference_name : (_dl_argv[0] ?: "<main program>")), - current_value.m->l_name[0] - ? current_value.m->l_name : _dl_argv[0], - protected ? "protected" : "normal", undef_name); - } - - if (__builtin_expect (protected == 0, 1)) - { - *ref = current_value.s; - return LOOKUP_VALUE (current_value.m); - } - else + if (__builtin_expect (protected != 0, 0)) { /* It is very tricky. We need to figure out what value to return for the protected symbol */ @@ -280,14 +268,20 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map, 0, NULL, ELF_RTYPE_CLASS_PLT)) break; - if (protected_value.s == NULL || protected_value.m == undef_map) + if (protected_value.s != NULL && protected_value.m != undef_map) { - *ref = current_value.s; - return LOOKUP_VALUE (current_value.m); + current_value.s = *ref; + current_value.m = undef_map; } - - return LOOKUP_VALUE (undef_map); } + + if (__builtin_expect (_dl_debug_mask + & (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0)) + _dl_debug_bindings (undef_name, undef_map, ref, symbol_scope, + ¤t_value, NULL, type_class, protected); + + *ref = current_value.s; + return LOOKUP_VALUE (current_value.m); } @@ -303,7 +297,6 @@ _dl_lookup_symbol_skip (const char *undef_name, struct r_scope_elem *symbol_scope[], struct link_map *skip_map) { - const char *reference_name = undef_map ? undef_map->l_name : NULL; const unsigned long int hash = _dl_elf_hash (undef_name); struct sym_val current_value = { NULL, NULL }; struct r_scope_elem **scope; @@ -332,20 +325,7 @@ _dl_lookup_symbol_skip (const char *undef_name, protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED; - if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 0)) - _dl_debug_printf ("binding file %s to %s: %s symbol `%s'\n", - (reference_name && reference_name[0] - ? reference_name : (_dl_argv[0] ?: "<main program>")), - current_value.m->l_name[0] - ? current_value.m->l_name : _dl_argv[0], - protected ? "protected" : "normal", undef_name); - - if (__builtin_expect (protected == 0, 1)) - { - *ref = current_value.s; - return LOOKUP_VALUE (current_value.m); - } - else + if (__builtin_expect (protected != 0, 0)) { /* It is very tricky. We need to figure out what value to return for the protected symbol. */ @@ -359,14 +339,20 @@ _dl_lookup_symbol_skip (const char *undef_name, 0, skip_map, ELF_RTYPE_CLASS_PLT)) break; - if (protected_value.s == NULL || protected_value.m == undef_map) + if (protected_value.s != NULL && protected_value.m != undef_map) { - *ref = current_value.s; - return LOOKUP_VALUE (current_value.m); + current_value.s = *ref; + current_value.m = undef_map; } - - return LOOKUP_VALUE (undef_map); } + + if (__builtin_expect (_dl_debug_mask + & (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0)) + _dl_debug_bindings (undef_name, undef_map, ref, symbol_scope, + ¤t_value, NULL, 0, protected); + + *ref = current_value.s; + return LOOKUP_VALUE (current_value.m); } @@ -383,7 +369,7 @@ _dl_lookup_versioned_symbol (const char *undef_name, const struct r_found_version *version, int type_class, int explicit) { - unsigned long int hash = _dl_elf_hash (undef_name); + const unsigned long int hash = _dl_elf_hash (undef_name); struct sym_val current_value = { NULL, NULL }; struct r_scope_elem **scope; int protected; @@ -423,7 +409,7 @@ _dl_lookup_versioned_symbol (const char *undef_name, const char *reference_name = undef_map ? undef_map->l_name : NULL; /* XXX We cannot translate the message. */ - _dl_signal_cerror (0, (reference_name && reference_name[0] + _dl_signal_cerror (0, (reference_name[0] ? reference_name : (_dl_argv[0] ?: "<main program>")), N_("relocation error"), @@ -447,7 +433,7 @@ _dl_lookup_versioned_symbol (const char *undef_name, const char *reference_name = undef_map ? undef_map->l_name : NULL; /* XXX We cannot translate the message. */ - _dl_signal_cerror (0, (reference_name && reference_name[0] + _dl_signal_cerror (0, (reference_name[0] ? reference_name : (_dl_argv[0] ?: "<main program>")), NULL, make_string (undefined_msg, undef_name, @@ -460,25 +446,7 @@ _dl_lookup_versioned_symbol (const char *undef_name, protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED; - if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 0)) - { - const char *reference_name = undef_map ? undef_map->l_name : NULL; - - _dl_debug_printf ("binding file %s to %s: %s symbol `%s' [%s]\n", - (reference_name && reference_name[0] - ? reference_name : (_dl_argv[0] ?: "<main program>")), - current_value.m->l_name[0] - ? current_value.m->l_name : _dl_argv[0], - protected ? "protected" : "normal", - undef_name, version->name); - } - - if (__builtin_expect (protected == 0, 1)) - { - *ref = current_value.s; - return LOOKUP_VALUE (current_value.m); - } - else + if (__builtin_expect (protected != 0, 0)) { /* It is very tricky. We need to figure out what value to return for the protected symbol */ @@ -490,14 +458,20 @@ _dl_lookup_versioned_symbol (const char *undef_name, ELF_RTYPE_CLASS_PLT)) break; - if (protected_value.s == NULL || protected_value.m == undef_map) + if (protected_value.s != NULL && protected_value.m != undef_map) { - *ref = current_value.s; - return LOOKUP_VALUE (current_value.m); + current_value.s = *ref; + current_value.m = undef_map; } - - return LOOKUP_VALUE (undef_map); } + + if (__builtin_expect (_dl_debug_mask + & (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0)) + _dl_debug_bindings (undef_name, undef_map, ref, symbol_scope, + ¤t_value, version, type_class, protected); + + *ref = current_value.s; + return LOOKUP_VALUE (current_value.m); } @@ -512,7 +486,7 @@ _dl_lookup_versioned_symbol_skip (const char *undef_name, const struct r_found_version *version, struct link_map *skip_map) { - const char *reference_name = undef_map ? undef_map->l_name : NULL; + const char *reference_name = undef_map->l_name; const unsigned long int hash = _dl_elf_hash (undef_name); struct sym_val current_value = { NULL, NULL }; struct r_scope_elem **scope; @@ -543,7 +517,7 @@ _dl_lookup_versioned_symbol_skip (const char *undef_name, __mempcpy (__mempcpy (buf, undefined_msg, sizeof undefined_msg - 1), undef_name, len + 1); /* XXX We cannot translate the messages. */ - _dl_signal_cerror (0, (reference_name && reference_name[0] + _dl_signal_cerror (0, (reference_name[0] ? reference_name : (_dl_argv[0] ?: "<main program>")), NULL, buf); @@ -554,21 +528,7 @@ _dl_lookup_versioned_symbol_skip (const char *undef_name, protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED; - if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 0)) - _dl_debug_printf ("binding file %s to %s: %s symbol `%s' [%s]\n", - (reference_name && reference_name[0] - ? reference_name : (_dl_argv[0] ?: "<main program>")), - current_value.m->l_name[0] - ? current_value.m->l_name : _dl_argv[0], - protected ? "protected" : "normal", - undef_name, version->name); - - if (__builtin_expect (protected == 0, 1)) - { - *ref = current_value.s; - return LOOKUP_VALUE (current_value.m); - } - else + if (__builtin_expect (protected != 0, 0)) { /* It is very tricky. We need to figure out what value to return for the protected symbol */ @@ -584,14 +544,20 @@ _dl_lookup_versioned_symbol_skip (const char *undef_name, skip_map, ELF_RTYPE_CLASS_PLT)) break; - if (protected_value.s == NULL || protected_value.m == undef_map) + if (protected_value.s != NULL && protected_value.m != undef_map) { - *ref = current_value.s; - return LOOKUP_VALUE (current_value.m); + current_value.s = *ref; + current_value.m = undef_map; } - - return LOOKUP_VALUE (undef_map); } + + if (__builtin_expect (_dl_debug_mask + & (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0)) + _dl_debug_bindings (undef_name, undef_map, ref, symbol_scope, + ¤t_value, version, 0, protected); + + *ref = current_value.s; + return LOOKUP_VALUE (current_value.m); } @@ -615,6 +581,79 @@ _dl_setup_hash (struct link_map *map) map->l_chain = hash; } +static void +internal_function +_dl_debug_bindings (const char *undef_name, struct link_map *undef_map, + const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[], + struct sym_val *value, const struct r_found_version *version, + int type_class, int protected) +{ + const char *reference_name = undef_map->l_name; + + if (_dl_debug_mask & DL_DEBUG_BINDINGS) + { + _dl_debug_printf ("binding file %s to %s: %s symbol `%s'", + (reference_name[0] + ? reference_name : (_dl_argv[0] ?: "<main program>")), + value->m->l_name[0] ? value->m->l_name : _dl_argv[0], + protected ? "protected" : "normal", + undef_name); + if (version) + _dl_debug_printf_c (" [%s]\n", version->name); + else + _dl_debug_printf_c ("\n"); + } +#ifdef SHARED + if (_dl_debug_mask & DL_DEBUG_PRELINK) + { + int conflict = 0; + struct sym_val val = { NULL, NULL }; + + if ((_dl_trace_prelink_map == NULL + || _dl_trace_prelink_map == _dl_loaded) + && undef_map != _dl_loaded) + { + const unsigned long int hash = _dl_elf_hash (undef_name); + + if (version == 0) + _dl_do_lookup (undef_name, hash, *ref, &val, + undef_map->l_local_scope[0], 0, NULL, type_class); + else + _dl_do_lookup_versioned (undef_name, hash, *ref, &val, + undef_map->l_local_scope[0], 0, version, + NULL, type_class); + + if (val.s != value->s || val.m != value->m) + conflict = 1; + } + + if (conflict + || _dl_trace_prelink_map == undef_map + || _dl_trace_prelink_map == NULL) + { + _dl_printf ("%s 0x%0*Zx 0x%0*Zx -> 0x%0*Zx 0x%0*Zx ", + conflict ? "conflict" : "lookup", + (int) sizeof (ElfW(Addr)) * 2, undef_map->l_map_start, + (int) sizeof (ElfW(Addr)) * 2, + ((ElfW(Addr)) *ref) - undef_map->l_map_start, + (int) sizeof (ElfW(Addr)) * 2, + (ElfW(Addr)) (value->s ? value->m->l_map_start : 0), + (int) sizeof (ElfW(Addr)) * 2, + (ElfW(Addr)) (value->s ? value->s->st_value : 0)); + + if (conflict) + _dl_printf ("x 0x%0*Zx 0x%0*Zx ", + (int) sizeof (ElfW(Addr)) * 2, + (ElfW(Addr)) (val.s ? val.m->l_map_start : 0), + (int) sizeof (ElfW(Addr)) * 2, + (ElfW(Addr)) (val.s ? val.s->st_value : 0)); + + _dl_printf ("/%x %s\n", type_class, undef_name); + } + } +#endif +} + /* These are here so that we only inline do_lookup{,_versioned} in the common case, not everywhere. */ static int |