/* dynamic_link is a common interface for searching for required symbols in an executable and dynamic libraries. dynamic_link provides certain guarantees: 1. Either all or none of the requested symbols are resolved. Moreover, if symbols are not resolved, the dynamic_link_descriptor table is not modified; 2. All returned symbols have secured life time: this means that none of them can be invalidated until dynamic_unlink is called; 3. Any loaded library is loaded only via the full path. The full path is that from which the runtime itself was loaded. (This is done to avoid security issues caused by loading libraries from insecure paths). dynamic_link searches for the requested symbols in three stages, stopping as soon as all of the symbols have been resolved. 1. Search the global scope: a. On Windows: dynamic_link tries to obtain the handle of the requested library and if it succeeds it resolves the symbols via that handle. b. On Linux: dynamic_link tries to search for the symbols in the global scope via the main program handle. If the symbols are present in the global scope their life time is not guaranteed (since dynamic_link does not know anything about the library from which they are exported). Therefore it tries to "pin" the symbols by obtaining the library name and reopening it. dlopen may fail to reopen the library in two cases: i. The symbols are exported from the executable. Currently dynamic _link cannot handle this situation, so it will not find these symbols in this step. ii. The necessary library has been unloaded and cannot be reloaded. It seems there is nothing that can be done in this case. No symbols are returned. 2. Dynamic load: an attempt is made to load the requested library via the full path. The full path used is that from which the runtime itself was loaded. If the library can be loaded, then an attempt is made to resolve the requested symbols in the newly loaded library. If the symbols are not found the library is unloaded. 3. Weak symbols: if weak symbols are available they are returned. */ OPEN_INTERNAL_NAMESPACE #if __TBB_WEAK_SYMBOLS_PRESENT || __TBB_DYNAMIC_LOAD_ENABLED #if !defined(DYNAMIC_LINK_WARNING) && !__TBB_WIN8UI_SUPPORT // Report runtime errors and continue. #define DYNAMIC_LINK_WARNING dynamic_link_warning static void dynamic_link_warning( dynamic_link_error_t code, ... ) { (void) code; } // library_warning #endif /* DYNAMIC_LINK_WARNING */ static bool resolve_symbols( dynamic_link_handle module, const dynamic_link_descriptor descriptors[], size_t required ) { LIBRARY_ASSERT( module != NULL, "Module handle is NULL" ); if ( module == NULL ) return false; #if __TBB_WEAK_SYMBOLS_PRESENT if ( !dlsym ) return false; #endif /* __TBB_WEAK_SYMBOLS_PRESENT */ const size_t n_desc=20; // Usually we don't have more than 20 descriptors per library LIBRARY_ASSERT( required <= n_desc, "Too many descriptors is required" ); if ( required > n_desc ) return false; pointer_to_handler h[n_desc]; for ( size_t k = 0; k < required; ++k ) { dynamic_link_descriptor const & desc = descriptors[k]; pointer_to_handler addr = (pointer_to_handler)dlsym( module, desc.name ); if ( !addr ) { return false; } h[k] = addr; } // Commit the entry points. // Cannot use memset here, because the writes must be atomic. for( size_t k = 0; k < required; ++k ) *descriptors[k].handler = h[k]; return true; }
void add_handle(const dynamic_link_handle &handle) { #if !__USE_TBB_ATOMICS int res = pthread_spin_lock( &my_lock ); LIBRARY_ASSERT( res==0, "pthread_spin_lock failed" ); #endif const size_t ind = my_size++; #if !__USE_TBB_ATOMICS res = pthread_spin_unlock( &my_lock ); LIBRARY_ASSERT( res==0, "pthread_spin_unlock failed" ); #endif LIBRARY_ASSERT( ind < MAX_LOADED_MODULES, "Too many modules are loaded" ); my_handles[ind] = handle; }
/* There is a security issue on Windows: LoadLibrary() may load and execute malicious code. See http://www.microsoft.com/technet/security/advisory/2269637.mspx for details. To avoid the issue, we have to pass full path (not just library name) to LoadLibrary. This function constructs full path to the specified library (it is assumed the library located side-by-side with the tbb.dll. The function constructs absolute path for given relative path. Important: Base directory is not current one, it is the directory tbb.dll loaded from. Example: Let us assume "tbb.dll" is located in "c:\program files\common\intel\" directory, e. g. absolute path of tbb library is "c:\program files\common\intel\tbb.dll". Absolute path for "tbbmalloc.dll" would be "c:\program files\common\intel\tbbmalloc.dll". Absolute path for "malloc\tbbmalloc.dll" would be "c:\program files\common\intel\malloc\tbbmalloc.dll". Arguments: in name -- Name of a file (may be with relative path; it must not be an absolute one). out path -- Buffer to save result (absolute path) to. in len -- Size of buffer. ret -- 0 -- Error occurred. > len -- Buffer too short, required size returned. otherwise -- Ok, number of characters (not counting terminating null) written to buffer. */ static size_t abs_path( char const * name, char * path, size_t len ) { // Get handle of our DLL first. HMODULE handle; BOOL brc = GetModuleHandleEx( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR)( & abs_path ), & handle ); if ( ! brc ) { // Error occurred. int err = GetLastError(); DYNAMIC_LINK_WARNING( dl_sys_fail, "GetModuleHandleEx", err ); return 0; } // if // Now get path to our DLL. DWORD drc = GetModuleFileName( handle, path, static_cast< DWORD >( len ) ); if ( drc == 0 ) { // Error occurred. int err = GetLastError(); DYNAMIC_LINK_WARNING( dl_sys_fail, "GetModuleFileName", err ); return drc; } // if if ( drc >= len ) { // Buffer too short. DYNAMIC_LINK_WARNING( dl_buff_too_small ); return drc; } // if // Find the position of the last backslash. char * backslash = path + drc; // backslash points behind the path. LIBRARY_ASSERT( * backslash == 0, NULL ); while ( backslash > path && * backslash != '\\' ) { -- backslash; } // while if ( backslash <= path ) { // Backslash not found. return 0; // Unbelievable. } // if // Now append name to construct the full path. LIBRARY_ASSERT( * backslash == '\\', NULL ); size_t rc = ( backslash + 1 - path ) + strlen( name ); if ( rc >= len ) { DYNAMIC_LINK_WARNING( dl_buff_too_small ); return rc + 1; } // if strcpy( backslash + 1, name ); LIBRARY_ASSERT( rc == strlen( path ), NULL ); return rc; } // abs_path
static dynamic_link_handle global_symbols_link( const wchar_t* library, const dynamic_link_descriptor descriptors[], size_t required ) { ::tbb::internal::suppress_unused_warning( library ); dynamic_link_handle library_handle; #if _WIN32 if ( GetModuleHandleEx( 0, library, &library_handle ) ) { if ( resolve_symbols( library_handle, descriptors, required ) ) return library_handle; else FreeLibrary( library_handle ); } #else /* _WIN32 */ #if !__TBB_DYNAMIC_LOAD_ENABLED /* only __TBB_WEAK_SYMBOLS_PRESENT is defined */ if ( !dlopen ) return 0; #endif /* !__TBB_DYNAMIC_LOAD_ENABLED */ library_handle = dlopen( NULL, RTLD_LAZY ); #if !__ANDROID__ // On Android dlopen( NULL ) returns NULL if it is called during dynamic module initialization. LIBRARY_ASSERT( library_handle, "The handle for the main program is NULL" ); #endif // Check existence of the first symbol only, then use it to find the library and load all necessary symbols. pointer_to_handler handler; dynamic_link_descriptor desc; desc.name = descriptors[0].name; desc.handler = &handler; if ( resolve_symbols( library_handle, &desc, 1 ) ) return pin_symbols( library_handle, desc, descriptors, required ); #endif /* _WIN32 */ return 0; }
static void init_dl_data() { init_ap_data(); #if !__USE_TBB_ATOMICS int res; res = pthread_spin_init( &handles.my_lock, PTHREAD_PROCESS_SHARED ); LIBRARY_ASSERT( res==0, "pthread_spin_init failed" ); #endif }
static void save_library_handle( dynamic_link_handle src, dynamic_link_handle *dst ) { LIBRARY_ASSERT( src, "The library handle to store must be non-zero" ); if ( dst ) *dst = src; #if __TBB_DYNAMIC_LOAD_ENABLED else handles.add( src ); #endif /* __TBB_DYNAMIC_LOAD_ENABLED */ }
//----------------------------------------------------------------------------- CPUTBuffer *CPUTAssetLibrary::GetConstantBuffer(const std::string &name) { // If we already have one by this name, then return it CPUTBuffer *pBuffer = FindConstantBuffer(name, true); LIBRARY_ASSERT(pBuffer, "Can't find constant buffer " + name); if(pBuffer != NULL) pBuffer->AddRef(); return pBuffer; }
void dynamic_unlink( dynamic_link_handle handle ) { if ( handle ) { #if __TBB_WEAK_SYMBOLS_PRESENT LIBRARY_ASSERT( dlclose != NULL, "dlopen is present but dlclose is NOT present!?" ); #endif /* __TBB_WEAK_SYMBOLS_PRESENT */ #if __TBB_DYNAMIC_LOAD_ENABLED dlclose( handle ); #endif /* __TBB_DYNAMIC_LOAD_ENABLED */ } }
bool dynamic_link( dynamic_link_handle module, const dynamic_link_descriptor descriptors[], size_t n, size_t required ) { LIBRARY_ASSERT( module != NULL, "Module handle is NULL" ); if ( module == NULL ) { return false; } // if pointer_to_handler *h = (pointer_to_handler*)alloca(n * sizeof(pointer_to_handler)); if ( required == ~(size_t)0 ) required = n; LIBRARY_ASSERT( required<=n, "Number of required entry points exceeds their total number" ); size_t k = 0; for ( ; k < n; ++k ) { dynamic_link_descriptor const & desc = descriptors[k]; #if _WIN32||_WIN64 FARPROC addr = GetProcAddress( module, desc.name ); if ( addr == NULL ) { int err = GetLastError(); DYNAMIC_LINK_WARNING( dl_sym_not_found, desc.name, err ); } // if h[k] = pointer_to_handler( addr ); #else /* !WIN */ void * addr = dlsym( module, desc.name ); if ( addr == NULL ) { char const * err = dlerror(); DYNAMIC_LINK_WARNING( dl_sym_not_found, desc.name, err ); } // if // Lvalue casting is used; this way icc -strict-ansi does not warn about nonstandard pointer conversion (void *&)h[k] = addr; #endif /* !WIN */ if ( !h[k] && k < required ) return false; } LIBRARY_ASSERT( k == n, "if required entries are initialized, all entries are expected to be walked"); // Commit the entry points. // Cannot use memset here, because the writes must be atomic. for( k = 0; k < n; ++k ) *descriptors[k].handler = h[k]; return true; }
bool dynamic_link( void* module, const dynamic_link_descriptor descriptors[], size_t n, size_t required ) { pointer_to_handler *h = (pointer_to_handler*)alloca(n * sizeof(pointer_to_handler)); if ( required == ~(size_t)0 ) required = n; LIBRARY_ASSERT( required<=n, "Number of required entry points exceeds their total number" ); size_t k = 0; for ( ; k < n; ++k ) { #if _WIN32||_WIN64 h[k] = pointer_to_handler(GetProcAddress( (HMODULE)module, descriptors[k].name )); #else // Lvalue casting is used; this way icc -strict-ansi does not warn about nonstandard pointer conversion (void *&)h[k] = dlsym( module, descriptors[k].name ); #endif /* _WIN32||_WIN64 */ if ( !h[k] && k < required ) return false; } LIBRARY_ASSERT( k == n, "if required entries are initialized, all entries are expected to be walked"); // Commit the entry points. // Cannot use memset here, because the writes must be atomic. for( k = 0; k < n; ++k ) *descriptors[k].handler = h[k]; return true; }
bool dynamic_link( dynamic_link_handle, const dynamic_link_descriptor descriptors[], size_t n, size_t required ) { if ( required == ~(size_t)0 ) required = n; LIBRARY_ASSERT( required<=n, "Number of required entry points exceeds their total number" ); size_t k = 0; // Check if the first required entries are present in what was loaded into our process while ( k < required && descriptors[k].ptr ) ++k; if ( k < required ) return false; // Commit all the entry points. for ( k = 0; k < n; ++k ) *descriptors[k].handler = (pointer_to_handler) descriptors[k].ptr; return true; }
//----------------------------------------------------------------------------- CPUTFont *CPUTAssetLibrary::GetFont(const std::string &name ) { // Resolve name to absolute path std::string absolutePathAndFilename; CPUTFileSystem::ResolveAbsolutePathAndFilename( (mFontDirectoryName + name), &absolutePathAndFilename); // If we already have one by this name, then return it CPUTFont *pFont = FindFont(absolutePathAndFilename, true); if(NULL==pFont) { CPUTFont *pFont = CPUTFont::Create( name, absolutePathAndFilename); LIBRARY_ASSERT(pFont, "Could not create font " + absolutePathAndFilename); if (pFont != NULL) AddFont(name, "", "", pFont); return pFont; } pFont->AddRef(); return pFont; }
//----------------------------------------------------------------------------- CPUTAnimation * CPUTAssetLibrary::GetAnimation( const std::string &name, bool nameIsFullPathAndFilename ) { std::string animationFileName; CPUTFileSystem::ResolveAbsolutePathAndFilename( nameIsFullPathAndFilename? name + ".anm" : (mAnimationSetDirectoryName + name + ".anm"), &animationFileName); // If we already have one by this name, then return it CPUTAnimation *pAnimation = FindAnimation(animationFileName,true); if(pAnimation == NULL) { CPUTAnimation *pAnimation = CPUTAnimation::Create(animationFileName); LIBRARY_ASSERT(pAnimation, "Could not create animation " + animationFileName); if (pAnimation != NULL) AddAnimationSet(animationFileName, "", "", pAnimation); return pAnimation; } pAnimation->AddRef(); return pAnimation; }
// TODO: All of these Get() functions look very similar. // Keep them all for their interface, but have them call a common function //----------------------------------------------------------------------------- CPUTMaterial *CPUTAssetLibrary::GetMaterial( const std::string &name, bool nameIsFullPathAndFilename ){ // Resolve name to absolute path before searching std::string absolutePathAndFilename; if (name[0] == '%') { absolutePathAndFilename = mSystemDirectoryName + "Material/" + name.substr(1) + ".mtl"; // TODO: Instead of having the Material/directory hardcoded here it could be set like the normal material directory. But then there would need to be a bunch new variables like SetSystemMaterialDirectory CPUTFileSystem::ResolveAbsolutePathAndFilename(absolutePathAndFilename, &absolutePathAndFilename); } else if( !nameIsFullPathAndFilename ) { CPUTFileSystem::ResolveAbsolutePathAndFilename( mMaterialDirectoryName + name + ".mtl", &absolutePathAndFilename); } else { absolutePathAndFilename = name; } CPUTMaterial *pMaterial = NULL; pMaterial = FindMaterial(absolutePathAndFilename, true); if( pMaterial ) { pMaterial->AddRef(); } else { pMaterial = CPUTMaterial::Create(absolutePathAndFilename); LIBRARY_ASSERT(pMaterial, "Failed creating material Effect."); if (pMaterial != NULL) { AddMaterial(absolutePathAndFilename, "", "", pMaterial); } } return pMaterial; }
bool prepare_full_path() { LIBRARY_ASSERT( _state==ap_only_cwd, NULL ); Dl_info dlinfo; int res = dladdr( (void*)&dynamic_unlink, &dlinfo ); if ( !res ) { char const * err = dlerror(); DYNAMIC_LINK_WARNING( dl_sys_fail, "dladdr", err ); return false; } size_t fname_len = strlen( dlinfo.dli_fname ); // Find the position of the last backslash. while ( fname_len>0 && dlinfo.dli_fname[fname_len-1]!='/' ) fname_len-=1; size_t rc; if ( dlinfo.dli_fname[0]=='/' ) { rc = 0; _len = fname_len; } else { rc = _len; _len += fname_len; } if ( fname_len>0 ) { if ( _len>PATH_MAX ) { DYNAMIC_LINK_WARNING( dl_buff_too_small ); return false; } memcpy( _path+rc, dlinfo.dli_fname, fname_len*sizeof(char) ); _path[_len]=0; } return true; }
static void init_ap_data() { #if _WIN32 // Get handle of our DLL first. HMODULE handle; BOOL brc = GetModuleHandleEx( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (PCWSTR)( & dynamic_link ), // any function inside the library can be used for the address & handle ); if ( !brc ) { // Error occurred. int err = GetLastError(); DYNAMIC_LINK_WARNING( dl_sys_fail, "GetModuleHandleEx", err ); return; } // Now get path to our DLL. DWORD drc = GetModuleFileName( handle, ap_data._path, static_cast< DWORD >( PATH_MAX ) ); if ( drc == 0 ) { // Error occurred. int err = GetLastError(); DYNAMIC_LINK_WARNING( dl_sys_fail, "GetModuleFileName", err ); return; } if ( drc >= PATH_MAX ) { // Buffer too short. DYNAMIC_LINK_WARNING( dl_buff_too_small ); return; } // Find the position of the last backslash. wchar_t *backslash = wcsrchr( ap_data._path, '\\' ); if ( !backslash ) { // Backslash not found. LIBRARY_ASSERT( backslash!=NULL, "Unbelievable."); return; } LIBRARY_ASSERT( backslash >= ap_data._path, "Unbelievable."); ap_data._len = (size_t)(backslash - ap_data._path) + 1; *(backslash+1) = 0; #else // Get the library path Dl_info dlinfo; int res = dladdr( (void*)&dynamic_link, &dlinfo ); // any function inside the library can be used for the address if ( !res ) { char const * err = dlerror(); DYNAMIC_LINK_WARNING( dl_sys_fail, "dladdr", err ); return; } else { LIBRARY_ASSERT( dlinfo.dli_fname!=NULL, "Unbelievable." ); } char const *slash = strrchr( dlinfo.dli_fname, '/' ); size_t fname_len=0; if ( slash ) { LIBRARY_ASSERT( slash >= dlinfo.dli_fname, "Unbelievable."); fname_len = (size_t)(slash - dlinfo.dli_fname) + 1; } size_t rc; if ( dlinfo.dli_fname[0]=='/' ) { // The library path is absolute rc = 0; ap_data._len = 0; } else { // The library path is relative so get the current working directory if ( !getcwd( ap_data._path, sizeof(ap_data._path)/sizeof(ap_data._path[0]) ) ) { DYNAMIC_LINK_WARNING( dl_buff_too_small ); return; } ap_data._len = strlen( ap_data._path ); ap_data._path[ap_data._len++]='/'; rc = ap_data._len; } if ( fname_len>0 ) { if ( ap_data._len>PATH_MAX ) { DYNAMIC_LINK_WARNING( dl_buff_too_small ); ap_data._len=0; return; } strncpy( ap_data._path+rc, dlinfo.dli_fname, fname_len ); ap_data._len += fname_len; ap_data._path[ap_data._len]=0; } #endif /* _WIN32 */ }
void add(const dynamic_link_handle &handle) { const size_t ind = my_size++; LIBRARY_ASSERT( ind < MAX_LOADED_MODULES, "Too many modules are loaded" ); my_handles[ind] = handle; }
static void pthread_assert( int error_code, const char* msg ) { LIBRARY_ASSERT( error_code == 0, msg ); }
static dynamic_link_handle pin_symbols( dynamic_link_handle library_handle, dynamic_link_descriptor desc, const dynamic_link_descriptor* descriptors, size_t required ) { ::tbb::internal::suppress_unused_warning( desc, descriptors, required ); #if __TBB_DYNAMIC_LOAD_ENABLED // It is supposed that all symbols are from the only one library // The library has been loaded by another module and contains at least one requested symbol. // But after we obtained the symbol the library can be unloaded by another thread // invalidating our symbol. Therefore we need to pin the library in memory. const char * dli_fname; #ifdef __CYGWIN__ MEMORY_BASIC_INFORMATION mbi; char path[MAX_PATH]; VirtualQuery((void*)&dynamic_link, &mbi, sizeof(mbi)); if(GetModuleFileNameA((HINSTANCE)mbi.AllocationBase, path, MAX_PATH)) { char posix_path[MAX_PATH]; cygwin_conv_path(CCP_WIN_A_TO_POSIX | CCP_RELATIVE, path, posix_path, MAX_PATH); dli_fname = posix_path; #else Dl_info info; // Get library's name from earlier found symbol if ( dladdr( (void*)*desc.handler, &info ) ) { dli_fname = info.dli_fname; #endif // Pin the library library_handle = dlopen( dli_fname, RTLD_LAZY ); if ( library_handle ) { // If original library was unloaded before we pinned it // and then another module loaded in its place, the earlier // found symbol would become invalid. So revalidate them. if ( !resolve_symbols( library_handle, descriptors, required ) ) { // Wrong library. dynamic_unlink(library_handle); library_handle = 0; } } else { char const * err = dlerror(); DYNAMIC_LINK_WARNING( dl_lib_not_found, dli_fname, err ); } } else { // The library have been unloaded by another thread library_handle = 0; } #endif /* __TBB_DYNAMIC_LOAD_ENABLED */ return library_handle; } #endif /* !_WIN32 */ static dynamic_link_handle global_symbols_link( const char* library, const dynamic_link_descriptor descriptors[], size_t required ) { ::tbb::internal::suppress_unused_warning( library ); dynamic_link_handle library_handle; #if _WIN32 if ( GetModuleHandleEx( 0, library, &library_handle ) ) { if ( resolve_symbols( library_handle, descriptors, required ) ) return library_handle; else FreeLibrary( library_handle ); } #else /* _WIN32 */ #if !__TBB_DYNAMIC_LOAD_ENABLED /* only __TBB_WEAK_SYMBOLS_PRESENT is defined */ if ( !dlopen ) return 0; #endif /* !__TBB_DYNAMIC_LOAD_ENABLED */ library_handle = dlopen( NULL, RTLD_LAZY ); #if !__ANDROID__ // On Android dlopen( NULL ) returns NULL if it is called during dynamic module initialization. LIBRARY_ASSERT( library_handle, "The handle for the main program is NULL" ); #endif // Check existence of the first symbol only, then use it to find the library and load all necessary symbols. pointer_to_handler handler; dynamic_link_descriptor desc; desc.name = descriptors[0].name; desc.handler = &handler; if ( resolve_symbols( library_handle, &desc, 1 ) ) return pin_symbols( library_handle, desc, descriptors, required ); #endif /* _WIN32 */ return 0; }
static void init_ap_data() { #if _WIN32 // Get handle of our DLL first. HMODULE handle; BOOL brc = GetModuleHandleEx( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR)( & dynamic_link ), // any function inside the library can be used for the address & handle ); if ( !brc ) { // Error occurred. int err = GetLastError(); DYNAMIC_LINK_WARNING( dl_sys_fail, "GetModuleHandleEx", err ); return; } // Now get path to our DLL. DWORD drc = GetModuleFileName( handle, ap_data._path, static_cast< DWORD >( PATH_MAX ) ); if ( drc == 0 ) { // Error occurred. int err = GetLastError(); DYNAMIC_LINK_WARNING( dl_sys_fail, "GetModuleFileName", err ); return; } if ( drc >= PATH_MAX ) { // Buffer too short. DYNAMIC_LINK_WARNING( dl_buff_too_small ); return; } // Find the position of the last backslash. char *backslash = strrchr( ap_data._path, '\\' ); if ( !backslash ) { // Backslash not found. LIBRARY_ASSERT( backslash!=NULL, "Unbelievable."); return; } LIBRARY_ASSERT( backslash >= ap_data._path, "Unbelievable."); ap_data._len = (size_t)(backslash - ap_data._path) + 1; *(backslash+1) = 0; #else // Get the library path /*Dl_info dlinfo; int res = dladdr( (void*)&dynamic_link, &dlinfo ); // any function inside the library can be used for the address if ( !res ) { char const * err = dlerror(); DYNAMIC_LINK_WARNING( dl_sys_fail, "dladdr", err ); return; } else { LIBRARY_ASSERT( dlinfo.dli_fname!=NULL, "Unbelievable." ); }*/ const char *dli_fname; #ifdef __CYGWIN__ MEMORY_BASIC_INFORMATION mbi; char path[MAX_PATH]; VirtualQuery((void*)&dynamic_link, &mbi, sizeof(mbi)); GetModuleFileNameA((HINSTANCE)mbi.AllocationBase, path, MAX_PATH); char posix_path[MAX_PATH]; cygwin_conv_path(CCP_WIN_A_TO_POSIX | CCP_RELATIVE, path, posix_path, MAX_PATH); dli_fname = posix_path; #else Dl_info dlinfo; int res = dladdr( (void*)&dynamic_link, &dlinfo ); // any function inside the library can be used for the address if ( !res ) { char const * err = dlerror(); DYNAMIC_LINK_WARNING( dl_sys_fail, "dladdr", err ); return; } else { LIBRARY_ASSERT( dlinfo.dli_fname!=NULL, "Unbelievable." ); } dli_fname = dlinfo.dli_fname; #endif char const *slash = strrchr( dli_fname, '/' ); size_t fname_len=0; if ( slash ) { LIBRARY_ASSERT( slash >= dli_fname, "Unbelievable."); fname_len = (size_t)(slash - dli_fname) + 1; } size_t rc; if ( dli_fname[0]=='/' ) { // The library path is absolute rc = 0; ap_data._len = 0; } else { // The library path is relative so get the current working directory if ( !getcwd( ap_data._path, sizeof(ap_data._path)/sizeof(ap_data._path[0]) ) ) { DYNAMIC_LINK_WARNING( dl_buff_too_small ); return; } ap_data._len = strlen( ap_data._path ); ap_data._path[ap_data._len++]='/'; rc = ap_data._len; } if ( fname_len>0 ) { if ( ap_data._len>PATH_MAX ) { DYNAMIC_LINK_WARNING( dl_buff_too_small ); ap_data._len=0; return; } strncpy( ap_data._path+rc, dli_fname, fname_len ); ap_data._len += fname_len; ap_data._path[ap_data._len]=0; } #endif /* _WIN32 */ }
~_static_init_dl_data() { int res; res = pthread_spin_destroy( &handles.my_lock ); LIBRARY_ASSERT( res==0, "pthread_spin_destroy failed" ); }