From ee188d555b8c32ad9704a7440cab400af967292f Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Wed, 5 Jun 1996 01:07:21 +0000 Subject: Tue Jun 4 21:01:20 1996 Roland McGrath * sysdeps/mach/hurd/getlogin_r.c: New file. Wed Jun 5 02:11:30 1996 Ulrich Drepper * io/Makefile (routines): Add ttyname_r. * resolv/res_debug.c, resolv/resolv.h: Update from bind-4.3.4-T4A. * sysdeps/libm-i387/e_asinl.S, sysdeps/libm-i387/e_atan2l.S, sysdeps/libm-i387/e_expl.S, sysdeps/libm-i387/e_fmodl.S, sysdeps/libm-i387/e_log10l.S, sysdeps/libm-i387/e_logl.S, sysdeps/libm-i387/e_remainderl.S, sysdeps/libm-i387/e_scalbl.S, sysdeps/libm-i387/e_sqrtl.S, sysdeps/libm-i387/s_atanl.S, sysdeps/libm-i387/s_cosl.S, sysdeps/libm-i387/s_ilogbl.S, sysdeps/libm-i387/s_log1pl.S, sysdeps/libm-i387/s_logbl.S, sysdeps/libm-i387/s_scalbnl.S, sysdeps/libm-i387/s_sinl.S, sysdeps/libm-i387/s_tanl.S: New files. i387 assembler versions of `long double' math functions. * sysdeps/libm-ieee754/k_standard.c: Add handling for errors in long double functions. * sysdeps/libm-ieee754/s_ilogbl.c, sysdeps/libm-ieee754/s_logbl.c, sysdeps/libm-ieee754/s_modfl.c: New files. Generic versions of `long double' math functions. * sysdeps/libm-ieee754/s_isinf.c [NO_LONG_DOUBLE]: Add string alias for __isinfl. * sysdeps/libm-ieee754/w_acoshl.c, sysdeps/libm-ieee754/w_acosl.c, sysdeps/libm-ieee754/w_asinl.c, sysdeps/libm-ieee754/w_atan2l.c, sysdeps/libm-ieee754/w_atanhl.c, sysdeps/libm-ieee754/w_cabsl.c, sysdeps/libm-ieee754/w_coshl.c, sysdeps/libm-ieee754/w_dreml.c, sysdeps/libm-ieee754/w_expl.c, sysdeps/libm-ieee754/w_fmodl.c, sysdeps/libm-ieee754/w_gammal.c, sysdeps/libm-ieee754/w_gammal_r.c, sysdeps/libm-ieee754/w_hypotl.c, sysdeps/libm-ieee754/w_j0l.c, sysdeps/libm-ieee754/w_j1l.c, sysdeps/libm-ieee754/w_jnl.c, sysdeps/libm-ieee754/w_lgammal.c, sysdeps/libm-ieee754/w_lgammal_r.c, sysdeps/libm-ieee754/w_log10l.c, sysdeps/libm-ieee754/w_logl.c, sysdeps/libm-ieee754/w_powl.c, sysdeps/libm-ieee754/w_remainderl.c, sysdeps/libm-ieee754/w_scalbl.c, sysdeps/libm-ieee754/w_sinhl.c, sysdeps/libm-ieee754/w_sqrtl.c: New files. Wrapper functions around long double function implementations. * sysdeps/posix/ttyname_r.c (ttyname_r): Use _D_EXACT_NAMLEN to determine length of directory entry name. * posix/Makefile (routines): Add getlogin_r. * posix/unistd.h: Add prototype for getlogin_r. * sysdeps/stub/getlogin_r.c: New file. Reentrant version of getlogin function, specified in P1003.1c/D6. Stub version. * sysdeps/unix/getlogin.c (getlogin): Use ttyname_r instead of ttyname. This avoids saving and restoring the old content. Also use setutent_r, getutline_r and endutent_r instead of accing UTMP file directly. * sysdeps/unix/getlogin_r.c: New file. Reentrant version of getlogin function, specified in P1003.1c/D6. Tue Jun 4 20:10:09 1996 J.T. Conklin * sysdeps/libm-i387/s_finitef.S: Fix mask for exponent. * elf/dl-lookup.c (_dl_lookup_symbol): Grok magical undefined symbols _GNU_libc_dl_{open,close,symbol} and resolve them to dl functions. * elf/rtld.c (rtld_map): Renamed to _dl_rtld_map, made global. * elf/link.h: Declare _dl_rtld_map. * elf/dl-lookup.c (_dl_symbol_value): New function. * elf/link.h: Declare it. stdio-common/vfscanf.c: Prepare for reentrant libio. Used in reentrant libio. --- elf/dl-lookup.c | 50 +++++++++++++++++++++++++++++++++++++++++++++----- elf/link.h | 6 ++++++ elf/rtld.c | 47 ++++++++++++++++++++++++----------------------- 3 files changed, 75 insertions(+), 28 deletions(-) (limited to 'elf') diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c index 26357c2..b2e9bff 100644 --- a/elf/dl-lookup.c +++ b/elf/dl-lookup.c @@ -110,11 +110,39 @@ _dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref, if (weak_value.s == NULL && ELF32_ST_BIND ((*ref)->st_info) != STB_WEAK) { - const char msg[] = "undefined symbol: "; - char buf[sizeof msg + strlen (undef_name)]; - memcpy (buf, msg, sizeof msg - 1); - memcpy (&buf[sizeof msg - 1], undef_name, sizeof buf - sizeof msg + 1); - _dl_signal_error (0, reference_name, buf); + /* The symbol was not defined by any object in scope. To allow + access to dynamic linker functionality without using -ldl and + thereby brining the dynamic linker's symbols into scope, we + recognize a few magical symbol names and resolve them to the + addresses of functions inside the dynamic linker. */ + + struct magic + { + unsigned long int hash; + const char *name; + Elf32_Addr value; + }; + static struct magic magic[] = + { + { 0xd6a2a5e, "_GNU_libc_dl_open", (Elf32_Addr) &_dl_open }, + { 0x69ef845, "_GNU_libc_dl_close", (Elf32_Addr) &_dl_close }, + { 0xae4d63c, "_GNU_libc_dl_symbol", (Elf32_Addr) &_dl_symbol_value }, + { 0, NULL, 0 } + }; + struct magic *m; + + for (m = magic; m->hash; ++m) + if (hash == m->hash && !strcmp (name, m->name)) + return m->value; + + { + const char msg[] = "undefined symbol: "; + char buf[sizeof msg + strlen (undef_name)]; + memcpy (buf, msg, sizeof msg - 1); + memcpy (&buf[sizeof msg - 1], undef_name, + sizeof buf - sizeof msg + 1); + _dl_signal_error (0, reference_name, buf); + } } *ref = weak_value.s; @@ -135,3 +163,15 @@ _dl_setup_hash (struct link_map *map) hash += map->l_nbuckets; map->l_chain = hash; } + +/* Look up symbol NAME in MAP's scope and return its run-time address. */ + +Elf32_Addr +_dl_symbol_value (struct link_map *map, const char *name) +{ + Elf32_Addr loadbase; + const Elf32_Sym *ref = NULL; + struct link_map *scope[2] = { map, NULL }; + loadbase = _dl_lookup_symbol (name, &ref, scope, map->l_name, 0, 0); + return loadbase + ref->st_value; +} diff --git a/elf/link.h b/elf/link.h index 51740ee..a89e258 100644 --- a/elf/link.h +++ b/elf/link.h @@ -216,6 +216,12 @@ extern Elf32_Addr _dl_lookup_symbol (const char *undef, Elf32_Addr reloc_addr, int noplt); +/* Look up symbol NAME in MAP's scope and return its run-time address. */ +extern Elf32_Addr _dl_symbol_value (struct link_map *map, const char *name); + + +/* Structure describing the dynamic linker itself. */ +extern struct link_map _dl_rtld_map; /* List of objects currently loaded. */ extern struct link_map *_dl_loaded; diff --git a/elf/rtld.c b/elf/rtld.c index 6dc6822..032bb8e 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -52,7 +52,7 @@ static void dl_main (const Elf32_Phdr *phdr, Elf32_Word phent, Elf32_Addr *user_entry); -static struct link_map rtld_map; +struct link_map _dl_rtld_map; Elf32_Addr _dl_start (void *arg) @@ -92,16 +92,17 @@ _dl_start (void *arg) /* Transfer data about ourselves to the permanent link_map structure. */ - rtld_map.l_addr = bootstrap_map.l_addr; - rtld_map.l_ld = bootstrap_map.l_ld; - memcpy (rtld_map.l_info, bootstrap_map.l_info, sizeof rtld_map.l_info); - _dl_setup_hash (&rtld_map); + _dl_rtld_map.l_addr = bootstrap_map.l_addr; + _dl_rtld_map.l_ld = bootstrap_map.l_ld; + memcpy (_dl_rtld_map.l_info, bootstrap_map.l_info, + sizeof _dl_rtld_map.l_info); + _dl_setup_hash (&_dl_rtld_map); /* Cache the DT_RPATH stored in ld.so itself; this will be the default search path. */ - _dl_rpath = (void *) (rtld_map.l_addr + - rtld_map.l_info[DT_STRTAB]->d_un.d_ptr + - rtld_map.l_info[DT_RPATH]->d_un.d_val); + _dl_rpath = (void *) (_dl_rtld_map.l_addr + + _dl_rtld_map.l_info[DT_STRTAB]->d_un.d_ptr + + _dl_rtld_map.l_info[DT_RPATH]->d_un.d_val); /* Call the OS-dependent function to set up life so we can do things like file access. It will call `dl_main' (below) to do all the real work @@ -243,12 +244,12 @@ of this helper program; chances are you did not intend to run this program.\n", /* Put the link_map for ourselves on the chain so it can be found by name. */ - rtld_map.l_name = (char *) rtld_map.l_libname = interpreter_name; - rtld_map.l_type = lt_interpreter; + _dl_rtld_map.l_name = (char *) _dl_rtld_map.l_libname = interpreter_name; + _dl_rtld_map.l_type = lt_interpreter; while (l->l_next) l = l->l_next; - l->l_next = &rtld_map; - rtld_map.l_prev = l; + l->l_next = &_dl_rtld_map; + _dl_rtld_map.l_prev = l; /* Load all the libraries specified by DT_NEEDED entries. */ _dl_map_object_deps (l); @@ -257,12 +258,12 @@ of this helper program; chances are you did not intend to run this program.\n", it will determine gdb's search order. Perhaps do this always, so later dlopen by name finds it? XXX But then gdb always considers it present. */ - if (rtld_map.l_opencount == 0) + if (_dl_rtld_map.l_opencount == 0) { /* No DT_NEEDED entry referred to the interpreter object itself, so remove it from the list of visible objects. */ - rtld_map.l_prev->l_next = rtld_map.l_next; - rtld_map.l_next->l_prev = rtld_map.l_prev; + _dl_rtld_map.l_prev->l_next = _dl_rtld_map.l_next; + _dl_rtld_map.l_next->l_prev = _dl_rtld_map.l_prev; } if (list_only) @@ -325,7 +326,7 @@ of this helper program; chances are you did not intend to run this program.\n", l = l->l_next; do { - if (l != &rtld_map) + if (l != &_dl_rtld_map) _dl_relocate_object (l, lazy); l = l->l_prev; } while (l); @@ -337,28 +338,28 @@ of this helper program; chances are you did not intend to run this program.\n", _dl_relocate_object might need to call `mprotect' for DT_TEXTREL. */ _dl_sysdep_start_cleanup (); - if (rtld_map.l_opencount > 0) + if (_dl_rtld_map.l_opencount > 0) /* There was an explicit ref to the dynamic linker as a shared lib. Re-relocate ourselves with user-controlled symbol definitions. */ - _dl_relocate_object (&rtld_map, lazy); + _dl_relocate_object (&_dl_rtld_map, lazy); /* Tell the debugger where to find the map of loaded objects. */ dl_r_debug.r_version = 1 /* R_DEBUG_VERSION XXX */; - dl_r_debug.r_ldbase = rtld_map.l_addr; /* Record our load address. */ + dl_r_debug.r_ldbase = _dl_rtld_map.l_addr; /* Record our load address. */ dl_r_debug.r_map = _dl_loaded; dl_r_debug.r_brk = (Elf32_Addr) &_dl_r_debug_state; - if (rtld_map.l_info[DT_INIT]) + if (_dl_rtld_map.l_info[DT_INIT]) { /* Call the initializer for the compatibility version of the dynamic linker. There is no additional initialization required for the ABI-compliant dynamic linker. */ - (*(void (*) (void)) (rtld_map.l_addr + - rtld_map.l_info[DT_INIT]->d_un.d_ptr)) (); + (*(void (*) (void)) (_dl_rtld_map.l_addr + + _dl_rtld_map.l_info[DT_INIT]->d_un.d_ptr)) (); /* Clear the field so a future dlopen won't run it again. */ - rtld_map.l_info[DT_INIT] = NULL; + _dl_rtld_map.l_info[DT_INIT] = NULL; } /* Once we return, _dl_sysdep_start will invoke -- cgit v1.1