/* * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ #ifdef SHLIB #include "shlib.h" #endif #import #import #import #ifndef __OPENSTEP__ #import #endif #import "stuff/bool.h" #import #import static enum bool names_match( char *install_name, const char *libraryName); void NSInstallLinkEditErrorHandlers( NSLinkEditErrorHandlers *handlers) { static void (*p)( void (*undefined)(const char *symbol_name), NSModule (*multiple)(NSSymbol s, NSModule old, NSModule new), void (*linkEdit)(NSLinkEditErrors c, int errorNumber, const char *fileName, const char *errorString)) = NULL; if(p == NULL) _dyld_func_lookup("__dyld_install_handlers", (unsigned long *)&p); p(handlers->undefined, handlers->multiple, handlers->linkEdit); } const char * NSNameOfModule( NSModule module) { static char * (*p)(NSModule module) = NULL; if(p == NULL) _dyld_func_lookup("__dyld_NSNameOfModule", (unsigned long *)&p); return(p(module)); } const char * NSLibraryNameForModule( NSModule module) { static char * (*p)(NSModule module) = NULL; if(p == NULL) _dyld_func_lookup("__dyld_NSLibraryNameForModule", (unsigned long *)&p); return(p(module)); } enum bool NSIsSymbolNameDefined( const char *symbolName) { static enum bool (*p)(const char *symbolName) = NULL; if(p == NULL) _dyld_func_lookup("__dyld_NSIsSymbolNameDefined", (unsigned long *)&p); return(p(symbolName)); } enum bool NSIsSymbolNameDefinedWithHint( const char *symbolName, const char *libraryNameHint) { static enum bool (*p)(const char *symbolName, const char *libraryNameHint) = NULL; if(p == NULL) _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedWithHint", (unsigned long *)&p); return(p(symbolName, libraryNameHint)); } enum bool NSIsSymbolNameDefinedInImage( const struct mach_header *image, const char *symbolName) { static enum bool (*p)(const struct mach_header *image, const char *symbolName) = NULL; if(p == NULL) _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage", (unsigned long *)&p); return(p(image, symbolName)); } NSSymbol NSLookupAndBindSymbol( const char *symbolName) { static NSSymbol (*p)(const char *symbolName) = NULL; if(p == NULL) _dyld_func_lookup("__dyld_NSLookupAndBindSymbol", (unsigned long *)&p); return(p(symbolName)); } NSSymbol NSLookupAndBindSymbolWithHint( const char *symbolName, const char *libraryNameHint) { static NSSymbol (*p)(const char *symbolName, const char *libraryNameHint) = NULL; if(p == NULL) _dyld_func_lookup("__dyld_NSLookupAndBindSymbolWithHint", (unsigned long *)&p); return(p(symbolName, libraryNameHint)); } NSSymbol NSLookupSymbolInModule( NSModule module, const char *symbolName) { static NSSymbol (*p)(NSModule module, const char *symbolName) = NULL; if(p == NULL) _dyld_func_lookup("__dyld_NSLookupSymbolInModule", (unsigned long *)&p); return(p(module, symbolName)); } NSSymbol NSLookupSymbolInImage( const struct mach_header *image, const char *symbolName, unsigned long options) { static NSSymbol (*p)(const struct mach_header *image, const char *symbolName, unsigned long options) = NULL; if(p == NULL) _dyld_func_lookup("__dyld_NSLookupSymbolInImage", (unsigned long *)&p); return(p(image, symbolName, options)); } const char * NSNameOfSymbol( NSSymbol symbol) { static char * (*p)(NSSymbol symbol) = NULL; if(p == NULL) _dyld_func_lookup("__dyld_NSNameOfSymbol", (unsigned long *)&p); return(p(symbol)); } void * NSAddressOfSymbol( NSSymbol symbol) { static void * (*p)(NSSymbol symbol) = NULL; if(p == NULL) _dyld_func_lookup("__dyld_NSAddressOfSymbol", (unsigned long *)&p); return(p(symbol)); } NSModule NSModuleForSymbol( NSSymbol symbol) { static NSModule (*p)(NSSymbol symbol) = NULL; if(p == NULL) _dyld_func_lookup("__dyld_NSModuleForSymbol", (unsigned long *)&p); return(p(symbol)); } enum bool NSAddLibrary( const char *pathName) { static enum bool (*p)(const char *pathName) = NULL; if(p == NULL) _dyld_func_lookup("__dyld_NSAddLibrary", (unsigned long *)&p); return(p(pathName)); } enum bool NSAddLibraryWithSearching( const char *pathName) { static enum bool (*p)(const char *pathName) = NULL; if(p == NULL) _dyld_func_lookup("__dyld_NSAddLibraryWithSearching", (unsigned long *)&p); return(p(pathName)); } const struct mach_header * NSAddImage( const char *image_name, unsigned long options) { static const struct mach_header * (*p)(const char *image_name, unsigned long options) = NULL; if(p == NULL) _dyld_func_lookup("__dyld_NSAddImage", (unsigned long *)&p); return(p(image_name, options)); } /* * This routine returns the current version of the named shared library the * executable it was built with. The libraryName parameter is the same as the * -lx or -framework Foo argument passed to the static link editor when building * the executable (with -lx it would be "x" and with -framework Foo it would be * "Foo"). If this the executable was not built against the specified library * it returns -1. It should be noted that if this only returns the value the * current version of the named shared library the executable was built with * and not a list of current versions that dependent libraries and bundles the * program is using were built with. */ long NSVersionOfLinkTimeLibrary( const char *libraryName) { unsigned long i; struct load_command *load_commands, *lc; struct dylib_command *dl; char *install_name; #ifndef __OPENSTEP__ static struct mach_header *mh = NULL; if(mh == NULL) mh = _NSGetMachExecuteHeader(); #else /* defined(__OPENSTEP__) */ #ifdef __DYNAMIC__ static struct mach_header *mh = NULL; if(mh == NULL) _dyld_lookup_and_bind("__mh_execute_header", (unsigned long *)&mh, NULL); #else struct mach_header *mh; mh = (struct mach_header *)&_mh_execute_header; #endif #endif /* __OPENSTEP__ */ load_commands = (struct load_command *) ((char *)mh + sizeof(struct mach_header)); lc = load_commands; for(i = 0; i < mh->ncmds; i++){ if(lc->cmd == LC_LOAD_DYLIB){ dl = (struct dylib_command *)lc; install_name = (char *)dl + dl->dylib.name.offset; if(names_match(install_name, libraryName) == TRUE) return(dl->dylib.current_version); } lc = (struct load_command *)((char *)lc + lc->cmdsize); } return(-1); } /* * This routine returns the current version of the named shared library the * program it is running against. The libraryName parameter is the same as * would be static link editor using the -lx or -framework Foo flags (with -lx * it would be "x" and with -framework Foo it would be "Foo"). If the program * is not using the specified library it returns -1. */ long NSVersionOfRunTimeLibrary( const char *libraryName) { unsigned long i, j, n; char *install_name; struct load_command *load_commands, *lc; struct dylib_command *dl; struct mach_header *mh; n = _dyld_image_count(); for(i = 0; i < n; i++){ mh = _dyld_get_image_header(i); if(mh->filetype != MH_DYLIB) continue; load_commands = (struct load_command *) ((char *)mh + sizeof(struct mach_header)); lc = load_commands; for(j = 0; j < mh->ncmds; j++){ if(lc->cmd == LC_ID_DYLIB){ dl = (struct dylib_command *)lc; install_name = (char *)dl + dl->dylib.name.offset; if(names_match(install_name, libraryName) == TRUE) return(dl->dylib.current_version); } lc = (struct load_command *)((char *)lc + lc->cmdsize); } } return(-1); } /* * names_match() takes an install_name from an LC_LOAD_DYLIB command and a * libraryName (which is -lx or -framework Foo argument passed to the static * link editor for the same library) and determines if they match. This depends * on conventional use of names including major versioning. */ static enum bool names_match( char *install_name, const char *libraryName) { char *basename; unsigned long n; /* * Conventional install names have these forms: * /System/Library/Frameworks/AppKit.framework/Versions/A/Appkit * /Local/Library/Frameworks/AppKit.framework/Appkit * /lib/libsys_s.A.dylib * /usr/lib/libsys_s.dylib */ basename = strrchr(install_name, '/'); if(basename == NULL) basename = install_name; else basename++; /* * By checking the base name matching the library name we take care * of the -framework cases. */ if(strcmp(basename, libraryName) == 0) return(TRUE); /* * Now check the base name for "lib" if so proceed to check for the * -lx case dealing with a possible .X.dylib and a .dylib extension. */ if(strncmp(basename, "lib", 3) ==0){ n = strlen(libraryName); if(strncmp(basename+3, libraryName, n) == 0){ if(strncmp(basename+3+n, ".dylib", 6) == 0) return(TRUE); if(basename[3+n] == '.' && basename[3+n+1] != '\0' && strncmp(basename+3+n+2, ".dylib", 6) == 0) return(TRUE); } } return(FALSE); } /* *_NSGetExecutablePath copies the path of the executable into the buffer and * returns 0 if the path was successfully copied in the provided buffer. If the * buffer is not large enough, -1 is returned and the expected buffer size is * copied in *bufsize. Note that _NSGetExecutablePath will return "a path" to * the executable not a "real path" to the executable. That is the path may be * a symbolic link and not the real file. And with deep directories the total * bufsize needed could be more than MAXPATHLEN. */ int _NSGetExecutablePath( char *buf, unsigned long *bufsize) { static int (*p)(char *buf, unsigned long *bufsize) = NULL; if(p == NULL) _dyld_func_lookup("__dyld__NSGetExecutablePath", (unsigned long *)&p); return(p(buf, bufsize)); }