Skip to content

Commit 85bb252

Browse files
committed
ffi: trace create event ccall helper
1 parent d006079 commit 85bb252

11 files changed

Lines changed: 202 additions & 1 deletion

notes/ffi-callxs-record-gate.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,8 @@ The exact CreateFileMapping-shaped slice traces
167167
`void *(void *, void *, uint32_t, uint32_t, uint32_t, void *)` calls.
168168
The exact CreateThread-shaped slice traces
169169
`void *(void *, uint64_t, void *, void *, uint32_t, void *)` calls.
170+
The exact CreateEvent/CreateSemaphore-shaped slice traces
171+
`void *(void *, int32_t, int32_t, void *)` calls.
170172
Other multi-argument pointer/size shapes remain interpreted.
171173
The shared GPR helper matrix separately covers exact two-argument
172174
`pointer,int64_t` and `pointer,uint64_t` span shapes; broader pointer/size

notes/ffi-ccall-jit-trampoline.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ unsigned-int/pointer argument shape,
136136
pointer/pointer/unsigned-int/unsigned-int/unsigned-int/pointer argument shape,
137137
`lj_ccall_jit_ptr_ptr_u64_ptr_ptr_u32_ptr()` for the exact pointer-returning
138138
pointer/size/pointer/pointer/unsigned-int/pointer argument shape,
139+
`lj_ccall_jit_ptr_ptr_i32_i32_ptr()` for the exact pointer-returning
140+
pointer/signed-int/signed-int/pointer argument shape,
139141
`lj_ccall_jit_i32_ptr_ptr_u64()` for the exact pointer/pointer/size argument
140142
shape,
141143
`lj_ccall_jit_i32_ptr_ptr_u32()` / `lj_ccall_jit_u32_ptr_ptr_u32()` for exact
@@ -264,6 +266,9 @@ The scope is deliberately narrow:
264266
- exact `pointer(pointer, uint64_t, pointer, pointer, uint32_t, pointer)`
265267
calls, preserving security attributes, stack size, start address, parameter,
266268
creation flags, and thread-id pointer for CreateThread-style ABI classes;
269+
- exact `pointer(pointer, int32_t, int32_t, pointer)` calls, preserving
270+
security attributes, boolean/count fields, and name pointer for
271+
CreateEvent/CreateSemaphore-style ABI classes;
267272
- exact `int32_t(pointer, pointer, uint64_t)` calls, with the final size
268273
argument preserved before the helper casts to the exact unsigned 64-bit ABI
269274
width;
@@ -400,6 +405,8 @@ traced CreateFileMapping-shaped pointer/pointer/uint32/uint32/uint32/pointer
400405
pointer-returning loops,
401406
traced CreateThread-shaped pointer/uint64/ptr/ptr/uint32/ptr
402407
pointer-returning loops,
408+
traced CreateEvent/CreateSemaphore-shaped pointer/int32/int32/pointer
409+
pointer-returning loops,
403410
traced ReadFile/WriteFile-shaped pointer/pointer/uint32/pointer/pointer
404411
signed-int-result loops,
405412
traced DeviceIoControl-shaped pointer/uint32/pointer/uint32/pointer/uint32/

notes/ffi-ccall-native-helpers.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,10 @@ preserving handle, security attributes, protection flags, max size high/low,
183183
mapping name, and pointer result. The exact CreateThread-shaped slice traces
184184
`void *(void *, uint64_t, void *, void *, uint32_t, void *)` calls while
185185
preserving security attributes, stack size, start address, parameter, creation
186-
flags, thread-id pointer, and pointer result. Exact
186+
flags, thread-id pointer, and pointer result. The exact
187+
CreateEvent/CreateSemaphore-shaped slice traces
188+
`void *(void *, int32_t, int32_t, void *)` calls while preserving security
189+
attributes, boolean/count fields, name pointer, and pointer result. Exact
187190
two-argument `pointer,int64_t` and `pointer,uint64_t` span-style shapes are
188191
covered by the shared GPR helper matrix, while broader pointer/size families
189192
still fall back. Broad traced ordinary FFI C calls remain interpreted because
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# FFI CreateEvent/CreateSemaphore-shaped C-call helper
2+
3+
Added exact traced native-state FFI C-call coverage for:
4+
5+
- `void *(void *, int32_t, int32_t, void *)`;
6+
- runtime helper `lj_ccall_jit_ptr_ptr_i32_i32_ptr()`;
7+
- recorder matcher `crec_call_jit_ptr_ptr_i32_i32_ptr()`;
8+
- IR call metadata `IRCALL_lj_ccall_jit_ptr_ptr_i32_i32_ptr`.
9+
10+
This covers Windows CreateEvent/CreateSemaphore-shaped
11+
security/boolean-or-count/name ABI classes without enabling generic
12+
`IR_CALLXS`. The matcher requires a fixed non-vararg prototype, a pointer
13+
return, pointer arguments at the security/name positions, and exact signed
14+
32-bit integer fields in the middle. The helper remains on the audited
15+
native-state path and boxes the returned handle pointer as cdata.
16+
17+
Validation plan:
18+
19+
- `make -C src -j$(getconf _NPROCESSORS_ONLN) TARGET_STRIP=:`
20+
- `LJ_TEST_DISABLE_BUILD_CACHE=1 tools/ci/lua_test.sh m7_ffi_ccall_native`
21+
- `LUA=$PWD/src/luajit tools/ci/lua_test.sh run_stock_tests -- --quiet lib/ffi`

