(linenum→info "unix/slp.c:2238")

glibc/2.7/elf/dl-libc.c

    1: /* Handle loading and unloading shared objects for internal libc purposes.
    2:    Copyright (C) 1999-2002,2004,2005,2006 Free Software Foundation, Inc.
    3:    This file is part of the GNU C Library.
    4:    Contributed by Zack Weinberg <zack@rabi.columbia.edu>, 1999.
    5: 
    6:    The GNU C Library is free software; you can redistribute it and/or
    7:    modify it under the terms of the GNU Lesser General Public
    8:    License as published by the Free Software Foundation; either
    9:    version 2.1 of the License, or (at your option) any later version.
   10: 
   11:    The GNU C Library is distributed in the hope that it will be useful,
   12:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   13:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   14:    Lesser General Public License for more details.
   15: 
   16:    You should have received a copy of the GNU Lesser General Public
   17:    License along with the GNU C Library; if not, write to the Free
   18:    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   19:    02111-1307 USA.  */
   20: 
   21: #include <dlfcn.h>
   22: #include <stdlib.h>
   23: #include <ldsodefs.h>
   24: 
   25: extern int __libc_argc attribute_hidden;
   26: extern char **__libc_argv attribute_hidden;
   27: 
   28: extern char **__environ;
   29: 
   30: /* The purpose of this file is to provide wrappers around the dynamic
   31:    linker error mechanism (similar to dlopen() et al in libdl) which
   32:    are usable from within libc.  Generally we want to throw away the
   33:    string that dlerror() would return and just pass back a null pointer
   34:    for errors.  This also lets the rest of libc not know about the error
   35:    handling mechanism.
   36: 
   37:    Much of this code came from gconv_dl.c with slight modifications. */
   38: 
   39: static int
   40: internal_function
   41: dlerror_run (void (*operate) (void *), void *args)
   42: {
   43:   const char *objname;
   44:   const char *last_errstring = NULL;
   45:   bool malloced;
   46: 
   47:   (void) GLRO(dl_catch_error) (&objname, &last_errstring, &malloced,
   48:                                operate, args);
   49: 
   50:   int result = last_errstring != NULL;
   51:   if (result && malloced)
   52:     free ((char *) last_errstring);
   53: 
   54:   return result;
   55: }
   56: 
   57: /* These functions are called by dlerror_run... */
   58: 
   59: struct do_dlopen_args
   60: {
   61:   /* Argument to do_dlopen.  */
   62:   const char *name;
   63:   /* Opening mode.  */
   64:   int mode;
   65: 
   66:   /* Return from do_dlopen.  */
   67:   struct link_map *map;
   68: };
   69: 
   70: struct do_dlsym_args
   71: {
   72:   /* Arguments to do_dlsym.  */
   73:   struct link_map *map;
   74:   const char *name;
   75: 
   76:   /* Return values of do_dlsym.  */
   77:   lookup_t loadbase;
   78:   const ElfW(Sym) *ref;
   79: };
   80: 
   81: static void
   82: do_dlopen (void *ptr)
   83: {
   84:   struct do_dlopen_args *args = (struct do_dlopen_args *) ptr;
   85:   /* Open and relocate the shared object.  */
   86:   args->map = GLRO(dl_open) (args->name, args->mode, NULL, __LM_ID_CALLER,
   87:                              __libc_argc, __libc_argv, __environ);
   88: }
   89: 
   90: static void
   91: do_dlsym (void *ptr)
   92: {
   93:   struct do_dlsym_args *args = (struct do_dlsym_args *) ptr;
   94:   args->ref = NULL;
   95:   args->loadbase = GLRO(dl_lookup_symbol_x) (args->name, args->map, &args->ref,
   96:                                              args->map->l_local_scope, NULL, 0,
   97:                                              DL_LOOKUP_RETURN_NEWEST, NULL);
   98: }
   99: 
  100: static void
  101: do_dlclose (void *ptr)
  102: {
  103:   GLRO(dl_close) ((struct link_map *) ptr);
  104: }
  105: 
  106: /* This code is to support __libc_dlopen from __libc_dlopen'ed shared
  107:    libraries.  We need to ensure the statically linked __libc_dlopen
  108:    etc. functions are used instead of the dynamically loaded.  */
  109: struct dl_open_hook
  110: {
  111:   void *(*dlopen_mode) (const char *name, int mode);
  112:   void *(*dlsym) (void *map, const char *name);
  113:   int (*dlclose) (void *map);
  114: };
  115: 
  116: #ifdef SHARED
  117: extern struct dl_open_hook *_dl_open_hook;
  118: libc_hidden_proto (_dl_open_hook);
  119: struct dl_open_hook *_dl_open_hook __attribute__ ((nocommon));
  120: libc_hidden_data_def (_dl_open_hook);
  121: #else
  122: static void
  123: do_dlsym_private (void *ptr)
  124: {
  125:   lookup_t l;
  126:   struct r_found_version vers;
  127:   vers.name = "GLIBC_PRIVATE";
  128:   vers.hidden = 1;
  129:   /* vers.hash = _dl_elf_hash (vers.name);  */
  130:   vers.hash = 0x0963cf85;
  131:   vers.filename = NULL;
  132: 
  133:   struct do_dlsym_args *args = (struct do_dlsym_args *) ptr;
  134:   args->ref = NULL;
  135:   l = GLRO(dl_lookup_symbol_x) (args->name, args->map, &args->ref,
  136:                                 args->map->l_scope, &vers, 0, 0, NULL);
  137:   args->loadbase = l;
  138: }
  139: 
  140: static struct dl_open_hook _dl_open_hook =
  141:   {
  142:     .dlopen_mode = __libc_dlopen_mode,
  143:     .dlsym = __libc_dlsym,
  144:     .dlclose = __libc_dlclose
  145:   };
  146: #endif
  147: 
  148: /* ... and these functions call dlerror_run. */
  149: 
  150: void *
  151: __libc_dlopen_mode (const char *name, int mode)
  152: {
  153:   struct do_dlopen_args args;
  154:   args.name = name;
  155:   args.mode = mode;
  156: 
  157: #ifdef SHARED
  158:   if (__builtin_expect (_dl_open_hook != NULL, 0))
  159:     return _dl_open_hook->dlopen_mode (name, mode);
  160:   return (dlerror_run (do_dlopen, &args) ? NULL : (void *) args.map);
  161: #else
  162:   if (dlerror_run (do_dlopen, &args))
  163:     return NULL;
  164: 
  165:   __libc_register_dl_open_hook (args.map);
  166:   __libc_register_dlfcn_hook (args.map);
  167:   return (void *) args.map;
  168: #endif
  169: }
  170: libc_hidden_def (__libc_dlopen_mode)
  171: 
  172: #ifndef SHARED
  173: void *
  174: __libc_dlsym_private (struct link_map *map, const char *name)
  175: {
  176:   struct do_dlsym_args sargs;
  177:   sargs.map = map;
  178:   sargs.name = name;
  179: 
  180:   if (! dlerror_run (do_dlsym_private, &sargs))
  181:     return DL_SYMBOL_ADDRESS (sargs.loadbase, sargs.ref);
  182:   return NULL;
  183: }
  184: 
  185: void
  186: __libc_register_dl_open_hook (struct link_map *map)
  187: {
  188:   struct dl_open_hook **hook;
  189: 
  190:   hook = (struct dl_open_hook **) __libc_dlsym_private (map, "_dl_open_hook");
  191:   if (hook != NULL)
  192:     *hook = &_dl_open_hook;
  193: }
  194: #endif
  195: 
  196: void *
  197: __libc_dlsym (void *map, const char *name)
  198: {
  199:   struct do_dlsym_args args;
  200:   args.map = map;
  201:   args.name = name;
  202: 
  203: #ifdef SHARED
  204:   if (__builtin_expect (_dl_open_hook != NULL, 0))
  205:     return _dl_open_hook->dlsym (map, name);
  206: #endif
  207:   return (dlerror_run (do_dlsym, &args) ? NULL
  208:           : (void *) (DL_SYMBOL_ADDRESS (args.loadbase, args.ref)));
  209: }
  210: libc_hidden_def (__libc_dlsym)
  211: 
  212: int
  213: __libc_dlclose (void *map)
  214: {
  215: #ifdef SHARED
  216:   if (__builtin_expect (_dl_open_hook != NULL, 0))
  217:     return _dl_open_hook->dlclose (map);
  218: #endif
  219:   return dlerror_run (do_dlclose, map);
  220: }
  221: libc_hidden_def (__libc_dlclose)
  222: 
  223: 
  224: libc_freeres_fn (free_mem)
  225: {
  226:   struct link_map *l;
  227:   struct r_search_path_elem *d;
  228: 
  229:   /* Remove all search directories.  */
  230:   d = GL(dl_all_dirs);
  231:   while (d != GLRO(dl_init_all_dirs))
  232:     {
  233:       struct r_search_path_elem *old = d;
  234:       d = d->next;
  235:       free (old);
  236:     }
  237: 
  238:   /* Remove all additional names added to the objects.  */
  239:   for (Lmid_t ns = 0; ns < DL_NNS; ++ns)
  240:     for (l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next)
  241:       {
  242:         struct libname_list *lnp = l->l_libname->next;
  243: 
  244:         l->l_libname->next = NULL;
  245: 
  246:         while (lnp != NULL)
  247:           {
  248:             struct libname_list *old = lnp;
  249:             lnp = lnp->next;
  250:             if (! old->dont_free)
  251:             free (old);
  252:           }
  253:       }
  254: }
Syntax (Markdown)