From ea1947ffcc606d757357398b24e74a3f4ecefa07 Mon Sep 17 00:00:00 2001 From: neonloop Date: Wed, 20 Oct 2021 14:54:27 +0000 Subject: Initial commit from steward-fu release --- core/include/loadlib.h | 336 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 336 insertions(+) create mode 100644 core/include/loadlib.h (limited to 'core/include/loadlib.h') diff --git a/core/include/loadlib.h b/core/include/loadlib.h new file mode 100644 index 0000000..9d217e1 --- /dev/null +++ b/core/include/loadlib.h @@ -0,0 +1,336 @@ +/* + * Copyright © 2006-2013 SplinterGU (Fenix/Bennugd) + * + * This file is part of Bennu - Game Development + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + */ + +#ifndef _LOADLIB_H +#define _LOADLIB_H + +/* --------------------------------------------------------------------------- */ + +#ifdef _WIN32 +#include +#include +#else +#define _GNU_SOURCE +#include +#include +#include +#include + +#define __stdcall +#define __dllexport +#define __dllimport +#endif + +#include + +/******************************************************************************* + * COMMON * + *******************************************************************************/ + +static char * __dliberr = NULL; + +/* --------------------------------------------------------------------------- */ + +static char * dliberror( void ) +{ + return __dliberr; +} + +/* --------------------------------------------------------------------------- */ + +#ifndef __STATIC__ + +/******************************************************************************* + * MODULAR * + *******************************************************************************/ + +#ifdef _WIN32 +#define dlclose(a) +#endif + +/* --------------------------------------------------------------------------- */ + +typedef struct +{ + char * fname; + void * hnd; +} dlibhandle ; + +/* --------------------------------------------------------------------------- */ + +static int dlibclose( void * _handle ) +{ + dlibhandle * handle = ( dlibhandle * ) _handle; + dlclose( handle->hnd ); + free( handle->fname ); + free( handle ); + + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static void * dlibopen( const char * fname ) +{ + char *f; + char *_fname = NULL; +#ifdef _WIN32 + void * hnd = LoadLibrary( fname ); +#else + void * hnd = dlopen( fname, RTLD_NOW | RTLD_GLOBAL ); +#endif + + if ( !hnd ) + { + f = ( char * ) fname + strlen( fname ); + while ( f > fname && f[-1] != '\\' && f[-1] != '/' ) f-- ; + + if ( strncmp( f, "lib", 3 ) ) + { + if ( ( _fname = malloc( strlen( fname ) + 4 ) ) ) + { + sprintf( _fname, "%.*slib%s", ( int ) ( f - fname ), fname, f ); +#ifdef _WIN32 + hnd = LoadLibrary( _fname ); +#else + hnd = dlopen( _fname, RTLD_NOW | RTLD_GLOBAL ); +#endif + } + } + } + + if ( !hnd ) + { +#ifdef _WIN32 + __dliberr = "Could not load library." ; +#else + __dliberr = dlerror() ; +#endif + if ( _fname ) free( _fname ); + return NULL; + } + + dlibhandle * dlib = (dlibhandle*) malloc( sizeof( dlibhandle ) ); + if ( !dlib ) + { + __dliberr = "Could not load library." ; + dlclose( hnd ); + if ( _fname ) free( _fname ); + return NULL; + } + + f = ( char * ) fname + strlen( fname ); + while ( f > fname && f[-1] != '\\' && f[-1] != '/' ) f-- ; + dlib->fname = strdup( f ); + if ( !dlib->fname ) + { + __dliberr = "Could not load library." ; + free( dlib ); + dlclose( hnd ); + if ( _fname ) free( _fname ); + return NULL; + } + + dlib->hnd = hnd; + + if ( _fname ) free( _fname ); + + return ( ( void * ) dlib ); +} + +/* --------------------------------------------------------------------------- */ + +static void * dlibaddr( void * _handle, const char * symbol ) +{ + dlibhandle * handle = ( dlibhandle * ) _handle; + char * ptr, * f; + +#ifdef _WIN32 + void * addr = GetProcAddress( (HMODULE)handle->hnd, symbol ); + if ( !addr ) + { + __dliberr = "Symbol not found." ; + return NULL; + } +#else + void * addr = dlsym( handle->hnd, symbol ) ; + if ( !addr ) + { + __dliberr = dlerror() ; + return NULL; + } + +#ifndef TARGET_BEOS + Dl_info dli; + dladdr( addr, &dli ); + + ptr = ( char * ) dli.dli_fname; f = NULL; +/* + printf( "dli_fname=%s\n", dli.dli_fname ); + printf( "dli_fbase=%p\n", dli.dli_fbase ); + printf( "dli_sname=%s\n", dli.dli_sname ); + printf( "dli_saddr=%p\n", dli.dli_saddr ); +*/ + + while ( *ptr ) + { + if ( *ptr == '/' || *ptr == '\\' ) f = ptr ; + ptr++; + } + if ( f ) ptr = f + 1; + + if ( strcmp( ptr, handle->fname ) ) + { + if ( strncmp( ptr, "lib", 3 ) || strcmp( ptr + 3, handle->fname ) ) + { + __dliberr = "Symbol not found." ; + return NULL; + } + } +#endif +#endif + + return addr; +} + +/* --------------------------------------------------------------------------- */ + +static void * _dlibaddr( void * _handle, const char * symbol ) +{ + dlibhandle * handle = ( dlibhandle * ) _handle; + char * ptr, * f; + char * sym = (char*)malloc( strlen( handle->fname ) + strlen( symbol ) + 2 ); + if ( !sym ) + { + __dliberr = "Can't load symbol." ; + return NULL; + } + + strcpy( sym, handle->fname ); + ptr = ( char * ) sym; f = NULL; + while ( *ptr ) + { + if ( *ptr == '.' ) f = ptr ; + ptr++; + } + + if ( f ) *f = '\0'; + strcat( sym, "_" ); strcat( sym, symbol ); + + { + void * addr = dlibaddr( handle, sym ); + free( sym ); + return addr; + } +} + +/* --------------------------------------------------------------------------- */ + +#else + +/******************************************************************************* + * MONOLITH * + *******************************************************************************/ + +#include + +static int fake_dl_inited = 0; + +/* --------------------------------------------------------------------------- */ + +#define _dlibaddr(a,b) dlibaddr(a,b) + +/* --------------------------------------------------------------------------- */ + +static int dlibclose( void * handle ) +{ + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static void * dlibopen( const char * fname ) +{ + __FAKE_DL * fdl = __fake_dl; + char dlname[32], *p; + + if ( !fake_dl_inited ) + { + fake_dl_init(); + fake_dl_inited = 1; + } + + strcpy( dlname, basename( fname ) ); + + p = strrchr( dlname, '.' ); + if ( p ) *p = '\0' ; + + while( fdl->dlname ) + { + if ( !strcmp( dlname, fdl->dlname ) ) return ( void * ) fdl; + fdl++; + } + + __dliberr = "Could not load library." ; + + return NULL; +} + +/* --------------------------------------------------------------------------- */ + +static void * dlibaddr( void * handle, const char * symbol ) +{ + __FAKE_DL * fdl = ( __FAKE_DL * ) handle; + + if ( !fdl ) return NULL; + + if ( !strcmp( symbol, "constants_def" ) ) return ( fdl->constants_def ); + if ( !strcmp( symbol, "types_def" ) ) return ( fdl->types_def ); + if ( !strcmp( symbol, "globals_def" ) ) return ( fdl->globals_def ); + if ( !strcmp( symbol, "locals_def" ) ) return ( fdl->locals_def ); + if ( !strcmp( symbol, "globals_fixup" ) ) return ( fdl->globals_fixup ); + if ( !strcmp( symbol, "locals_fixup" ) ) return ( fdl->locals_fixup ); + if ( !strcmp( symbol, "functions_exports" ) ) return ( fdl->functions_exports ); + if ( !strcmp( symbol, "module_initialize" ) ) return ( fdl->module_initialize ); + if ( !strcmp( symbol, "module_finalize" ) ) return ( fdl->module_finalize ); + if ( !strcmp( symbol, "instance_create_hook" ) ) return ( fdl->instance_create_hook ); + if ( !strcmp( symbol, "instance_destroy_hook" ) ) return ( fdl->instance_destroy_hook ); + if ( !strcmp( symbol, "instance_pre_execute_hook" ) ) return ( fdl->instance_pre_execute_hook ); + if ( !strcmp( symbol, "instance_pos_execute_hook" ) ) return ( fdl->instance_pos_execute_hook ); + if ( !strcmp( symbol, "process_exec_hook" ) ) return ( fdl->process_exec_hook ); + if ( !strcmp( symbol, "handler_hooks" ) ) return ( fdl->handler_hooks ); + if ( !strcmp( symbol, "modules_dependency" ) ) return ( fdl->modules_dependency ); + + return NULL; +} + +/* --------------------------------------------------------------------------- */ + +#endif + +/* --------------------------------------------------------------------------- */ + +#endif -- cgit v1.2.3