summaryrefslogtreecommitdiff
path: root/Build/source/libs/luajit/LuaJIT-2.1.0-beta1/src/lj_clib.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/luajit/LuaJIT-2.1.0-beta1/src/lj_clib.c')
-rw-r--r--Build/source/libs/luajit/LuaJIT-2.1.0-beta1/src/lj_clib.c418
1 files changed, 418 insertions, 0 deletions
diff --git a/Build/source/libs/luajit/LuaJIT-2.1.0-beta1/src/lj_clib.c b/Build/source/libs/luajit/LuaJIT-2.1.0-beta1/src/lj_clib.c
new file mode 100644
index 00000000000..1e927ebe99e
--- /dev/null
+++ b/Build/source/libs/luajit/LuaJIT-2.1.0-beta1/src/lj_clib.c
@@ -0,0 +1,418 @@
+/*
+** FFI C library loader.
+** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
+*/
+
+#include "lj_obj.h"
+
+#if LJ_HASFFI
+
+#include "lj_gc.h"
+#include "lj_err.h"
+#include "lj_tab.h"
+#include "lj_str.h"
+#include "lj_udata.h"
+#include "lj_ctype.h"
+#include "lj_cconv.h"
+#include "lj_cdata.h"
+#include "lj_clib.h"
+#include "lj_strfmt.h"
+
+/* -- OS-specific functions ----------------------------------------------- */
+
+#if LJ_TARGET_DLOPEN
+
+#include <dlfcn.h>
+#include <stdio.h>
+
+#if defined(RTLD_DEFAULT)
+#define CLIB_DEFHANDLE RTLD_DEFAULT
+#elif LJ_TARGET_OSX || LJ_TARGET_BSD
+#define CLIB_DEFHANDLE ((void *)(intptr_t)-2)
+#else
+#define CLIB_DEFHANDLE NULL
+#endif
+
+LJ_NORET LJ_NOINLINE static void clib_error_(lua_State *L)
+{
+ lj_err_callermsg(L, dlerror());
+}
+
+#define clib_error(L, fmt, name) clib_error_(L)
+
+#if defined(__CYGWIN__)
+#define CLIB_SOPREFIX "cyg"
+#else
+#define CLIB_SOPREFIX "lib"
+#endif
+
+#if LJ_TARGET_OSX
+#define CLIB_SOEXT "%s.dylib"
+#elif defined(__CYGWIN__)
+#define CLIB_SOEXT "%s.dll"
+#else
+#define CLIB_SOEXT "%s.so"
+#endif
+
+static const char *clib_extname(lua_State *L, const char *name)
+{
+ if (!strchr(name, '/')
+#ifdef __CYGWIN__
+ && !strchr(name, '\\')
+#endif
+ ) {
+ if (!strchr(name, '.')) {
+ name = lj_strfmt_pushf(L, CLIB_SOEXT, name);
+ L->top--;
+#ifdef __CYGWIN__
+ } else {
+ return name;
+#endif
+ }
+ if (!(name[0] == CLIB_SOPREFIX[0] && name[1] == CLIB_SOPREFIX[1] &&
+ name[2] == CLIB_SOPREFIX[2])) {
+ name = lj_strfmt_pushf(L, CLIB_SOPREFIX "%s", name);
+ L->top--;
+ }
+ }
+ return name;
+}
+
+/* Check for a recognized ld script line. */
+static const char *clib_check_lds(lua_State *L, const char *buf)
+{
+ char *p, *e;
+ if ((!strncmp(buf, "GROUP", 5) || !strncmp(buf, "INPUT", 5)) &&
+ (p = strchr(buf, '('))) {
+ while (*++p == ' ') ;
+ for (e = p; *e && *e != ' ' && *e != ')'; e++) ;
+ return strdata(lj_str_new(L, p, e-p));
+ }
+ return NULL;
+}
+
+/* Quick and dirty solution to resolve shared library name from ld script. */
+static const char *clib_resolve_lds(lua_State *L, const char *name)
+{
+ FILE *fp = fopen(name, "r");
+ const char *p = NULL;
+ if (fp) {
+ char buf[256];
+ if (fgets(buf, sizeof(buf), fp)) {
+ if (!strncmp(buf, "/* GNU ld script", 16)) { /* ld script magic? */
+ while (fgets(buf, sizeof(buf), fp)) { /* Check all lines. */
+ p = clib_check_lds(L, buf);
+ if (p) break;
+ }
+ } else { /* Otherwise check only the first line. */
+ p = clib_check_lds(L, buf);
+ }
+ }
+ fclose(fp);
+ }
+ return p;
+}
+
+static void *clib_loadlib(lua_State *L, const char *name, int global)
+{
+ void *h = dlopen(clib_extname(L, name),
+ RTLD_LAZY | (global?RTLD_GLOBAL:RTLD_LOCAL));
+ if (!h) {
+ const char *e, *err = dlerror();
+ if (*err == '/' && (e = strchr(err, ':')) &&
+ (name = clib_resolve_lds(L, strdata(lj_str_new(L, err, e-err))))) {
+ h = dlopen(name, RTLD_LAZY | (global?RTLD_GLOBAL:RTLD_LOCAL));
+ if (h) return h;
+ err = dlerror();
+ }
+ lj_err_callermsg(L, err);
+ }
+ return h;
+}
+
+static void clib_unloadlib(CLibrary *cl)
+{
+ if (cl->handle && cl->handle != CLIB_DEFHANDLE)
+ dlclose(cl->handle);
+}
+
+static void *clib_getsym(CLibrary *cl, const char *name)
+{
+ void *p = dlsym(cl->handle, name);
+ return p;
+}
+
+#elif LJ_TARGET_WINDOWS
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#ifndef GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
+#define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 4
+#define GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT 2
+BOOL WINAPI GetModuleHandleExA(DWORD, LPCSTR, HMODULE*);
+#endif
+
+#define CLIB_DEFHANDLE ((void *)-1)
+
+/* Default libraries. */
+enum {
+ CLIB_HANDLE_EXE,
+ CLIB_HANDLE_DLL,
+ CLIB_HANDLE_CRT,
+ CLIB_HANDLE_KERNEL32,
+ CLIB_HANDLE_USER32,
+ CLIB_HANDLE_GDI32,
+ CLIB_HANDLE_MAX
+};
+
+static void *clib_def_handle[CLIB_HANDLE_MAX];
+
+LJ_NORET LJ_NOINLINE static void clib_error(lua_State *L, const char *fmt,
+ const char *name)
+{
+ DWORD err = GetLastError();
+#if LJ_TARGET_XBOXONE
+ wchar_t wbuf[128];
+ char buf[128*2];
+ if (!FormatMessageW(FORMAT_MESSAGE_IGNORE_INSERTS|FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, err, 0, wbuf, sizeof(wbuf)/sizeof(wchar_t), NULL) ||
+ !WideCharToMultiByte(CP_ACP, 0, wbuf, 128, buf, 128*2, NULL, NULL))
+#else
+ char buf[128];
+ if (!FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS|FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, err, 0, buf, sizeof(buf), NULL))
+#endif
+ buf[0] = '\0';
+ lj_err_callermsg(L, lj_strfmt_pushf(L, fmt, name, buf));
+}
+
+static int clib_needext(const char *s)
+{
+ while (*s) {
+ if (*s == '/' || *s == '\\' || *s == '.') return 0;
+ s++;
+ }
+ return 1;
+}
+
+static const char *clib_extname(lua_State *L, const char *name)
+{
+ if (clib_needext(name)) {
+ name = lj_strfmt_pushf(L, "%s.dll", name);
+ L->top--;
+ }
+ return name;
+}
+
+static void *clib_loadlib(lua_State *L, const char *name, int global)
+{
+ DWORD oldwerr = GetLastError();
+ void *h = (void *)LoadLibraryExA(clib_extname(L, name), NULL, 0);
+ if (!h) clib_error(L, "cannot load module " LUA_QS ": %s", name);
+ SetLastError(oldwerr);
+ UNUSED(global);
+ return h;
+}
+
+static void clib_unloadlib(CLibrary *cl)
+{
+ if (cl->handle == CLIB_DEFHANDLE) {
+ MSize i;
+ for (i = CLIB_HANDLE_KERNEL32; i < CLIB_HANDLE_MAX; i++) {
+ void *h = clib_def_handle[i];
+ if (h) {
+ clib_def_handle[i] = NULL;
+ FreeLibrary((HINSTANCE)h);
+ }
+ }
+ } else if (cl->handle) {
+ FreeLibrary((HINSTANCE)cl->handle);
+ }
+}
+
+static void *clib_getsym(CLibrary *cl, const char *name)
+{
+ void *p = NULL;
+ if (cl->handle == CLIB_DEFHANDLE) { /* Search default libraries. */
+ MSize i;
+ for (i = 0; i < CLIB_HANDLE_MAX; i++) {
+ HINSTANCE h = (HINSTANCE)clib_def_handle[i];
+ if (!(void *)h) { /* Resolve default library handles (once). */
+ switch (i) {
+ case CLIB_HANDLE_EXE: GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, NULL, &h); break;
+ case CLIB_HANDLE_DLL:
+ GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS|GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
+ (const char *)clib_def_handle, &h);
+ break;
+ case CLIB_HANDLE_CRT:
+ GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS|GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
+ (const char *)&_fmode, &h);
+ break;
+ case CLIB_HANDLE_KERNEL32: h = LoadLibraryExA("kernel32.dll", NULL, 0); break;
+ case CLIB_HANDLE_USER32: h = LoadLibraryExA("user32.dll", NULL, 0); break;
+ case CLIB_HANDLE_GDI32: h = LoadLibraryExA("gdi32.dll", NULL, 0); break;
+ }
+ if (!h) continue;
+ clib_def_handle[i] = (void *)h;
+ }
+ p = (void *)GetProcAddress(h, name);
+ if (p) break;
+ }
+ } else {
+ p = (void *)GetProcAddress((HINSTANCE)cl->handle, name);
+ }
+ return p;
+}
+
+#else
+
+#define CLIB_DEFHANDLE NULL
+
+LJ_NORET LJ_NOINLINE static void clib_error(lua_State *L, const char *fmt,
+ const char *name)
+{
+ lj_err_callermsg(L, lj_strfmt_pushf(L, fmt, name, "no support for this OS"));
+}
+
+static void *clib_loadlib(lua_State *L, const char *name, int global)
+{
+ lj_err_callermsg(L, "no support for loading dynamic libraries for this OS");
+ UNUSED(name); UNUSED(global);
+ return NULL;
+}
+
+static void clib_unloadlib(CLibrary *cl)
+{
+ UNUSED(cl);
+}
+
+static void *clib_getsym(CLibrary *cl, const char *name)
+{
+ UNUSED(cl); UNUSED(name);
+ return NULL;
+}
+
+#endif
+
+/* -- C library indexing -------------------------------------------------- */
+
+#if LJ_TARGET_X86 && LJ_ABI_WIN
+/* Compute argument size for fastcall/stdcall functions. */
+static CTSize clib_func_argsize(CTState *cts, CType *ct)
+{
+ CTSize n = 0;
+ while (ct->sib) {
+ CType *d;
+ ct = ctype_get(cts, ct->sib);
+ if (ctype_isfield(ct->info)) {
+ d = ctype_rawchild(cts, ct);
+ n += ((d->size + 3) & ~3);
+ }
+ }
+ return n;
+}
+#endif
+
+/* Get redirected or mangled external symbol. */
+static const char *clib_extsym(CTState *cts, CType *ct, GCstr *name)
+{
+ if (ct->sib) {
+ CType *ctf = ctype_get(cts, ct->sib);
+ if (ctype_isxattrib(ctf->info, CTA_REDIR))
+ return strdata(gco2str(gcref(ctf->name)));
+ }
+ return strdata(name);
+}
+
+/* Index a C library by name. */
+TValue *lj_clib_index(lua_State *L, CLibrary *cl, GCstr *name)
+{
+ TValue *tv = lj_tab_setstr(L, cl->cache, name);
+ if (LJ_UNLIKELY(tvisnil(tv))) {
+ CTState *cts = ctype_cts(L);
+ CType *ct;
+ CTypeID id = lj_ctype_getname(cts, &ct, name, CLNS_INDEX);
+ if (!id)
+ lj_err_callerv(L, LJ_ERR_FFI_NODECL, strdata(name));
+ if (ctype_isconstval(ct->info)) {
+ CType *ctt = ctype_child(cts, ct);
+ lua_assert(ctype_isinteger(ctt->info) && ctt->size <= 4);
+ if ((ctt->info & CTF_UNSIGNED) && (int32_t)ct->size < 0)
+ setnumV(tv, (lua_Number)(uint32_t)ct->size);
+ else
+ setintV(tv, (int32_t)ct->size);
+ } else {
+ const char *sym = clib_extsym(cts, ct, name);
+#if LJ_TARGET_WINDOWS
+ DWORD oldwerr = GetLastError();
+#endif
+ void *p = clib_getsym(cl, sym);
+ GCcdata *cd;
+ lua_assert(ctype_isfunc(ct->info) || ctype_isextern(ct->info));
+#if LJ_TARGET_X86 && LJ_ABI_WIN
+ /* Retry with decorated name for fastcall/stdcall functions. */
+ if (!p && ctype_isfunc(ct->info)) {
+ CTInfo cconv = ctype_cconv(ct->info);
+ if (cconv == CTCC_FASTCALL || cconv == CTCC_STDCALL) {
+ CTSize sz = clib_func_argsize(cts, ct);
+ const char *symd = lj_strfmt_pushf(L,
+ cconv == CTCC_FASTCALL ? "@%s@%d" : "_%s@%d",
+ sym, sz);
+ L->top--;
+ p = clib_getsym(cl, symd);
+ }
+ }
+#endif
+ if (!p)
+ clib_error(L, "cannot resolve symbol " LUA_QS ": %s", sym);
+#if LJ_TARGET_WINDOWS
+ SetLastError(oldwerr);
+#endif
+ cd = lj_cdata_new(cts, id, CTSIZE_PTR);
+ *(void **)cdataptr(cd) = p;
+ setcdataV(L, tv, cd);
+ }
+ }
+ return tv;
+}
+
+/* -- C library management ------------------------------------------------ */
+
+/* Create a new CLibrary object and push it on the stack. */
+static CLibrary *clib_new(lua_State *L, GCtab *mt)
+{
+ GCtab *t = lj_tab_new(L, 0, 0);
+ GCudata *ud = lj_udata_new(L, sizeof(CLibrary), t);
+ CLibrary *cl = (CLibrary *)uddata(ud);
+ cl->cache = t;
+ ud->udtype = UDTYPE_FFI_CLIB;
+ /* NOBARRIER: The GCudata is new (marked white). */
+ setgcref(ud->metatable, obj2gco(mt));
+ setudataV(L, L->top++, ud);
+ return cl;
+}
+
+/* Load a C library. */
+void lj_clib_load(lua_State *L, GCtab *mt, GCstr *name, int global)
+{
+ void *handle = clib_loadlib(L, strdata(name), global);
+ CLibrary *cl = clib_new(L, mt);
+ cl->handle = handle;
+}
+
+/* Unload a C library. */
+void lj_clib_unload(CLibrary *cl)
+{
+ clib_unloadlib(cl);
+ cl->handle = NULL;
+}
+
+/* Create the default C library object. */
+void lj_clib_default(lua_State *L, GCtab *mt)
+{
+ CLibrary *cl = clib_new(L, mt);
+ cl->handle = CLIB_DEFHANDLE;
+}
+
+#endif