From 8a37df8c8bc0311c4822ee989087d212af2bf73f Mon Sep 17 00:00:00 2001 From: Satoshi Tagomori Date: Thu, 7 Dec 2023 20:38:53 +0900 Subject: [PATCH] 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. --- dln.c | 70 +++++++++++++++++++++++++++++++++++++++----------------- dln.h | 1 + dmydln.c | 9 ++++++++ 3 files changed, 59 insertions(+), 21 deletions(-) diff --git a/dln.c b/dln.c index bbed3af78ce1ac..9e01c45a514afe 100644 --- a/dln.c +++ b/dln.c @@ -419,33 +419,63 @@ dln_open(const char *file) static void * dln_sym(void *handle, const char *symbol) { - void *func; - const char *error; - #if defined(_WIN32) - char message[1024]; + 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); - func = GetProcAddress(handle, symbol); if (func == NULL) { + const char *error; +#if defined(_WIN32) + char message[1024]; 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 - + dln_loaderror("%s - %s", error, symbol); + } return func; - - failed: - dln_loaderror("%s - %s", error, symbol); } + +#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 @@ -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; diff --git a/dln.h b/dln.h index 902f753450a30a..d624bb6611d207 100644 --- a/dln.h +++ b/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 diff --git a/dmydln.c b/dmydln.c index d05cda0b8eb922..b1516937d39822 100644 --- a/dmydln.c +++ b/dmydln.c @@ -8,3 +8,12 @@ dln_load(const char *file) UNREACHABLE_RETURN(NULL); } + +NORETURN(void *dln_symbol(void*,const char*)); +void* +dln_symbol(void *handle, const char *symbol) +{ + rb_loaderror("this executable file can't load extension libraries"); + + UNREACHABLE_RETURN(NULL); +}