2000-05-01 13:42:38 +04:00
|
|
|
/**********************************************************************
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
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-25 07:29:39 +04:00
|
|
|
Copyright (C) 1993-2007 Yukihiro Matsumoto
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2000-05-01 13:42:38 +04:00
|
|
|
**********************************************************************/
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2009-09-28 17:46:18 +04:00
|
|
|
#ifdef RUBY_EXPORT
|
2007-06-10 07:06:15 +04:00
|
|
|
#include "ruby/ruby.h"
|
2009-09-28 17:46:18 +04:00
|
|
|
#define dln_notimplement rb_notimplement
|
|
|
|
#define dln_memerror rb_memerror
|
|
|
|
#define dln_exit rb_exit
|
|
|
|
#define dln_loaderror rb_loaderror
|
2022-02-17 11:35:38 +03:00
|
|
|
#define dln_fatalerror rb_fatal
|
2009-09-28 17:46:18 +04:00
|
|
|
#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 11:35:38 +03:00
|
|
|
#define dln_fatalerror dln_loaderror
|
2009-09-28 17:46:18 +04:00
|
|
|
#endif
|
1998-01-16 15:13:05 +03:00
|
|
|
#include "dln.h"
|
2018-01-02 09:46:40 +03:00
|
|
|
#include "internal.h"
|
2021-09-09 06:19:20 +03:00
|
|
|
#include "internal/compilers.h"
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2002-02-18 12:52:48 +03:00
|
|
|
#ifdef HAVE_STDLIB_H
|
|
|
|
# include <stdlib.h>
|
|
|
|
#endif
|
|
|
|
|
2003-07-24 22:33:50 +04:00
|
|
|
#if defined(HAVE_ALLOCA_H)
|
1998-01-16 15:13:05 +03:00
|
|
|
#include <alloca.h>
|
|
|
|
#endif
|
|
|
|
|
1998-01-16 15:19:22 +03:00
|
|
|
#ifdef HAVE_STRING_H
|
|
|
|
# include <string.h>
|
|
|
|
#else
|
|
|
|
# include <strings.h>
|
|
|
|
#endif
|
|
|
|
|
2022-10-19 13:49:45 +03:00
|
|
|
#if defined __APPLE__
|
|
|
|
# include <AvailabilityMacros.h>
|
|
|
|
#endif
|
|
|
|
|
1999-08-13 09:45:20 +04:00
|
|
|
#ifndef xmalloc
|
1998-01-16 15:13:05 +03:00
|
|
|
void *xmalloc();
|
|
|
|
void *xcalloc();
|
|
|
|
void *xrealloc();
|
1999-08-13 09:45:20 +04:00
|
|
|
#endif
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2014-06-05 09:16:46 +04:00
|
|
|
#undef free
|
* array.c, bignum.c, cont.c, dir.c, dln.c, encoding.c, enumerator.c,
enumerator.c (enumerator_allocate), eval_jump.c, file.c, hash.c,
io.c, load.c, pack.c, proc.c, random.c, re.c, ruby.c, st.c,
string.c, thread.c, thread_pthread.c, time.c, util.c, variable.c,
vm.c, gc.c:
allocated memory objects by xmalloc (ruby_xmalloc) should be
freed by xfree (ruby_xfree).
* ext/curses/curses.c, ext/dbm/dbm.c, ext/digest/digest.c,
ext/gdbm/gdbm.c, ext/json/ext/parser/parser.c,
ext/json/ext/parser/unicode.c, ext/openssl/ossl_cipher.c,
ext/openssl/ossl_hmac.c, ext/openssl/ossl_pkey_ec.c,
ext/sdbm/init.c, ext/strscan/strscan.c, ext/zlib/zlib.c:
ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@17017 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-06-08 14:01:40 +04:00
|
|
|
#define free(x) xfree(x)
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
#include <stdio.h>
|
2008-10-04 17:57:06 +04:00
|
|
|
#if defined(_WIN32)
|
1998-01-16 15:13:05 +03:00
|
|
|
#include "missing/file.h"
|
|
|
|
#endif
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
2001-05-30 13:12:34 +04:00
|
|
|
#ifndef S_ISDIR
|
2022-10-19 13:49:45 +03:00
|
|
|
# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
|
2001-05-30 13:12:34 +04:00
|
|
|
#endif
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
#ifdef HAVE_SYS_PARAM_H
|
|
|
|
# include <sys/param.h>
|
|
|
|
#endif
|
2002-11-27 12:11:55 +03:00
|
|
|
#ifndef MAXPATHLEN
|
|
|
|
# define MAXPATHLEN 1024
|
|
|
|
#endif
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
#ifdef HAVE_UNISTD_H
|
|
|
|
# include <unistd.h>
|
|
|
|
#endif
|
|
|
|
|
2009-09-28 17:46:18 +04:00
|
|
|
#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
|
|
|
|
|
2022-01-14 18:33:42 +03:00
|
|
|
#if defined(HAVE_DLOPEN) && !defined(_AIX) && !defined(_UNICOSMP)
|
1998-01-16 15:13:05 +03:00
|
|
|
/* dynamic load with dlopen() */
|
|
|
|
# define USE_DLN_DLOPEN
|
|
|
|
#endif
|
|
|
|
|
2022-01-14 18:33:42 +03:00
|
|
|
#if defined(__hp9000s300) || ((defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)) && !defined(__ELF__)) || defined(NeXT)
|
2015-05-01 10:27:03 +03:00
|
|
|
# define EXTERNAL_PREFIX "_"
|
|
|
|
#else
|
|
|
|
# define EXTERNAL_PREFIX ""
|
|
|
|
#endif
|
|
|
|
#define FUNCNAME_PREFIX EXTERNAL_PREFIX"Init_"
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2010-11-09 15:57:53 +03:00
|
|
|
#if defined __CYGWIN__ || defined DOSISH
|
|
|
|
#define isdirsep(x) ((x) == '/' || (x) == '\\')
|
|
|
|
#else
|
|
|
|
#define isdirsep(x) ((x) == '/')
|
|
|
|
#endif
|
|
|
|
|
2022-01-20 04:03:59 +03:00
|
|
|
#if defined(_WIN32) || defined(USE_DLN_DLOPEN)
|
2009-03-14 04:56:15 +03:00
|
|
|
static size_t
|
2010-11-09 15:57:53 +03:00
|
|
|
init_funcname_len(const char **file)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2010-11-09 15:57:53 +03:00
|
|
|
const char *p = *file, *base, *dot = NULL;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
/* Load the file as an object one */
|
2010-11-09 15:57:53 +03:00
|
|
|
for (base = p; *p; p++) { /* Find position of last '/' */
|
2011-01-05 23:03:28 +03:00
|
|
|
if (*p == '.' && !dot) dot = p;
|
|
|
|
if (isdirsep(*p)) base = p+1, dot = NULL;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2010-11-09 15:57:53 +03:00
|
|
|
*file = base;
|
|
|
|
/* Delete suffix if it exists */
|
2011-01-05 23:03:28 +03:00
|
|
|
return (dot ? dot : p) - base;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2010-11-09 15:57:53 +03:00
|
|
|
static const char funcname_prefix[sizeof(FUNCNAME_PREFIX) - 1] = FUNCNAME_PREFIX;
|
|
|
|
|
2002-09-05 13:17:48 +04:00
|
|
|
#define init_funcname(buf, file) do {\
|
2010-12-09 13:26:14 +03:00
|
|
|
const char *base = (file);\
|
2010-11-09 15:57:53 +03:00
|
|
|
const size_t flen = init_funcname_len(&base);\
|
|
|
|
const size_t plen = sizeof(funcname_prefix);\
|
|
|
|
char *const tmp = ALLOCA_N(char, plen+flen+1);\
|
2002-09-05 13:17:48 +04:00
|
|
|
if (!tmp) {\
|
2009-09-28 17:46:18 +04:00
|
|
|
dln_memerror();\
|
2002-09-05 13:17:48 +04:00
|
|
|
}\
|
2010-11-09 15:57:53 +03:00
|
|
|
memcpy(tmp, funcname_prefix, plen);\
|
|
|
|
memcpy(tmp+plen, base, flen);\
|
|
|
|
tmp[plen+flen] = '\0';\
|
2010-12-09 13:26:14 +03:00
|
|
|
*(buf) = tmp;\
|
2002-09-05 13:17:48 +04:00
|
|
|
} while (0)
|
2022-01-20 04:03:59 +03:00
|
|
|
#endif
|
2002-09-05 13:17:48 +04:00
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
#ifdef USE_DLN_DLOPEN
|
2003-12-25 11:49:20 +03:00
|
|
|
# include <dlfcn.h>
|
1998-01-16 15:13:05 +03:00
|
|
|
#endif
|
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
#if defined(_AIX)
|
1998-01-16 15:13:05 +03:00
|
|
|
#include <ctype.h> /* for isdigit() */
|
|
|
|
#include <errno.h> /* for global errno */
|
|
|
|
#include <sys/ldr.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef NeXT
|
1999-01-20 07:59:39 +03:00
|
|
|
#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-22 07:00:03 +03:00
|
|
|
#ifndef NSLINKMODULE_OPTION_BINDNOW
|
|
|
|
#define NSLINKMODULE_OPTION_BINDNOW 1
|
1999-01-20 07:59:39 +03:00
|
|
|
#endif
|
1998-01-16 15:13:05 +03:00
|
|
|
#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-22 07:00:03 +03:00
|
|
|
#endif
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2015-10-18 05:08:56 +03:00
|
|
|
#ifdef _WIN32
|
1998-01-16 15:19:22 +03:00
|
|
|
#include <windows.h>
|
2010-05-16 10:09:40 +04:00
|
|
|
#include <imagehlp.h>
|
1998-01-16 15:19:22 +03:00
|
|
|
#endif
|
|
|
|
|
2015-10-18 05:08:56 +03:00
|
|
|
#ifdef _WIN32
|
2010-05-16 10:09:40 +04:00
|
|
|
static const char *
|
|
|
|
dln_strerror(char *message, size_t size)
|
|
|
|
{
|
|
|
|
int error = GetLastError();
|
|
|
|
char *p = message;
|
|
|
|
size_t len = snprintf(message, size, "%d: ", error);
|
|
|
|
|
2010-10-16 03:39:16 +04:00
|
|
|
#define format_message(sublang) FormatMessage(\
|
|
|
|
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, \
|
2010-12-09 13:26:14 +03:00
|
|
|
NULL, error, MAKELANGID(LANG_NEUTRAL, (sublang)), \
|
2010-10-16 03:39:16 +04:00
|
|
|
message + len, size - len, NULL)
|
|
|
|
if (format_message(SUBLANG_ENGLISH_US) == 0)
|
|
|
|
format_message(SUBLANG_DEFAULT);
|
2010-05-16 10:09:40 +04:00
|
|
|
for (p = message + len; *p; p++) {
|
|
|
|
if (*p == '\n' || *p == '\r')
|
|
|
|
*p = ' ';
|
|
|
|
}
|
|
|
|
return message;
|
|
|
|
}
|
|
|
|
#define dln_strerror() dln_strerror(message, sizeof message)
|
2021-12-16 18:44:54 +03:00
|
|
|
#elif defined USE_DLN_DLOPEN
|
1999-08-13 09:45:20 +04:00
|
|
|
static const char *
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
dln_strerror(void)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
return (char*)dlerror();
|
|
|
|
}
|
2009-09-23 20:18:59 +04:00
|
|
|
#endif
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2019-06-19 12:06:57 +03:00
|
|
|
#if defined(_AIX)
|
1998-01-16 15:13:05 +03:00
|
|
|
static void
|
1999-08-13 09:45:20 +04:00
|
|
|
aix_loaderror(const char *pathname)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2014-02-27 11:10:14 +04:00
|
|
|
char *message[1024], errbuf[1024];
|
|
|
|
int i;
|
2014-02-27 11:10:13 +04:00
|
|
|
#define ERRBUF_APPEND(s) strlcat(errbuf, (s), sizeof(errbuf))
|
2014-02-27 11:10:14 +04:00
|
|
|
snprintf(errbuf, sizeof(errbuf), "load failed - %s. ", pathname);
|
|
|
|
|
|
|
|
if (loadquery(L_GETMESSAGES, &message[0], sizeof(message)) != -1) {
|
|
|
|
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 {
|
|
|
|
ERRBUF_APPEND(strerror(errno));
|
|
|
|
ERRBUF_APPEND("[loadquery failed]");
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2014-02-27 11:10:14 +04:00
|
|
|
dln_loaderror("%s", errbuf);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2010-05-16 10:09:40 +04:00
|
|
|
#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) {
|
|
|
|
PIMAGE_THUNK_DATA pint = (PIMAGE_THUNK_DATA)((char *)ext + desc->Characteristics);
|
|
|
|
PIMAGE_THUNK_DATA piat = (PIMAGE_THUNK_DATA)((char *)ext + desc->FirstThunk);
|
2012-04-17 08:11:17 +04:00
|
|
|
for (; piat->u1.Function; piat++, pint++) {
|
2010-05-16 10:09:40 +04:00
|
|
|
static const char prefix[] = "rb_";
|
2012-04-16 16:25:29 +04:00
|
|
|
PIMAGE_IMPORT_BY_NAME pii;
|
|
|
|
const char *name;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2012-04-16 16:25:29 +04:00
|
|
|
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;
|
2010-10-12 18:53:59 +04:00
|
|
|
if (strncmp(name, prefix, sizeof(prefix) - 1) == 0) {
|
|
|
|
FARPROC addr = GetProcAddress(mine, name);
|
2010-05-16 10:09:40 +04:00
|
|
|
if (addr) return (FARPROC)piat->u1.Function == addr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
desc++;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2010-02-24 05:52:08 +03:00
|
|
|
#if defined(DLN_NEEDS_ALT_SEPARATOR) && DLN_NEEDS_ALT_SEPARATOR
|
|
|
|
#define translit_separator(src) do { \
|
|
|
|
char *tmp = ALLOCA_N(char, strlen(src) + 1), *p = tmp, c; \
|
|
|
|
do { \
|
|
|
|
*p++ = ((c = *file++) == '/') ? DLN_NEEDS_ALT_SEPARATOR : c; \
|
|
|
|
} while (c); \
|
2010-12-09 13:26:14 +03:00
|
|
|
(src) = tmp; \
|
2010-02-24 05:52:08 +03:00
|
|
|
} while (0)
|
|
|
|
#else
|
|
|
|
#define translit_separator(str) (void)(str)
|
|
|
|
#endif
|
|
|
|
|
2018-01-03 12:05:18 +03:00
|
|
|
#ifdef USE_DLN_DLOPEN
|
2020-05-08 12:31:09 +03:00
|
|
|
# include "ruby/internal/stdbool.h"
|
2019-12-04 11:16:30 +03:00
|
|
|
# include "internal/warnings.h"
|
2022-02-17 11:49:16 +03:00
|
|
|
static bool
|
|
|
|
dln_incompatible_func(void *handle, const char *funcname, void *const fp, const char **libname)
|
|
|
|
{
|
|
|
|
void *ex = dlsym(handle, funcname);
|
|
|
|
if (!ex) return false;
|
|
|
|
if (ex == fp) return false;
|
2023-12-17 17:21:17 +03:00
|
|
|
# if defined(HAVE_DLADDR)
|
|
|
|
Dl_info dli;
|
2022-02-17 11:49:16 +03:00
|
|
|
if (dladdr(ex, &dli)) {
|
|
|
|
*libname = dli.dli_fname;
|
|
|
|
}
|
2023-12-17 17:21:17 +03:00
|
|
|
# endif
|
2022-02-17 11:49:16 +03:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-07-30 10:07:48 +03:00
|
|
|
COMPILER_WARNING_PUSH
|
|
|
|
#if defined(__clang__) || GCC_VERSION_SINCE(4, 2, 0)
|
|
|
|
COMPILER_WARNING_IGNORED(-Wpedantic)
|
2018-01-02 09:41:55 +03:00
|
|
|
#endif
|
2018-01-03 12:19:11 +03:00
|
|
|
static bool
|
2022-02-17 11:49:16 +03:00
|
|
|
dln_incompatible_library_p(void *handle, const char **libname)
|
2018-01-02 09:41:55 +03:00
|
|
|
{
|
2022-02-17 11:49:16 +03:00
|
|
|
#define check_func(func) \
|
|
|
|
if (dln_incompatible_func(handle, EXTERNAL_PREFIX #func, (void *)&func, libname)) \
|
|
|
|
return true
|
|
|
|
check_func(ruby_xmalloc);
|
|
|
|
return false;
|
2018-01-02 09:41:55 +03:00
|
|
|
}
|
2018-07-30 10:07:48 +03:00
|
|
|
COMPILER_WARNING_POP
|
2018-01-03 12:05:18 +03:00
|
|
|
#endif
|
2018-01-02 09:41:55 +03:00
|
|
|
|
2022-06-26 18:20:21 +03:00
|
|
|
#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
|
|
|
|
|
2022-10-17 08:46:10 +03:00
|
|
|
#elif MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_11
|
|
|
|
/* targeting newer versions only */
|
|
|
|
# define dln_disable_dlclose() false
|
|
|
|
|
2022-06-26 18:20:21 +03:00
|
|
|
#else
|
|
|
|
/* support both versions, and check at runtime */
|
2022-02-17 11:35:38 +03: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
|
|
|
|
|
2022-01-19 17:00:33 +03:00
|
|
|
#if defined(_WIN32) || defined(USE_DLN_DLOPEN)
|
|
|
|
static void *
|
|
|
|
dln_open(const char *file)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2016-04-08 02:46:45 +03:00
|
|
|
static const char incompatible[] = "incompatible library version";
|
2022-01-19 17:00:33 +03:00
|
|
|
const char *error = NULL;
|
|
|
|
void *handle;
|
2002-06-17 05:54:51 +04:00
|
|
|
|
2022-01-19 17:00:33 +03:00
|
|
|
#if defined(_WIN32)
|
2010-05-16 10:09:40 +04:00
|
|
|
char message[1024];
|
1998-01-16 15:19:22 +03:00
|
|
|
|
2014-04-06 03:52:52 +04:00
|
|
|
/* Convert the file path to wide char */
|
2022-01-19 17:00:33 +03:00
|
|
|
WCHAR *winfile = rb_w32_mbstr_to_wstr(CP_UTF8, file, -1, NULL);
|
2014-04-06 03:52:52 +04:00
|
|
|
if (!winfile) {
|
|
|
|
dln_memerror();
|
|
|
|
}
|
1998-01-16 15:19:22 +03:00
|
|
|
|
|
|
|
/* Load file */
|
2014-04-06 03:52:52 +04:00
|
|
|
handle = LoadLibraryW(winfile);
|
|
|
|
free(winfile);
|
|
|
|
|
|
|
|
if (!handle) {
|
2002-06-17 05:54:51 +04:00
|
|
|
error = dln_strerror();
|
1998-01-16 15:19:22 +03:00
|
|
|
goto failed;
|
|
|
|
}
|
|
|
|
|
2022-01-19 17:00:33 +03:00
|
|
|
# if defined(RUBY_EXPORT)
|
2010-05-16 10:09:40 +04:00
|
|
|
if (!rb_w32_check_imported(handle, rb_libruby_handle())) {
|
|
|
|
FreeLibrary(handle);
|
2016-04-08 02:46:45 +03:00
|
|
|
error = incompatible;
|
2010-05-16 10:09:40 +04:00
|
|
|
goto failed;
|
|
|
|
}
|
2022-01-19 17:00:33 +03:00
|
|
|
# endif
|
2002-02-18 12:52:48 +03:00
|
|
|
|
2022-01-19 17:00:33 +03:00
|
|
|
#elif defined(USE_DLN_DLOPEN)
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2022-01-19 17:00:33 +03:00
|
|
|
# ifndef RTLD_LAZY
|
|
|
|
# define RTLD_LAZY 1
|
|
|
|
# endif
|
|
|
|
# ifdef __INTERIX
|
|
|
|
# undef RTLD_GLOBAL
|
|
|
|
# endif
|
|
|
|
# ifndef RTLD_GLOBAL
|
|
|
|
# define RTLD_GLOBAL 0
|
|
|
|
# endif
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2022-01-19 17:00:33 +03:00
|
|
|
/* Load file */
|
|
|
|
handle = dlopen(file, RTLD_LAZY|RTLD_GLOBAL);
|
|
|
|
if (handle == NULL) {
|
|
|
|
error = dln_strerror();
|
|
|
|
goto failed;
|
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2022-01-19 17:00:33 +03:00
|
|
|
# if defined(RUBY_EXPORT)
|
2022-02-17 11:35:38 +03:00
|
|
|
{
|
2022-02-17 11:49:16 +03:00
|
|
|
const char *libruby_name = NULL;
|
|
|
|
if (dln_incompatible_library_p(handle, &libruby_name)) {
|
2022-02-17 11:35:38 +03:00
|
|
|
if (dln_disable_dlclose()) {
|
2015-05-01 07:30:26 +03:00
|
|
|
/* dlclose() segfaults */
|
2022-02-17 11:49:16 +03:00
|
|
|
if (libruby_name) {
|
|
|
|
dln_fatalerror("linked to incompatible %s - %s", libruby_name, file);
|
|
|
|
}
|
2022-02-17 11:35:38 +03:00
|
|
|
dln_fatalerror("%s - %s", incompatible, file);
|
|
|
|
}
|
|
|
|
else {
|
2023-03-21 13:10:19 +03:00
|
|
|
if (libruby_name) {
|
|
|
|
const size_t len = strlen(libruby_name);
|
|
|
|
char *const tmp = ALLOCA_N(char, len + 1);
|
|
|
|
if (tmp) memcpy(tmp, libruby_name, len + 1);
|
|
|
|
libruby_name = tmp;
|
|
|
|
}
|
2015-05-01 07:30:26 +03:00
|
|
|
dlclose(handle);
|
2022-02-17 11:49:16 +03:00
|
|
|
if (libruby_name) {
|
|
|
|
dln_loaderror("linked to incompatible %s - %s", libruby_name, file);
|
|
|
|
}
|
2015-05-01 07:30:26 +03:00
|
|
|
error = incompatible;
|
|
|
|
goto failed;
|
|
|
|
}
|
|
|
|
}
|
2022-02-17 11:35:38 +03:00
|
|
|
}
|
2015-05-01 07:30:26 +03:00
|
|
|
# endif
|
2022-01-19 17:00:33 +03:00
|
|
|
#endif
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2022-01-19 17:00:33 +03:00
|
|
|
return handle;
|
2002-02-18 12:52:48 +03:00
|
|
|
|
2022-01-19 17:00:33 +03:00
|
|
|
failed:
|
|
|
|
dln_loaderror("%s - %s", error, file);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *
|
|
|
|
dln_sym(void *handle, const char *symbol)
|
|
|
|
{
|
|
|
|
#if defined(_WIN32)
|
2023-12-07 14:38:53 +03:00
|
|
|
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);
|
2022-01-19 17:00:33 +03:00
|
|
|
|
|
|
|
if (func == NULL) {
|
2023-12-07 14:38:53 +03:00
|
|
|
const char *error;
|
|
|
|
#if defined(_WIN32)
|
|
|
|
char message[1024];
|
2022-01-19 17:00:33 +03:00
|
|
|
error = dln_strerror();
|
|
|
|
#elif defined(USE_DLN_DLOPEN)
|
|
|
|
const size_t errlen = strlen(error = dln_strerror()) + 1;
|
|
|
|
error = memcpy(ALLOCA_N(char, errlen), error, errlen);
|
|
|
|
#endif
|
2023-12-07 14:38:53 +03:00
|
|
|
dln_loaderror("%s - %s", error, symbol);
|
|
|
|
}
|
2022-01-19 17:00:33 +03:00
|
|
|
return func;
|
|
|
|
}
|
2023-12-07 14:38:53 +03:00
|
|
|
|
|
|
|
#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)
|
2023-12-08 09:06:12 +03:00
|
|
|
handle = dlopen(NULL, RTLD_LAZY | RTLD_GLOBAL);
|
|
|
|
# elif defined(_WIN32)
|
2023-12-07 14:38:53 +03:00
|
|
|
handle = rb_libruby_handle();
|
|
|
|
# else
|
|
|
|
return NULL;
|
|
|
|
# endif
|
|
|
|
}
|
|
|
|
return dln_sym(handle, symbol);
|
|
|
|
#else
|
|
|
|
return NULL;
|
2022-01-19 17:00:33 +03:00
|
|
|
#endif
|
2023-12-07 14:38:53 +03:00
|
|
|
}
|
|
|
|
|
2022-01-19 17:00:33 +03:00
|
|
|
|
2022-03-01 17:44:39 +03:00
|
|
|
#if defined(RUBY_DLN_CHECK_ABI) && defined(USE_DLN_DLOPEN)
|
2022-02-18 18:59:45 +03:00
|
|
|
static bool
|
|
|
|
abi_check_enabled_p(void)
|
|
|
|
{
|
|
|
|
const char *val = getenv("RUBY_ABI_CHECK");
|
|
|
|
return val == NULL || !(val[0] == '0' && val[1] == '\0');
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2022-01-19 17:00:33 +03:00
|
|
|
void *
|
|
|
|
dln_load(const char *file)
|
|
|
|
{
|
|
|
|
#if defined(_WIN32) || defined(USE_DLN_DLOPEN)
|
|
|
|
void *handle = dln_open(file);
|
|
|
|
|
2022-03-01 17:44:39 +03:00
|
|
|
#ifdef RUBY_DLN_CHECK_ABI
|
2023-11-15 17:31:11 +03:00
|
|
|
typedef unsigned long long abi_version_number;
|
2023-12-07 14:38:53 +03:00
|
|
|
abi_version_number binary_abi_version =
|
|
|
|
dln_sym_callable(abi_version_number, (void), handle, EXTERNAL_PREFIX "ruby_abi_version")();
|
2022-02-18 18:59:45 +03:00
|
|
|
if (binary_abi_version != ruby_abi_version() && abi_check_enabled_p()) {
|
2022-07-17 02:59:20 +03:00
|
|
|
dln_loaderror("incompatible ABI version of binary - %s", file);
|
2022-02-18 18:59:45 +03:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2022-01-19 17:00:33 +03:00
|
|
|
char *init_fct_name;
|
|
|
|
init_funcname(&init_fct_name, file);
|
|
|
|
|
|
|
|
/* Call the init code */
|
2023-12-07 14:38:53 +03:00
|
|
|
dln_sym_callable(void, (void), handle, init_fct_name)();
|
2022-01-19 17:00:33 +03:00
|
|
|
|
|
|
|
return handle;
|
|
|
|
|
|
|
|
#elif defined(_AIX)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2021-05-06 18:04:36 +03:00
|
|
|
void (*init_fct)(void);
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2021-05-06 18:04:36 +03:00
|
|
|
init_fct = (void(*)(void))load((char*)file, 1, 0);
|
1998-01-16 15:13:05 +03:00
|
|
|
if (init_fct == NULL) {
|
|
|
|
aix_loaderror(file);
|
|
|
|
}
|
1999-08-13 09:45:20 +04:00
|
|
|
if (loadbind(0, (void*)dln_load, (void*)init_fct) == -1) {
|
|
|
|
aix_loaderror(file);
|
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
(*init_fct)();
|
2001-05-02 08:22:21 +04:00
|
|
|
return (void*)init_fct;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2022-01-19 17:00:33 +03:00
|
|
|
#else
|
2009-09-28 17:46:18 +04:00
|
|
|
dln_notimplement();
|
1998-01-16 15:13:05 +03:00
|
|
|
#endif
|
|
|
|
|
2001-05-16 13:05:54 +04:00
|
|
|
return 0; /* dummy return */
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|