aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2011-01-11 03:08:54 +0100
committerMike Pall <mike>2011-01-11 03:08:54 +0100
commita54843bb510d4f51e4ce404fe2d42ba80fc74a04 (patch)
tree3c21e52606aefeba6f2f7a16d836f9f462876355 /src
parent87a6c8a980edf4bd8ba6b2126269400a925b4d05 (diff)
downloadluajit-a54843bb510d4f51e4ce404fe2d42ba80fc74a04.tar.gz
luajit-a54843bb510d4f51e4ce404fe2d42ba80fc74a04.tar.bz2
luajit-a54843bb510d4f51e4ce404fe2d42ba80fc74a04.zip
FFI: Lookup decorated name for fastcall/stdcall functions.
Diffstat (limited to 'src')
-rw-r--r--src/lj_clib.c93
1 files changed, 63 insertions, 30 deletions
diff --git a/src/lj_clib.c b/src/lj_clib.c
index 91309eb2..3fc91a72 100644
--- a/src/lj_clib.c
+++ b/src/lj_clib.c
@@ -31,38 +31,39 @@
31#define CLIB_DEFHANDLE NULL 31#define CLIB_DEFHANDLE NULL
32#endif 32#endif
33 33
34LJ_NORET LJ_NOINLINE static void clib_error(lua_State *L) 34LJ_NORET LJ_NOINLINE static void clib_error_(lua_State *L)
35{ 35{
36 lj_err_callermsg(L, dlerror()); 36 lj_err_callermsg(L, dlerror());
37} 37}
38 38
39#define clib_error(L, fmt, name) clib_error_(L)
40
39#if LJ_TARGET_OSX 41#if LJ_TARGET_OSX
40#define CLIB_SOEXT "%s.dylib" 42#define CLIB_SOEXT "%s.dylib"
41#else 43#else
42#define CLIB_SOEXT "%s.so" 44#define CLIB_SOEXT "%s.so"
43#endif 45#endif
44 46
45static const char *clib_extname(lua_State *L, GCstr *name) 47static const char *clib_extname(lua_State *L, const char *name)
46{ 48{
47 const char *s = strdata(name); 49 if (!strchr(name, '/')) {
48 if (!strchr(s, '/')) { 50 if (!strchr(name, '.')) {
49 if (!strchr(s, '.')) { 51 name = lj_str_pushf(L, CLIB_SOEXT, name);
50 s = lj_str_pushf(L, CLIB_SOEXT, s);
51 L->top--; 52 L->top--;
52 } 53 }
53 if (!(s[0] == 'l' && s[1] == 'i' && s[2] == 'b')) { 54 if (!(name[0] == 'l' && name[1] == 'i' && name[2] == 'b')) {
54 s = lj_str_pushf(L, "lib%s", s); 55 name = lj_str_pushf(L, "lib%s", name);
55 L->top--; 56 L->top--;
56 } 57 }
57 } 58 }
58 return s; 59 return name;
59} 60}
60 61
61static void *clib_loadlib(lua_State *L, GCstr *name, int global) 62static void *clib_loadlib(lua_State *L, const char *name, int global)
62{ 63{
63 void *h = dlopen(clib_extname(L, name), 64 void *h = dlopen(clib_extname(L, name),
64 RTLD_LAZY | (global?RTLD_GLOBAL:RTLD_LOCAL)); 65 RTLD_LAZY | (global?RTLD_GLOBAL:RTLD_LOCAL));
65 if (!h) clib_error(L); 66 if (!h) clib_error_(L);
66 return h; 67 return h;
67} 68}
68 69
@@ -72,10 +73,9 @@ static void clib_unloadlib(CLibrary *cl)
72 dlclose(cl->handle); 73 dlclose(cl->handle);
73} 74}
74 75
75static void *clib_getsym(lua_State *L, CLibrary *cl, GCstr *name) 76static void *clib_getsym(CLibrary *cl, const char *name)
76{ 77{
77 void *p = dlsym(cl->handle, strdata(name)); 78 void *p = dlsym(cl->handle, name);
78 if (!p) clib_error(L);
79 return p; 79 return p;
80} 80}
81 81
@@ -127,17 +127,16 @@ static int clib_needext(const char *s)
127 return 1; 127 return 1;
128} 128}
129 129
130static const char *clib_extname(lua_State *L, GCstr *name) 130static const char *clib_extname(lua_State *L, const char *name)
131{ 131{
132 const char *s = strdata(name); 132 if (clib_needext(name)) {
133 if (clib_needext(s)) { 133 name = lj_str_pushf(L, "%s.dll", name);
134 s = lj_str_pushf(L, "%s.dll", s);
135 L->top--; 134 L->top--;
136 } 135 }
137 return s; 136 return name;
138} 137}
139 138
140static void *clib_loadlib(lua_State *L, GCstr *name, int global) 139static void *clib_loadlib(lua_State *L, const char *name, int global)
141{ 140{
142 void *h = (void *)LoadLibraryA(clib_extname(L, name)); 141 void *h = (void *)LoadLibraryA(clib_extname(L, name));
143 if (!h) clib_error(L, "cannot load module " LUA_QS ": %s", strdata(name)); 142 if (!h) clib_error(L, "cannot load module " LUA_QS ": %s", strdata(name));
@@ -157,9 +156,8 @@ static void clib_unloadlib(CLibrary *cl)
157 } 156 }
158} 157}
159 158
160static void *clib_getsym(lua_State *L, CLibrary *cl, GCstr *name) 159static void *clib_getsym(CLibrary *cl, const char *name)
161{ 160{
162 const char *sym = strdata(name);
163 void *p; 161 void *p;
164 if (cl->handle == CLIB_DEFHANDLE) { /* Search default libraries. */ 162 if (cl->handle == CLIB_DEFHANDLE) { /* Search default libraries. */
165 MSize i; 163 MSize i;
@@ -183,13 +181,12 @@ static void *clib_getsym(lua_State *L, CLibrary *cl, GCstr *name)
183 if (!h) continue; 181 if (!h) continue;
184 clib_def_handle[i] = (void *)h; 182 clib_def_handle[i] = (void *)h;
185 } 183 }
186 p = (void *)GetProcAddress(h, sym); 184 p = (void *)GetProcAddress(h, name);
187 if (p) break; 185 if (p) break;
188 } 186 }
189 } else { 187 } else {
190 p = (void *)GetProcAddress((HINSTANCE)cl->handle, sym); 188 p = (void *)GetProcAddress((HINSTANCE)cl->handle, name);
191 } 189 }
192 if (!p) clib_error(L, "cannot resolve symbol " LUA_QS ": %s", sym);
193 return p; 190 return p;
194} 191}
195 192
@@ -197,7 +194,13 @@ static void *clib_getsym(lua_State *L, CLibrary *cl, GCstr *name)
197 194
198#define CLIB_DEFHANDLE NULL 195#define CLIB_DEFHANDLE NULL
199 196
200static void *clib_loadlib(lua_State *L, GCstr *name, int global) 197LJ_NORET LJ_NOINLINE static void clib_error(lua_State *L, const char *fmt,
198 const char *name)
199{
200 lj_err_callermsg(L, lj_str_pushf(L, fmt, name, "no support for this OS"));
201}
202
203static void *clib_loadlib(lua_State *L, const char *name, int global)
201{ 204{
202 lj_err_callermsg(L, "no support for loading dynamic libraries for this OS"); 205 lj_err_callermsg(L, "no support for loading dynamic libraries for this OS");
203 UNUSED(name); UNUSED(global); 206 UNUSED(name); UNUSED(global);
@@ -209,9 +212,8 @@ static void clib_unloadlib(CLibrary *cl)
209 UNUSED(cl); 212 UNUSED(cl);
210} 213}
211 214
212static void *clib_getsym(lua_State *L, CLibrary *cl, GCstr *name) 215static void *clib_getsym(CLibrary *cl, const char *name)
213{ 216{
214 lj_err_callermsg(L, "no support for resolving symbols for this OS");
215 UNUSED(cl); UNUSED(name); 217 UNUSED(cl); UNUSED(name);
216 return NULL; 218 return NULL;
217} 219}
@@ -224,6 +226,22 @@ static void *clib_getsym(lua_State *L, CLibrary *cl, GCstr *name)
224#define CLNS_INDEX \ 226#define CLNS_INDEX \
225 ((1u<<CT_FUNC)|(1u<<CT_EXTERN)|(1u<<CT_CONSTVAL)) 227 ((1u<<CT_FUNC)|(1u<<CT_EXTERN)|(1u<<CT_CONSTVAL))
226 228
229#if LJ_TARGET_X86 && LJ_ABI_WIN
230/* Compute argument size for fastcall/stdcall functions. */
231static CTSize clib_func_argsize(CTState *cts, CType *ct)
232{
233 CTSize n = 0;
234 while (ct->sib) {
235 CType *d;
236 ct = ctype_get(cts, ct->sib);
237 lua_assert(ctype_isfield(ct->info));
238 d = ctype_rawchild(cts, ct);
239 n += ((d->size + 3) & ~3);
240 }
241 return n;
242}
243#endif
244
227/* Index a C library by name. */ 245/* Index a C library by name. */
228TValue *lj_clib_index(lua_State *L, CLibrary *cl, GCstr *name) 246TValue *lj_clib_index(lua_State *L, CLibrary *cl, GCstr *name)
229{ 247{
@@ -242,9 +260,24 @@ TValue *lj_clib_index(lua_State *L, CLibrary *cl, GCstr *name)
242 else 260 else
243 setnumV(tv, (lua_Number)(int32_t)ct->size); 261 setnumV(tv, (lua_Number)(int32_t)ct->size);
244 } else { 262 } else {
245 void *p = clib_getsym(L, cl, name); 263 void *p = clib_getsym(cl, strdata(name));
246 GCcdata *cd; 264 GCcdata *cd;
247 lua_assert(ctype_isfunc(ct->info) || ctype_isextern(ct->info)); 265 lua_assert(ctype_isfunc(ct->info) || ctype_isextern(ct->info));
266#if LJ_TARGET_X86 && LJ_ABI_WIN
267 /* Retry with decorated name for fastcall/stdcall functions. */
268 if (!p && ctype_isfunc(ct->info)) {
269 CTInfo cconv = ctype_cconv(ct->info);
270 if (cconv == CTCC_FASTCALL || cconv == CTCC_STDCALL) {
271 CTSize sz = clib_func_argsize(cts, ct);
272 const char *sym = lj_str_pushf(L,
273 cconv == CTCC_FASTCALL ? "@%s@%d" : "_%s@%d", strdata(name), sz);
274 L->top--;
275 p = clib_getsym(cl, sym);
276 }
277 }
278#endif
279 if (!p)
280 clib_error(L, "cannot resolve symbol " LUA_QS ": %s", strdata(name));
248 cd = lj_cdata_new(cts, id, CTSIZE_PTR); 281 cd = lj_cdata_new(cts, id, CTSIZE_PTR);
249 *(void **)cdataptr(cd) = p; 282 *(void **)cdataptr(cd) = p;
250 setcdataV(L, tv, cd); 283 setcdataV(L, tv, cd);
@@ -272,7 +305,7 @@ static CLibrary *clib_new(lua_State *L, GCtab *mt)
272/* Load a C library. */ 305/* Load a C library. */
273void lj_clib_load(lua_State *L, GCtab *mt, GCstr *name, int global) 306void lj_clib_load(lua_State *L, GCtab *mt, GCstr *name, int global)
274{ 307{
275 void *handle = clib_loadlib(L, name, global); 308 void *handle = clib_loadlib(L, strdata(name), global);
276 CLibrary *cl = clib_new(L, mt); 309 CLibrary *cl = clib_new(L, mt);
277 cl->handle = handle; 310 cl->handle = handle;
278} 311}