"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.17.5/libltdl/loaders/dyld.c" (4 Sep 2020, 13617 Bytes) of package /linux/misc/dns/bind9/9.17.5/bind-9.17.5.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "dyld.c" see the Fossies "Dox" file reference documentation.

    1 /* loader-dyld.c -- dynamic linking on darwin and OS X
    2 
    3    Copyright (C) 1998-2000, 2004, 2006-2008, 2011-2015 Free Software
    4    Foundation, Inc.
    5    Written by Peter O'Gorman, 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  dyld_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_init  (lt_user_data loader_data);
   49 static int   vl_exit  (lt_user_data loader_data);
   50 static lt_module vm_open  (lt_user_data loader_data, const char *filename,
   51                            lt_dladvise advise);
   52 static int   vm_close (lt_user_data loader_data, lt_module module);
   53 static void *    vm_sym   (lt_user_data loader_data, lt_module module,
   54               const char *symbolname);
   55 
   56 static lt_dlvtable *vtable = 0;
   57 
   58 /* Return the vtable for this loader, only the name and sym_prefix
   59    attributes (plus the virtual function implementations, obviously)
   60    change between loaders.  */
   61 lt_dlvtable *
   62 get_vtable (lt_user_data loader_data)
   63 {
   64   if (!vtable)
   65     {
   66       vtable = lt__zalloc (sizeof *vtable);
   67     }
   68 
   69   if (vtable && !vtable->name)
   70     {
   71       vtable->name      = "lt_dyld";
   72       vtable->sym_prefix    = "_";
   73       vtable->dlloader_init = vl_init;
   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_APPEND;
   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_MACH_O_DYLD_H
   97 #  if !defined __APPLE_CC__ && !defined __MWERKS__ && !defined __private_extern__
   98   /* Is this correct? Does it still function properly? */
   99 #    define __private_extern__ extern
  100 #  endif
  101 #  include <mach-o/dyld.h>
  102 #endif
  103 
  104 #include <mach-o/getsect.h>
  105 
  106 /* We have to put some stuff here that isn't in older dyld.h files */
  107 #if !defined ENUM_DYLD_BOOL
  108 # define ENUM_DYLD_BOOL
  109 # undef FALSE
  110 # undef TRUE
  111  enum DYLD_BOOL {
  112     FALSE,
  113     TRUE
  114  };
  115 #endif
  116 #if !defined LC_REQ_DYLD
  117 # define LC_REQ_DYLD 0x80000000
  118 #endif
  119 #if !defined LC_LOAD_WEAK_DYLIB
  120 # define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD)
  121 #endif
  122 
  123 #if !defined NSADDIMAGE_OPTION_NONE
  124 #  define NSADDIMAGE_OPTION_NONE                          0x0
  125 #endif
  126 #if !defined NSADDIMAGE_OPTION_RETURN_ON_ERROR
  127 #  define NSADDIMAGE_OPTION_RETURN_ON_ERROR               0x1
  128 #endif
  129 #if !defined NSADDIMAGE_OPTION_WITH_SEARCHING
  130 #  define NSADDIMAGE_OPTION_WITH_SEARCHING                0x2
  131 #endif
  132 #if !defined NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
  133 #  define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED         0x4
  134 #endif
  135 #if !defined NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME
  136 #  define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8
  137 #endif
  138 
  139 #if !defined NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
  140 #  define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND               0x0
  141 #endif
  142 #if !defined NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
  143 #  define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW           0x1
  144 #endif
  145 #if !defined NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY
  146 #  define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY         0x2
  147 #endif
  148 #if !defined NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
  149 #  define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR    0x4
  150 #endif
  151 
  152 #define LT__SYMLOOKUP_OPTS  (NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW \
  153                 | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR)
  154 
  155 #if defined __BIG_ENDIAN__
  156 #  define LT__MAGIC MH_MAGIC
  157 #else
  158 #  define LT__MAGIC MH_CIGAM
  159 #endif
  160 
  161 #define DYLD__SETMYERROR(errmsg)    LT__SETERRORSTR (dylderror (errmsg))
  162 #define DYLD__SETERROR(errcode)     DYLD__SETMYERROR (LT__STRERROR (errcode))
  163 
  164 typedef struct mach_header mach_header;
  165 typedef struct dylib_command dylib_command;
  166 
  167 static const char *dylderror (const char *errmsg);
  168 static const mach_header *lt__nsmodule_get_header (NSModule module);
  169 static const char *lt__header_get_instnam (const mach_header *mh);
  170 static const mach_header *lt__match_loadedlib (const char *name);
  171 static NSSymbol lt__linkedlib_symbol (const char *symname, const mach_header *mh);
  172 
  173 static const mach_header *(*lt__addimage)   (const char *image_name,
  174                          unsigned long options) = 0;
  175 static NSSymbol (*lt__image_symbol)     (const mach_header *image,
  176                          const char *symbolName,
  177                          unsigned long options) = 0;
  178 static enum DYLD_BOOL (*lt__image_symbol_p) (const mach_header *image,
  179                          const char *symbolName) = 0;
  180 static enum DYLD_BOOL (*lt__module_export)  (NSModule module) = 0;
  181 
  182 static int dyld_cannot_close                  = 0;
  183 
  184 
  185 /* A function called through the vtable when this loader is no
  186    longer needed by the application.  */
  187 static int
  188 vl_exit (lt_user_data loader_data LT__UNUSED)
  189 {
  190   vtable = NULL;
  191   return 0;
  192 }
  193 
  194 /* A function called through the vtable to initialise this loader.  */
  195 static int
  196 vl_init (lt_user_data loader_data)
  197 {
  198   int errors = 0;
  199 
  200   if (! dyld_cannot_close)
  201     {
  202       if (!_dyld_present ())
  203     {
  204       ++errors;
  205     }
  206       else
  207     {
  208       (void) _dyld_func_lookup ("__dyld_NSAddImage",
  209                     (unsigned long*) &lt__addimage);
  210       (void) _dyld_func_lookup ("__dyld_NSLookupSymbolInImage",
  211                     (unsigned long*)&lt__image_symbol);
  212       (void) _dyld_func_lookup ("__dyld_NSIsSymbolNameDefinedInImage",
  213                     (unsigned long*) &lt__image_symbol_p);
  214       (void) _dyld_func_lookup ("__dyld_NSMakePrivateModulePublic",
  215                     (unsigned long*) &lt__module_export);
  216       dyld_cannot_close = lt_dladderror ("can't close a dylib");
  217     }
  218     }
  219 
  220   return errors;
  221 }
  222 
  223 
  224 /* A function called through the vtable to open a module with this
  225    loader.  Returns an opaque representation of the newly opened
  226    module for processing with this loader's other vtable functions.  */
  227 static lt_module
  228 vm_open (lt_user_data loader_data, const char *filename,
  229          lt_dladvise advise LT__UNUSED)
  230 {
  231   lt_module module = 0;
  232   NSObjectFileImage ofi = 0;
  233 
  234   if (!filename)
  235     {
  236       return (lt_module) -1;
  237     }
  238 
  239   switch (NSCreateObjectFileImageFromFile (filename, &ofi))
  240     {
  241     case NSObjectFileImageSuccess:
  242       module = NSLinkModule (ofi, filename, NSLINKMODULE_OPTION_RETURN_ON_ERROR
  243                         | NSLINKMODULE_OPTION_PRIVATE
  244                         | NSLINKMODULE_OPTION_BINDNOW);
  245       NSDestroyObjectFileImage (ofi);
  246 
  247       if (module)
  248     {
  249       lt__module_export (module);
  250     }
  251       break;
  252 
  253     case NSObjectFileImageInappropriateFile:
  254       if (lt__image_symbol_p && lt__image_symbol)
  255     {
  256       module = (lt_module) lt__addimage(filename,
  257                         NSADDIMAGE_OPTION_RETURN_ON_ERROR);
  258     }
  259       break;
  260 
  261     case NSObjectFileImageFailure:
  262     case NSObjectFileImageArch:
  263     case NSObjectFileImageFormat:
  264     case NSObjectFileImageAccess:
  265       /*NOWORK*/
  266       break;
  267     }
  268 
  269   if (!module)
  270     {
  271       DYLD__SETERROR (CANNOT_OPEN);
  272     }
  273 
  274   return module;
  275 }
  276 
  277 
  278 /* A function called through the vtable when a particular module
  279    should be unloaded.  */
  280 static int
  281 vm_close (lt_user_data loader_data, lt_module module)
  282 {
  283   int errors = 0;
  284 
  285   if (module != (lt_module) -1)
  286     {
  287       const mach_header *mh = (const mach_header *) module;
  288       int flags = 0;
  289       if (mh->magic == LT__MAGIC)
  290     {
  291       lt_dlseterror (dyld_cannot_close);
  292       ++errors;
  293     }
  294       else
  295     {
  296       /* Currently, if a module contains c++ static destructors and it
  297          is unloaded, we get a segfault in atexit(), due to compiler and
  298          dynamic loader differences of opinion, this works around that.  */
  299       if ((const struct section *) NULL !=
  300           getsectbynamefromheader (lt__nsmodule_get_header (module),
  301                        "__DATA", "__mod_term_func"))
  302         {
  303           flags |= NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED;
  304         }
  305 #if defined __ppc__
  306       flags |= NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES;
  307 #endif
  308       if (!NSUnLinkModule (module, flags))
  309         {
  310           DYLD__SETERROR (CANNOT_CLOSE);
  311           ++errors;
  312         }
  313     }
  314     }
  315 
  316   return errors;
  317 }
  318 
  319 /* A function called through the vtable to get the address of
  320    a symbol loaded from a particular module.  */
  321 static void *
  322 vm_sym (lt_user_data loader_data, lt_module module, const char *name)
  323 {
  324   NSSymbol *nssym = 0;
  325   const mach_header *mh = (const mach_header *) module;
  326   char saveError[256] = "Symbol not found";
  327 
  328   if (module == (lt_module) -1)
  329     {
  330       void *address, *unused;
  331       _dyld_lookup_and_bind (name, (unsigned long*) &address, &unused);
  332       return address;
  333     }
  334 
  335   if (mh->magic == LT__MAGIC)
  336     {
  337       if (lt__image_symbol_p && lt__image_symbol)
  338     {
  339       if (lt__image_symbol_p (mh, name))
  340         {
  341           nssym = lt__image_symbol (mh, name, LT__SYMLOOKUP_OPTS);
  342         }
  343     }
  344 
  345     }
  346   else
  347     {
  348       nssym = NSLookupSymbolInModule (module, name);
  349     }
  350 
  351   if (!nssym)
  352     {
  353       strlcpy (saveError, dylderror (LT__STRERROR (SYMBOL_NOT_FOUND)), 255);
  354       saveError[255] = 0;
  355       if (!mh)
  356     {
  357       mh = (mach_header *)lt__nsmodule_get_header (module);
  358     }
  359       nssym = lt__linkedlib_symbol (name, mh);
  360     }
  361 
  362   if (!nssym)
  363     {
  364       LT__SETERRORSTR (saveError);
  365     }
  366 
  367   return nssym ? NSAddressOfSymbol (nssym) : 0;
  368 }
  369 
  370 
  371 
  372 
  373 /* --- HELPER FUNCTIONS --- */
  374 
  375 
  376 /* Return the dyld error string, or the passed in error string if none. */
  377 static const char *
  378 dylderror (const char *errmsg)
  379 {
  380   NSLinkEditErrors ler;
  381   int lerno;
  382   const char *file;
  383   const char *errstr;
  384 
  385   NSLinkEditError (&ler, &lerno, &file, &errstr);
  386 
  387   if (! (errstr && *errstr))
  388     {
  389       errstr = errmsg;
  390     }
  391 
  392   return errstr;
  393 }
  394 
  395 /* There should probably be an apple dyld api for this. */
  396 static const mach_header *
  397 lt__nsmodule_get_header (NSModule module)
  398 {
  399   int i = _dyld_image_count();
  400   const char *modname = NSNameOfModule (module);
  401   const mach_header *mh = 0;
  402 
  403   if (!modname)
  404     return NULL;
  405 
  406   while (i > 0)
  407     {
  408       --i;
  409       if (strneq (_dyld_get_image_name (i), modname))
  410     {
  411       mh = _dyld_get_image_header (i);
  412       break;
  413     }
  414     }
  415 
  416   return mh;
  417 }
  418 
  419 /* NSAddImage is also used to get the loaded image, but it only works if
  420    the lib is installed, for uninstalled libs we need to check the
  421    install_names against each other.  Note that this is still broken if
  422    DYLD_IMAGE_SUFFIX is set and a different lib was loaded as a result.  */
  423 static const char *
  424 lt__header_get_instnam (const mach_header *mh)
  425 {
  426   unsigned long offset = sizeof(mach_header);
  427   const char* result   = 0;
  428   int j;
  429 
  430   for (j = 0; j < mh->ncmds; j++)
  431     {
  432       struct load_command *lc;
  433 
  434       lc = (struct load_command*) (((unsigned long) mh) + offset);
  435       if (LC_ID_DYLIB == lc->cmd)
  436     {
  437       result=(char*)(((dylib_command*) lc)->dylib.name.offset +
  438              (unsigned long) lc);
  439     }
  440       offset += lc->cmdsize;
  441     }
  442 
  443   return result;
  444 }
  445 
  446 static const mach_header *
  447 lt__match_loadedlib (const char *name)
  448 {
  449   const mach_header *mh = 0;
  450   int i = _dyld_image_count();
  451 
  452   while (i > 0)
  453     {
  454       const char *id;
  455 
  456       --i;
  457       id = lt__header_get_instnam (_dyld_get_image_header (i));
  458       if (id && strneq (id, name))
  459     {
  460       mh = _dyld_get_image_header (i);
  461       break;
  462     }
  463     }
  464 
  465   return mh;
  466 }
  467 
  468 /* Safe to assume our mh is good. */
  469 static NSSymbol
  470 lt__linkedlib_symbol (const char *symname, const mach_header *mh)
  471 {
  472   NSSymbol symbol = 0;
  473 
  474   if (lt__image_symbol && NSIsSymbolNameDefined (symname))
  475     {
  476       unsigned long offset = sizeof(mach_header);
  477       struct load_command *lc;
  478       int j;
  479 
  480       for (j = 0; j < mh->ncmds; j++)
  481     {
  482       lc = (struct load_command*) (((unsigned long) mh) + offset);
  483       if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd))
  484         {
  485           unsigned long base = ((dylib_command *) lc)->dylib.name.offset;
  486           char *name = (char *) (base + (unsigned long) lc);
  487           const mach_header *mh1 = lt__match_loadedlib (name);
  488 
  489           if (!mh1)
  490         {
  491           /* Maybe NSAddImage can find it */
  492           mh1 = lt__addimage (name,
  493                       NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
  494                       | NSADDIMAGE_OPTION_WITH_SEARCHING
  495                       | NSADDIMAGE_OPTION_RETURN_ON_ERROR);
  496         }
  497 
  498           if (mh1)
  499         {
  500           symbol = lt__image_symbol (mh1, symname, LT__SYMLOOKUP_OPTS);
  501           if (symbol)
  502             break;
  503         }
  504         }
  505 
  506       offset += lc->cmdsize;
  507     }
  508     }
  509 
  510   return symbol;
  511 }