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*) <__addimage);
! 210: (void) _dyld_func_lookup ("__dyld_NSLookupSymbolInImage",
! 211: (unsigned long*)<__image_symbol);
! 212: (void) _dyld_func_lookup ("__dyld_NSIsSymbolNameDefinedInImage",
! 213: (unsigned long*) <__image_symbol_p);
! 214: (void) _dyld_func_lookup ("__dyld_NSMakePrivateModulePublic",
! 215: (unsigned long*) <__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>