diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/luajit-2.0/src/lj_clib.c | 389 |
1 files changed, 0 insertions, 389 deletions
diff --git a/libraries/luajit-2.0/src/lj_clib.c b/libraries/luajit-2.0/src/lj_clib.c deleted file mode 100644 index 68398cf..0000000 --- a/libraries/luajit-2.0/src/lj_clib.c +++ /dev/null | |||
@@ -1,389 +0,0 @@ | |||
1 | /* | ||
2 | ** FFI C library loader. | ||
3 | ** Copyright (C) 2005-2011 Mike Pall. See Copyright Notice in luajit.h | ||
4 | */ | ||
5 | |||
6 | #include "lj_obj.h" | ||
7 | |||
8 | #if LJ_HASFFI | ||
9 | |||
10 | #include "lj_gc.h" | ||
11 | #include "lj_err.h" | ||
12 | #include "lj_tab.h" | ||
13 | #include "lj_str.h" | ||
14 | #include "lj_udata.h" | ||
15 | #include "lj_ctype.h" | ||
16 | #include "lj_cconv.h" | ||
17 | #include "lj_cdata.h" | ||
18 | #include "lj_clib.h" | ||
19 | |||
20 | /* -- OS-specific functions ----------------------------------------------- */ | ||
21 | |||
22 | #if LJ_TARGET_DLOPEN | ||
23 | |||
24 | #include <dlfcn.h> | ||
25 | #include <stdio.h> | ||
26 | |||
27 | #if defined(RTLD_DEFAULT) | ||
28 | #define CLIB_DEFHANDLE RTLD_DEFAULT | ||
29 | #elif LJ_TARGET_OSX || LJ_TARGET_BSD | ||
30 | #define CLIB_DEFHANDLE ((void *)(intptr_t)-2) | ||
31 | #else | ||
32 | #define CLIB_DEFHANDLE NULL | ||
33 | #endif | ||
34 | |||
35 | LJ_NORET LJ_NOINLINE static void clib_error_(lua_State *L) | ||
36 | { | ||
37 | lj_err_callermsg(L, dlerror()); | ||
38 | } | ||
39 | |||
40 | #define clib_error(L, fmt, name) clib_error_(L) | ||
41 | |||
42 | #if LJ_TARGET_OSX | ||
43 | #define CLIB_SOEXT "%s.dylib" | ||
44 | #else | ||
45 | #define CLIB_SOEXT "%s.so" | ||
46 | #endif | ||
47 | |||
48 | static const char *clib_extname(lua_State *L, const char *name) | ||
49 | { | ||
50 | if (!strchr(name, '/')) { | ||
51 | if (!strchr(name, '.')) { | ||
52 | name = lj_str_pushf(L, CLIB_SOEXT, name); | ||
53 | L->top--; | ||
54 | } | ||
55 | if (!(name[0] == 'l' && name[1] == 'i' && name[2] == 'b')) { | ||
56 | name = lj_str_pushf(L, "lib%s", name); | ||
57 | L->top--; | ||
58 | } | ||
59 | } | ||
60 | return name; | ||
61 | } | ||
62 | |||
63 | /* Check for a recognized ld script line. */ | ||
64 | static const char *clib_check_lds(lua_State *L, const char *buf) | ||
65 | { | ||
66 | char *p, *e; | ||
67 | if ((!strncmp(buf, "GROUP", 5) || !strncmp(buf, "INPUT", 5)) && | ||
68 | (p = strchr(buf, '('))) { | ||
69 | while (*++p == ' ') ; | ||
70 | for (e = p; *e && *e != ' ' && *e != ')'; e++) ; | ||
71 | return strdata(lj_str_new(L, p, e-p)); | ||
72 | } | ||
73 | return NULL; | ||
74 | } | ||
75 | |||
76 | /* Quick and dirty solution to resolve shared library name from ld script. */ | ||
77 | static const char *clib_resolve_lds(lua_State *L, const char *name) | ||
78 | { | ||
79 | FILE *fp = fopen(name, "r"); | ||
80 | const char *p = NULL; | ||
81 | if (fp) { | ||
82 | char buf[256]; | ||
83 | if (fgets(buf, sizeof(buf), fp)) { | ||
84 | if (!strncmp(buf, "/* GNU ld script", 16)) { /* ld script magic? */ | ||
85 | while (fgets(buf, sizeof(buf), fp)) { /* Check all lines. */ | ||
86 | p = clib_check_lds(L, buf); | ||
87 | if (p) break; | ||
88 | } | ||
89 | } else { /* Otherwise check only the first line. */ | ||
90 | p = clib_check_lds(L, buf); | ||
91 | } | ||
92 | } | ||
93 | fclose(fp); | ||
94 | } | ||
95 | return p; | ||
96 | } | ||
97 | |||
98 | static void *clib_loadlib(lua_State *L, const char *name, int global) | ||
99 | { | ||
100 | void *h = dlopen(clib_extname(L, name), | ||
101 | RTLD_LAZY | (global?RTLD_GLOBAL:RTLD_LOCAL)); | ||
102 | if (!h) { | ||
103 | const char *e, *err = dlerror(); | ||
104 | if (*err == '/' && (e = strchr(err, ':')) && | ||
105 | (name = clib_resolve_lds(L, strdata(lj_str_new(L, err, e-err))))) { | ||
106 | h = dlopen(name, RTLD_LAZY | (global?RTLD_GLOBAL:RTLD_LOCAL)); | ||
107 | if (h) return h; | ||
108 | err = dlerror(); | ||
109 | } | ||
110 | lj_err_callermsg(L, err); | ||
111 | } | ||
112 | return h; | ||
113 | } | ||
114 | |||
115 | static void clib_unloadlib(CLibrary *cl) | ||
116 | { | ||
117 | if (!cl->handle && cl->handle != CLIB_DEFHANDLE) | ||
118 | dlclose(cl->handle); | ||
119 | } | ||
120 | |||
121 | static void *clib_getsym(CLibrary *cl, const char *name) | ||
122 | { | ||
123 | void *p = dlsym(cl->handle, name); | ||
124 | return p; | ||
125 | } | ||
126 | |||
127 | #elif LJ_TARGET_WINDOWS | ||
128 | |||
129 | #define WIN32_LEAN_AND_MEAN | ||
130 | #ifndef WINVER | ||
131 | #define WINVER 0x0500 | ||
132 | #endif | ||
133 | #include <windows.h> | ||
134 | |||
135 | #ifndef GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | ||
136 | #define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 4 | ||
137 | #define GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT 2 | ||
138 | BOOL WINAPI GetModuleHandleExA(DWORD, LPCSTR, HMODULE*); | ||
139 | #endif | ||
140 | |||
141 | #define CLIB_DEFHANDLE ((void *)-1) | ||
142 | |||
143 | /* Default libraries. */ | ||
144 | enum { | ||
145 | CLIB_HANDLE_EXE, | ||
146 | CLIB_HANDLE_DLL, | ||
147 | CLIB_HANDLE_CRT, | ||
148 | CLIB_HANDLE_KERNEL32, | ||
149 | CLIB_HANDLE_USER32, | ||
150 | CLIB_HANDLE_GDI32, | ||
151 | CLIB_HANDLE_MAX | ||
152 | }; | ||
153 | |||
154 | static void *clib_def_handle[CLIB_HANDLE_MAX]; | ||
155 | |||
156 | LJ_NORET LJ_NOINLINE static void clib_error(lua_State *L, const char *fmt, | ||
157 | const char *name) | ||
158 | { | ||
159 | DWORD err = GetLastError(); | ||
160 | char buf[128]; | ||
161 | if (!FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS|FORMAT_MESSAGE_FROM_SYSTEM, | ||
162 | NULL, err, 0, buf, sizeof(buf), NULL)) | ||
163 | buf[0] = '\0'; | ||
164 | lj_err_callermsg(L, lj_str_pushf(L, fmt, name, buf)); | ||
165 | } | ||
166 | |||
167 | static int clib_needext(const char *s) | ||
168 | { | ||
169 | while (*s) { | ||
170 | if (*s == '/' || *s == '\\' || *s == '.') return 0; | ||
171 | s++; | ||
172 | } | ||
173 | return 1; | ||
174 | } | ||
175 | |||
176 | static const char *clib_extname(lua_State *L, const char *name) | ||
177 | { | ||
178 | if (clib_needext(name)) { | ||
179 | name = lj_str_pushf(L, "%s.dll", name); | ||
180 | L->top--; | ||
181 | } | ||
182 | return name; | ||
183 | } | ||
184 | |||
185 | static void *clib_loadlib(lua_State *L, const char *name, int global) | ||
186 | { | ||
187 | DWORD oldwerr = GetLastError(); | ||
188 | void *h = (void *)LoadLibraryA(clib_extname(L, name)); | ||
189 | if (!h) clib_error(L, "cannot load module " LUA_QS ": %s", name); | ||
190 | SetLastError(oldwerr); | ||
191 | UNUSED(global); | ||
192 | return h; | ||
193 | } | ||
194 | |||
195 | static void clib_unloadlib(CLibrary *cl) | ||
196 | { | ||
197 | if (cl->handle == CLIB_DEFHANDLE) { | ||
198 | MSize i; | ||
199 | for (i = 0; i < CLIB_HANDLE_MAX; i++) { | ||
200 | void *h = clib_def_handle[i]; | ||
201 | if (h) { | ||
202 | clib_def_handle[i] = NULL; | ||
203 | FreeLibrary((HINSTANCE)h); | ||
204 | } | ||
205 | } | ||
206 | } else if (!cl->handle) { | ||
207 | FreeLibrary((HINSTANCE)cl->handle); | ||
208 | } | ||
209 | } | ||
210 | |||
211 | static void *clib_getsym(CLibrary *cl, const char *name) | ||
212 | { | ||
213 | void *p = NULL; | ||
214 | DWORD oldwerr = GetLastError(); | ||
215 | if (cl->handle == CLIB_DEFHANDLE) { /* Search default libraries. */ | ||
216 | MSize i; | ||
217 | for (i = 0; i < CLIB_HANDLE_MAX; i++) { | ||
218 | HINSTANCE h = (HINSTANCE)clib_def_handle[i]; | ||
219 | if (!(void *)h) { /* Resolve default library handles (once). */ | ||
220 | switch (i) { | ||
221 | case CLIB_HANDLE_EXE: GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, NULL, &h); break; | ||
222 | case CLIB_HANDLE_DLL: | ||
223 | GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS|GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, | ||
224 | (const char *)clib_def_handle, &h); | ||
225 | break; | ||
226 | case CLIB_HANDLE_CRT: | ||
227 | GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS|GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, | ||
228 | (const char *)&_fmode, &h); | ||
229 | break; | ||
230 | case CLIB_HANDLE_KERNEL32: h = LoadLibraryA("kernel32.dll"); break; | ||
231 | case CLIB_HANDLE_USER32: h = LoadLibraryA("user32.dll"); break; | ||
232 | case CLIB_HANDLE_GDI32: h = LoadLibraryA("gdi32.dll"); break; | ||
233 | } | ||
234 | if (!h) continue; | ||
235 | clib_def_handle[i] = (void *)h; | ||
236 | } | ||
237 | p = (void *)GetProcAddress(h, name); | ||
238 | if (p) break; | ||
239 | } | ||
240 | } else { | ||
241 | p = (void *)GetProcAddress((HINSTANCE)cl->handle, name); | ||
242 | } | ||
243 | SetLastError(oldwerr); | ||
244 | return p; | ||
245 | } | ||
246 | |||
247 | #else | ||
248 | |||
249 | #define CLIB_DEFHANDLE NULL | ||
250 | |||
251 | LJ_NORET LJ_NOINLINE static void clib_error(lua_State *L, const char *fmt, | ||
252 | const char *name) | ||
253 | { | ||
254 | lj_err_callermsg(L, lj_str_pushf(L, fmt, name, "no support for this OS")); | ||
255 | } | ||
256 | |||
257 | static void *clib_loadlib(lua_State *L, const char *name, int global) | ||
258 | { | ||
259 | lj_err_callermsg(L, "no support for loading dynamic libraries for this OS"); | ||
260 | UNUSED(name); UNUSED(global); | ||
261 | return NULL; | ||
262 | } | ||
263 | |||
264 | static void clib_unloadlib(CLibrary *cl) | ||
265 | { | ||
266 | UNUSED(cl); | ||
267 | } | ||
268 | |||
269 | static void *clib_getsym(CLibrary *cl, const char *name) | ||
270 | { | ||
271 | UNUSED(cl); UNUSED(name); | ||
272 | return NULL; | ||
273 | } | ||
274 | |||
275 | #endif | ||
276 | |||
277 | /* -- C library indexing -------------------------------------------------- */ | ||
278 | |||
279 | #if LJ_TARGET_X86 && LJ_ABI_WIN | ||
280 | /* Compute argument size for fastcall/stdcall functions. */ | ||
281 | static CTSize clib_func_argsize(CTState *cts, CType *ct) | ||
282 | { | ||
283 | CTSize n = 0; | ||
284 | while (ct->sib) { | ||
285 | CType *d; | ||
286 | ct = ctype_get(cts, ct->sib); | ||
287 | lua_assert(ctype_isfield(ct->info)); | ||
288 | d = ctype_rawchild(cts, ct); | ||
289 | n += ((d->size + 3) & ~3); | ||
290 | } | ||
291 | return n; | ||
292 | } | ||
293 | #endif | ||
294 | |||
295 | /* Get redirected or mangled external symbol. */ | ||
296 | static const char *clib_extsym(CTState *cts, CType *ct, GCstr *name) | ||
297 | { | ||
298 | if (ct->sib) { | ||
299 | CType *ctf = ctype_get(cts, ct->sib); | ||
300 | if (ctype_isxattrib(ctf->info, CTA_REDIR)) | ||
301 | return strdata(gco2str(gcref(ctf->name))); | ||
302 | } | ||
303 | return strdata(name); | ||
304 | } | ||
305 | |||
306 | /* Index a C library by name. */ | ||
307 | TValue *lj_clib_index(lua_State *L, CLibrary *cl, GCstr *name) | ||
308 | { | ||
309 | TValue *tv = lj_tab_setstr(L, cl->cache, name); | ||
310 | if (LJ_UNLIKELY(tvisnil(tv))) { | ||
311 | CTState *cts = ctype_cts(L); | ||
312 | CType *ct; | ||
313 | CTypeID id = lj_ctype_getname(cts, &ct, name, CLNS_INDEX); | ||
314 | if (!id) | ||
315 | lj_err_callerv(L, LJ_ERR_FFI_NODECL, strdata(name)); | ||
316 | if (ctype_isconstval(ct->info)) { | ||
317 | CType *ctt = ctype_child(cts, ct); | ||
318 | lua_assert(ctype_isinteger(ctt->info) && ctt->size <= 4); | ||
319 | if ((ctt->info & CTF_UNSIGNED) && (int32_t)ct->size < 0) | ||
320 | setnumV(tv, (lua_Number)(uint32_t)ct->size); | ||
321 | else | ||
322 | setintV(tv, (int32_t)ct->size); | ||
323 | } else { | ||
324 | const char *sym = clib_extsym(cts, ct, name); | ||
325 | void *p = clib_getsym(cl, sym); | ||
326 | GCcdata *cd; | ||
327 | lua_assert(ctype_isfunc(ct->info) || ctype_isextern(ct->info)); | ||
328 | #if LJ_TARGET_X86 && LJ_ABI_WIN | ||
329 | /* Retry with decorated name for fastcall/stdcall functions. */ | ||
330 | if (!p && ctype_isfunc(ct->info)) { | ||
331 | CTInfo cconv = ctype_cconv(ct->info); | ||
332 | if (cconv == CTCC_FASTCALL || cconv == CTCC_STDCALL) { | ||
333 | CTSize sz = clib_func_argsize(cts, ct); | ||
334 | sym = lj_str_pushf(L, cconv == CTCC_FASTCALL ? "@%s@%d" : "_%s@%d", | ||
335 | sym, sz); | ||
336 | L->top--; | ||
337 | p = clib_getsym(cl, sym); | ||
338 | } | ||
339 | } | ||
340 | #endif | ||
341 | if (!p) | ||
342 | clib_error(L, "cannot resolve symbol " LUA_QS ": %s", strdata(name)); | ||
343 | cd = lj_cdata_new(cts, id, CTSIZE_PTR); | ||
344 | *(void **)cdataptr(cd) = p; | ||
345 | setcdataV(L, tv, cd); | ||
346 | } | ||
347 | } | ||
348 | return tv; | ||
349 | } | ||
350 | |||
351 | /* -- C library management ------------------------------------------------ */ | ||
352 | |||
353 | /* Create a new CLibrary object and push it on the stack. */ | ||
354 | static CLibrary *clib_new(lua_State *L, GCtab *mt) | ||
355 | { | ||
356 | GCtab *t = lj_tab_new(L, 0, 0); | ||
357 | GCudata *ud = lj_udata_new(L, sizeof(CLibrary), t); | ||
358 | CLibrary *cl = (CLibrary *)uddata(ud); | ||
359 | cl->cache = t; | ||
360 | ud->udtype = UDTYPE_FFI_CLIB; | ||
361 | /* NOBARRIER: The GCudata is new (marked white). */ | ||
362 | setgcref(ud->metatable, obj2gco(mt)); | ||
363 | setudataV(L, L->top++, ud); | ||
364 | return cl; | ||
365 | } | ||
366 | |||
367 | /* Load a C library. */ | ||
368 | void lj_clib_load(lua_State *L, GCtab *mt, GCstr *name, int global) | ||
369 | { | ||
370 | void *handle = clib_loadlib(L, strdata(name), global); | ||
371 | CLibrary *cl = clib_new(L, mt); | ||
372 | cl->handle = handle; | ||
373 | } | ||
374 | |||
375 | /* Unload a C library. */ | ||
376 | void lj_clib_unload(CLibrary *cl) | ||
377 | { | ||
378 | clib_unloadlib(cl); | ||
379 | cl->handle = NULL; | ||
380 | } | ||
381 | |||
382 | /* Create the default C library object. */ | ||
383 | void lj_clib_default(lua_State *L, GCtab *mt) | ||
384 | { | ||
385 | CLibrary *cl = clib_new(L, mt); | ||
386 | cl->handle = CLIB_DEFHANDLE; | ||
387 | } | ||
388 | |||
389 | #endif | ||