aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/luajit-2.0/src/lj_clib.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/luajit-2.0/src/lj_clib.c')
-rw-r--r--libraries/luajit-2.0/src/lj_clib.c389
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
35LJ_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
48static 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. */
64static 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. */
77static 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
98static 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
115static void clib_unloadlib(CLibrary *cl)
116{
117 if (!cl->handle && cl->handle != CLIB_DEFHANDLE)
118 dlclose(cl->handle);
119}
120
121static 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
138BOOL WINAPI GetModuleHandleExA(DWORD, LPCSTR, HMODULE*);
139#endif
140
141#define CLIB_DEFHANDLE ((void *)-1)
142
143/* Default libraries. */
144enum {
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
154static void *clib_def_handle[CLIB_HANDLE_MAX];
155
156LJ_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
167static 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
176static 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
185static 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
195static 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
211static 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
251LJ_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
257static 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
264static void clib_unloadlib(CLibrary *cl)
265{
266 UNUSED(cl);
267}
268
269static 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. */
281static 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. */
296static 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. */
307TValue *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. */
354static 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. */
368void 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. */
376void lj_clib_unload(CLibrary *cl)
377{
378 clib_unloadlib(cl);
379 cl->handle = NULL;
380}
381
382/* Create the default C library object. */
383void 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