LibraryDYLD.cpp

Go to the documentation of this file.
00001 /****************** <VPR heading BEGIN do not edit this line> *****************
00002  *
00003  * VR Juggler Portable Runtime
00004  *
00005  * Original Authors:
00006  *   Allen Bierbaum, Patrick Hartling, Kevin Meinert, Carolina Cruz-Neira
00007  *
00008  * -----------------------------------------------------------------
00009  * File:          $RCSfile$
00010  * Date modified: $Date: 2005-01-01 11:48:13 -0600 (Sat, 01 Jan 2005) $
00011  * Version:       $Revision: 16520 $
00012  * -----------------------------------------------------------------
00013  *
00014  ****************** <VPR heading END do not edit this line> ******************/
00015 
00016 /*************** <auto-copyright.pl BEGIN do not edit this line> **************
00017  *
00018  * VR Juggler is (C) Copyright 1998-2005 by Iowa State University
00019  *
00020  * Original Authors:
00021  *   Allen Bierbaum, Christopher Just,
00022  *   Patrick Hartling, Kevin Meinert,
00023  *   Carolina Cruz-Neira, Albert Baker
00024  *
00025  * This library is free software; you can redistribute it and/or
00026  * modify it under the terms of the GNU Library General Public
00027  * License as published by the Free Software Foundation; either
00028  * version 2 of the License, or (at your option) any later version.
00029  *
00030  * This library is distributed in the hope that it will be useful,
00031  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00032  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00033  * Library General Public License for more details.
00034  *
00035  * You should have received a copy of the GNU Library General Public
00036  * License along with this library; if not, write to the
00037  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00038  * Boston, MA 02111-1307, USA.
00039  *
00040  *************** <auto-copyright.pl END do not edit this line> ***************/
00041 
00042 /*
00043 Copyright (c) 2002 Peter O'Gorman <ogorman@users.sourceforge.net>
00044 
00045 Permission is hereby granted, free of charge, to any person obtaining
00046 a copy of this software and associated documentation files (the
00047 "Software"), to deal in the Software without restriction, including
00048 without limitation the rights to use, copy, modify, merge, publish,
00049 distribute, sublicense, and/or sell copies of the Software, and to
00050 permit persons to whom the Software is furnished to do so, subject to
00051 the following conditions:
00052 
00053 The above copyright notice and this permission notice shall be
00054 included in all copies or substantial portions of the Software.
00055 
00056 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00057 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00058 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00059 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00060 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00061 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00062 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00063 */
00064 
00065 #include <vpr/vprConfig.h>
00066 
00067 #include <stdio.h>
00068 #include <stdlib.h>
00069 #include <string.h>
00070 #include <sys/types.h>
00071 #include <sys/stat.h>
00072 #include <stdarg.h>
00073 #include <limits.h>
00074 #include <mach-o/dyld.h>
00075 #include <boost/concept_check.hpp>
00076 
00077 #include <vpr/Util/Assert.h>
00078 #include <vpr/Util/Debug.h>
00079 #include <vpr/md/DARWIN/DynLoad/LibraryDYLD.h>
00080 
00081 
00082 #ifndef _POSIX_SOURCE
00083 /*
00084  * Structure filled in by dladdr().
00085  */
00086 typedef struct dl_info {
00087         const char      *dli_fname;     /* Pathname of shared object */
00088         void            *dli_fbase;     /* Base address of shared object */
00089         const char      *dli_sname;     /* Name of nearest symbol */
00090         void            *dli_saddr;     /* Address of nearest symbol */
00091 } Dl_info;
00092 
00093 #endif /* ! _POSIX_SOURCE */
00094 
00095 #define RTLD_LAZY   0x1
00096 #define RTLD_NOW    0x2
00097 #define RTLD_LOCAL  0x4
00098 #define RTLD_GLOBAL 0x8
00099 
00100 #ifndef _POSIX_SOURCE
00101 #define RTLD_NOLOAD   0x10
00102 #define RTLD_NODELETE 0x80
00103 
00104 /*
00105  * Special handle arguments for dlsym().
00106  */
00107 #define RTLD_NEXT    ((void *) -1)     /* Search subsequent objects. */
00108 #define RTLD_DEFAULT ((void *) -2)     /* Use default search algorithm. */
00109 #endif /* ! _POSIX_SOURCE */
00110 
00111 namespace
00112 {
00113 
00114 static const unsigned int ERR_STR_LEN(256);
00115 
00116 // Copied from error() found in dlfcn_simple.c from dlcompat.
00117 static const char* error(int setget, const char *str, ...)
00118 {
00119    static char errstr[ERR_STR_LEN];
00120    static int err_filled = 0;
00121    const char *retval;
00122    NSLinkEditErrors ler;
00123    int lerno;
00124    const char *dylderrstr;
00125    const char *file;
00126    va_list arg;
00127    if (setget <= 0)
00128    {
00129       va_start(arg, str);
00130       strncpy(errstr, "dlsimple: ", ERR_STR_LEN);
00131       vsnprintf(errstr + 10, ERR_STR_LEN - 10, str, arg);
00132       va_end(arg);
00133    /* We prefer to use the dyld error string if setget is 0 */
00134       if (setget == 0) {
00135          NSLinkEditError(&ler, &lerno, &file, &dylderrstr);
00136          fprintf(stderr,"dyld: %s\n",dylderrstr);
00137          if (dylderrstr && strlen(dylderrstr))
00138             strncpy(errstr,dylderrstr,ERR_STR_LEN);
00139       }      
00140       err_filled = 1;
00141       retval = NULL;
00142    }
00143    else
00144    {
00145       if (!err_filled)
00146          retval = NULL;
00147       else
00148          retval = errstr;
00149       err_filled = 0;
00150    }
00151    return retval;
00152 }
00153 
00154 }
00155 
00156 namespace vpr
00157 {
00158 
00159 vpr::ReturnStatus LibraryDYLD::load()
00160 {
00161    vpr::ReturnStatus status;
00162 
00163    if ( std::string("") != mName )
00164    {
00165       mLibrary = internalDlopen(mName.c_str(), RTLD_NOW | RTLD_GLOBAL);
00166    }
00167    else
00168    {
00169       mLibrary = internalDlopen(NULL, RTLD_NOW | RTLD_GLOBAL);
00170    }
00171 
00172    if ( NULL == mLibrary )
00173    {
00174       vprDEBUG_CONT(vprDBG_ALL, vprDBG_WARNING_LVL)
00175          << std::endl << vprDEBUG_FLUSH;
00176       vprDEBUG(vprDBG_ALL, vprDBG_WARNING_LVL)
00177          << clrOutNORM(clrYELLOW, "WARNING:") << " Could not load '" << mName
00178          << "'\n" << vprDEBUG_FLUSH;
00179       vprDEBUG_NEXT(vprDBG_ALL, vprDBG_WARNING_LVL)
00180          << internalDlerror() << std::endl << vprDEBUG_FLUSH;
00181       status.setCode(vpr::ReturnStatus::Fail);
00182    }
00183 
00184    return status;
00185 }
00186 
00187 vpr::ReturnStatus LibraryDYLD::unload()
00188 {
00189    vprASSERT(mLibrary != NULL && "No library to unload");
00190    vpr::ReturnStatus status;
00191 
00192    if ( internalDlclose(mLibrary) != 0 )
00193    {
00194       status.setCode(vpr::ReturnStatus::Fail);
00195    }
00196    else
00197    {
00198       mLibrary = NULL;
00199    }
00200 
00201    return status;
00202 }
00203 
00204 void* LibraryDYLD::findSymbolAndLibrary(const char* symbolName,
00205                                         LibraryDYLD& lib)
00206 {
00207    boost::ignore_unused_variable_warning(symbolName);
00208    boost::ignore_unused_variable_warning(lib);
00209    vprASSERT(false && "Not implemented yet");
00210    return NULL;
00211 }
00212 
00213 // Copied from dlopen() found in dlfcn_simple.c from dlcompat.
00214 void* LibraryDYLD::internalDlopen(const char* path, int mode)
00215 {
00216    void *module = 0;
00217    NSObjectFileImage ofi = 0;
00218    NSObjectFileImageReturnCode ofirc;
00219    static int (*make_private_module_public) (NSModule module) = 0;
00220    unsigned int flags =  NSLINKMODULE_OPTION_RETURN_ON_ERROR | NSLINKMODULE_OPTION_PRIVATE;
00221 
00222    /* If we got no path, the app wants the global namespace, use -1 as the marker
00223       in this case */
00224    if (!path)
00225       return (void *)-1;
00226 
00227    /* Create the object file image, works for things linked with the -bundle arg to ld */
00228    ofirc = NSCreateObjectFileImageFromFile(path, &ofi);
00229    switch (ofirc)
00230    {
00231       case NSObjectFileImageSuccess:
00232          /* It was okay, so use NSLinkModule to link in the image */
00233          if (!(mode & RTLD_LAZY)) flags += NSLINKMODULE_OPTION_BINDNOW;
00234          module = NSLinkModule(ofi, path,flags);
00235          /* Don't forget to destroy the object file image, unless you like leaks */
00236          NSDestroyObjectFileImage(ofi);
00237          /* If the mode was global, then change the module, this avoids
00238             multiply defined symbol errors to first load private then make
00239             global. Silly, isn't it. */
00240          if ((mode & RTLD_GLOBAL))
00241          {
00242            if (!make_private_module_public)
00243            {
00244              _dyld_func_lookup("__dyld_NSMakePrivateModulePublic", 
00245             (unsigned long *)&make_private_module_public);
00246            }
00247            make_private_module_public(module);
00248          }
00249          break;
00250       case NSObjectFileImageInappropriateFile:
00251          /* It may have been a dynamic library rather than a bundle, try to load it */
00252          module = (void *)NSAddImage(path, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
00253          break;
00254       case NSObjectFileImageFailure:
00255          error(0,"Object file setup failure :  \"%s\"", path);
00256          return 0;
00257       case NSObjectFileImageArch:
00258          error(0,"No object for this architecture :  \"%s\"", path);
00259          return 0;
00260       case NSObjectFileImageFormat:
00261          error(0,"Bad object file format :  \"%s\"", path);
00262          return 0;
00263       case NSObjectFileImageAccess:
00264          error(0,"Can't read object file :  \"%s\"", path);
00265          return 0;      
00266    }
00267    if (!module)
00268       error(0, "Can not open \"%s\"", path);
00269    return module;
00270 }
00271 
00272 // Copied from dlerror() found in dlfcn_simple.c from dlcompat.
00273 const char* LibraryDYLD::internalDlerror()
00274 {
00275    return error(1, (char *)NULL);
00276 }
00277 
00278 // Copied from dlclose() found in dlfcn_simple.c from dlcompat.
00279 int LibraryDYLD::internalDlclose(void* handle)
00280 {
00281    if ((((struct mach_header *)handle)->magic == MH_MAGIC) ||
00282       (((struct mach_header *)handle)->magic == MH_CIGAM))
00283    {
00284       error(-1, "Can't remove dynamic libraries on darwin");
00285       return 0;
00286    }
00287    if (!NSUnLinkModule(handle, 0))
00288    {
00289       error(0, "unable to unlink module %s", NSNameOfModule(handle));
00290       return 1;
00291    }
00292    return 0;
00293 }
00294 
00295 // Copied from dlsym found in dlfcn_simple.c from dlcompat.
00296 void* LibraryDYLD::internalDlsym(void* handle, const char* symbol)
00297 {
00298    int sym_len = strlen(symbol);
00299    void *value = NULL;
00300    char *malloc_sym = NULL;
00301    NSSymbol *nssym = 0;
00302    malloc_sym = malloc(sym_len + 2);
00303    if (malloc_sym)
00304    {
00305       sprintf(malloc_sym, "_%s", symbol);
00306       /* If the handle is -1, if is the app global context */
00307       if (handle == (void *)-1)
00308       {
00309          /* Global context, use NSLookupAndBindSymbol */
00310          if (NSIsSymbolNameDefined(malloc_sym))
00311          {
00312             nssym = NSLookupAndBindSymbol(malloc_sym);
00313          }
00314       }
00315       /* Now see if the handle is a struch mach_header* or not, use NSLookupSymbol in image
00316          for libraries, and NSLookupSymbolInModule for bundles */
00317       else
00318       {
00319          /* Check for both possible magic numbers depending on x86/ppc byte order */
00320          if ((((struct mach_header *)handle)->magic == MH_MAGIC) ||
00321             (((struct mach_header *)handle)->magic == MH_CIGAM))
00322          {
00323             if (NSIsSymbolNameDefinedInImage((struct mach_header *)handle, malloc_sym))
00324             {
00325                nssym = NSLookupSymbolInImage((struct mach_header *)handle,
00326                                       malloc_sym,
00327                                       NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
00328                                       | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
00329             }
00330    
00331          }
00332          else
00333          {
00334             nssym = NSLookupSymbolInModule(handle, malloc_sym);
00335          }
00336       }
00337       if (!nssym)
00338       {
00339          error(0, "Symbol \"%s\" Not found", symbol);
00340       }
00341       value = NSAddressOfSymbol(nssym);
00342       free(malloc_sym);
00343    }
00344    else
00345    {
00346       error(-1, "Unable to allocate memory");
00347    }
00348    return value;
00349 }
00350 
00351 } // End of vpr namespace

Generated on Thu Jan 4 10:52:09 2007 for VR Juggler Portable Runtime by  doxygen 1.5.1