Annotation of parser3/src/lib/ltdl/loaders/dyld.c, revision 1.2

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

E-mail: