aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSatoshi Tagomori <tagomoris@gmail.com>2023-12-07 20:38:53 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2023-12-14 17:39:42 +0900
commit8a37df8c8bc0311c4822ee989087d212af2bf73f (patch)
treeaedec147365812ed69cfb848bab08cf697ea8e38
parent35a6b69f6c3cda7afd84c686978cf7ac79f68e04 (diff)
downloadruby-8a37df8c8bc0311c4822ee989087d212af2bf73f.tar.gz
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.
-rw-r--r--dln.c70
-rw-r--r--dln.h1
-rw-r--r--dmydln.c9
3 files changed, 59 insertions, 21 deletions
diff --git a/dln.c b/dln.c
index bbed3af78c..9e01c45a51 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 902f753450..d624bb6611 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 d05cda0b8e..b1516937d3 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);
+}