|
8 | 8 | #include "internal/dir.h"
|
9 | 9 | #include "internal/error.h"
|
10 | 10 | #include "internal/file.h"
|
| 11 | +#include "internal/hash.h" |
11 | 12 | #include "internal/load.h"
|
12 | 13 | #include "internal/ruby_parser.h"
|
13 | 14 | #include "internal/thread.h"
|
|
18 | 19 | #include "ruby/encoding.h"
|
19 | 20 | #include "ruby/util.h"
|
20 | 21 |
|
21 |
| -static VALUE ruby_dln_librefs; |
| 22 | +static VALUE ruby_dln_libmap; |
22 | 23 |
|
23 | 24 | #define IS_RBEXT(e) (strcmp((e), ".rb") == 0)
|
24 | 25 | #define IS_SOEXT(e) (strcmp((e), ".so") == 0 || strcmp((e), ".o") == 0)
|
25 | 26 | #define IS_DLEXT(e) (strcmp((e), DLEXT) == 0)
|
26 | 27 |
|
| 28 | +#if SIZEOF_VALUE <= SIZEOF_LONG |
| 29 | +# define SVALUE2NUM(x) LONG2NUM((long)(x)) |
| 30 | +# define NUM2SVALUE(x) (SIGNED_VALUE)NUM2LONG(x) |
| 31 | +#elif SIZEOF_VALUE <= SIZEOF_LONG_LONG |
| 32 | +# define SVALUE2NUM(x) LL2NUM((LONG_LONG)(x)) |
| 33 | +# define NUM2SVALUE(x) (SIGNED_VALUE)NUM2LL(x) |
| 34 | +#else |
| 35 | +# error Need integer for VALUE |
| 36 | +#endif |
| 37 | + |
27 | 38 | enum {
|
28 | 39 | loadable_ext_rb = (0+ /* .rb extension is the first in both tables */
|
29 | 40 | 1) /* offset by rb_find_file_ext() */
|
@@ -1225,7 +1236,7 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception, bool wa
|
1225 | 1236 | ec->errinfo = Qnil; /* ensure */
|
1226 | 1237 | th->top_wrapper = 0;
|
1227 | 1238 | if ((state = EC_EXEC_TAG()) == TAG_NONE) {
|
1228 |
| - long handle; |
| 1239 | + VALUE handle; |
1229 | 1240 | int found;
|
1230 | 1241 |
|
1231 | 1242 | RUBY_DTRACE_HOOK(FIND_REQUIRE_ENTRY, RSTRING_PTR(fname));
|
@@ -1256,9 +1267,9 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception, bool wa
|
1256 | 1267 | case 's':
|
1257 | 1268 | reset_ext_config = true;
|
1258 | 1269 | ext_config_push(th, &prev_ext_config);
|
1259 |
| - handle = (long)rb_vm_call_cfunc(rb_vm_top_self(), load_ext, |
1260 |
| - path, VM_BLOCK_HANDLER_NONE, path); |
1261 |
| - rb_ary_push(ruby_dln_librefs, LONG2NUM(handle)); |
| 1270 | + handle = rb_vm_call_cfunc(rb_vm_top_self(), load_ext, |
| 1271 | + path, VM_BLOCK_HANDLER_NONE, path); |
| 1272 | + rb_hash_aset(ruby_dln_libmap, path, SVALUE2NUM((SIGNED_VALUE)handle)); |
1262 | 1273 | break;
|
1263 | 1274 | }
|
1264 | 1275 | result = TAG_RETURN;
|
@@ -1518,6 +1529,37 @@ rb_f_autoload_p(int argc, VALUE *argv, VALUE obj)
|
1518 | 1529 | return rb_mod_autoload_p(argc, argv, klass);
|
1519 | 1530 | }
|
1520 | 1531 |
|
| 1532 | +void * |
| 1533 | +rb_ext_resolve_symbol(const char* fname, const char* symbol) |
| 1534 | +{ |
| 1535 | + VALUE handle; |
| 1536 | + VALUE resolved; |
| 1537 | + VALUE path; |
| 1538 | + char *ext; |
| 1539 | + VALUE fname_str = rb_str_new_cstr(fname); |
| 1540 | + |
| 1541 | + resolved = rb_resolve_feature_path((VALUE)NULL, fname_str); |
| 1542 | + if (NIL_P(resolved)) { |
| 1543 | + ext = strrchr(fname, '.'); |
| 1544 | + if (!ext || !IS_SOEXT(ext)) { |
| 1545 | + rb_str_cat_cstr(fname_str, ".so"); |
| 1546 | + } |
| 1547 | + if (rb_feature_p(GET_VM(), fname, 0, FALSE, FALSE, 0)) { |
| 1548 | + return dln_symbol(NULL, symbol); |
| 1549 | + } |
| 1550 | + return NULL; |
| 1551 | + } |
| 1552 | + if (RARRAY_LEN(resolved) != 2 || rb_ary_entry(resolved, 0) != ID2SYM(rb_intern("so"))) { |
| 1553 | + return NULL; |
| 1554 | + } |
| 1555 | + path = rb_ary_entry(resolved, 1); |
| 1556 | + handle = rb_hash_lookup(ruby_dln_libmap, path); |
| 1557 | + if (NIL_P(handle)) { |
| 1558 | + return NULL; |
| 1559 | + } |
| 1560 | + return dln_symbol((void *)NUM2SVALUE(handle), symbol); |
| 1561 | +} |
| 1562 | + |
1521 | 1563 | void
|
1522 | 1564 | Init_load(void)
|
1523 | 1565 | {
|
@@ -1552,6 +1594,6 @@ Init_load(void)
|
1552 | 1594 | rb_define_global_function("autoload", rb_f_autoload, 2);
|
1553 | 1595 | rb_define_global_function("autoload?", rb_f_autoload_p, -1);
|
1554 | 1596 |
|
1555 |
| - ruby_dln_librefs = rb_ary_hidden_new(0); |
1556 |
| - rb_gc_register_mark_object(ruby_dln_librefs); |
| 1597 | + ruby_dln_libmap = rb_hash_new_with_size(0); |
| 1598 | + rb_gc_register_mark_object(ruby_dln_libmap); |
1557 | 1599 | }
|
0 commit comments