Annotation of gforth/libltdl/loaders/dyld.c, revision 1.1

1.1     ! anton       1: /* loader-dyld.c -- dynamic linking on darwin and OS X
        !             2: 
        !             3:    Copyright (C) 1998, 1999, 2000, 2004, 2006,
        !             4:                  2007, 2008 Free Software 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 LT__UNUSED loader_data)
        !           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 LT__UNUSED advise)
        !           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:       strncpy (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: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>