/home/travis/build/MoarVM/MoarVM/src/core/dll.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include "moar.h" |
2 | | |
3 | 0 | int MVM_dll_load(MVMThreadContext *tc, MVMString *name, MVMString *path) { |
4 | 0 | MVMDLLRegistry *entry; |
5 | 0 | char *cpath; |
6 | 0 | DLLib *lib; |
7 | 0 |
|
8 | 0 | uv_mutex_lock(&tc->instance->mutex_dll_registry); |
9 | 0 |
|
10 | 0 | MVM_HASH_GET(tc, tc->instance->dll_registry, name, entry); |
11 | 0 |
|
12 | 0 | /* already loaded */ |
13 | 0 | if (entry && entry->lib) { |
14 | 0 | uv_mutex_unlock(&tc->instance->mutex_dll_registry); |
15 | 0 | return 0; |
16 | 0 | } |
17 | 0 |
|
18 | 0 | MVMROOT(tc, name, { |
19 | 0 | MVMROOT(tc, path, { |
20 | 0 | path = MVM_file_in_libpath(tc, path); |
21 | 0 | }); |
22 | 0 | }); |
23 | 0 |
|
24 | 0 | cpath = MVM_string_utf8_c8_encode_C_string(tc, path); |
25 | 0 | lib = MVM_nativecall_load_lib(cpath); |
26 | 0 |
|
27 | 0 | if (!lib) { |
28 | 0 | char *waste[] = { cpath, NULL }; |
29 | 0 | uv_mutex_unlock(&tc->instance->mutex_dll_registry); |
30 | 0 | MVM_exception_throw_adhoc_free(tc, waste, "failed to load library '%s'", cpath); |
31 | 0 | } |
32 | 0 |
|
33 | 0 | MVM_free(cpath); |
34 | 0 |
|
35 | 0 | if (!entry) { |
36 | 0 | entry = MVM_malloc(sizeof *entry); |
37 | 0 | entry->name = name; |
38 | 0 | entry->refcount = 0; |
39 | 0 |
|
40 | 0 | MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->name, |
41 | 0 | "DLL name"); |
42 | 0 | MVM_HASH_BIND(tc, tc->instance->dll_registry, name, entry); |
43 | 0 | MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->hash_handle.key, |
44 | 0 | "DLL name hash key"); |
45 | 0 | } |
46 | 0 |
|
47 | 0 | entry->lib = lib; |
48 | 0 |
|
49 | 0 | uv_mutex_unlock(&tc->instance->mutex_dll_registry); |
50 | 0 |
|
51 | 0 | return 1; |
52 | 0 | } |
53 | | |
54 | 0 | int MVM_dll_free(MVMThreadContext *tc, MVMString *name) { |
55 | 0 | MVMDLLRegistry *entry; |
56 | 0 |
|
57 | 0 | uv_mutex_lock(&tc->instance->mutex_dll_registry); |
58 | 0 |
|
59 | 0 | MVM_HASH_GET(tc, tc->instance->dll_registry, name, entry); |
60 | 0 |
|
61 | 0 | if (!entry) { |
62 | 0 | uv_mutex_unlock(&tc->instance->mutex_dll_registry); |
63 | 0 | MVM_exception_throw_adhoc(tc, "cannot free non-existent library"); |
64 | 0 | } |
65 | 0 |
|
66 | 0 | /* already freed */ |
67 | 0 | if (!entry->lib) { |
68 | 0 | uv_mutex_unlock(&tc->instance->mutex_dll_registry); |
69 | 0 | return 0; |
70 | 0 | } |
71 | 0 |
|
72 | 0 | if (entry->refcount > 0) { |
73 | 0 | uv_mutex_unlock(&tc->instance->mutex_dll_registry); |
74 | 0 | MVM_exception_throw_adhoc(tc, "cannot free in-use library"); |
75 | 0 | } |
76 | 0 |
|
77 | 0 | MVM_nativecall_free_lib(entry->lib); |
78 | 0 | entry->lib = NULL; |
79 | 0 |
|
80 | 0 | uv_mutex_unlock(&tc->instance->mutex_dll_registry); |
81 | 0 |
|
82 | 0 | return 1; |
83 | 0 | } |
84 | | |
85 | | MVMObject * MVM_dll_find_symbol(MVMThreadContext *tc, MVMString *lib, |
86 | 0 | MVMString *sym) { |
87 | 0 | MVMDLLRegistry *entry; |
88 | 0 | MVMDLLSym *obj; |
89 | 0 | char *csym; |
90 | 0 | void *address; |
91 | 0 |
|
92 | 0 | uv_mutex_lock(&tc->instance->mutex_dll_registry); |
93 | 0 |
|
94 | 0 | MVM_HASH_GET(tc, tc->instance->dll_registry, lib, entry); |
95 | 0 |
|
96 | 0 | if (!entry) { |
97 | 0 | uv_mutex_unlock(&tc->instance->mutex_dll_registry); |
98 | 0 | MVM_exception_throw_adhoc(tc, |
99 | 0 | "cannot find symbol in non-existent library"); |
100 | 0 | } |
101 | 0 |
|
102 | 0 | if (!entry->lib) { |
103 | 0 | uv_mutex_unlock(&tc->instance->mutex_dll_registry); |
104 | 0 | MVM_exception_throw_adhoc(tc, |
105 | 0 | "cannot find symbol in unloaded library"); |
106 | 0 | } |
107 | 0 |
|
108 | 0 | csym = MVM_string_utf8_c8_encode_C_string(tc, sym); |
109 | 0 | address = MVM_nativecall_find_sym(entry->lib, csym); |
110 | 0 | MVM_free(csym); |
111 | 0 |
|
112 | 0 | if (!address) { |
113 | 0 | uv_mutex_unlock(&tc->instance->mutex_dll_registry); |
114 | 0 | return NULL; |
115 | 0 | } |
116 | 0 |
|
117 | 0 | obj = (MVMDLLSym *)MVM_repr_alloc_init(tc, |
118 | 0 | tc->instance->raw_types.RawDLLSym); |
119 | 0 | obj->body.address = address; |
120 | 0 | obj->body.dll = entry; |
121 | 0 |
|
122 | 0 | entry->refcount++; |
123 | 0 |
|
124 | 0 | uv_mutex_unlock(&tc->instance->mutex_dll_registry); |
125 | 0 | return (MVMObject *)obj; |
126 | 0 | } |
127 | | |
128 | 0 | void MVM_dll_drop_symbol(MVMThreadContext *tc, MVMObject *obj) { |
129 | 0 | MVMDLLSym *sym; |
130 | 0 | MVMDLLRegistry *dll; |
131 | 0 |
|
132 | 0 | if (REPR(obj)->ID != MVM_REPR_ID_MVMDLLSym) |
133 | 0 | MVM_exception_throw_adhoc(tc, |
134 | 0 | "unexpected object with REPR other than MVMDLLSym"); |
135 | 0 |
|
136 | 0 | sym = (MVMDLLSym *)obj; |
137 | 0 | dll = sym->body.dll; |
138 | 0 |
|
139 | 0 | if (!dll) |
140 | 0 | return; |
141 | 0 |
|
142 | 0 | MVM_decr(&dll->refcount); |
143 | 0 |
|
144 | 0 | sym->body.address = NULL; |
145 | 0 | sym->body.dll = NULL; |
146 | 0 | } |