Example #1
0
/*
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;
    }
Example #2
0
 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;
 }
Example #3
0
/*
    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
Example #4
0
    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;
    }
Example #5
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
 }
Example #6
0
 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;
}
Example #8
0
 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 */
     }
 }
Example #9
0
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;
}
Example #10
0
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;
}
Example #11
0
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;
}
Example #15
0
        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;
        }
Example #16
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,
            (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 */
    }
Example #17
0
 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;
 }
Example #18
0
 static void pthread_assert( int error_code, const char* msg ) {
     LIBRARY_ASSERT( error_code == 0, msg );
 }
Example #19
0
    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;
    }
Example #20
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 */
    }
Example #21
0
 ~_static_init_dl_data() {
     int res;
     res = pthread_spin_destroy( &handles.my_lock );
     LIBRARY_ASSERT( res==0, "pthread_spin_destroy failed" );
 }