mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-03 21:09:12 +00:00 
			
		
		
		
	Add dlfcn library for win32
This commit is contained in:
		
							parent
							
								
									518194fac1
								
							
						
					
					
						commit
						05218ec900
					
				
					 2 changed files with 914 additions and 0 deletions
				
			
		
							
								
								
									
										820
									
								
								libs/dlfcn-win32/dlfcn.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										820
									
								
								libs/dlfcn-win32/dlfcn.cc
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,820 @@
 | 
			
		|||
/*
 | 
			
		||||
 * dlfcn-win32
 | 
			
		||||
 * Copyright (c) 2007 Ramiro Polla
 | 
			
		||||
 * Copyright (c) 2015 Tiancheng "Timothy" Gu
 | 
			
		||||
 * Copyright (c) 2019 Pali Rohár <pali.rohar@gmail.com>
 | 
			
		||||
 * Copyright (c) 2020 Ralf Habacker <ralf.habacker@freenet.de>
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
 * of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
 * in the Software without restriction, including without limitation the rights
 | 
			
		||||
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
 * copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
 * furnished to do so, subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in
 | 
			
		||||
 * all copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 | 
			
		||||
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
 * THE SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifdef _DEBUG
 | 
			
		||||
#define _CRTDBG_MAP_ALLOC
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <crtdbg.h>
 | 
			
		||||
#endif
 | 
			
		||||
#include <windows.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
/* Older versions do not have this type */
 | 
			
		||||
#if _WIN32_WINNT < 0x0500
 | 
			
		||||
typedef ULONG ULONG_PTR;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Older SDK versions do not have these macros */
 | 
			
		||||
#ifndef GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
 | 
			
		||||
#define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 0x4
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT
 | 
			
		||||
#define GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT 0x2
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef _MSC_VER
 | 
			
		||||
/* https://docs.microsoft.com/en-us/cpp/intrinsics/returnaddress */
 | 
			
		||||
#pragma intrinsic( _ReturnAddress )
 | 
			
		||||
#else
 | 
			
		||||
/* https://gcc.gnu.org/onlinedocs/gcc/Return-Address.html */
 | 
			
		||||
#ifndef _ReturnAddress
 | 
			
		||||
#define _ReturnAddress( ) ( __builtin_extract_return_addr( __builtin_return_address( 0 ) ) )
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef DLFCN_WIN32_SHARED
 | 
			
		||||
#define DLFCN_WIN32_EXPORTS
 | 
			
		||||
#endif
 | 
			
		||||
#include "dlfcn.h"
 | 
			
		||||
 | 
			
		||||
#if defined( _MSC_VER ) && _MSC_VER >= 1300
 | 
			
		||||
/* https://docs.microsoft.com/en-us/cpp/cpp/noinline */
 | 
			
		||||
#define DLFCN_NOINLINE __declspec( noinline )
 | 
			
		||||
#elif defined( __GNUC__ ) && ( ( __GNUC__ > 3 ) || ( __GNUC__ == 3 && __GNUC_MINOR__ >= 1 ) )
 | 
			
		||||
/* https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html */
 | 
			
		||||
#define DLFCN_NOINLINE __attribute__(( noinline ))
 | 
			
		||||
#else
 | 
			
		||||
#define DLFCN_NOINLINE
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Note:
 | 
			
		||||
 * MSDN says these functions are not thread-safe. We make no efforts to have
 | 
			
		||||
 * any kind of thread safety.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
typedef struct local_object {
 | 
			
		||||
    HMODULE hModule;
 | 
			
		||||
    struct local_object *previous;
 | 
			
		||||
    struct local_object *next;
 | 
			
		||||
} local_object;
 | 
			
		||||
 | 
			
		||||
static local_object first_object;
 | 
			
		||||
 | 
			
		||||
/* These functions implement a double linked list for the local objects. */
 | 
			
		||||
