root/libltdl/loaders/dlopen.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_vtable
  2. vl_exit
  3. vm_open
  4. vm_close
  5. vm_sym

   1 /* loader-dlopen.c --  dynamic linking with dlopen/dlsym
   2 
   3    Copyright (C) 1998-2000, 2004, 2006-2008, 2011-2015 Free Software
   4    Foundation, Inc.
   5    Written by Thomas Tanner, 1998
   6 
   7    NOTE: The canonical source of this file is maintained with the
   8    GNU Libtool package.  Report bugs to bug-libtool@gnu.org.
   9 
  10 GNU Libltdl is free software; you can redistribute it and/or
  11 modify it under the terms of the GNU Lesser General Public
  12 License as published by the Free Software Foundation; either
  13 version 2 of the License, or (at your option) any later version.
  14 
  15 As a special exception to the GNU Lesser General Public License,
  16 if you distribute this file as part of a program or library that
  17 is built using GNU Libtool, you may include this file under the
  18 same distribution terms that you use for the rest of that program.
  19 
  20 GNU Libltdl is distributed in the hope that it will be useful,
  21 but WITHOUT ANY WARRANTY; without even the implied warranty of
  22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  23 GNU Lesser General Public License for more details.
  24 
  25 You should have received a copy of the GNU Lesser General Public
  26 License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
  27 copy can be downloaded from  http://www.gnu.org/licenses/lgpl.html,
  28 or obtained by writing to the Free Software Foundation, Inc.,
  29 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  30 */
  31 
  32 #include "lt__private.h"
  33 #include "lt_dlloader.h"
  34 
  35 /* Use the preprocessor to rename non-static symbols to avoid namespace
  36    collisions when the loader code is statically linked into libltdl.
  37    Use the "<module_name>_LTX_" prefix so that the symbol addresses can
  38    be fetched from the preloaded symbol list by lt_dlsym():  */
  39 #define get_vtable      dlopen_LTX_get_vtable
  40 
  41 LT_BEGIN_C_DECLS
  42 LT_SCOPE lt_dlvtable *get_vtable (lt_user_data loader_data);
  43 LT_END_C_DECLS
  44 
  45 
  46 /* Boilerplate code to set up the vtable for hooking this loader into
  47    libltdl's loader list:  */
  48 static int       vl_exit  (lt_user_data loader_data);
  49 static lt_module vm_open  (lt_user_data loader_data, const char *filename,
  50                            lt_dladvise advise);
  51 static int       vm_close (lt_user_data loader_data, lt_module module);
  52 static void *    vm_sym   (lt_user_data loader_data, lt_module module,
  53                           const char *symbolname);
  54 
  55 static lt_dlvtable *vtable = 0;
  56 
  57 /* Return the vtable for this loader, only the name and sym_prefix
  58    attributes (plus the virtual function implementations, obviously)
  59    change between loaders.  */
  60 lt_dlvtable *
  61 get_vtable (lt_user_data loader_data)
     /* [previous][next][first][last][top][bottom][index][help] */
  62 {
  63   if (!vtable)
  64     {
  65       vtable = (lt_dlvtable *) lt__zalloc (sizeof *vtable);
  66     }
  67 
  68   if (vtable && !vtable->name)
  69     {
  70       vtable->name              = "lt_dlopen";
  71 #if defined DLSYM_USCORE
  72       vtable->sym_prefix        = "_";
  73 #endif
  74       vtable->module_open       = vm_open;
  75       vtable->module_close      = vm_close;
  76       vtable->find_sym          = vm_sym;
  77       vtable->dlloader_exit     = vl_exit;
  78       vtable->dlloader_data     = loader_data;
  79       vtable->priority          = LT_DLLOADER_PREPEND;
  80     }
  81 
  82   if (vtable && (vtable->dlloader_data != loader_data))
  83     {
  84       LT__SETERROR (INIT_LOADER);
  85       return 0;
  86     }
  87 
  88   return vtable;
  89 }
  90 
  91 
  92 
  93 /* --- IMPLEMENTATION --- */
  94 
  95 
  96 #if defined HAVE_DLFCN_H
  97 #  include <dlfcn.h>
  98 #endif
  99 
 100 #if defined HAVE_SYS_DL_H
 101 #  include <sys/dl.h>
 102 #endif
 103 
 104 
 105 /* We may have to define LT_LAZY_OR_NOW in the command line if we
 106    find out it does not work in some platform. */
 107 #if !defined LT_LAZY_OR_NOW
 108 #  if defined RTLD_LAZY
 109 #    define LT_LAZY_OR_NOW      RTLD_LAZY
 110 #  else
 111 #    if defined DL_LAZY
 112 #      define LT_LAZY_OR_NOW    DL_LAZY
 113 #    endif
 114 #  endif /* !RTLD_LAZY */
 115 #endif
 116 #if !defined LT_LAZY_OR_NOW
 117 #  if defined RTLD_NOW
 118 #    define LT_LAZY_OR_NOW      RTLD_NOW
 119 #  else
 120 #    if defined DL_NOW
 121 #      define LT_LAZY_OR_NOW    DL_NOW
 122 #    endif
 123 #  endif /* !RTLD_NOW */
 124 #endif
 125 #if !defined LT_LAZY_OR_NOW
 126 #  define LT_LAZY_OR_NOW        0
 127 #endif /* !LT_LAZY_OR_NOW */
 128 
 129 /* We only support local and global symbols from modules for loaders
 130    that provide such a thing, otherwise the system default is used.  */
 131 #if !defined RTLD_GLOBAL
 132 #  if defined DL_GLOBAL
 133 #    define RTLD_GLOBAL         DL_GLOBAL
 134 #  endif
 135 #endif /* !RTLD_GLOBAL */
 136 #if !defined RTLD_LOCAL
 137 #  if defined DL_LOCAL
 138 #    define RTLD_LOCAL          DL_LOCAL
 139 #  endif
 140 #endif /* !RTLD_LOCAL */
 141 
 142 #if defined HAVE_DLERROR
 143 #  define DLERROR(arg)  dlerror ()
 144 #else
 145 #  define DLERROR(arg)  LT__STRERROR (arg)
 146 #endif
 147 
 148 #define DL__SETERROR(errorcode) \
 149         LT__SETERRORSTR (DLERROR (errorcode))
 150 
 151 
 152 /* A function called through the vtable when this loader is no
 153    longer needed by the application.  */
 154 static int
 155 vl_exit (lt_user_data loader_data LT__UNUSED)
     /* [previous][next][first][last][top][bottom][index][help] */
 156 {
 157   vtable = NULL;
 158   return 0;
 159 }
 160 
 161 
 162 /* A function called through the vtable to open a module with this
 163    loader.  Returns an opaque representation of the newly opened
 164    module for processing with this loader's other vtable functions.  */
 165 static lt_module
 166 vm_open (lt_user_data loader_data LT__UNUSED, const char *filename,
     /* [previous][next][first][last][top][bottom][index][help] */
 167          lt_dladvise advise)
 168 {
 169   int           module_flags = LT_LAZY_OR_NOW;
 170   lt_module     module;
 171 #ifdef RTLD_MEMBER
 172   int           len = LT_STRLEN (filename);
 173 #endif
 174 
 175   if (advise)
 176     {
 177 #ifdef RTLD_GLOBAL
 178       /* If there is some means of asking for global symbol resolution,
 179          do so.  */
 180       if (advise->is_symglobal)
 181         module_flags |= RTLD_GLOBAL;
 182 #else
 183       /* Otherwise, reset that bit so the caller can tell it wasn't
 184          acted on.  */
 185       advise->is_symglobal = 0;
 186 #endif
 187 
 188 /* And similarly for local only symbol resolution.  */
 189 #ifdef RTLD_LOCAL
 190       if (advise->is_symlocal)
 191         module_flags |= RTLD_LOCAL;
 192 #else
 193       advise->is_symlocal = 0;
 194 #endif
 195     }
 196 
 197 #ifdef RTLD_MEMBER /* AIX */
 198   if (len >= 4) /* at least "l(m)" */
 199     {
 200       /* Advise loading an archive member only if the filename really
 201          contains both the opening and closing parent, and a member. */
 202       if (filename[len-1] == ')')
 203         {
 204           const char *opening = strrchr(filename, '(');
 205           if (opening && opening < (filename+len-2) && strchr(opening+1, '/') == NULL)
 206             module_flags |= RTLD_MEMBER;
 207         }
 208     }
 209 #endif
 210 
 211   module = dlopen (filename, module_flags);
 212 
 213 #if defined RTLD_MEMBER && defined LT_SHARED_LIB_MEMBER
 214   if (!module && len && !(module_flags & RTLD_MEMBER) && errno == ENOEXEC)
 215     {
 216       /* Loading without a member specified failed with "Exec format error".
 217          So the file is there, but either has wrong bitwidth, or is an
 218          archive eventually containing the default shared archive member.
 219          Retry with default member, getting same error in worst case. */
 220       const char *member = LT_SHARED_LIB_MEMBER;
 221 
 222       char *attempt = MALLOC (char, len + strlen (member) + 1);
 223       if (!attempt)
 224         {
 225           LT__SETERROR (NO_MEMORY);
 226           return module;
 227         }
 228 
 229       sprintf (attempt, "%s%s", filename, member);
 230       module = vm_open (loader_data, attempt, advise);
 231       FREE (attempt);
 232       return module;
 233     }
 234 #endif
 235 
 236   if (!module)
 237     {
 238       DL__SETERROR (CANNOT_OPEN);
 239     }
 240 
 241   return module;
 242 }
 243 
 244 
 245 /* A function called through the vtable when a particular module
 246    should be unloaded.  */
 247 static int
 248 vm_close (lt_user_data loader_data LT__UNUSED, lt_module module)
     /* [previous][next][first][last][top][bottom][index][help] */
 249 {
 250   int errors = 0;
 251 
 252   if (dlclose (module) != 0)
 253     {
 254       DL__SETERROR (CANNOT_CLOSE);
 255       ++errors;
 256     }
 257 
 258   return errors;
 259 }
 260 
 261 
 262 /* A function called through the vtable to get the address of
 263    a symbol loaded from a particular module.  */
 264 static void *
 265 vm_sym (lt_user_data loader_data LT__UNUSED, lt_module module, const char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
 266 {
 267   void *address = dlsym (module, name);
 268 
 269   if (!address)
 270     {
 271       DL__SETERROR (SYMBOL_NOT_FOUND);
 272     }
 273 
 274   return address;
 275 }

/* [previous][next][first][last][top][bottom][index][help] */