dln_symbol: make dln_sym accessible Ruby internally
The symbol resolved by dln_symbol will eventually be passed to extensions. The error handling of dln_sym is also separated into dln_sym_func because the new call resolving symbols will not raise LoadError.
This commit is contained in:
parent
35a6b69f6c
commit
8a37df8c8b
70
dln.c
70
dln.c
@ -419,34 +419,64 @@ dln_open(const char *file)
|
||||
static void *
|
||||
dln_sym(void *handle, const char *symbol)
|
||||
{
|
||||
void *func;
|
||||
const char *error;
|
||||
#if defined(_WIN32)
|
||||
return GetProcAddress(handle, symbol);
|
||||
#elif defined(USE_DLN_DLOPEN)
|
||||
return dlsym(handle, symbol);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void *
|
||||
dln_sym_func(void *handle, const char *symbol)
|
||||
{
|
||||
void *func = dln_sym(handle, symbol);
|
||||
|
||||
if (func == NULL) {
|
||||
const char *error;
|
||||
#if defined(_WIN32)
|
||||
char message[1024];
|
||||
|
||||
func = GetProcAddress(handle, symbol);
|
||||
if (func == NULL) {
|
||||
error = dln_strerror();
|
||||
goto failed;
|
||||
}
|
||||
|
||||
#elif defined(USE_DLN_DLOPEN)
|
||||
func = dlsym(handle, symbol);
|
||||
if (func == NULL) {
|
||||
const size_t errlen = strlen(error = dln_strerror()) + 1;
|
||||
error = memcpy(ALLOCA_N(char, errlen), error, errlen);
|
||||
goto failed;
|
||||
}
|
||||
#endif
|
||||
|
||||
return func;
|
||||
|
||||
failed:
|
||||
dln_loaderror("%s - %s", error, symbol);
|
||||
}
|
||||
return func;
|
||||
}
|
||||
|
||||
#define dln_sym_callable(rettype, argtype, handle, symbol) \
|
||||
(*(rettype (*)argtype)dln_sym_func(handle, symbol))
|
||||
#endif
|
||||
|
||||
void *
|
||||
dln_symbol(void *handle, const char *symbol)
|
||||
{
|
||||
#if defined(_WIN32) || defined(USE_DLN_DLOPEN)
|
||||
if (EXTERNAL_PREFIX[0]) {
|
||||
const size_t symlen = strlen(symbol);
|
||||
char *const tmp = ALLOCA_N(char, symlen + sizeof(EXTERNAL_PREFIX));
|
||||
if (!tmp) dln_memerror();
|
||||
memcpy(tmp, EXTERNAL_PREFIX, sizeof(EXTERNAL_PREFIX) - 1);
|
||||
memcpy(tmp + sizeof(EXTERNAL_PREFIX) - 1, symbol, symlen + 1);
|
||||
symbol = tmp;
|
||||
}
|
||||
if (handle == NULL) {
|
||||
# if defined(USE_DLN_DLOPEN)
|
||||
handle = dlopen(NULL, 0);
|
||||
# elif defined(_WIN32) && defined(RUBY_EXPORT)
|
||||
handle = rb_libruby_handle();
|
||||
# else
|
||||
return NULL;
|
||||
# endif
|
||||
}
|
||||
return dln_sym(handle, symbol);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if defined(RUBY_DLN_CHECK_ABI) && defined(USE_DLN_DLOPEN)
|
||||
static bool
|
||||
abi_check_enabled_p(void)
|
||||
@ -464,9 +494,8 @@ dln_load(const char *file)
|
||||
|
||||
#ifdef RUBY_DLN_CHECK_ABI
|
||||
typedef unsigned long long abi_version_number;
|
||||
typedef abi_version_number abi_version_func(void);
|
||||
abi_version_func *abi_version_fct = (abi_version_func *)dln_sym(handle, EXTERNAL_PREFIX "ruby_abi_version");
|
||||
abi_version_number binary_abi_version = (*abi_version_fct)();
|
||||
abi_version_number binary_abi_version =
|
||||
dln_sym_callable(abi_version_number, (void), handle, EXTERNAL_PREFIX "ruby_abi_version")();
|
||||
if (binary_abi_version != ruby_abi_version() && abi_check_enabled_p()) {
|
||||
dln_loaderror("incompatible ABI version of binary - %s", file);
|
||||
}
|
||||
@ -474,10 +503,9 @@ dln_load(const char *file)
|
||||
|
||||
char *init_fct_name;
|
||||
init_funcname(&init_fct_name, file);
|
||||
void (*init_fct)(void) = (void(*)(void))dln_sym(handle, init_fct_name);
|
||||
|
||||
/* Call the init code */
|
||||
(*init_fct)();
|
||||
dln_sym_callable(void, (void), handle, init_fct_name)();
|
||||
|
||||
return handle;
|
||||
|
||||
|
1
dln.h
1
dln.h
@ -25,6 +25,7 @@ RUBY_SYMBOL_EXPORT_BEGIN
|
||||
char *dln_find_exe_r(const char*,const char*,char*,size_t DLN_FIND_EXTRA_ARG_DECL);
|
||||
char *dln_find_file_r(const char*,const char*,char*,size_t DLN_FIND_EXTRA_ARG_DECL);
|
||||
void *dln_load(const char*);
|
||||
void *dln_symbol(void*,const char*);
|
||||
|
||||
RUBY_SYMBOL_EXPORT_END
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user