static local_object *local_search( HMODULE hModule )
 | 
			
		||||
{
 | 
			
		||||
    local_object *pobject;
 | 
			
		||||
 | 
			
		||||
    if( hModule == NULL )
 | 
			
		||||
        return NULL;
 | 
			
		||||
 | 
			
		||||
    for( pobject = &first_object; pobject; pobject = pobject->next )
 | 
			
		||||
        if( pobject->hModule == hModule )
 | 
			
		||||
            return pobject;
 | 
			
		||||
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static BOOL local_add( HMODULE hModule )
 | 
			
		||||
{
 | 
			
		||||
    local_object *pobject;
 | 
			
		||||
    local_object *nobject;
 | 
			
		||||
 | 
			
		||||
    if( hModule == NULL )
 | 
			
		||||
        return TRUE;
 | 
			
		||||
 | 
			
		||||
    pobject = local_search( hModule );
 | 
			
		||||
 | 
			
		||||
    /* Do not add object again if it's already on the list */
 | 
			
		||||
    if( pobject != NULL )
 | 
			
		||||
        return TRUE;
 | 
			
		||||
 | 
			
		||||
    for( pobject = &first_object; pobject->next; pobject = pobject->next );
 | 
			
		||||
 | 
			
		||||
    nobject = (local_object *) malloc( sizeof( local_object ) );
 | 
			
		||||
 | 
			
		||||
    if( !nobject )
 | 
			
		||||
        return FALSE;
 | 
			
		||||
 | 
			
		||||
    pobject->next = nobject;
 | 
			
		||||
    nobject->next = NULL;
 | 
			
		||||
    nobject->previous = pobject;
 | 
			
		||||
    nobject->hModule = hModule;
 | 
			
		||||
 | 
			
		||||
    return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void local_rem( HMODULE hModule )
 | 
			
		||||
{
 | 
			
		||||
    local_object *pobject;
 | 
			
		||||
 | 
			
		||||
    if( hModule == NULL )
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    pobject = local_search( hModule );
 | 
			
		||||
 | 
			
		||||
    if( pobject == NULL )
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    if( pobject->next )
 | 
			
		||||
        pobject->next->previous = pobject->previous;
 | 
			
		||||
    if( pobject->previous )
 | 
			
		||||
        pobject->previous->next = pobject->next;
 | 
			
		||||
 | 
			
		||||
    free( pobject );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* POSIX says dlerror( ) doesn't have to be thread-safe, so we use one
 | 
			
		||||
 * static buffer.
 | 
			
		||||
 * MSDN says the buffer cannot be larger than 64K bytes, so we set it to
 | 
			
		||||
 * the limit.
 | 
			
		||||
 */
 | 
			
		||||
static char error_buffer[65535];
 | 
			
		||||
static BOOL error_occurred;
 | 
			
		||||
 | 
			
		||||
static void save_err_str( const char *str, DWORD dwMessageId )
 | 
			
		||||
{
 | 
			
		||||
    DWORD ret;
 | 
			
		||||
    size_t pos, len;
 | 
			
		||||
 | 
			
		||||
    len = strlen( str );
 | 
			
		||||
    if( len > sizeof( error_buffer ) - 5 )
 | 
			
		||||
        len = sizeof( error_buffer ) - 5;
 | 
			
		||||
 | 
			
		||||
    /* Format error message to:
 | 
			
		||||
     * "<argument to function that failed>": <Windows localized error message>
 | 
			
		||||
      */
 | 
			
		||||
    pos = 0;
 | 
			
		||||
    error_buffer[pos++] = '"';
 | 
			
		||||
    memcpy( error_buffer + pos, str, len );
 | 
			
		||||
    pos += len;
 | 
			
		||||
    error_buffer[pos++] = '"';
 | 
			
		||||
    error_buffer[pos++] = ':';
 | 
			
		||||
    error_buffer[pos++] = ' ';
 | 
			
		||||
 | 
			
		||||
    ret = FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwMessageId,
 | 
			
		||||
        MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
 | 
			
		||||
        error_buffer + pos, (DWORD) ( sizeof( error_buffer ) - pos ), NULL );
 | 
			
		||||
    pos += ret;
 | 
			
		||||
 | 
			
		||||
    /* When FormatMessageA() fails it returns zero and does not touch buffer
 | 
			
		||||
     * so add trailing null byte */
 | 
			
		||||
    if( ret == 0 )
 | 
			
		||||
        error_buffer[pos] = '\0';
 | 
			
		||||
 | 
			
		||||
    if( pos > 1 )
 | 
			
		||||
    {
 | 
			
		||||
        /* POSIX says the string must not have trailing <newline> */
 | 
			
		||||
        if( error_buffer[pos-2] == '\r' && error_buffer[pos-1] == '\n' )
 | 
			
		||||
            error_buffer[pos-2] = '\0';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    error_occurred = TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void save_err_ptr_str( const void *ptr, DWORD dwMessageId )
 | 
			
		||||
{
 | 
			
		||||
    char ptr_buf[2 + 2 * sizeof( ptr ) + 1];
 | 
			
		||||
    char num;
 | 
			
		||||
    size_t i;
 | 
			
		||||
 | 
			
		||||
    ptr_buf[0] = '0';
 | 
			
		||||
    ptr_buf[1] = 'x';
 | 
			
		||||
 | 
			
		||||
    for( i = 0; i < 2 * sizeof( ptr ); i++ )
 | 
			
		||||
    {
 | 
			
		||||
        num = (char) ( ( ( (ULONG_PTR) ptr ) >> ( 8 * sizeof( ptr ) - 4 * ( i + 1 ) ) ) & 0xF );
 | 
			
		||||
        ptr_buf[2 + i] = num + ( ( num < 0xA ) ? '0' : ( 'A' - 0xA ) );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ptr_buf[2 + 2 * sizeof( ptr )] = 0;
 | 
			
		||||
 | 
			
		||||
    save_err_str( ptr_buf, dwMessageId );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static UINT MySetErrorMode( UINT uMode )
 | 
			
		||||
{
 | 
			
		||||
    static BOOL (WINAPI *SetThreadErrorModePtr)(DWORD, DWORD *) = NULL;
 | 
			
		||||
    static BOOL failed = FALSE;
 | 
			
		||||
    HMODULE kernel32;
 | 
			
		||||
    DWORD oldMode;
 | 
			
		||||
 | 
			
		||||
    if( !failed && SetThreadErrorModePtr == NULL )
 | 
			
		||||
    {
 | 
			
		||||
        kernel32 = GetModuleHandleA( "Kernel32.dll" );
 | 
			
		||||
        if( kernel32 != NULL )
 | 
			
		||||
            SetThreadErrorModePtr = (BOOL (WINAPI *)(DWORD, DWORD *)) (LPVOID) GetProcAddress( kernel32, "SetThreadErrorMode" );
 | 
			
		||||
        if( SetThreadErrorModePtr == NULL )
 | 
			
		||||
            failed = TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if( !failed )
 | 
			
		||||
    {
 | 
			
		||||
        if( !SetThreadErrorModePtr( uMode, &oldMode ) )
 | 
			
		||||
            return 0;
 | 
			
		||||
        else
 | 
			
		||||
            return oldMode;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        return SetErrorMode( uMode );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static HMODULE MyGetModuleHandleFromAddress( const void *addr )
 | 
			
		||||
{
 | 
			
		||||
    static BOOL (WINAPI *GetModuleHandleExAPtr)(DWORD, LPCSTR, HMODULE *) = NULL;
 | 
			
		||||
    static BOOL failed = FALSE;
 | 
			
		||||
    HMODULE kernel32;
 | 
			
		||||
    HMODULE hModule;
 | 
			
		||||
    MEMORY_BASIC_INFORMATION info;
 | 
			
		||||
    SIZE_T sLen;
 | 
			
		||||
 | 
			
		||||
    if( !failed && GetModuleHandleExAPtr == NULL )
 | 
			
		||||
    {
 | 
			
		||||
        kernel32 = GetModuleHandleA( "Kernel32.dll" );
 | 
			
		||||
        if( kernel32 != NULL )
 | 
			
		||||
            GetModuleHandleExAPtr = (BOOL (WINAPI *)(DWORD, LPCSTR, HMODULE *)) (LPVOID) GetProcAddress( kernel32, "GetModuleHandleExA" );
 | 
			
		||||
        if( GetModuleHandleExAPtr == NULL )
 | 
			
		||||
            failed = TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if( !failed )
 | 
			
		||||
    {
 | 
			
		||||
        /* If GetModuleHandleExA is available use it with GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS */
 | 
			
		||||
        if( !GetModuleHandleExAPtr( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (const char *)addr, &hModule ) )
 | 
			
		||||
            return NULL;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        /* To get HMODULE from address use undocumented hack from https://stackoverflow.com/a/2396380
 | 
			
		||||
         * The HMODULE of a DLL is the same value as the module's base address.
 | 
			
		||||
         */
 | 
			
		||||
        sLen = VirtualQuery( addr, &info, sizeof( info ) );
 | 
			
		||||
        if( sLen != sizeof( info ) )
 | 
			
		||||
            return NULL;
 | 
			
		||||
        hModule = (HMODULE) info.AllocationBase;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return hModule;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Load Psapi.dll at runtime, this avoids linking caveat */
 | 
			
		||||
static BOOL MyEnumProcessModules( HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded )
 | 
			
		||||
{
 | 
			
		||||
    static BOOL (WINAPI *EnumProcessModulesPtr)(HANDLE, HMODULE *, DWORD, LPDWORD) = NULL;
 | 
			
		||||
    static BOOL failed = FALSE;
 | 
			
		||||
    UINT uMode;
 | 
			
		||||
    HMODULE psapi;
 | 
			
		||||
 | 
			
		||||
    if( failed )
 | 
			
		||||
        return FALSE;
 | 
			
		||||
 | 
			
		||||
    if( EnumProcessModulesPtr == NULL )
 | 
			
		||||
    {
 | 
			
		||||
        /* Windows 7 and newer versions have K32EnumProcessModules in Kernel32.dll which is always pre-loaded */
 | 
			
		||||
        psapi = GetModuleHandleA( "Kernel32.dll" );
 | 
			
		||||
        if( psapi != NULL )
 | 
			
		||||
            EnumProcessModulesPtr = (BOOL (WINAPI *)(HANDLE, HMODULE *, DWORD, LPDWORD)) (LPVOID) GetProcAddress( psapi, "K32EnumProcessModules" );
 | 
			
		||||
 | 
			
		||||
        /* Windows Vista and older version have EnumProcessModules in Psapi.dll which needs to be loaded */
 | 
			
		||||
        if( EnumProcessModulesPtr == NULL )
 | 
			
		||||
        {
 | 
			
		||||
            /* Do not let Windows display the critical-error-handler message box */
 | 
			
		||||
            uMode = MySetErrorMode( SEM_FAILCRITICALERRORS );
 | 
			
		||||
            psapi = LoadLibraryA( "Psapi.dll" );
 | 
			
		||||
            if( psapi != NULL )
 | 
			
		||||
            {
 | 
			
		||||
                EnumProcessModulesPtr = (BOOL (WINAPI *)(HANDLE, HMODULE *, DWORD, LPDWORD)) (LPVOID) GetProcAddress( psapi, "EnumProcessModules" );
 | 
			
		||||
                if( EnumProcessModulesPtr == NULL )
 | 
			
		||||
                    FreeLibrary( psapi );
 | 
			
		||||
            }
 | 
			
		||||
            MySetErrorMode( uMode );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if( EnumProcessModulesPtr == NULL )
 | 
			
		||||
        {
 | 
			
		||||
            failed = TRUE;
 | 
			
		||||
            return FALSE;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return EnumProcessModulesPtr( hProcess, lphModule, cb, lpcbNeeded );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DLFCN_EXPORT
 | 
			
		||||
void *dlopen( const char *file, int mode )
 | 
			
		||||
{
 | 
			
		||||
    HMODULE hModule;
 | 
			
		||||
    UINT uMode;
 | 
			
		||||
 | 
			
		||||
    error_occurred = FALSE;
 | 
			
		||||
 | 
			
		||||
    /* Do not let Windows display the critical-error-handler message box */
 | 
			
		||||
    uMode = MySetErrorMode( SEM_FAILCRITICALERRORS );
 | 
			
		||||
 | 
			
		||||
    if( file == NULL )
 | 
			
		||||
    {
 | 
			
		||||
        /* POSIX says that if the value of file is NULL, a handle on a global
 | 
			
		||||
         * symbol object must be provided. That object must be able to access
 | 
			
		||||
         * all symbols from the original program file, and any objects loaded
 | 
			
		||||
         * with the RTLD_GLOBAL flag.
 | 
			
		||||
         * The return value from GetModuleHandle( ) allows us to retrieve
 | 
			
		||||
         * symbols only from the original program file. EnumProcessModules() is
 | 
			
		||||
         * used to access symbols from other libraries. For objects loaded
 | 
			
		||||
         * with the RTLD_LOCAL flag, we create our own list later on. They are
 | 
			
		||||
         * excluded from EnumProcessModules() iteration.
 | 
			
		||||
         */
 | 
			
		||||
        hModule = GetModuleHandle( NULL );
 | 
			
		||||
 | 
			
		||||
        if( !hModule )
 | 
			
		||||
            save_err_str( "(null)", GetLastError( ) );
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        HANDLE hCurrentProc;
 | 
			
		||||
        DWORD dwProcModsBefore, dwProcModsAfter;
 | 
			
		||||
        char lpFileName[MAX_PATH];
 | 
			
		||||
        size_t i, len;
 | 
			
		||||
 | 
			
		||||
        len = strlen( file );
 | 
			
		||||
 | 
			
		||||
        if( len >= sizeof( lpFileName ) )
 | 
			
		||||
        {
 | 
			
		||||
            save_err_str( file, ERROR_FILENAME_EXCED_RANGE );
 | 
			
		||||
            hModule = NULL;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            /* MSDN says backslashes *must* be used instead of forward slashes. */
 | 
			
		||||
            for( i = 0; i < len; i++ )
 | 
			
		||||
            {
 | 
			
		||||
                if( file[i] == '/' )
 | 
			
		||||
                    lpFileName[i] = '\\';
 | 
			
		||||
                else
 | 
			
		||||
                    lpFileName[i] = file[i];
 | 
			
		||||
            }
 | 
			
		||||
            lpFileName[len] = '\0';
 | 
			
		||||
 | 
			
		||||
            hCurrentProc = GetCurrentProcess( );
 | 
			
		||||
 | 
			
		||||
            if( MyEnumProcessModules( hCurrentProc, NULL, 0, &dwProcModsBefore ) == 0 )
 | 
			
		||||
                dwProcModsBefore = 0;
 | 
			
		||||
 | 
			
		||||
            /* POSIX says the search path is implementation-defined.
 | 
			
		||||
             * LOAD_WITH_ALTERED_SEARCH_PATH is used to make it behave more closely
 | 
			
		||||
             * to UNIX's search paths (start with system folders instead of current
 | 
			
		||||
             * folder).
 | 
			
		||||
             */
 | 
			
		||||
            hModule = LoadLibraryExA( lpFileName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH );
 | 
			
		||||
 | 
			
		||||
            if( !hModule )
 | 
			
		||||
            {
 | 
			
		||||
                save_err_str( lpFileName, GetLastError( ) );
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                if( MyEnumProcessModules( hCurrentProc, NULL, 0, &dwProcModsAfter ) == 0 )
 | 
			
		||||
                    dwProcModsAfter = 0;
 | 
			
		||||
 | 
			
		||||
                /* If the object was loaded with RTLD_LOCAL, add it to list of local
 | 
			
		||||
                 * objects, so that its symbols cannot be retrieved even if the handle for
 | 
			
		||||
                 * the original program file is passed. POSIX says that if the same
 | 
			
		||||
                 * file is specified in multiple invocations, and any of them are
 | 
			
		||||
                 * RTLD_GLOBAL, even if any further invocations use RTLD_LOCAL, the
 | 
			
		||||
                 * symbols will remain global. If number of loaded modules was not
 | 
			
		||||
                 * changed after calling LoadLibraryEx(), it means that library was
 | 
			
		||||
                 * already loaded.
 | 
			
		||||
                 */
 | 
			
		||||
                if( (mode & RTLD_LOCAL) && dwProcModsBefore != dwProcModsAfter )
 | 
			
		||||
                {
 | 
			
		||||
                    if( !local_add( hModule ) )
 | 
			
		||||
                    {
 | 
			
		||||
                        save_err_str( lpFileName, ERROR_NOT_ENOUGH_MEMORY );
 | 
			
		||||
                        FreeLibrary( hModule );
 | 
			
		||||
                        hModule = NULL;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else if( !(mode & RTLD_LOCAL) && dwProcModsBefore == dwProcModsAfter )
 | 
			
		||||
                {
 | 
			
		||||
                    local_rem( hModule );
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Return to previous state of the error-mode bit flags. */
 | 
			
		||||
    MySetErrorMode( uMode );
 | 
			
		||||
 | 
			
		||||
    return (void *) hModule;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DLFCN_EXPORT
 | 
			
		||||
int dlclose( void *handle )
 | 
			
		||||
{
 | 
			
		||||
    HMODULE hModule = (HMODULE) handle;
 | 
			
		||||
    BOOL ret;
 | 
			
		||||
 | 
			
		||||
    error_occurred = FALSE;
 | 
			
		||||
 | 
			
		||||
    ret = FreeLibrary( hModule );
 | 
			
		||||
 | 
			
		||||
    /* If the object was loaded with RTLD_LOCAL, remove it from list of local
 | 
			
		||||
     * objects.
 | 
			
		||||
     */
 | 
			
		||||
    if( ret )
 | 
			
		||||
        local_rem( hModule );
 | 
			
		||||
    else
 | 
			
		||||
        save_err_ptr_str( handle, GetLastError( ) );
 | 
			
		||||
 | 
			
		||||
    /* dlclose's return value in inverted in relation to FreeLibrary's. */
 | 
			
		||||
    ret = !ret;
 | 
			
		||||
 | 
			
		||||
    return (int) ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DLFCN_NOINLINE /* Needed for _ReturnAddress() */
 | 
			
		||||
DLFCN_EXPORT
 | 
			
		||||
void *dlsym( void *handle, const char *name )
 | 
			
		||||
{
 | 
			
		||||
    FARPROC symbol;
 | 
			
		||||
    HMODULE hCaller;
 | 
			
		||||
    HMODULE hModule;
 | 
			
		||||
    DWORD dwMessageId;
 | 
			
		||||
 | 
			
		||||
    error_occurred = FALSE;
 | 
			
		||||
 | 
			
		||||
    symbol = NULL;
 | 
			
		||||
    hCaller = NULL;
 | 
			
		||||
    hModule = GetModuleHandle( NULL );
 | 
			
		||||
    dwMessageId = 0;
 | 
			
		||||
 | 
			
		||||
    if( handle == RTLD_DEFAULT )
 | 
			
		||||
    {
 | 
			
		||||
        /* The symbol lookup happens in the normal global scope; that is,
 | 
			
		||||
         * a search for a symbol using this handle would find the same
 | 
			
		||||
         * definition as a direct use of this symbol in the program code.
 | 
			
		||||
         * So use same lookup procedure as when filename is NULL.
 | 
			
		||||
         */
 | 
			
		||||
        handle = hModule;
 | 
			
		||||
    }
 | 
			
		||||
    else if( handle == RTLD_NEXT )
 | 
			
		||||
    {
 | 
			
		||||
        /* Specifies the next object after this one that defines name.
 | 
			
		||||
         * This one refers to the object containing the invocation of dlsym().
 | 
			
		||||
         * The next object is the one found upon the application of a load
 | 
			
		||||
         * order symbol resolution algorithm. To get caller function of dlsym()
 | 
			
		||||
         * use _ReturnAddress() intrinsic. To get HMODULE of caller function
 | 
			
		||||
         * use MyGetModuleHandleFromAddress() which calls either standard
 | 
			
		||||
         * GetModuleHandleExA() function or hack via VirtualQuery().
 | 
			
		||||
         */
 | 
			
		||||
        hCaller = MyGetModuleHandleFromAddress( _ReturnAddress( ) );
 | 
			
		||||
 | 
			
		||||
        if( hCaller == NULL )
 | 
			
		||||
        {
 | 
			
		||||
            dwMessageId = ERROR_INVALID_PARAMETER;
 | 
			
		||||
            goto end;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if( handle != RTLD_NEXT )
 | 
			
		||||
    {
 | 
			
		||||
        symbol = GetProcAddress( (HMODULE) handle, name );
 | 
			
		||||
 | 
			
		||||
        if( symbol != NULL )
 | 
			
		||||
            goto end;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* If the handle for the original program file is passed, also search
 | 
			
		||||
     * in all globally loaded objects.
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    if( hModule == handle || handle == RTLD_NEXT )
 | 
			
		||||
    {
 | 
			
		||||
        HANDLE hCurrentProc;
 | 
			
		||||
        HMODULE *modules;
 | 
			
		||||
        DWORD cbNeeded;
 | 
			
		||||
        DWORD dwSize;
 | 
			
		||||
        size_t i;
 | 
			
		||||
 | 
			
		||||
        hCurrentProc = GetCurrentProcess( );
 | 
			
		||||
 | 
			
		||||
        /* GetModuleHandle( NULL ) only returns the current program file. So
 | 
			
		||||
         * if we want to get ALL loaded module including those in linked DLLs,
 | 
			
		||||
         * we have to use EnumProcessModules( ).
 | 
			
		||||
         */
 | 
			
		||||
        if( MyEnumProcessModules( hCurrentProc, NULL, 0, &dwSize ) != 0 )
 | 
			
		||||
        {
 | 
			
		||||
            modules = (HMODULE *)malloc( dwSize );
 | 
			
		||||
            if( modules )
 | 
			
		||||
            {
 | 
			
		||||
                if( MyEnumProcessModules( hCurrentProc, modules, dwSize, &cbNeeded ) != 0 && dwSize == cbNeeded )
 | 
			
		||||
                {
 | 
			
		||||
                    for( i = 0; i < dwSize / sizeof( HMODULE ); i++ )
 | 
			
		||||
                    {
 | 
			
		||||
                        if( handle == RTLD_NEXT && hCaller )
 | 
			
		||||
                        {
 | 
			
		||||
                            /* Next modules can be used for RTLD_NEXT */
 | 
			
		||||
                            if( hCaller == modules[i] )
 | 
			
		||||
                                hCaller = NULL;
 | 
			
		||||
                            continue;
 | 
			
		||||
                        }
 | 
			
		||||
                        if( local_search( modules[i] ) )
 | 
			
		||||
                            continue;
 | 
			
		||||
                        symbol = GetProcAddress( modules[i], name );
 | 
			
		||||
                        if( symbol != NULL )
 | 
			
		||||
                        {
 | 
			
		||||
                            free( modules );
 | 
			
		||||
                            goto end;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                }
 | 
			
		||||
                free( modules );
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                dwMessageId = ERROR_NOT_ENOUGH_MEMORY;
 | 
			
		||||
                goto end;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
end:
 | 
			
		||||
    if( symbol == NULL )
 | 
			
		||||
    {
 | 
			
		||||
        if( !dwMessageId )
 | 
			
		||||
            dwMessageId = ERROR_PROC_NOT_FOUND;
 | 
			
		||||
        save_err_str( name, dwMessageId );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return *(void **) (&symbol);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DLFCN_EXPORT
 | 
			
		||||
char *dlerror( void )
 | 
			
		||||
{
 | 
			
		||||
    /* If this is the second consecutive call to dlerror, return NULL */
 | 
			
		||||
    if( !error_occurred )
 | 
			
		||||
        return NULL;
 | 
			
		||||
 | 
			
		||||
    /* POSIX says that invoking dlerror( ) a second time, immediately following
 | 
			
		||||
     * a prior invocation, shall result in NULL being returned.
 | 
			
		||||
     */
 | 
			
		||||
    error_occurred = FALSE;
 | 
			
		||||
 | 
			
		||||
    return error_buffer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* See https://docs.microsoft.com/en-us/archive/msdn-magazine/2002/march/inside-windows-an-in-depth-look-into-the-win32-portable-executable-file-format-part-2
 | 
			
		||||
 * for details */
 | 
			
		||||
 | 
			
		||||
/* Get specific image section */
 | 
			
		||||
static BOOL get_image_section( HMODULE module, int index, void **ptr, DWORD *size )
 | 
			
		||||
{
 | 
			
		||||
    IMAGE_DOS_HEADER *dosHeader;
 | 
			
		||||
    IMAGE_NT_HEADERS *ntHeaders;
 | 
			
		||||
    IMAGE_OPTIONAL_HEADER *optionalHeader;
 | 
			
		||||
 | 
			
		||||
    dosHeader = (IMAGE_DOS_HEADER *) module;
 | 
			
		||||
 | 
			
		||||
    if( dosHeader->e_magic != IMAGE_DOS_SIGNATURE )
 | 
			
		||||
        return FALSE;
 | 
			
		||||
 | 
			
		||||
    ntHeaders = (IMAGE_NT_HEADERS *) ( (BYTE *) dosHeader + dosHeader->e_lfanew );
 | 
			
		||||
 | 
			
		||||
    if( ntHeaders->Signature != IMAGE_NT_SIGNATURE )
 | 
			
		||||
        return FALSE;
 | 
			
		||||
 | 
			
		||||
    optionalHeader = &ntHeaders->OptionalHeader;
 | 
			
		||||
 | 
			
		||||
    if( optionalHeader->Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC )
 | 
			
		||||
        return FALSE;
 | 
			
		||||
 | 
			
		||||
    if( index < 0 || index > IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR )
 | 
			
		||||
        return FALSE;
 | 
			
		||||
 | 
			
		||||
    if( optionalHeader->DataDirectory[index].Size == 0 || optionalHeader->DataDirectory[index].VirtualAddress == 0 )
 | 
			
		||||
        return FALSE;
 | 
			
		||||
 | 
			
		||||
    if( size != NULL )
 | 
			
		||||
        *size = optionalHeader->DataDirectory[index].Size;
 | 
			
		||||
 | 
			
		||||
    *ptr = (void *)( (BYTE *) module + optionalHeader->DataDirectory[index].VirtualAddress );
 | 
			
		||||
 | 
			
		||||
    return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Return symbol name for a given address from export table */
 | 
			
		||||
static const char *get_export_symbol_name( HMODULE module, IMAGE_EXPORT_DIRECTORY *ied, const void *addr, void **func_address )
 | 
			
		||||
{
 | 
			
		||||
    DWORD i;
 | 
			
		||||
    void *candidateAddr = NULL;
 | 
			
		||||
    int candidateIndex = -1;
 | 
			
		||||
    BYTE *base = (BYTE *) module;
 | 
			
		||||
    DWORD *functionAddressesOffsets = (DWORD *) (base + ied->AddressOfFunctions);
 | 
			
		||||
    DWORD *functionNamesOffsets = (DWORD *) (base + ied->AddressOfNames);
 | 
			
		||||
    USHORT *functionNameOrdinalsIndexes = (USHORT *) (base + ied->AddressOfNameOrdinals);
 | 
			
		||||
 | 
			
		||||
    for( i = 0; i < ied->NumberOfFunctions; i++ )
 | 
			
		||||
    {
 | 
			
		||||
        if( (void *) ( base + functionAddressesOffsets[i] ) > addr || candidateAddr >= (void *) ( base + functionAddressesOffsets[i] ) )
 | 
			
		||||
            continue;
 | 
			
		||||
 | 
			
		||||
        candidateAddr = (void *) ( base + functionAddressesOffsets[i] );
 | 
			
		||||
        candidateIndex = i;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if( candidateIndex == -1 )
 | 
			
		||||
        return NULL;
 | 
			
		||||
 | 
			
		||||
    *func_address = candidateAddr;
 | 
			
		||||
 | 
			
		||||
    for( i = 0; i < ied->NumberOfNames; i++ )
 | 
			
		||||
    {
 | 
			
		||||
        if( functionNameOrdinalsIndexes[i] == candidateIndex )
 | 
			
		||||
            return (const char *) ( base + functionNamesOffsets[i] );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static BOOL is_valid_address( const void *addr )
 | 
			
		||||
{
 | 
			
		||||
    MEMORY_BASIC_INFORMATION info;
 | 
			
		||||
    SIZE_T result;
 | 
			
		||||
 | 
			
		||||
    if( addr == NULL )
 | 
			
		||||
        return FALSE;
 | 
			
		||||
 | 
			
		||||
    /* check valid pointer */
 | 
			
		||||
    result = VirtualQuery( addr, &info, sizeof( info ) );
 | 
			
		||||
 | 
			
		||||
    if( result == 0 || info.AllocationBase == NULL || info.AllocationProtect == 0 || info.AllocationProtect == PAGE_NOACCESS )
 | 
			
		||||
        return FALSE;
 | 
			
		||||
 | 
			
		||||
    return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Return state if address points to an import thunk
 | 
			
		||||
 *
 | 
			
		||||
 * An import thunk is setup with a 'jmp' instruction followed by an
 | 
			
		||||
 * absolute address (32bit) or relative offset (64bit) pointing into
 | 
			
		||||
 * the import address table (iat), which is partially maintained by
 | 
			
		||||
 * the runtime linker.
 | 
			
		||||
 */
 | 
			
		||||
static BOOL is_import_thunk( const void *addr )
 | 
			
		||||
{
 | 
			
		||||
    return *(short *) addr == 0x25ff ? TRUE : FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Return adress from the import address table (iat),
 | 
			
		||||
 * if the original address points to a thunk table entry.
 | 
			
		||||
 */
 | 
			
		||||
static void *get_address_from_import_address_table( void *iat, DWORD iat_size, const void *addr )
 | 
			
		||||
{
 | 
			
		||||
    BYTE *thkp = (BYTE *) addr;
 | 
			
		||||
    /* Get offset from thunk table (after instruction 0xff 0x25)
 | 
			
		||||
     *   4018c8 <_VirtualQuery>: ff 25 4a 8a 00 00
 | 
			
		||||
     */
 | 
			
		||||
    ULONG offset = *(ULONG *)( thkp + 2 );
 | 
			
		||||
#ifdef _WIN64
 | 
			
		||||
    /* On 64 bit the offset is relative
 | 
			
		||||
     *      4018c8:   ff 25 4a 8a 00 00    jmpq    *0x8a4a(%rip)    # 40a318 <__imp_VirtualQuery>
 | 
			
		||||
     * And can be also negative (MSVC in WDK)
 | 
			
		||||
     *   100002f20:   ff 25 3a e1 ff ff    jmpq   *-0x1ec6(%rip)    # 0x100001060
 | 
			
		||||
     * So cast to signed LONG type
 | 
			
		||||
     */
 | 
			
		||||
    BYTE *ptr = (BYTE *)( thkp + 6 + (LONG) offset );
 | 
			
		||||
#else
 | 
			
		||||
    /* On 32 bit the offset is absolute
 | 
			
		||||
     *   4019b4:    ff 25 90 71 40 00    jmp    *0x40719
 | 
			
		||||
     */
 | 
			
		||||
    BYTE *ptr = (BYTE *) offset;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    if( !is_valid_address( ptr ) || ptr < (BYTE *) iat || ptr > (BYTE *) iat + iat_size )
 | 
			
		||||
        return NULL;
 | 
			
		||||
 | 
			
		||||
    return *(void **) ptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Holds module filename */
 | 
			
		||||
static char module_filename[2*MAX_PATH];
 | 
			
		||||
 | 
			
		||||
static BOOL fill_info( const void *addr, Dl_info *info )
 | 
			
		||||
{
 | 
			
		||||
    HMODULE hModule;
 | 
			
		||||
    DWORD dwSize;
 | 
			
		||||
    IMAGE_EXPORT_DIRECTORY *ied;
 | 
			
		||||
    void *funcAddress = NULL;
 | 
			
		||||
 | 
			
		||||
    /* Get module of the specified address */
 | 
			
		||||
    hModule = MyGetModuleHandleFromAddress( addr );
 | 
			
		||||
 | 
			
		||||
    if( hModule == NULL )
 | 
			
		||||
        return FALSE;
 | 
			
		||||
 | 
			
		||||
    dwSize = GetModuleFileNameA( hModule, module_filename, sizeof( module_filename ) );
 | 
			
		||||
 | 
			
		||||
    if( dwSize == 0 || dwSize == sizeof( module_filename ) )
 | 
			
		||||
        return FALSE;
 | 
			
		||||
 | 
			
		||||
    info->dli_fname = module_filename;
 | 
			
		||||
    info->dli_fbase = (void *) hModule;
 | 
			
		||||
 | 
			
		||||
    /* Find function name and function address in module's export table */
 | 
			
		||||
    if( get_image_section( hModule, IMAGE_DIRECTORY_ENTRY_EXPORT, (void **) &ied, NULL ) )
 | 
			
		||||
        info->dli_sname = get_export_symbol_name( hModule, ied, addr, &funcAddress );
 | 
			
		||||
    else
 | 
			
		||||
        info->dli_sname = NULL;
 | 
			
		||||
 | 
			
		||||
    info->dli_saddr = info->dli_sname == NULL ? NULL : funcAddress != NULL ? funcAddress : (void *) addr;
 | 
			
		||||
 | 
			
		||||
    return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DLFCN_EXPORT
 | 
			
		||||
int dladdr( const void *addr, Dl_info *info )
 | 
			
		||||
{
 | 
			
		||||
    if( info == NULL )
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    if( !is_valid_address( addr ) )
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    if( is_import_thunk( addr ) )
 | 
			
		||||
    {
 | 
			
		||||
        void *iat;
 | 
			
		||||
        DWORD iatSize;
 | 
			
		||||
        HMODULE hModule;
 | 
			
		||||
 | 
			
		||||
        /* Get module of the import thunk address */
 | 
			
		||||
        hModule = MyGetModuleHandleFromAddress( addr );
 | 
			
		||||
 | 
			
		||||
        if( hModule == NULL )
 | 
			
		||||
            return 0;
 | 
			
		||||
 | 
			
		||||
        if( !get_image_section( hModule, IMAGE_DIRECTORY_ENTRY_IAT, &iat, &iatSize ) )
 | 
			
		||||
        {
 | 
			
		||||
            /* Fallback for cases where the iat is not defined,
 | 
			
		||||
             * for example i586-mingw32msvc-gcc */
 | 
			
		||||
            IMAGE_IMPORT_DESCRIPTOR *iid;
 | 
			
		||||
            DWORD iidSize;
 | 
			
		||||
 | 
			
		||||
            if( !get_image_section( hModule, IMAGE_DIRECTORY_ENTRY_IMPORT, (void **) &iid, &iidSize ) )
 | 
			
		||||
                return 0;
 | 
			
		||||
 | 
			
		||||
            if( iid == NULL || iid->Characteristics == 0 || iid->FirstThunk == 0 )
 | 
			
		||||
                return 0;
 | 
			
		||||
 | 
			
		||||
            iat = (void *)( (BYTE *) hModule + iid->FirstThunk );
 | 
			
		||||
            /* We assume that in this case iid and iat's are in linear order */
 | 
			
		||||
            iatSize = iidSize - (DWORD) ( (BYTE *) iat - (BYTE *) iid );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        addr = get_address_from_import_address_table( iat, iatSize, addr );
 | 
			
		||||
 | 
			
		||||
        if( !is_valid_address( addr ) )
 | 
			
		||||
            return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if( !fill_info( addr, info ) )
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef DLFCN_WIN32_SHARED
 | 
			
		||||
BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
 | 
			
		||||
{
 | 
			
		||||
    (void) hinstDLL;
 | 
			
		||||
    (void) fdwReason;
 | 
			
		||||
    (void) lpvReserved;
 | 
			
		||||
    return TRUE;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										94
									
								
								libs/dlfcn-win32/dlfcn.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								libs/dlfcn-win32/dlfcn.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,94 @@
 | 
			
		|||
/*
 | 
			
		||||
 * dlfcn-win32
 | 
			
		||||
 * Copyright (c) 2007 Ramiro Polla
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
 * of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
 * in the Software without restriction, including without limitation the rights
 | 
			
		||||
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
 * copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
 * furnished to do so, subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in
 | 
			
		||||
 * all copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 | 
			
		||||
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
 * THE SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef DLFCN_H
 | 
			
		||||
#define DLFCN_H
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(DLFCN_WIN32_SHARED)
 | 
			
		||||
#if defined(DLFCN_WIN32_EXPORTS)
 | 
			
		||||
#   define DLFCN_EXPORT __declspec(dllexport)
 | 
			
		||||
#else
 | 
			
		||||
#   define DLFCN_EXPORT __declspec(dllimport)
 | 
			
		||||
#endif
 | 
			
		||||
#else
 | 
			
		||||
#   define DLFCN_EXPORT
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Relocations are performed when the object is loaded. */
 | 
			
		||||
#define RTLD_NOW    0
 | 
			
		||||
 | 
			
		||||
/* Relocations are performed at an implementation-defined time.
 | 
			
		||||
 * Windows API does not support lazy symbol resolving (when first reference
 | 
			
		||||
 * to a given symbol occurs). So RTLD_LAZY implementation is same as RTLD_NOW.
 | 
			
		||||
 */
 | 
			
		||||
#define RTLD_LAZY   RTLD_NOW
 | 
			
		||||
 | 
			
		||||
/* All symbols are available for relocation processing of other modules. */
 | 
			
		||||
#define RTLD_GLOBAL (1 << 1)
 | 
			
		||||
 | 
			
		||||
/* All symbols are not made available for relocation processing by other modules. */
 | 
			
		||||
#define RTLD_LOCAL  (1 << 2)
 | 
			
		||||
 | 
			
		||||
/* These two were added in The Open Group Base Specifications Issue 6.
 | 
			
		||||
 * Note: All other RTLD_* flags in any dlfcn.h are not standard compliant.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* The symbol lookup happens in the normal global scope. */
 | 
			
		||||
#define RTLD_DEFAULT    ((void *)0)
 | 
			
		||||
 | 
			
		||||
/* Specifies the next object after this one that defines name. */
 | 
			
		||||
#define RTLD_NEXT       ((void *)-1)
 | 
			
		||||
 | 
			
		||||
/* Structure filled in by dladdr() */
 | 
			
		||||
typedef struct dl_info
 | 
			
		||||
{
 | 
			
		||||
   const char *dli_fname;  /* Filename of defining object (thread unsafe and reused on every call to dladdr) */
 | 
			
		||||
   void       *dli_fbase;  /* Load address of that object */
 | 
			
		||||
   const char *dli_sname;  /* Name of nearest lower symbol */
 | 
			
		||||
   void       *dli_saddr;  /* Exact value of nearest symbol */
 | 
			
		||||
} Dl_info;
 | 
			
		||||
 | 
			
		||||
/* Open a symbol table handle. */
 | 
			
		||||
DLFCN_EXPORT void *dlopen(const char *file, int mode);
 | 
			
		||||
 | 
			
		||||
/* Close a symbol table handle. */
 | 
			
		||||
DLFCN_EXPORT int dlclose(void *handle);
 | 
			
		||||
 | 
			
		||||
/* Get the address of a symbol from a symbol table handle. */
 | 
			
		||||
DLFCN_EXPORT void *dlsym(void *handle, const char *name);
 | 
			
		||||
 | 
			
		||||
/* Get diagnostic information. */
 | 
			
		||||
DLFCN_EXPORT char *dlerror(void);
 | 
			
		||||
 | 
			
		||||
/* Translate address to symbolic information (no POSIX standard) */
 | 
			
		||||
DLFCN_EXPORT int dladdr(const void *addr, Dl_info *info);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* DLFCN_H */
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue