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