fixed pointer argument handling issues when interfacing with libffi in mod/ffi.c
This commit is contained in:
parent
70c97f5ab5
commit
85eae9e78b
@ -210,3 +210,14 @@ what looks better as a shorthand expression for block value?
|
|||||||
a->()? block value?
|
a->()? block value?
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### FFI
|
||||||
|
|
||||||
|
```
|
||||||
|
ffi := FFI new: 'libc.so.6'.
|
||||||
|
(ffi call: #printf signature: 's|sl>i' arguments: #("[%s ffi test %ld]\n" "sloppy" 12345678)) dump.
|
||||||
|
(ffi call: #printf signature: 's>i' arguments: #("[%% ffi test %%]\n")) dump.
|
||||||
|
(ffi call: #puts signature: 's>i' arguments: #("this is ffi test")) dump.
|
||||||
|
(ffi call: #time signature: 'p>l' arguments: #(#\p0)) dump.
|
||||||
|
ffi close.
|
||||||
|
```
|
||||||
|
@ -34,7 +34,8 @@ class FFI(Object)
|
|||||||
self.name := name.
|
self.name := name.
|
||||||
|
|
||||||
x := self.ffi open(name).
|
x := self.ffi open(name).
|
||||||
(x isError) ifTrue: [^x].
|
//(x isError) ifTrue: [^x].
|
||||||
|
if (x isError) { FFIException signal: ('Unable to open %s' strfmt(name)) }.
|
||||||
|
|
||||||
^self.
|
^self.
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/*
|
/*arg
|
||||||
* $Id$
|
* $Id$
|
||||||
*
|
*
|
||||||
Copyright (c) 2014-2018 Chung, Hyung-Hwan. All rights reserved.
|
Copyright (c) 2014-2018 Chung, Hyung-Hwan. All rights reserved.
|
||||||
@ -57,9 +57,9 @@
|
|||||||
#define FMTC_INT 'i'
|
#define FMTC_INT 'i'
|
||||||
#define FMTC_LONG 'l'
|
#define FMTC_LONG 'l'
|
||||||
#define FMTC_LONGLONG 'L'
|
#define FMTC_LONGLONG 'L'
|
||||||
#define FMTC_POINTER 'p'
|
|
||||||
#define FMTC_BCS 's'
|
#define FMTC_BCS 's'
|
||||||
#define FMTC_UCS 'S'
|
#define FMTC_UCS 'S'
|
||||||
|
#define FMTC_POINTER 'p'
|
||||||
|
|
||||||
typedef struct link_t link_t;
|
typedef struct link_t link_t;
|
||||||
struct link_t
|
struct link_t
|
||||||
@ -232,8 +232,7 @@ static moo_pfrc_t pf_close (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
|
|||||||
#if defined(USE_DYNCALL)
|
#if defined(USE_DYNCALL)
|
||||||
dcFree (ffi->dc);
|
dcFree (ffi->dc);
|
||||||
ffi->dc = MOO_NULL;
|
ffi->dc = MOO_NULL;
|
||||||
#endif
|
#elif defined(USE_LIBFFI)
|
||||||
#if defined(USE_LIBFFI)
|
|
||||||
if (ffi->arg_types)
|
if (ffi->arg_types)
|
||||||
{
|
{
|
||||||
moo_freemem (moo, ffi->arg_types);
|
moo_freemem (moo, ffi->arg_types);
|
||||||
@ -264,8 +263,7 @@ softfail:
|
|||||||
return MOO_PF_SUCCESS;
|
return MOO_PF_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static MOO_INLINE int add_ffi_arg (moo_t* moo, ffi_t* ffi, moo_ooch_t fmtc, int _unsigned, moo_oop_t arg)
|
||||||
static int add_ffi_arg (moo_t* moo, ffi_t* ffi, moo_ooch_t fmtc, int _unsigned, moo_oop_t arg)
|
|
||||||
{
|
{
|
||||||
#if defined(USE_LIBFFI)
|
#if defined(USE_LIBFFI)
|
||||||
if (ffi->arg_count >= ffi->arg_max)
|
if (ffi->arg_count >= ffi->arg_max)
|
||||||
@ -294,7 +292,7 @@ static int add_ffi_arg (moo_t* moo, ffi_t* ffi, moo_ooch_t fmtc, int _unsigned,
|
|||||||
switch (fmtc)
|
switch (fmtc)
|
||||||
{
|
{
|
||||||
case FMTC_CHAR:
|
case FMTC_CHAR:
|
||||||
if (!MOO_OOP_IS_CHAR(arg)) goto inval;
|
if (!MOO_OOP_IS_CHAR(arg)) goto inval_arg_value;
|
||||||
if (_unsigned)
|
if (_unsigned)
|
||||||
{
|
{
|
||||||
#if defined(USE_DYNCALL)
|
#if defined(USE_DYNCALL)
|
||||||
@ -319,7 +317,7 @@ static int add_ffi_arg (moo_t* moo, ffi_t* ffi, moo_ooch_t fmtc, int _unsigned,
|
|||||||
if (_unsigned)
|
if (_unsigned)
|
||||||
{
|
{
|
||||||
moo_oow_t v;
|
moo_oow_t v;
|
||||||
if (moo_inttooow(moo, arg, &v) == 0) goto inval;
|
if (moo_inttooow(moo, arg, &v) == 0) goto inval_arg_value;
|
||||||
#if defined(USE_DYNCALL)
|
#if defined(USE_DYNCALL)
|
||||||
dcArgShort (ffi->dc, v);
|
dcArgShort (ffi->dc, v);
|
||||||
#elif defined(USE_LIBFFI)
|
#elif defined(USE_LIBFFI)
|
||||||
@ -330,7 +328,7 @@ static int add_ffi_arg (moo_t* moo, ffi_t* ffi, moo_ooch_t fmtc, int _unsigned,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
moo_ooi_t v;
|
moo_ooi_t v;
|
||||||
if (moo_inttoooi(moo, arg, &v) == 0) goto inval;
|
if (moo_inttoooi(moo, arg, &v) == 0) goto oops;
|
||||||
#if defined(USE_DYNCALL)
|
#if defined(USE_DYNCALL)
|
||||||
dcArgShort (ffi->dc, v);
|
dcArgShort (ffi->dc, v);
|
||||||
#elif defined(USE_LIBFFI)
|
#elif defined(USE_LIBFFI)
|
||||||
@ -344,7 +342,7 @@ static int add_ffi_arg (moo_t* moo, ffi_t* ffi, moo_ooch_t fmtc, int _unsigned,
|
|||||||
if (_unsigned)
|
if (_unsigned)
|
||||||
{
|
{
|
||||||
moo_oow_t v;
|
moo_oow_t v;
|
||||||
if (moo_inttooow(moo, arg, &v) == 0) goto inval;
|
if (moo_inttooow(moo, arg, &v) == 0) goto oops;
|
||||||
#if defined(USE_DYNCALL)
|
#if defined(USE_DYNCALL)
|
||||||
dcArgInt (ffi->dc, v);
|
dcArgInt (ffi->dc, v);
|
||||||
#elif defined(USE_LIBFFI)
|
#elif defined(USE_LIBFFI)
|
||||||
@ -355,7 +353,7 @@ static int add_ffi_arg (moo_t* moo, ffi_t* ffi, moo_ooch_t fmtc, int _unsigned,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
moo_ooi_t v;
|
moo_ooi_t v;
|
||||||
if (moo_inttoooi(moo, arg, &v) == 0) goto inval;
|
if (moo_inttoooi(moo, arg, &v) == 0) goto oops;
|
||||||
#if defined(USE_DYNCALL)
|
#if defined(USE_DYNCALL)
|
||||||
dcArgInt (ffi->dc, v);
|
dcArgInt (ffi->dc, v);
|
||||||
#elif defined(USE_LIBFFI)
|
#elif defined(USE_LIBFFI)
|
||||||
@ -370,7 +368,7 @@ static int add_ffi_arg (moo_t* moo, ffi_t* ffi, moo_ooch_t fmtc, int _unsigned,
|
|||||||
if (_unsigned)
|
if (_unsigned)
|
||||||
{
|
{
|
||||||
moo_oow_t v;
|
moo_oow_t v;
|
||||||
if (moo_inttooow(moo, arg, &v) == 0) goto inval;
|
if (moo_inttooow(moo, arg, &v) == 0) goto oops;
|
||||||
#if defined(USE_DYNCALL)
|
#if defined(USE_DYNCALL)
|
||||||
dcArgLong (ffi->dc, v);
|
dcArgLong (ffi->dc, v);
|
||||||
#elif defined(USE_LIBFFI)
|
#elif defined(USE_LIBFFI)
|
||||||
@ -381,7 +379,7 @@ static int add_ffi_arg (moo_t* moo, ffi_t* ffi, moo_ooch_t fmtc, int _unsigned,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
moo_ooi_t v;
|
moo_ooi_t v;
|
||||||
if (moo_inttoooi(moo, arg, &v) == 0) goto inval;
|
if (moo_inttoooi(moo, arg, &v) == 0) goto oops;
|
||||||
#if defined(USE_DYNCALL)
|
#if defined(USE_DYNCALL)
|
||||||
dcArgLong (ffi->dc, v);
|
dcArgLong (ffi->dc, v);
|
||||||
#elif defined(USE_LIBFFI)
|
#elif defined(USE_LIBFFI)
|
||||||
@ -399,7 +397,7 @@ static int add_ffi_arg (moo_t* moo, ffi_t* ffi, moo_ooch_t fmtc, int _unsigned,
|
|||||||
{
|
{
|
||||||
moo_oow_t v;
|
moo_oow_t v;
|
||||||
/* TODO: if (MOO_SIZEOF_LONG_LONG > MOO_SIZEOF_OOI_T) use moo_inttointmax() or something */
|
/* TODO: if (MOO_SIZEOF_LONG_LONG > MOO_SIZEOF_OOI_T) use moo_inttointmax() or something */
|
||||||
if (moo_inttooow(moo, arg, &v) == 0) goto inval;
|
if (moo_inttooow(moo, arg, &v) == 0) goto oops;
|
||||||
#if defined(USE_DYNCALL)
|
#if defined(USE_DYNCALL)
|
||||||
dcArgLongLong (ffi->dc, v);
|
dcArgLongLong (ffi->dc, v);
|
||||||
#elif defined(USE_LIBFFI)
|
#elif defined(USE_LIBFFI)
|
||||||
@ -410,7 +408,7 @@ static int add_ffi_arg (moo_t* moo, ffi_t* ffi, moo_ooch_t fmtc, int _unsigned,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
moo_ooi_t v;
|
moo_ooi_t v;
|
||||||
if (moo_inttoooi(moo, arg, &v) == 0) goto inval;
|
if (moo_inttoooi(moo, arg, &v) == 0) goto oops;
|
||||||
#if defined(USE_DYNCALL)
|
#if defined(USE_DYNCALL)
|
||||||
dcArgLongLong (ffi->dc, v);
|
dcArgLongLong (ffi->dc, v);
|
||||||
#elif defined(USE_LIBFFI)
|
#elif defined(USE_LIBFFI)
|
||||||
@ -428,7 +426,7 @@ static int add_ffi_arg (moo_t* moo, ffi_t* ffi, moo_ooch_t fmtc, int _unsigned,
|
|||||||
{
|
{
|
||||||
moo_bch_t* ptr;
|
moo_bch_t* ptr;
|
||||||
|
|
||||||
if (!MOO_OBJ_IS_CHAR_POINTER(arg)) goto inval;
|
if (!MOO_OBJ_IS_CHAR_POINTER(arg)) goto inval_arg_value;
|
||||||
|
|
||||||
#if defined(MOO_OOCH_IS_UCH)
|
#if defined(MOO_OOCH_IS_UCH)
|
||||||
ptr = moo_dupootobcharswithheadroom(moo, MOO_SIZEOF_VOID_P, MOO_OBJ_GET_CHAR_SLOT(arg), MOO_OBJ_GET_SIZE(arg), MOO_NULL);
|
ptr = moo_dupootobcharswithheadroom(moo, MOO_SIZEOF_VOID_P, MOO_OBJ_GET_CHAR_SLOT(arg), MOO_OBJ_GET_SIZE(arg), MOO_NULL);
|
||||||
@ -443,7 +441,8 @@ static int add_ffi_arg (moo_t* moo, ffi_t* ffi, moo_ooch_t fmtc, int _unsigned,
|
|||||||
#if defined(USE_DYNCALL)
|
#if defined(USE_DYNCALL)
|
||||||
dcArgPointer (ffi->dc, ptr);
|
dcArgPointer (ffi->dc, ptr);
|
||||||
#elif defined(USE_LIBFFI)
|
#elif defined(USE_LIBFFI)
|
||||||
ffi->arg_values[ffi->arg_count] = ptr;
|
ffi->arg_values[ffi->arg_count] = &ffi->arg_svs[ffi->arg_count].p;
|
||||||
|
ffi->arg_svs[ffi->arg_count].p = ptr;
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -452,7 +451,7 @@ static int add_ffi_arg (moo_t* moo, ffi_t* ffi, moo_ooch_t fmtc, int _unsigned,
|
|||||||
{
|
{
|
||||||
moo_uch_t* ptr;
|
moo_uch_t* ptr;
|
||||||
|
|
||||||
if (!MOO_OBJ_IS_CHAR_POINTER(arg)) goto inval;
|
if (!MOO_OBJ_IS_CHAR_POINTER(arg)) goto inval_arg_value;
|
||||||
|
|
||||||
#if defined(MOO_OOCH_IS_UCH)
|
#if defined(MOO_OOCH_IS_UCH)
|
||||||
ptr = MOO_OBJ_GET_CHAR_SLOT(arg);
|
ptr = MOO_OBJ_GET_CHAR_SLOT(arg);
|
||||||
@ -467,14 +466,33 @@ static int add_ffi_arg (moo_t* moo, ffi_t* ffi, moo_ooch_t fmtc, int _unsigned,
|
|||||||
#if defined(USE_DYNCALL)
|
#if defined(USE_DYNCALL)
|
||||||
dcArgPointer (ffi->dc, ptr);
|
dcArgPointer (ffi->dc, ptr);
|
||||||
#elif defined(USE_LIBFFI)
|
#elif defined(USE_LIBFFI)
|
||||||
ffi->arg_values[ffi->arg_count] = ptr;
|
ffi->arg_values[ffi->arg_count] = &ffi->arg_svs[ffi->arg_count].p;
|
||||||
|
ffi->arg_svs[ffi->arg_count].p = ptr;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case FMTC_POINTER:
|
||||||
|
{
|
||||||
|
void* ptr;
|
||||||
|
|
||||||
|
/* TODO: map nil to NULL? or should #\p0 be enough? */
|
||||||
|
if (!MOO_OOP_IS_SMPTR(arg)) goto inval_arg_value;
|
||||||
|
ptr = MOO_OOP_TO_SMPTR(arg);
|
||||||
|
|
||||||
|
#if defined(USE_DYNCALL)
|
||||||
|
dcArgPointer (ffic->dc, ptr);
|
||||||
|
#elif defined(USE_LIBFFI)
|
||||||
|
ffi->arg_values[ffi->arg_count] = &ffi->arg_svs[ffi->arg_count].p;
|
||||||
|
ffi->arg_svs[ffi->arg_count].p = ptr;
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* invalid argument signature specifier */
|
/* invalid argument signature specifier */
|
||||||
goto inval;
|
moo_seterrbfmt (moo, MOO_EINVAL, "invalid signature character - %jc", fmtc);
|
||||||
|
goto oops;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(USE_LIBFFI)
|
#if defined(USE_LIBFFI)
|
||||||
@ -483,8 +501,8 @@ static int add_ffi_arg (moo_t* moo, ffi_t* ffi, moo_ooch_t fmtc, int _unsigned,
|
|||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
inval:
|
inval_arg_value:
|
||||||
moo_seterrnum (moo, MOO_EINVAL);
|
moo_seterrbfmt (moo, MOO_EINVAL, "invalid argument value - %O", arg);
|
||||||
|
|
||||||
oops:
|
oops:
|
||||||
return -1;
|
return -1;
|
||||||
@ -583,7 +601,6 @@ static moo_pfrc_t pf_call (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
|
|||||||
fmtc = (i >= MOO_OBJ_GET_SIZE(sig)? FMTC_NULL: MOO_OBJ_GET_CHAR_VAL(sig, i));
|
fmtc = (i >= MOO_OBJ_GET_SIZE(sig)? FMTC_NULL: MOO_OBJ_GET_CHAR_VAL(sig, i));
|
||||||
#if defined(USE_LIBFFI)
|
#if defined(USE_LIBFFI)
|
||||||
/* TODO: handle unsigned */
|
/* TODO: handle unsigned */
|
||||||
//printf ("XXXXXXXXXXXXXXXXXXXXXXXXXXXxAAAAAAAA %d %d %d %p %p [%s] [%s] %ld\n", (int)j, (int)nfixedargs, (int)ffi->arg_count, ffi->fmtc_to_type[0][fmtc], &ffi_type_sint32, ffi->arg_values[0], ffi->arg_values[1], *(long*)ffi->arg_values[2]);
|
|
||||||
fs = (nfixedargs == j)? ffi_prep_cif(&ffi->cif, FFI_DEFAULT_ABI, j, ffi->fmtc_to_type[0][fmtc], ffi->arg_types):
|
fs = (nfixedargs == j)? ffi_prep_cif(&ffi->cif, FFI_DEFAULT_ABI, j, ffi->fmtc_to_type[0][fmtc], ffi->arg_types):
|
||||||
ffi_prep_cif_var(&ffi->cif, FFI_DEFAULT_ABI, nfixedargs, j, ffi->fmtc_to_type[0][fmtc], ffi->arg_types);
|
ffi_prep_cif_var(&ffi->cif, FFI_DEFAULT_ABI, nfixedargs, j, ffi->fmtc_to_type[0][fmtc], ffi->arg_types);
|
||||||
if (fs != FFI_OK)
|
if (fs != FFI_OK)
|
||||||
@ -685,7 +702,7 @@ static moo_pfrc_t pf_call (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
|
|||||||
|
|
||||||
#if defined(USE_DYNCALL)
|
#if defined(USE_DYNCALL)
|
||||||
r = dcCallPointer(ffi->dc, f);
|
r = dcCallPointer(ffi->dc, f);
|
||||||
#else
|
#elif defined(USE_LIBFFI)
|
||||||
r = ffi->ret_sv.p;
|
r = ffi->ret_sv.p;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -711,7 +728,7 @@ static moo_pfrc_t pf_call (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
|
|||||||
|
|
||||||
#if defined(USE_DYNCALL)
|
#if defined(USE_DYNCALL)
|
||||||
r = dcCallPointer(ffi->dc, f);
|
r = dcCallPointer(ffi->dc, f);
|
||||||
#else
|
#elif defined(USE_LIBFFI)
|
||||||
r = ffi->ret_sv.p;
|
r = ffi->ret_sv.p;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -730,6 +747,26 @@ static moo_pfrc_t pf_call (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case FMTC_POINTER:
|
||||||
|
{
|
||||||
|
void* r;
|
||||||
|
|
||||||
|
#if defined(USE_DYNCALL)
|
||||||
|
r = dcCallPointer(ffi->dc, f);
|
||||||
|
#elif defined(USE_LIBFFI)
|
||||||
|
r = ffi->ret_sv.p;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!MOO_IN_SMPTR_RANGE(r))
|
||||||
|
{
|
||||||
|
/* the returned pointer is not aligned */
|
||||||
|
goto softfail;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOO_STACK_SETRET (moo, nargs, MOO_SMPTR_TO_OOP(r));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
#if defined(USE_DYNCALL)
|
#if defined(USE_DYNCALL)
|
||||||
dcCallVoid (ffi->dc, f);
|
dcCallVoid (ffi->dc, f);
|
||||||
@ -842,6 +879,7 @@ static moo_pfbase_t* query (moo_t* moo, moo_mod_t* mod, const moo_ooch_t* name,
|
|||||||
static void unload (moo_t* moo, moo_mod_t* mod)
|
static void unload (moo_t* moo, moo_mod_t* mod)
|
||||||
{
|
{
|
||||||
/* TODO: anything? close open open dll handles? For that, pf_open must store the value it returns to mod->ctx or somewhere..*/
|
/* TODO: anything? close open open dll handles? For that, pf_open must store the value it returns to mod->ctx or somewhere..*/
|
||||||
|
/* TODO: track all opened shared objects... clear all external memories/resources created but not cleared (for lacking the call to 'close') */
|
||||||
}
|
}
|
||||||
|
|
||||||
int moo_mod_ffi (moo_t* moo, moo_mod_t* mod)
|
int moo_mod_ffi (moo_t* moo, moo_mod_t* mod)
|
||||||
|
Loading…
Reference in New Issue
Block a user