OpenWalnut
1.4.0
|
00001 //--------------------------------------------------------------------------- 00002 // 00003 // Project: OpenWalnut ( http://www.openwalnut.org ) 00004 // 00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS 00006 // For more information see http://www.openwalnut.org/copying 00007 // 00008 // This file is part of OpenWalnut. 00009 // 00010 // OpenWalnut is free software: you can redistribute it and/or modify 00011 // it under the terms of the GNU Lesser General Public License as published by 00012 // the Free Software Foundation, either version 3 of the License, or 00013 // (at your option) any later version. 00014 // 00015 // OpenWalnut is distributed in the hope that it will be useful, 00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 // GNU Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public License 00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>. 00022 // 00023 //--------------------------------------------------------------------------- 00024 00025 #include <algorithm> 00026 #include <cassert> 00027 #include <string> 00028 00029 #ifdef _WIN32 00030 #include <iostream> 00031 #include <windows.h> // NOLINT 00032 #endif 00033 00034 #include <boost/filesystem.hpp> 00035 00036 #include "exceptions/WLibraryFetchFailed.h" 00037 #include "exceptions/WLibraryLoadFailed.h" 00038 #include "WSharedLib.h" 00039 00040 #ifdef _WIN32 00041 00042 /** 00043 * Simple class holding an opened library. 00044 */ 00045 struct WSharedLib::data 00046 { 00047 /** 00048 * Path of lib. 00049 */ 00050 const std::string m_path; 00051 00052 /** 00053 * Handle describing the loaded lib. 00054 */ 00055 HMODULE m_hDLL; 00056 00057 /** 00058 * Constructor. Opens and loads the library. 00059 * 00060 * \see WSharedLib::WSharedLib for details. 00061 * 00062 * \param path the lib to open 00063 */ 00064 explicit data( const std::string& path ): 00065 m_path( path ), 00066 m_hDLL( LoadLibrary( path.c_str() ) ) 00067 { 00068 if( !m_hDLL ) 00069 { 00070 throw WLibraryLoadFailed( std::string( "Could not load library \"" + m_path + "\" due to the error: " + errmsg() ) ); 00071 } 00072 } 00073 00074 /** 00075 * Destructor. Closes the previously opened library handle. 00076 */ 00077 ~data() 00078 { 00079 FreeLibrary( m_hDLL ); 00080 } 00081 00082 /** 00083 * Searches the lib for the specified function symbol and returns it. 00084 * 00085 * \param name the name of the function 00086 * 00087 * \return the pointer to the requested function 00088 * 00089 * \throw WLibraryFetchFailed thrown if the symbol could not be found. 00090 */ 00091 func_ptr_type findFunction( const std::string& name ) 00092 { 00093 func_ptr_type func_ptr = reinterpret_cast< func_ptr_type >( GetProcAddress( m_hDLL, name.c_str() ) ); 00094 if( !func_ptr ) 00095 { 00096 throw WLibraryFetchFailed( std::string( "Could not fetch symbol \"" + name + "\"" + " due to the error: " + errmsg() ) ); 00097 } 00098 return func_ptr; 00099 } 00100 00101 /** 00102 * Check for existence of a given function pointer symbol. 00103 * 00104 * \param name the symbol 00105 * 00106 * \return true if it exists. 00107 */ 00108 bool existsFunction( const std::string& name ) 00109 { 00110 func_ptr_type func_ptr = reinterpret_cast< func_ptr_type >( GetProcAddress( m_hDLL, name.c_str() ) ); 00111 return func_ptr; 00112 } 00113 00114 /** 00115 * Searches the lib for the specified function symbol and returns it. 00116 * 00117 * \param name the name of the function 00118 * 00119 * \return the pointer to the requested function 00120 * 00121 * \throw WLibraryFetchFailed thrown if the symbol could not be found. 00122 */ 00123 void* findVariable( const std::string& name ) 00124 { 00125 return reinterpret_cast< void* >( findFunction( name ) ); 00126 } 00127 00128 /** 00129 * Constructs a nice looking error message for the last error occurred. 00130 * 00131 * \return the last error message 00132 */ 00133 static std::string errmsg() 00134 { 00135 std::string msg; 00136 LPTSTR lpMsgBuf = 0; 00137 FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, GetLastError(), 0, 00138 reinterpret_cast< LPTSTR >( &lpMsgBuf ), 0, 0 ); 00139 LPTSTR p = lpMsgBuf; 00140 while( *p ) 00141 { 00142 msg.push_back( *p++ ); 00143 } 00144 LocalFree( lpMsgBuf ); 00145 return msg; 00146 } 00147 }; 00148 #else 00149 #include <dlfcn.h> // NOLINT 00150 #include <pthread.h> // NOLINT 00151 00152 namespace 00153 { 00154 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 00155 struct auto_lock 00156 { 00157 auto_lock() 00158 { 00159 pthread_mutex_lock( &mutex ); 00160 } 00161 ~auto_lock() 00162 { 00163 pthread_mutex_unlock( &mutex ); 00164 } 00165 }; 00166 } 00167 00168 /** 00169 * Simple class holding an opened library. 00170 */ 00171 struct WSharedLib::data 00172 { 00173 /** 00174 * Path of lib. 00175 */ 00176 const std::string m_path; 00177 00178 /** 00179 * Handle describing the loaded lib. 00180 */ 00181 void* m_dl; 00182 00183 /** 00184 * Destructor. Closes the previously opened library handle. 00185 */ 00186 ~data() 00187 { 00188 assert( dlclose( m_dl ) == 0 ); 00189 } 00190 00191 /** 00192 * Constructor. Opens and loads the library. 00193 * 00194 * \see WSharedLib::WSharedLib for details. 00195 * 00196 * \param path the lib to open 00197 */ 00198 explicit data( const std::string& path ) 00199 : m_path( path ), m_dl( 0 ) 00200 { 00201 auto_lock lock; 00202 m_dl = dlopen( m_path.c_str(), RTLD_LAZY ); 00203 if( !m_dl ) 00204 { 00205 throw WLibraryLoadFailed( std::string( "Could not load library \"" + m_path + "\" due to the error: " + dlerror() ) ); 00206 } 00207 } 00208 00209 /** 00210 * Searches the lib for the specified function symbol and returns it. 00211 * 00212 * \param name the name of the function 00213 * 00214 * \return the pointer to the requested function 00215 * 00216 * \throw WLibraryFetchFailed thrown if the symbol could not be found. 00217 */ 00218 func_ptr_type findFunction( const std::string& name ) 00219 { 00220 // This cast is supposed to throw a warning because the cast 00221 // of void* to function pointers is not defined or required 00222 // in ISO C. Nevertheless, it works on most current compilers. 00223 // 00224 // man dlsym talks about introducing a new function to circumvent 00225 // this problem. 00226 return reinterpret_cast< func_ptr_type >( findVariable( name ) ); 00227 } 00228 00229 /** 00230 * Searches the lib for the specified symbol and returns it. 00231 * 00232 * \param name the name of the symbol to search. 00233 * \param suppressThrow set to true to suppress the exception. NULL is returned if the symbol does not exists 00234 * 00235 * \return pointer to the symbol. 00236 * 00237 * \throw WLibraryFetchFailed thrown if the symbol could not be found. 00238 * 00239 */ 00240 void* findVariable( const std::string& name, bool suppressThrow = false ) 00241 { 00242 auto_lock lock; 00243 dlerror(); 00244 void* variable_ptr = dlsym( m_dl, name.c_str() ); 00245 const char *err = dlerror(); 00246 if( !suppressThrow && err ) 00247 { 00248 throw WLibraryFetchFailed( std::string( "Could not fetch symbol \"" + name + "\"" + " due to the error: " + err ) ); 00249 } 00250 return variable_ptr; 00251 } 00252 00253 /** 00254 * Check for existence of a given function pointer symbol. 00255 * 00256 * \param name the symbol 00257 * 00258 * \return true if it exists. 00259 */ 00260 bool existsFunction( const std::string& name ) 00261 { 00262 return findVariable( name, true ); 00263 } 00264 }; 00265 #endif 00266 00267 WSharedLib::WSharedLib( boost::filesystem::path lib ): 00268 m_data( new data( lib.string() ) ), 00269 m_libPath( lib ) 00270 { 00271 } 00272 00273 WSharedLib::WSharedLib( const WSharedLib& rhs ): 00274 m_data( new data( rhs.m_data->m_path ) ), 00275 m_libPath( rhs.m_libPath ) 00276 { 00277 } 00278 00279 WSharedLib::~WSharedLib() 00280 { 00281 delete m_data; 00282 } 00283 00284 WSharedLib& WSharedLib::operator=( const WSharedLib& rhs ) 00285 { 00286 WSharedLib o( rhs ); 00287 swap( *this, o ); 00288 return *this; 00289 } 00290 00291 void swap( WSharedLib& lhs, WSharedLib& rhs ) 00292 { 00293 std::swap( lhs.m_data, rhs.m_data ); 00294 } 00295 00296 WSharedLib::func_ptr_type WSharedLib::findFunction( const std::string& name ) const 00297 { 00298 return m_data->findFunction( name ); 00299 } 00300 00301 void* WSharedLib::findVariable( const std::string& name ) const 00302 { 00303 return m_data->findVariable( name ); 00304 } 00305 00306 bool WSharedLib::existsFunction( const std::string& name ) const 00307 { 00308 return m_data->existsFunction( name ); 00309 } 00310 00311 std::string WSharedLib::getSystemPrefix() 00312 { 00313 return W_LIB_PREFIX; 00314 } 00315 00316 std::string WSharedLib::getSystemSuffix() 00317 { 00318 return W_LIB_SUFFIX; 00319 } 00320 00321 std::string WSharedLib::getSystemLibPath() 00322 { 00323 return "../lib"; 00324 } 00325 00326 std::string WSharedLib::getLibraryName() 00327 { 00328 // we want to strip the search directory from the path 00329 std::string relPath( m_libPath.filename().string() ); 00330 return relPath; 00331 } 00332