diff options
-rw-r--r-- | ChangeLog | 19 | ||||
-rw-r--r-- | elf/dl-lookup.c | 112 | ||||
-rw-r--r-- | elf/dl-object.c | 2 | ||||
-rw-r--r-- | elf/dl-support.c | 1 | ||||
-rw-r--r-- | elf/dl-version.c | 4 | ||||
-rw-r--r-- | elf/link.h | 4 | ||||
-rw-r--r-- | elf/rtld.c | 18 |
7 files changed, 119 insertions, 41 deletions
diff --git a/ChangeLog b/ChangeLog index 2b21f19f76..c63c207d20 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +1998-03-09 18:21 Ulrich Drepper <drepper@cygnus.com> + + * elf/dl-support.c (_dl_debug_bindings): Add definition. + * elf/rtld.c (_dl_debug_bindings): Add definition. + (process_dl_debug): Recognize bindings option. Update help message. + * elf/link.h (struct link_map): Add l_versyms member. + (_dl_debug_bindings): Add declaration. + * elf/version.c (_dl_check_map_versions): Initialize l_versyms. + * elf/dl-object.c (_dl_new_object): Don't initialize l_rpath_dirs + and l_reloc_result. + * elf/dl-lookup.c (do_lookup): Define verstab from l_versyms. + (sym_val): Remove a member, add m as link_map. + (do_lookup): Return result appropriately. + (_dl_lookup_symbol): If _dl_debug_bindings is defined print message. + Call do_lookup correctly. + (_dl_lookup_symbol_skip): Likewise. + (_dl_lookup_versioned_symbol): Likewise. + (_dl_lookup_versioned_symbol_skip): Likewise. + 1998-03-09 08:21 Ulrich Drepper <drepper@cygnus.com> * sysdeps/unix/sysv/linux/chown.c: Moved to ... diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c index c0f9731ce9..c3231ac2c5 100644 --- a/elf/dl-lookup.c +++ b/elf/dl-lookup.c @@ -34,8 +34,8 @@ static const char undefined_msg[] = "undefined symbol: "; struct sym_val { - ElfW(Addr) a; const ElfW(Sym) *s; + struct link_map *m; }; @@ -88,8 +88,8 @@ do_lookup (const char *undef_name, unsigned long int hash, continue; /* Don't search the executable when resolving a copy reloc. */ - if (elf_machine_lookup_noexec_p (reloc_type) && - map->l_type == lt_executable) + if (elf_machine_lookup_noexec_p (reloc_type) + && map->l_type == lt_executable) continue; /* Skip objects without symbol tables. */ @@ -98,11 +98,7 @@ do_lookup (const char *undef_name, unsigned long int hash, symtab = ((void *) map->l_addr + map->l_info[DT_SYMTAB]->d_un.d_ptr); strtab = ((void *) map->l_addr + map->l_info[DT_STRTAB]->d_un.d_ptr); - if (map->l_nversions > 0 && map->l_info[VERSTAG (DT_VERSYM)] != NULL) - verstab = ((void *) map->l_addr - + map->l_info[VERSTAG (DT_VERSYM)]->d_un.d_ptr); - else - verstab = NULL; + verstab = map->l_versyms; /* Search the appropriate hash bucket in this object's symbol table for a definition for the same symbol name. */ @@ -171,7 +167,7 @@ do_lookup (const char *undef_name, unsigned long int hash, case STB_GLOBAL: /* Global definition. Just what we need. */ result->s = sym; - result->a = map->l_addr; + result->m = map; return 1; case STB_WEAK: /* Weak definition. Use this value if we don't find @@ -179,7 +175,7 @@ do_lookup (const char *undef_name, unsigned long int hash, if (! result->s) { result->s = sym; - result->a = map->l_addr; + result->m = map; } break; default: @@ -212,7 +208,7 @@ _dl_lookup_symbol (const char *undef_name, const ElfW(Sym) **ref, int reloc_type) { const unsigned long int hash = _dl_elf_hash (undef_name); - struct sym_val current_value = { 0, NULL }; + struct sym_val current_value = { NULL, NULL }; struct link_map **scope; /* Search the relevant loaded objects for a definition. */ @@ -222,14 +218,24 @@ _dl_lookup_symbol (const char *undef_name, const ElfW(Sym) **ref, reference_name, NULL, NULL, reloc_type)) break; - if (current_value.s == NULL && - (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)) - /* We could find no value for a strong reference. */ - _dl_signal_error (0, reference_name, - make_string (undefined_msg, undef_name)); + if (current_value.s == NULL) + { + if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK) + /* We could find no value for a strong reference. */ + _dl_signal_error (0, reference_name, + make_string (undefined_msg, undef_name)); + *ref = NULL; + return 0; + } + + if (_dl_debug_bindings) + _dl_debug_message ("\tbinding file ", reference_name, " to ", + current_value.m->l_name[0] + ? current_value.m->l_name : _dl_argv[0], + ": symbol `", undef_name, "'\n", NULL); *ref = current_value.s; - return current_value.a; + return current_value.m->l_addr; } @@ -245,7 +251,7 @@ _dl_lookup_symbol_skip (const char *undef_name, const ElfW(Sym) **ref, struct link_map *skip_map) { const unsigned long int hash = _dl_elf_hash (undef_name); - struct sym_val current_value = { 0, NULL }; + struct sym_val current_value = { NULL, NULL }; struct link_map **scope; size_t i; @@ -263,8 +269,20 @@ _dl_lookup_symbol_skip (const char *undef_name, const ElfW(Sym) **ref, reference_name, NULL, skip_map, 0)) break; + if (current_value.s == NULL) + { + *ref = NULL; + return 0; + } + + if (_dl_debug_bindings) + _dl_debug_message ("\tbinding file ", reference_name, " to ", + current_value.m->l_name[0] + ? current_value.m->l_name : _dl_argv[0], + ": symbol `", undef_name, "'\n", NULL); + *ref = current_value.s; - return current_value.a; + return current_value.m->l_addr; } @@ -281,7 +299,7 @@ _dl_lookup_versioned_symbol (const char *undef_name, const ElfW(Sym) **ref, int reloc_type) { const unsigned long int hash = _dl_elf_hash (undef_name); - struct sym_val current_value = { 0, NULL }; + struct sym_val current_value = { NULL, NULL }; struct link_map **scope; /* Search the relevant loaded objects for a definition. */ @@ -308,15 +326,25 @@ _dl_lookup_versioned_symbol (const char *undef_name, const ElfW(Sym) **ref, ? " (no version symbols)" : "")); } - if (current_value.s == NULL && - (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)) - /* We could find no value for a strong reference. */ - _dl_signal_error (0, reference_name, - make_string (undefined_msg, undef_name, - ", version ", version->name ?: NULL)); + if (current_value.s == NULL) + { + if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK) + /* We could find no value for a strong reference. */ + _dl_signal_error (0, reference_name, + make_string (undefined_msg, undef_name, + ", version ", version->name ?: NULL)); + *ref = NULL; + return 0; + } + + if (_dl_debug_bindings) + _dl_debug_message ("\tbinding file ", reference_name, " to ", + current_value.m->l_name[0] + ? current_value.m->l_name : _dl_argv[0], + ": symbol `", undef_name, "'\n", NULL); *ref = current_value.s; - return current_value.a; + return current_value.m->l_addr; } @@ -331,7 +359,7 @@ _dl_lookup_versioned_symbol_skip (const char *undef_name, struct link_map *skip_map) { const unsigned long int hash = _dl_elf_hash (undef_name); - struct sym_val current_value = { 0, NULL }; + struct sym_val current_value = { NULL, NULL }; struct link_map **scope; size_t i; @@ -349,19 +377,29 @@ _dl_lookup_versioned_symbol_skip (const char *undef_name, reference_name, version, skip_map, 0)) break; - if (current_value.s == NULL && - (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)) + if (current_value.s == NULL) { - /* We could find no value for a strong reference. */ - const size_t len = strlen (undef_name); - char buf[sizeof undefined_msg + len]; - __mempcpy (__mempcpy (buf, undefined_msg, sizeof undefined_msg - 1), - undef_name, len + 1); - _dl_signal_error (0, reference_name, buf); + if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK) + { + /* We could find no value for a strong reference. */ + const size_t len = strlen (undef_name); + char buf[sizeof undefined_msg + len]; + __mempcpy (__mempcpy (buf, undefined_msg, sizeof undefined_msg - 1), + undef_name, len + 1); + _dl_signal_error (0, reference_name, buf); + } + *ref = NULL; + return 0; } + if (_dl_debug_bindings) + _dl_debug_message ("\tbinding file ", reference_name, " to ", + current_value.m->l_name[0] + ? current_value.m->l_name : _dl_argv[0], + ": symbol `", undef_name, "'\n", NULL); + *ref = current_value.s; - return current_value.a; + return current_value.m->l_addr; } diff --git a/elf/dl-object.c b/elf/dl-object.c index b2dbb83267..9bd600dd9e 100644 --- a/elf/dl-object.c +++ b/elf/dl-object.c @@ -44,8 +44,6 @@ _dl_new_object (char *realname, const char *libname, int type) newname->next = NULL; new->l_libname = newname; new->l_type = type; - new->l_rpath_dirs = NULL; - new->l_reloc_result = NULL; if (_dl_loaded == NULL) { diff --git a/elf/dl-support.c b/elf/dl-support.c index 797cc99de5..6b6a22d1d3 100644 --- a/elf/dl-support.c +++ b/elf/dl-support.c @@ -37,6 +37,7 @@ const char *_dl_platform; size_t _dl_platformlen; int _dl_debug_libs; int _dl_debug_impcalls; +int _dl_debug_bindings; /* If nonzero print warnings about problematic situations. */ int _dl_verbose; diff --git a/elf/dl-version.c b/elf/dl-version.c index a4f77f5f17..f615bb0cbc 100644 --- a/elf/dl-version.c +++ b/elf/dl-version.c @@ -273,6 +273,10 @@ _dl_check_map_versions (struct link_map *map, int verbose) /* Store the number of available symbols. */ map->l_nversions = ndx_high + 1; + /* Compute the pointer to the version symbols. */ + map->l_versyms = ((void *) map->l_addr + + map->l_info[VERSTAG (DT_VERSYM)]->d_un.d_ptr); + if (dyn != NULL) { ElfW(Verneed) *ent; diff --git a/elf/link.h b/elf/link.h index 5847945c58..d5e2b7f6b3 100644 --- a/elf/link.h +++ b/elf/link.h @@ -197,6 +197,9 @@ struct link_map /* Collected results of relocation while profiling. */ ElfW(Addr) *l_reloc_result; + + /* Pointer to the version information if available. */ + ElfW(Half) *l_versyms; }; @@ -248,6 +251,7 @@ extern struct link_map *_dl_profile_map; /* If nonzero the appropriate debug information is printed. */ extern int _dl_debug_libs; extern int _dl_debug_impcalls; +extern int _dl_debug_bindings; /* File deccriptor to write debug messages to. */ extern int _dl_debug_fd; diff --git a/elf/rtld.c b/elf/rtld.c index c466fa28c9..2cb11bb059 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -76,6 +76,7 @@ const char *_dl_profile_output; struct link_map *_dl_profile_map; int _dl_debug_libs; int _dl_debug_impcalls; +int _dl_debug_bindings; /* Set nonzero during loading and initialization of executable and libraries, cleared before the executable's entry point runs. This @@ -928,6 +929,14 @@ process_dl_debug (char *dl_debug) ++dl_debug; if (*dl_debug != '\0') { + if (strncmp (dl_debug, "bindings", 8) == 0 + && (issep (dl_debug[8]) || dl_debug[8] == '\0')) + { + _dl_debug_bindings = 1; + _dl_debug_impcalls = 1; + any_debug = 1; + dl_debug += 8; + } if (strncmp (dl_debug, "libs", 4) == 0 && (issep (dl_debug[4]) || dl_debug[4] == '\0')) { @@ -942,8 +951,13 @@ process_dl_debug (char *dl_debug) _dl_sysdep_message ("\ Valid options for the LD_DEBUG environment variable are:\n\ \n\ - help display this help message and exit - libs display library search paths\n", NULL); + bindings display information about symbol binding\n\ + help display this help message and exit\n\ + libs display library search paths\n\ +\n\ +To direct the debugging output into a file instead of standard output\n\ +a filename can be specified using the LD_DEBUG_OUTPUT environment variable.\n", + NULL); _exit (0); } else |