notes/m7.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1762,6 +1762,10 @@ FFI C-call JIT trampoline:
17621762
CreateThread-shaped security/stack-size/start-address/parameter/flags/thread-id
17631763
ABI classes with boxed pointer results, high-bit stack sizes, and high-bit
17641764
DWORD flags preserved.
1765+
Exact `void *(void *, int32_t, int32_t, void *)` calls now record through
1766+
`lj_ccall_jit_ptr_ptr_i32_i32_ptr()`, covering
1767+
CreateEvent/CreateSemaphore-shaped security/boolean-or-count/name ABI classes
1768+
with boxed pointer results and signed 32-bit fields preserved.
17651769
Exact `int32_t(void *, void *, uint64_t)` calls now record through
17661770
`lj_ccall_jit_i32_ptr_ptr_u64()`, covering memcmp/strncmp-style
17671771
pointer/pointer/size ABI classes with the unsigned 64-bit size preserved.

src/lj_ccall.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3848,6 +3848,23 @@ void *lj_ccall_jit_ptr_ptr_u64_ptr_ptr_u32_ptr(lua_State *L,
38483848
return ret;
38493849
}
38503850

3851+
void *lj_ccall_jit_ptr_ptr_i32_i32_ptr(lua_State *L, void *func,
3852+
void *a, int32_t b, int32_t c,
3853+
void *d)
3854+
{
3855+
CTState *cts = ctype_cts(L);
3856+
CCallNativeState native;
3857+
uint32_t actions;
3858+
void *ret;
3859+
lj_ccall_native_save(L, &native);
3860+
lj_ccall_native_enter(L, &native, func);
3861+
ret = ((void *(*)(void *, int32_t, int32_t, void *))(uintptr_t)func)(a, b,
3862+
c, d);
3863+
actions = lj_ccall_native_leave(L, cts, &native, func);
3864+
lj_ccall_native_checkstop(L, actions, &native);
3865+
return ret;
3866+
}
3867+
38513868
int32_t lj_ccall_jit_i32_ptr_ptr_u64(lua_State *L, void *func, void *a,
38523869
void *b, uint64_t c)
38533870
{

src/lj_ccall.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,9 @@ LJ_FUNC void *lj_ccall_jit_ptr_ptr_u64_ptr_ptr_u32_ptr(lua_State *L,
501501
uint64_t b,
502502
void *c, void *d,
503503
uint32_t e, void *f);
504+
LJ_FUNC void *lj_ccall_jit_ptr_ptr_i32_i32_ptr(lua_State *L, void *func,
505+
void *a, int32_t b,
506+
int32_t c, void *d);
504507
LJ_FUNC int32_t lj_ccall_jit_i32_ptr_ptr_u64(lua_State *L, void *func,
505508
void *a, void *b,
506509
uint64_t c);

src/lj_crecord.c

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6463,6 +6463,121 @@ static int crec_call_jit_ptr_ptr_u64_ptr_ptr_u32_ptr(jit_State *J,
64636463
return 1;
64646464
}
64656465

6466+
static int crec_call_jit_ptr_ptr_i32_i32_ptr(jit_State *J, RecordFFData *rd,
6467+
CTState *cts, CType *ct,
6468+
CTInfo info, GCcdata *cd,
6469+
IRType tp, CTSize fsz)
6470+
{
6471+
CType ctrsnap, ctfcopy, dcopy;
6472+
CType *ctr, *ctf, *d;
6473+
CTypeID fid, did;
6474+
CTInfo ctr_info, ctfinfo, dinfo;
6475+
TRef func, arg0, arg1, arg2, arg3, tr;
6476+
MSize narg = 0;
6477+
6478+
if ((info & CTF_VARARG))
6479+
return 0;
6480+
while (J->base[1+narg]) {
6481+
if (narg >= 4)
6482+
return 0;
6483+
narg++;
6484+
}
6485+
if (narg != 4)
6486+
return 0;
6487+
6488+
ctr = crec_ctype_rawchild(J, cts, ct, &ctrsnap);
6489+
ctr_info = ctype_info_acq(ctr);
6490+
if (!ctype_isptr(ctr_info) || ctype_size_acq(ctr) != CTSIZE_PTR)
6491+
return 0;
6492+
6493+
fid = ctype_sib_acq(ct);
6494+
while (fid) {
6495+
ctf = crec_ctype_snapshot(J, cts, fid, &ctfcopy);
6496+
ctfinfo = ctype_info_acq(ctf);
6497+
if (!ctype_isattrib(ctfinfo)) break;
6498+
fid = ctype_sib_acq(ctf);
6499+
}
6500+
6501+
if (!fid)
6502+
return 0;
6503+
ctf = crec_ctype_snapshot(J, cts, fid, &ctfcopy);
6504+
ctfinfo = ctype_info_acq(ctf);
6505+
if (!ctype_isfield(ctfinfo))
6506+
return 0;
6507+
fid = ctype_sib_acq(ctf);
6508+
did = ctype_cid(ctfinfo);
6509+
d = crec_ctype_rawrefid(J, cts, did, &did, &dcopy);
6510+
dinfo = ctype_info_acq(d);
6511+
if (!ctype_isptr(dinfo) || ctype_size_acq(d) != CTSIZE_PTR)
6512+
return 0;
6513+
arg0 = crec_ct_tv(J, d, 0, J->base[1], &rd->argv[1]);
6514+
if (!tref_istype(arg0, IRT_PTR))
6515+
lj_trace_err(J, LJ_TRERR_NYICALL);
6516+
6517+
if (!fid)
6518+
return 0;
6519+
ctf = crec_ctype_snapshot(J, cts, fid, &ctfcopy);
6520+
ctfinfo = ctype_info_acq(ctf);
6521+
if (!ctype_isfield(ctfinfo))
6522+
return 0;
6523+
fid = ctype_sib_acq(ctf);
6524+
did = ctype_cid(ctfinfo);
6525+
d = crec_ctype_rawrefid(J, cts, did, &did, &dcopy);
6526+
dinfo = ctype_info_acq(d);
6527+
if (!ctype_isinteger(dinfo) || ctype_size_acq(d) != 4 ||
6528+
(dinfo & CTF_UNSIGNED))
6529+
return 0;
6530+
arg1 = crec_ct_tv(J, d, 0, J->base[2], &rd->argv[2]);
6531+
if (!tref_isint(arg1))
6532+
lj_trace_err(J, LJ_TRERR_NYICALL);
6533+
6534+
if (!fid)
6535+
return 0;
6536+
ctf = crec_ctype_snapshot(J, cts, fid, &ctfcopy);
6537+
ctfinfo = ctype_info_acq(ctf);
6538+
if (!ctype_isfield(ctfinfo))
6539+
return 0;
6540+
fid = ctype_sib_acq(ctf);
6541+
did = ctype_cid(ctfinfo);
6542+
d = crec_ctype_rawrefid(J, cts, did, &did, &dcopy);
6543+
dinfo = ctype_info_acq(d);
6544+
if (!ctype_isinteger(dinfo) || ctype_size_acq(d) != 4 ||
6545+
(dinfo & CTF_UNSIGNED))
6546+
return 0;
6547+
arg2 = crec_ct_tv(J, d, 0, J->base[3], &rd->argv[3]);
6548+
if (!tref_isint(arg2))
6549+
lj_trace_err(J, LJ_TRERR_NYICALL);
6550+
6551+
if (!fid)
6552+
return 0;
6553+
ctf = crec_ctype_snapshot(J, cts, fid, &ctfcopy);
6554+
ctfinfo = ctype_info_acq(ctf);
6555+
if (!ctype_isfield(ctfinfo))
6556+
return 0;
6557+
fid = ctype_sib_acq(ctf);
6558+
did = ctype_cid(ctfinfo);
6559+
d = crec_ctype_rawrefid(J, cts, did, &did, &dcopy);
6560+
dinfo = ctype_info_acq(d);
6561+
if (!ctype_isptr(dinfo) || ctype_size_acq(d) != CTSIZE_PTR)
6562+
return 0;
6563+
arg3 = crec_ct_tv(J, d, 0, J->base[4], &rd->argv[4]);
6564+
if (!tref_istype(arg3, IRT_PTR))
6565+
lj_trace_err(J, LJ_TRERR_NYICALL);
6566+
if (fid)
6567+
return 0;
6568+
6569+
if (lj_ctype_cb_isblacklisted(cts, cdata_getptr(cdataptr(cd), fsz)))
6570+
lj_trace_err(J, LJ_TRERR_BLACKL);
6571+
6572+
func = emitir(IRT(IR_FLOAD, tp), J->base[0], IRFL_CDATA_PTR);
6573+
tr = lj_ir_call(J, IRCALL_lj_ccall_jit_ptr_ptr_i32_i32_ptr,
6574+
func, arg0, arg1, arg2, arg3);
6575+
J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, ctype_cid(info)),
6576+
tr);
6577+
J->needsnap = 1;
6578+
return 1;
6579+
}
6580+
64666581
static int crec_call_jit_32_ptr_ptr_u64(jit_State *J, RecordFFData *rd,
64676582
CTState *cts, CType *ct,
64686583
CTInfo info, GCcdata *cd,
@@ -10347,6 +10462,8 @@ static int crec_call(jit_State *J, RecordFFData *rd, GCcdata *cd)
1034710462
if (crec_call_jit_ptr_ptr_u64_ptr_ptr_u32_ptr(J, rd, cts, ct, info, cd,
1034810463
tp, fsz))
1034910464
return 1;
10465+
if (crec_call_jit_ptr_ptr_i32_i32_ptr(J, rd, cts, ct, info, cd, tp, fsz))
10466+
return 1;
1035010467
if (crec_call_jit_32_ptr_ptr_u64(J, rd, cts, ct, info, cd, tp, fsz))
1035110468
return 1;
1035210469
if (crec_call_jit_32_ptr_ptr_u32(J, rd, cts, ct, info, cd, tp, fsz))

src/lj_ircall.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,7 @@ typedef struct CCallInfo {
374374
_(FFI, lj_ccall_jit_ptr_ptr_u32_u32_ptr_u32_u32_ptr, 9, S, PTR, CCI_L|CCI_T) \
375375
_(FFI, lj_ccall_jit_ptr_ptr_ptr_u32_u32_u32_ptr, 8, S, PTR, CCI_L|CCI_T) \
376376
_(FFI, lj_ccall_jit_ptr_ptr_u64_ptr_ptr_u32_ptr, 8, S, PTR, CCI_L|CCI_T) \
377+
_(FFI, lj_ccall_jit_ptr_ptr_i32_i32_ptr, 6, S, PTR, CCI_L|CCI_T) \
377378
_(FFI, lj_ccall_jit_i32_ptr_ptr_u64, 5, S, INT, CCI_L|CCI_T) \
378379
_(FFI, lj_ccall_jit_u32_ptr_ptr_u64, 5, S, NUM, CCI_L|CCI_T) \
379380
_(FFI, lj_ccall_jit_i32_ptr_ptr_u32, 5, S, INT, CCI_L|CCI_T) \

tests/t-ffi-ccall-jit-lib.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,14 @@ int *lj_m7_ccall_jit_ptr_ptr_u64_ptr_ptr_u32_ptr(int *security,
336336
(uint64_t)(uint32_t)(thread_id ? *thread_id : 0)) & 3u);
337337
}
338338

339+
int *lj_m7_ccall_jit_ptr_ptr_i32_i32_ptr(int *security, int32_t manual,
340+
int32_t initial, int *name)
341+
{
342+
return security + (((uint64_t)(uint32_t)manual +
343+
(uint64_t)(uint32_t)initial +
344+
(uint64_t)(uint32_t)(name ? *name : 0)) & 3u);
345+
}
346+
339347
int32_t lj_m7_ccall_jit_i32_ptr_ptr_u64(int *a, int *b, uint64_t n)
340348
{
341349
return a[n & 3u] + b[(n + UINT64_C(1)) & 3u] +

0 commit comments

Comments
 (0)