1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
ruby--ruby/dln.c

496 lines
12 KiB
C
Raw Normal View History

/**********************************************************************
dln.c -
$Author$
created at: Tue Jan 18 17:05:06 JST 1994
* encoding.c: provide basic features for M17N. * parse.y: encoding aware parsing. * parse.y (pragma_encoding): encoding specification pragma. * parse.y (rb_intern3): encoding specified symbols. * string.c (rb_str_length): length based on characters. for older behavior, bytesize method added. * string.c (rb_str_index_m): index based on characters. rindex as well. * string.c (succ_char): encoding aware succeeding string. * string.c (rb_str_reverse): reverse based on characters. * string.c (rb_str_inspect): encoding aware string description. * string.c (rb_str_upcase_bang): encoding aware case conversion. downcase, capitalize, swapcase as well. * string.c (rb_str_tr_bang): tr based on characters. delete, squeeze, tr_s, count as well. * string.c (rb_str_split_m): split based on characters. * string.c (rb_str_each_line): encoding aware each_line. * string.c (rb_str_each_char): added. iteration based on characters. * string.c (rb_str_strip_bang): encoding aware whitespace stripping. lstrip, rstrip as well. * string.c (rb_str_justify): encoding aware justifying (ljust, rjust, center). * string.c (str_encoding): get encoding attribute from a string. * re.c (rb_reg_initialize): encoding aware regular expression * sprintf.c (rb_str_format): formatting (i.e. length count) based on characters. * io.c (rb_io_getc): getc to return one-character string. for older behavior, getbyte method added. * ext/stringio/stringio.c (strio_getc): ditto. * io.c (rb_io_ungetc): allow pushing arbitrary string at the current reading point. * ext/stringio/stringio.c (strio_ungetc): ditto. * ext/strscan/strscan.c: encoding support. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13261 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-08-24 23:29:39 -04:00
Copyright (C) 1993-2007 Yukihiro Matsumoto
**********************************************************************/
#ifdef RUBY_EXPORT
#include "ruby/ruby.h"
#define dln_notimplement rb_notimplement
#define dln_memerror rb_memerror
#define dln_exit rb_exit
#define dln_loaderror rb_loaderror
2022-02-17 03:35:38 -05:00
#define dln_fatalerror rb_fatal
#else
#define dln_notimplement --->>> dln not implemented <<<---
#define dln_memerror abort
#define dln_exit exit
static void dln_loaderror(const char *format, ...);
2022-02-17 03:35:38 -05:00
#define dln_fatalerror dln_loaderror
#endif
#include "dln.h"
#include "internal.h"
2021-09-08 23:19:20 -04:00
#include "internal/compilers.h"
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
#if defined(HAVE_ALLOCA_H)
#include <alloca.h>
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#else
# include <strings.h>
#endif
#if defined __APPLE__
# include <AvailabilityMacros.h>
#endif
#ifndef xmalloc
void *xmalloc();
void *xcalloc();
void *xrealloc();
#endif
#undef free
#define free(x) xfree(x)
#include <stdio.h>
#if defined(_WIN32)
#include "missing/file.h"
#endif
#include <sys/types.h>
#include <sys/stat.h>
#ifndef S_ISDIR
# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
#ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
#endif
#ifndef MAXPATHLEN
# define MAXPATHLEN 1024
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifndef dln_loaderror
static void
dln_loaderror(const char *format, ...)
{
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
abort();
}
#endif
#if defined(HAVE_DLOPEN) && !defined(_AIX) && !defined(_UNICOSMP)
/* dynamic load with dlopen() */
# define USE_DLN_DLOPEN
#endif
#if defined(__hp9000s300) || ((defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)) && !defined(__ELF__)) || defined(NeXT)
# define EXTERNAL_PREFIX "_"
#else
# define EXTERNAL_PREFIX ""
#endif
#define FUNCNAME_PREFIX EXTERNAL_PREFIX"Init_"
#if defined __CYGWIN__ || defined DOSISH
#define isdirsep(x) ((x) == '/' || (x) == '\\')
#else
#define isdirsep(x) ((x) == '/')
#endif
#if defined(_WIN32) || defined(USE_DLN_DLOPEN)
static size_t
init_funcname_len(const char **file)
{
const char *p = *file, *base, *dot = NULL;
/* Load the file as an object one */
for (base = p; *p; p++) { /* Find position of last '/' */
2022-07-21 12:23:58 -04:00
if (*p == '.' && !dot) dot = p;
if (isdirsep(*p)) base = p+1, dot = NULL;
}
*file = base;
/* Delete suffix if it exists */
return (dot ? dot : p) - base;
}
static const char funcname_prefix[sizeof(FUNCNAME_PREFIX) - 1] = FUNCNAME_PREFIX;
#define init_funcname(buf, file) do {\
const char *base = (file);\
const size_t flen = init_funcname_len(&base);\
const size_t plen = sizeof(funcname_prefix);\
char *const tmp = ALLOCA_N(char, plen+flen+1);\
if (!tmp) {\
2022-07-21 12:23:58 -04:00
dln_memerror();\
}\
memcpy(tmp, funcname_prefix, plen);\
memcpy(tmp+plen, base, flen);\
tmp[plen+flen] = '\0';\
*(buf) = tmp;\
} while (0)
#endif
#ifdef USE_DLN_DLOPEN
# include <dlfcn.h>
#endif
#if defined(_AIX)
#include <ctype.h> /* for isdigit() */
#include <errno.h> /* for global errno */
#include <sys/ldr.h>
#endif
#ifdef NeXT
#if NS_TARGET_MAJOR < 4
#include <mach-o/rld.h>
#else
#include <mach-o/dyld.h>
* gc.c (Init_stack): stack region is far smaller than usual if pthread is used. * marshal.c (w_extended): singleton methods should not be checked when dumping via marshal_dump() or _dump(). [ruby-talk:85909] * file.c (getcwdofdrv): avoid using getcwd() directly, use my_getcwd() instead. * merged NeXT, OpenStep, Rhapsody ports patch from Eric Sunshine <sunshine@sunshineco.com>. [ruby-core:01596] * marshal.c (w_object): LINK check earlier than anything else, i.e. do not dump TYPE_IVAR for already dumped objects. (ruby-bugs PR#1220) * eval.c (rb_eval): call "inherited" only when a new class is generated; not on reopening. * eval.c (eval): prepend error position in evaluating string to * configure.in: revived NextStep, OpenStep, and Rhapsody ports which had become unbuildable; enhanced --enable-fat-binary option so that it accepts a list of desired architectures (rather than assuming a fixed list), or defaults to a platform-appropriate list if user does not provide an explicit list; made the default list of architectures for MAB (fat binary) more comprehensive; now uses -fno-common even when building the interpreter (in addition to using it for extensions), thus allowing the interpreter to be embedded into a plugin module of an external project (in addition to allowing embedding directly into an application); added checks for <netinet/in_systm.h> (needed by `socket' extension) and getcwd(); now ensures that -I/usr/local/include is employed when extensions' extconf.rb scripts invoke have_header() since extension checks on NextStep and OpenStep will fail without it if the desired resource resides in the /usr/local tree; fixed formatting of --help message. * Makefile.in: $(LIBRUBY_A) rule now deletes the archive before invoking $(AR) since `ar' on Apple/NeXT can not "update" MAB archives (see configure's --enable-fat-binary option); added rule for new missing/getcwd.c. * defines.h: fixed endian handling during MAB build (see configure's --enable-fat-binary option) to ensure that all portions of the project see the correct WORDS_BIGENDIAN value (some extension modules were getting the wrong endian setting); added missing constants GETPGRP_VOID, WNOHANG, WUNTRACED, X_OK, and type pid_t for NextStep and OpenStep; removed unnecessary and problematic HAVE_SYS_WAIT_H define in NeXT section. * dir.c: do not allow NAMLEN() macro to trust dirent::d_namlen on NextStep since, on some installations, this value always resolves uselessly to zero. * dln.c: added error reporting to NextStep extension loader since the previous behavior of failing silently was not useful; now ensures that NSLINKMODULE_OPTION_BINDNOW compatibility constant is defined for OpenStep and Rhapsody; no longer includes <mach-o/dyld.h> twice on Rhapsody since this header lacks multiple-include protection, which resulted in "redefinition" compilation errors. * main.c: also create hard reference to objc_msgSend() on NeXT platforms (in addition to Apple platforms). * lib/mkmf.rb: now exports XCFLAGS from configure script to extension makefiles so that extensions can be built MAB (see configure's --enable-fat-binary option); also utilize XCFLAGS in cc_command() (but not cpp_command() because MAB flags are incompatible with direct invocation of `cpp'). * ext/curses/extconf.rb: now additionally checks for presence of these curses functions which are not present on NextStep or Openstep: bkgd(), bkgdset(), color(), curs(), getbkgd(), init(), scrl(), set(), setscrreg(), wattroff(), wattron(), wattrset(), wbkgd(), wbkgdset(), wscrl(), wsetscrreg() * ext/curses/curses.c: added appropriate #ifdef's for additional set of curses functions now checked by extconf.rb; fixed curses_bkgd() and window_bkgd() to correctly return boolean result rather than numeric result; fixed window_getbkgd() to correctly signal an error by returning nil rather than -1. * ext/etc/etc.c: setup_passwd() and setup_group() now check for null pointers before invoking rb_tainted_str_new2() upon fields extracted from `struct passwd' and `struct group' since null pointers in some fields are common on NextStep/OpenStep (especially so for the `pw_comment' field) and rb_tainted_str_new2() throws an exception when it receives a null pointer. * ext/pty/pty.c: include "util.h" for strdup()/ruby_strdup() for platforms such as NextStep and OpenStep which lack strdup(). * ext/socket/getaddrinfo.c: cast first argument of getservbyname(), gethostbyaddr(), and gethostbyname() from (const char*) to non-const (char*) for older platforms such as NextStep and OpenStep. * ext/socket/socket.c: include "util.h" for strdup()/ruby_strdup() for platforms such as NextStep and OpenStep which lack strdup(); include <netinet/in_systm.h> if present for NextStep and OpenStep; cast first argument of gethostbyaddr() and getservbyname() from (const char*) to non-const (char*) for older platforms. * ext/syslog/syslog.c: include "util.h" for strdup()/ruby_strdup() for platforms such as NextStep and OpenStep which lack strdup(). git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@5002 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-11-21 23:00:03 -05:00
#ifndef NSLINKMODULE_OPTION_BINDNOW
#define NSLINKMODULE_OPTION_BINDNOW 1
#endif
#endif
* gc.c (Init_stack): stack region is far smaller than usual if pthread is used. * marshal.c (w_extended): singleton methods should not be checked when dumping via marshal_dump() or _dump(). [ruby-talk:85909] * file.c (getcwdofdrv): avoid using getcwd() directly, use my_getcwd() instead. * merged NeXT, OpenStep, Rhapsody ports patch from Eric Sunshine <sunshine@sunshineco.com>. [ruby-core:01596] * marshal.c (w_object): LINK check earlier than anything else, i.e. do not dump TYPE_IVAR for already dumped objects. (ruby-bugs PR#1220) * eval.c (rb_eval): call "inherited" only when a new class is generated; not on reopening. * eval.c (eval): prepend error position in evaluating string to * configure.in: revived NextStep, OpenStep, and Rhapsody ports which had become unbuildable; enhanced --enable-fat-binary option so that it accepts a list of desired architectures (rather than assuming a fixed list), or defaults to a platform-appropriate list if user does not provide an explicit list; made the default list of architectures for MAB (fat binary) more comprehensive; now uses -fno-common even when building the interpreter (in addition to using it for extensions), thus allowing the interpreter to be embedded into a plugin module of an external project (in addition to allowing embedding directly into an application); added checks for <netinet/in_systm.h> (needed by `socket' extension) and getcwd(); now ensures that -I/usr/local/include is employed when extensions' extconf.rb scripts invoke have_header() since extension checks on NextStep and OpenStep will fail without it if the desired resource resides in the /usr/local tree; fixed formatting of --help message. * Makefile.in: $(LIBRUBY_A) rule now deletes the archive before invoking $(AR) since `ar' on Apple/NeXT can not "update" MAB archives (see configure's --enable-fat-binary option); added rule for new missing/getcwd.c. * defines.h: fixed endian handling during MAB build (see configure's --enable-fat-binary option) to ensure that all portions of the project see the correct WORDS_BIGENDIAN value (some extension modules were getting the wrong endian setting); added missing constants GETPGRP_VOID, WNOHANG, WUNTRACED, X_OK, and type pid_t for NextStep and OpenStep; removed unnecessary and problematic HAVE_SYS_WAIT_H define in NeXT section. * dir.c: do not allow NAMLEN() macro to trust dirent::d_namlen on NextStep since, on some installations, this value always resolves uselessly to zero. * dln.c: added error reporting to NextStep extension loader since the previous behavior of failing silently was not useful; now ensures that NSLINKMODULE_OPTION_BINDNOW compatibility constant is defined for OpenStep and Rhapsody; no longer includes <mach-o/dyld.h> twice on Rhapsody since this header lacks multiple-include protection, which resulted in "redefinition" compilation errors. * main.c: also create hard reference to objc_msgSend() on NeXT platforms (in addition to Apple platforms). * lib/mkmf.rb: now exports XCFLAGS from configure script to extension makefiles so that extensions can be built MAB (see configure's --enable-fat-binary option); also utilize XCFLAGS in cc_command() (but not cpp_command() because MAB flags are incompatible with direct invocation of `cpp'). * ext/curses/extconf.rb: now additionally checks for presence of these curses functions which are not present on NextStep or Openstep: bkgd(), bkgdset(), color(), curs(), getbkgd(), init(), scrl(), set(), setscrreg(), wattroff(), wattron(), wattrset(), wbkgd(), wbkgdset(), wscrl(), wsetscrreg() * ext/curses/curses.c: added appropriate #ifdef's for additional set of curses functions now checked by extconf.rb; fixed curses_bkgd() and window_bkgd() to correctly return boolean result rather than numeric result; fixed window_getbkgd() to correctly signal an error by returning nil rather than -1. * ext/etc/etc.c: setup_passwd() and setup_group() now check for null pointers before invoking rb_tainted_str_new2() upon fields extracted from `struct passwd' and `struct group' since null pointers in some fields are common on NextStep/OpenStep (especially so for the `pw_comment' field) and rb_tainted_str_new2() throws an exception when it receives a null pointer. * ext/pty/pty.c: include "util.h" for strdup()/ruby_strdup() for platforms such as NextStep and OpenStep which lack strdup(). * ext/socket/getaddrinfo.c: cast first argument of getservbyname(), gethostbyaddr(), and gethostbyname() from (const char*) to non-const (char*) for older platforms such as NextStep and OpenStep. * ext/socket/socket.c: include "util.h" for strdup()/ruby_strdup() for platforms such as NextStep and OpenStep which lack strdup(); include <netinet/in_systm.h> if present for NextStep and OpenStep; cast first argument of gethostbyaddr() and getservbyname() from (const char*) to non-const (char*) for older platforms. * ext/syslog/syslog.c: include "util.h" for strdup()/ruby_strdup() for platforms such as NextStep and OpenStep which lack strdup(). git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@5002 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-11-21 23:00:03 -05:00
#endif
#ifdef _WIN32
#include <windows.h>
#include <imagehlp.h>
#endif
#ifdef _WIN32
static const char *
dln_strerror(char *message, size_t size)
{
int error = GetLastError();
char *p = message;
size_t len = snprintf(message, size, "%d: ", error);
#define format_message(sublang) FormatMessage(\
2022-07-21 12:23:58 -04:00
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, \
NULL, error, MAKELANGID(LANG_NEUTRAL, (sublang)), \
message + len, size - len, NULL)
if (format_message(SUBLANG_ENGLISH_US) == 0)
2022-07-21 12:23:58 -04:00
format_message(SUBLANG_DEFAULT);
for (p = message + len; *p; p++) {
2022-07-21 12:23:58 -04:00
if (*p == '\n' || *p == '\r')
*p = ' ';
}
return message;
}
#define dln_strerror() dln_strerror(message, sizeof message)
#elif defined USE_DLN_DLOPEN
static const char *
dln_strerror(void)
{
return (char*)dlerror();
}
#endif
2019-06-19 05:06:57 -04:00
#if defined(_AIX)
static void
aix_loaderror(const char *pathname)
{
char *message[1024], errbuf[1024];
int i;
#define ERRBUF_APPEND(s) strlcat(errbuf, (s), sizeof(errbuf))
snprintf(errbuf, sizeof(errbuf), "load failed - %s. ", pathname);
if (loadquery(L_GETMESSAGES, &message[0], sizeof(message)) != -1) {
2022-07-21 12:23:58 -04:00
ERRBUF_APPEND("Please issue below command for detailed reasons:\n\t");
ERRBUF_APPEND("/usr/sbin/execerror ruby ");
for (i=0; message[i]; i++) {
ERRBUF_APPEND("\"");
ERRBUF_APPEND(message[i]);
ERRBUF_APPEND("\" ");
}
ERRBUF_APPEND("\n");
}
else {
2022-07-21 12:23:58 -04:00
ERRBUF_APPEND(strerror(errno));
ERRBUF_APPEND("[loadquery failed]");
}
dln_loaderror("%s", errbuf);
}
#endif
#if defined _WIN32 && defined RUBY_EXPORT
HANDLE rb_libruby_handle(void);
static int
rb_w32_check_imported(HMODULE ext, HMODULE mine)
{
ULONG size;
const IMAGE_IMPORT_DESCRIPTOR *desc;
desc = ImageDirectoryEntryToData(ext, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size);
if (!desc) return 0;
while (desc->Name) {
2022-07-21 12:23:58 -04:00
PIMAGE_THUNK_DATA pint = (PIMAGE_THUNK_DATA)((char *)ext + desc->Characteristics);
PIMAGE_THUNK_DATA piat = (PIMAGE_THUNK_DATA)((char *)ext + desc->FirstThunk);
for (; piat->u1.Function; piat++, pint++) {
static const char prefix[] = "rb_";
PIMAGE_IMPORT_BY_NAME pii;
const char *name;
if (IMAGE_SNAP_BY_ORDINAL(pint->u1.Ordinal)) continue;
pii = (PIMAGE_IMPORT_BY_NAME)((char *)ext + (size_t)pint->u1.AddressOfData);
name = (const char *)pii->Name;
if (strncmp(name, prefix, sizeof(prefix) - 1) == 0) {
FARPROC addr = GetProcAddress(mine, name);
if (addr) return (FARPROC)piat->u1.Function == addr;
}
}
desc++;
}
return 1;
}
#endif
#if defined(DLN_NEEDS_ALT_SEPARATOR) && DLN_NEEDS_ALT_SEPARATOR
#define translit_separator(src) do { \
2022-07-21 12:23:58 -04:00
char *tmp = ALLOCA_N(char, strlen(src) + 1), *p = tmp, c; \
do { \
*p++ = ((c = *file++) == '/') ? DLN_NEEDS_ALT_SEPARATOR : c; \
} while (c); \
(src) = tmp; \
} while (0)
#else
#define translit_separator(str) (void)(str)
#endif
#ifdef USE_DLN_DLOPEN
# include "ruby/internal/stdbool.h"
# include "internal/warnings.h"
static bool
dln_incompatible_func(void *handle, const char *funcname, void *const fp, const char **libname)
{
Dl_info dli;
void *ex = dlsym(handle, funcname);
if (!ex) return false;
if (ex == fp) return false;
if (dladdr(ex, &dli)) {
2022-07-21 12:23:58 -04:00
*libname = dli.dli_fname;
}
return true;
}
COMPILER_WARNING_PUSH
#if defined(__clang__) || GCC_VERSION_SINCE(4, 2, 0)
COMPILER_WARNING_IGNORED(-Wpedantic)
#endif
static bool
dln_incompatible_library_p(void *handle, const char **libname)
{
#define check_func(func) \
if (dln_incompatible_func(handle, EXTERNAL_PREFIX #func, (void *)&func, libname)) \
2022-07-21 12:23:58 -04:00
return true
check_func(ruby_xmalloc);
return false;
}
COMPILER_WARNING_POP
#endif
#if !defined(MAC_OS_X_VERSION_MIN_REQUIRED)
/* assume others than old Mac OS X have no problem */
# define dln_disable_dlclose() false
#elif !defined(MAC_OS_X_VERSION_10_11) || \
(MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_11)
/* targeting older versions only */
# define dln_disable_dlclose() true
#elif MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_11
/* targeting newer versions only */
# define dln_disable_dlclose() false
#else
/* support both versions, and check at runtime */
2022-02-17 03:35:38 -05:00
# include <sys/sysctl.h>
static bool
dln_disable_dlclose(void)
{
int mib[] = {CTL_KERN, KERN_OSREV};
int32_t rev;
size_t size = sizeof(rev);
if (sysctl(mib, numberof(mib), &rev, &size, NULL, 0)) return true;
if (rev < MAC_OS_X_VERSION_10_11) return true;
return false;
}
#endif
#if defined(_WIN32) || defined(USE_DLN_DLOPEN)
static void *
dln_open(const char *file)
{
static const char incompatible[] = "incompatible library version";
const char *error = NULL;
void *handle;
#if defined(_WIN32)
char message[1024];
/* Convert the file path to wide char */
WCHAR *winfile = rb_w32_mbstr_to_wstr(CP_UTF8, file, -1, NULL);
if (!winfile) {
2022-07-21 12:23:58 -04:00
dln_memerror();
}
/* Load file */
handle = LoadLibraryW(winfile);
free(winfile);
if (!handle) {
2022-07-21 12:23:58 -04:00
error = dln_strerror();
goto failed;
}
# if defined(RUBY_EXPORT)
if (!rb_w32_check_imported(handle, rb_libruby_handle())) {
2022-07-21 12:23:58 -04:00
FreeLibrary(handle);
error = incompatible;
goto failed;
}
# endif
#elif defined(USE_DLN_DLOPEN)
# ifndef RTLD_LAZY
# define RTLD_LAZY 1
# endif
# ifdef __INTERIX
# undef RTLD_GLOBAL
# endif
# ifndef RTLD_GLOBAL
# define RTLD_GLOBAL 0
# endif
/* Load file */
handle = dlopen(file, RTLD_LAZY|RTLD_GLOBAL);
if (handle == NULL) {
error = dln_strerror();
goto failed;
}
# if defined(RUBY_EXPORT)
2022-02-17 03:35:38 -05:00
{
2022-07-21 12:23:58 -04:00
const char *libruby_name = NULL;
if (dln_incompatible_library_p(handle, &libruby_name)) {
if (dln_disable_dlclose()) {
/* dlclose() segfaults */
if (libruby_name) {
dln_fatalerror("linked to incompatible %s - %s", libruby_name, file);
}
dln_fatalerror("%s - %s", incompatible, file);
}
else {
dlclose(handle);
if (libruby_name) {
dln_loaderror("linked to incompatible %s - %s", libruby_name, file);
}
error = incompatible;
goto failed;
}
}
2022-02-17 03:35:38 -05:00
}
# endif
#endif
return handle;
failed:
dln_loaderror("%s - %s", error, file);
}
static void *
dln_sym(void *handle, const char *symbol)
{
void *func;
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);
}
#endif
#if defined(RUBY_DLN_CHECK_ABI) && defined(USE_DLN_DLOPEN)
static bool
abi_check_enabled_p(void)
{
const char *val = getenv("RUBY_ABI_CHECK");
return val == NULL || !(val[0] == '0' && val[1] == '\0');
}
#endif
void *
dln_load(const char *file)
{
#if defined(_WIN32) || defined(USE_DLN_DLOPEN)
void *handle = dln_open(file);
#ifdef RUBY_DLN_CHECK_ABI
unsigned long long (*abi_version_fct)(void) = (unsigned long long(*)(void))dln_sym(handle, "ruby_abi_version");
unsigned long long binary_abi_version = (*abi_version_fct)();
if (binary_abi_version != ruby_abi_version() && abi_check_enabled_p()) {
2022-07-16 19:59:20 -04:00
dln_loaderror("incompatible ABI version of binary - %s", file);
}
#endif
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)();
return handle;
#elif defined(_AIX)
{
2022-07-21 12:23:58 -04:00
void (*init_fct)(void);
init_fct = (void(*)(void))load((char*)file, 1, 0);
if (init_fct == NULL) {
aix_loaderror(file);
}
if (loadbind(0, (void*)dln_load, (void*)init_fct) == -1) {
aix_loaderror(file);
}
(*init_fct)();
return (void*)init_fct;
}
#else
dln_notimplement();
#endif
return 0; /* dummy return */
}