WvStreams
loader.cc
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
00002  *
00003  * XPLC - Cross-Platform Lightweight Components
00004  * Copyright (C) 2002, Net Integration Technologies, Inc.
00005  * Copyright (C) 2002-2004, Pierre Phaneuf
00006  * Copyright (C) 2002-2004, Stéphane Lajoie
00007  *
00008  * This library is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public License
00010  * as published by the Free Software Foundation; either version 2.1 of
00011  * the License, or (at your option) any later version.
00012  *
00013  * This library is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with this library; if not, write to the Free Software
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00021  * USA
00022  */
00023 
00024 #include <stdlib.h>
00025 #include <stdio.h>
00026 
00027 #include "config.h"
00028 #include "loader.h"
00029 
00030 #ifdef HAVE_DLFCN_H
00031 #include <dlfcn.h>
00032 #endif
00033 
00034 #ifdef HAVE_MACH_O_DYLD_H
00035 #include <mach-o/dyld.h>
00036 #endif
00037 
00038 #if defined(WITH_DLOPEN) && defined(ENABLE_LOADER)
00039 const char* loaderOpen(const char* aFilename,
00040                        void** aHandle) {
00041   const char* rv = 0;
00042 
00043   /* clear out dl error */
00044   static_cast<void>(dlerror());
00045 
00046   *aHandle = dlopen(aFilename, RTLD_NOW);
00047 
00048   if(!*aHandle)
00049     rv = dlerror();
00050 
00051   return rv;
00052 }
00053 
00054 const char* loaderSymbol(void* aHandle,
00055                          const char* aSymbol,
00056                          void** aPointer) {
00057   /* clear out dl error */
00058   static_cast<void>(dlerror());
00059 
00060   *aPointer = dlsym(aHandle, aSymbol);
00061 
00062   return dlerror();
00063 }
00064 
00065 bool loaderClose(void*& aHandle) {
00066   bool rv;
00067 
00068   rv = dlclose(aHandle) == 0;
00069   aHandle = 0;
00070 
00071   return rv;
00072 }
00073 
00074 #elif defined(WITH_DYLD) && defined(ENABLE_LOADER)
00075 
00076 const char* loaderOpen(const char* aFilename,
00077                        void** aHandle) {
00078   NSObjectFileImage ofi = 0;
00079   NSObjectFileImageReturnCode ofirc;
00080 
00081   ofirc = NSCreateObjectFileImageFromFile(aFilename, &ofi);
00082   switch(ofirc) {
00083   case NSObjectFileImageSuccess:
00084     *aHandle = NSLinkModule(ofi, aFilename,
00085                             NSLINKMODULE_OPTION_RETURN_ON_ERROR
00086                             | NSLINKMODULE_OPTION_PRIVATE
00087                             | NSLINKMODULE_OPTION_BINDNOW);
00088     NSDestroyObjectFileImage(ofi);
00089     break;
00090   case NSObjectFileImageInappropriateFile:
00091     *aHandle =
00092       const_cast<void*>(reinterpret_cast<const void*>(NSAddImage(aFilename, NSADDIMAGE_OPTION_RETURN_ON_ERROR)));
00093     break;
00094   default:
00095     return "could not open dynamic library";
00096     break;
00097   }
00098 
00099   return 0;
00100 }
00101 
00102 const char* loaderSymbol(void* aHandle,
00103                          const char* aSymbol,
00104                          void** aPointer) {
00105   int len = strlen(aSymbol);
00106   char* sym = static_cast<char*>(malloc(len + 2));
00107   NSSymbol* nssym = 0;
00108 
00109   snprintf(sym, len + 2, "_%s", aSymbol);
00110 
00111   /* Check for both possible magic numbers depending on x86/ppc byte order */
00112   if ((((struct mach_header *)aHandle)->magic == MH_MAGIC) ||
00113       (((struct mach_header *)aHandle)->magic == MH_CIGAM)) {
00114     if (NSIsSymbolNameDefinedInImage((struct mach_header *)aHandle, sym)) {
00115       nssym = (NSModule *)NSLookupSymbolInImage((struct mach_header *)aHandle,
00116                                     sym,
00117                                     NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
00118                                     | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
00119     }
00120   } else {
00121     nssym = (NSModule *)NSLookupSymbolInModule(aHandle, sym);
00122   }
00123 
00124   free(sym);
00125 
00126   if(!nssym) {
00127     *aPointer = 0;
00128     return "symbol not found";
00129   }
00130 
00131   return 0;
00132 }
00133 
00134 bool loaderClose(void*& aHandle) {
00135   aHandle = 0;
00136   return false;
00137 }
00138 
00139 #elif defined(WIN32)
00140 
00141 #include <windows.h>
00142 
00143 const char* getErrorMessage() {
00144   static char error[1024];
00145   FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), 0, error, sizeof(error), 0);
00146   return error;
00147 }
00148 
00149 const char* loaderOpen(const char* aFilename,
00150                        void** aHandle) {
00151   const char* rv = 0;
00152 
00153   UINT oldErrorMode = SetErrorMode(0);
00154   SetErrorMode(oldErrorMode | SEM_FAILCRITICALERRORS);
00155   *aHandle = LoadLibrary(aFilename);
00156   SetErrorMode(oldErrorMode);
00157 
00158   if(!*aHandle)
00159     rv = getErrorMessage();
00160 
00161   return rv;
00162 }
00163 
00164 const char* loaderSymbol(void* aHandle,
00165                          const char* aSymbol,
00166                          void** aPointer) {
00167   const char* rv = 0;
00168 
00169   *aPointer = (void *)GetProcAddress(static_cast<HMODULE>(aHandle), aSymbol);
00170 
00171   if(!aPointer)
00172     rv = getErrorMessage();
00173 
00174   return rv;
00175 }
00176 
00177 bool loaderClose(void*& aHandle) {
00178   bool rv;
00179 
00180   rv = FreeLibrary(static_cast<HMODULE>(aHandle)) != 0;
00181   aHandle = 0;
00182 
00183   return rv;
00184 }
00185 
00186 #else
00187 
00188 const char* loaderOpen(const char* aFilename,
00189                        void** aHandle) {
00190   *aHandle = 0;
00191   return "dynamic loading not supported on this platform";
00192 }
00193 
00194 const char* loaderSymbol(void* aHandle,
00195                          const char* aSymbol,
00196                          void** aPointer) {
00197   *aPointer = 0;
00198   return "dynamic loading not supported on this platform";
00199 }
00200 
00201 bool loaderClose(void*& aHandle) {
00202   aHandle = 0;
00203   return false;
00204 }
00205 
00206 #endif