14#define dln_notimplement rb_notimplement
15#define dln_memerror rb_memerror
16#define dln_exit rb_exit
17#define dln_loaderror rb_loaderror
19#define dln_notimplement --->>> dln not implemented <<<---
20#define dln_memerror abort
22static void dln_loaderror(
const char *format, ...);
26#include "internal/compilers.h"
32#if defined(HAVE_ALLOCA_H)
49#define free(x) xfree(x)
53#include "missing/file.h"
59# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
62#ifdef HAVE_SYS_PARAM_H
63# include <sys/param.h>
66# define MAXPATHLEN 1024
78# if defined(HAVE_DLOPEN)
88dln_loaderror(
const char *format, ...)
92 vfprintf(stderr, format, ap);
98#if defined(HAVE_DLOPEN) && !defined(_AIX) && !defined(MACOSX_DYLD) && !defined(_UNICOSMP)
100# define USE_DLN_DLOPEN
103#if defined(__hp9000s300) || ((defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)) && !defined(__ELF__)) || defined(NeXT) || defined(MACOSX_DYLD)
104# define EXTERNAL_PREFIX "_"
106# define EXTERNAL_PREFIX ""
108#define FUNCNAME_PREFIX EXTERNAL_PREFIX"Init_"
110#if defined __CYGWIN__ || defined DOSISH
111#define isdirsep(x) ((x) == '/' || (x) == '\\')
113#define isdirsep(x) ((x) == '/')
117init_funcname_len(
const char **file)
119 const char *p = *file, *base, *dot = NULL;
122 for (base = p; *p; p++) {
123 if (*p ==
'.' && !dot) dot = p;
124 if (isdirsep(*p)) base = p+1, dot = NULL;
128 return (dot ? dot : p) - base;
131static const char funcname_prefix[
sizeof(FUNCNAME_PREFIX) - 1] = FUNCNAME_PREFIX;
133#define init_funcname(buf, file) do {\
134 const char *base = (file);\
135 const size_t flen = init_funcname_len(&base);\
136 const size_t plen = sizeof(funcname_prefix);\
137 char *const tmp = ALLOCA_N(char, plen+flen+1);\
141 memcpy(tmp, funcname_prefix, plen);\
142 memcpy(tmp+plen, base, flen);\
143 tmp[plen+flen] = '\0';\
163#if NS_TARGET_MAJOR < 4
164#include <mach-o/rld.h>
166#include <mach-o/dyld.h>
167#ifndef NSLINKMODULE_OPTION_BINDNOW
168#define NSLINKMODULE_OPTION_BINDNOW 1
173#include <mach-o/dyld.h>
184dln_strerror(
char *message,
size_t size)
186 int error = GetLastError();
188 size_t len = snprintf(message, size,
"%d: ", error);
190#define format_message(sublang) FormatMessage(\
191 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, \
192 NULL, error, MAKELANGID(LANG_NEUTRAL, (sublang)), \
193 message + len, size - len, NULL)
194 if (format_message(SUBLANG_ENGLISH_US) == 0)
195 format_message(SUBLANG_DEFAULT);
196 for (p = message + len; *p; p++) {
197 if (*p ==
'\n' || *p ==
'\r')
202#define dln_strerror() dln_strerror(message, sizeof message)
203#elif defined USE_DLN_DLOPEN
207 return (
char*)dlerror();
213aix_loaderror(
const char *pathname)
215 char *message[1024], errbuf[1024];
217#define ERRBUF_APPEND(s) strlcat(errbuf, (s), sizeof(errbuf))
218 snprintf(errbuf,
sizeof(errbuf),
"load failed - %s. ", pathname);
220 if (loadquery(L_GETMESSAGES, &message[0],
sizeof(message)) != -1) {
221 ERRBUF_APPEND(
"Please issue below command for detailed reasons:\n\t");
222 ERRBUF_APPEND(
"/usr/sbin/execerror ruby ");
223 for (i=0; message[i]; i++) {
225 ERRBUF_APPEND(message[i]);
226 ERRBUF_APPEND(
"\" ");
231 ERRBUF_APPEND(strerror(errno));
232 ERRBUF_APPEND(
"[loadquery failed]");
234 dln_loaderror(
"%s", errbuf);
238#if defined _WIN32 && defined RUBY_EXPORT
239HANDLE rb_libruby_handle(
void);
242rb_w32_check_imported(HMODULE ext, HMODULE mine)
245 const IMAGE_IMPORT_DESCRIPTOR *desc;
247 desc = ImageDirectoryEntryToData(ext, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size);
250 PIMAGE_THUNK_DATA pint = (PIMAGE_THUNK_DATA)((
char *)ext + desc->Characteristics);
251 PIMAGE_THUNK_DATA piat = (PIMAGE_THUNK_DATA)((
char *)ext + desc->FirstThunk);
252 for (; piat->u1.Function; piat++, pint++) {
253 static const char prefix[] =
"rb_";
254 PIMAGE_IMPORT_BY_NAME pii;
257 if (IMAGE_SNAP_BY_ORDINAL(pint->u1.Ordinal))
continue;
258 pii = (PIMAGE_IMPORT_BY_NAME)((
char *)ext + (size_t)pint->u1.AddressOfData);
259 name = (
const char *)pii->Name;
260 if (strncmp(name, prefix,
sizeof(prefix) - 1) == 0) {
261 FARPROC addr = GetProcAddress(mine, name);
262 if (addr)
return (FARPROC)piat->u1.Function == addr;
271#if defined(DLN_NEEDS_ALT_SEPARATOR) && DLN_NEEDS_ALT_SEPARATOR
272#define translit_separator(src) do { \
273 char *tmp = ALLOCA_N(char, strlen(src) + 1), *p = tmp, c; \
275 *p++ = ((c = *file++) == '/') ? DLN_NEEDS_ALT_SEPARATOR : c; \
280#define translit_separator(str) (void)(str)
285# include "internal/warnings.h"
287#if defined(__clang__) || GCC_VERSION_SINCE(4, 2, 0)
288COMPILER_WARNING_IGNORED(-Wpedantic)
291dln_incompatible_library_p(
void *handle)
293 void *ex = dlsym(handle, EXTERNAL_PREFIX
"ruby_xmalloc");
295 return ex && ex != fp;
301dln_load(
const char *file)
303#if (defined _WIN32 || defined USE_DLN_DLOPEN) && defined RUBY_EXPORT
304 static const char incompatible[] =
"incompatible library version";
306#if defined _WIN32 || defined USE_DLN_DLOPEN
307 const char *error = 0;
314 void (*init_fct)(void);
318 init_funcname(&buf, file);
321 winfile = rb_w32_mbstr_to_wstr(CP_UTF8, file, -1, NULL);
327 handle = LoadLibraryW(winfile);
331 error = dln_strerror();
335#if defined _WIN32 && defined RUBY_EXPORT
336 if (!rb_w32_check_imported(handle, rb_libruby_handle())) {
338 error = incompatible;
343 if ((init_fct = (
void(*)(
void))GetProcAddress(handle, buf)) == NULL) {
344 dln_loaderror(
"%s - %s\n%s", dln_strerror(), buf, file);
353 init_funcname(&buf, file);
354 translit_separator(file);
360 void (*init_fct)(void);
369# define RTLD_GLOBAL 0
373 if ((handle = (
void*)dlopen(file, RTLD_LAZY|RTLD_GLOBAL)) == NULL) {
374 error = dln_strerror();
377# if defined RUBY_EXPORT
379 if (dln_incompatible_library_p(handle)) {
381# if defined __APPLE__ && \
382 defined(MAC_OS_X_VERSION_MIN_REQUIRED) && \
383 (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_11)
385 rb_fatal(
"%s - %s", incompatible, file);
388 error = incompatible;
395 init_fct = (void(*)(void))(
VALUE)dlsym(handle, buf);
396 if (init_fct == NULL) {
397 const size_t errlen = strlen(error = dln_strerror()) + 1;
398 error = memcpy(
ALLOCA_N(
char, errlen), error, errlen);
414 void (*init_fct)(void);
416 flags = BIND_DEFERRED;
417 lib = shl_load(file, flags, 0);
420 dln_loaderror(
"%s - %s", strerror(errno), file);
422 shl_findsym(&lib, buf, TYPE_PROCEDURE, (
void*)&init_fct);
423 if (init_fct == NULL) {
424 shl_findsym(&lib, buf, TYPE_UNDEFINED, (
void*)&init_fct);
425 if (init_fct == NULL) {
427 dln_loaderror(
"%s - %s", strerror(ENOSYM), file);
438 void (*init_fct)(void);
440 init_fct = (void(*)(void))load((
char*)file, 1, 0);
441 if (init_fct == NULL) {
444 if (loadbind(0, (
void*)dln_load, (
void*)init_fct) == -1) {
448 return (
void*)init_fct;
452#if defined(MACOSX_DYLD)
465 NSObjectFileImage obj_file;
469 void (*init_fct)(void);
472 dyld_result = NSCreateObjectFileImageFromFile(file, &obj_file);
474 if (dyld_result != NSObjectFileImageSuccess) {
475 dln_loaderror(
"Failed to load %.200s", file);
478 NSLinkModule(obj_file, file, NSLINKMODULE_OPTION_BINDNOW);
481 if (!NSIsSymbolNameDefined(buf)) {
482 dln_loaderror(
"Failed to lookup Init function %.200s",file);
484 init_fct = NSAddressOfSymbol(NSLookupAndBindSymbol(buf));
487 return (
void*)init_fct;
496#if defined(_WIN32) || defined(USE_DLN_DLOPEN)
498 dln_loaderror(
"%s - %s", error, file);
#define xrealloc
Old name of ruby_xrealloc.
#define xmalloc
Old name of ruby_xmalloc.
#define xcalloc
Old name of ruby_xcalloc.
void rb_fatal(const char *fmt,...)
Raises the unsung "fatal" exception.
#define ALLOCA_N(type, n)
uintptr_t VALUE
Type that represents a Ruby object.
void * ruby_xmalloc(size_t size)
Allocates a storage instance.