diff --git a/liblfi/include/lfi.h b/liblfi/include/lfi.h index 51a30be..c08ba3b 100644 --- a/liblfi/include/lfi.h +++ b/liblfi/include/lfi.h @@ -95,4 +95,6 @@ struct LFILoadOpts { bool lfi_proc_loadelf(struct LFIAddrSpace* as, uint8_t* prog, size_t progsz, uint8_t* interp, size_t interpsz, struct LFILoadInfo* o_info, struct LFILoadOpts opts); bool lfi_proc_init(struct LFIContext* ctx, struct LFIAddrSpace* as, struct LFILoadInfo info); +void lfi_thread_init(void* thread_create, void* pausefn); + char* lfi_strerror(void); diff --git a/liblfi/pal/arch/arm64/regs.c b/liblfi/pal/arch/arm64/regs.c index 5062236..2263f3a 100644 --- a/liblfi/pal/arch/arm64/regs.c +++ b/liblfi/pal/arch/arm64/regs.c @@ -11,3 +11,15 @@ lfi_regs_init(struct TuxRegs* regs, struct LFIAddrSpace* as, struct LFIContext* regs->x30 = as->base; regs->REG_SYS = (uintptr_t) ctx->sys; } + +uintptr_t* +lfi_regs_entry(struct TuxRegs* regs) +{ + return ®s->x30; +} + +uintptr_t* +lfi_regs_arg0(struct TuxRegs* regs) +{ + return ®s->x0; +} diff --git a/liblfi/pal/arch/x64/regs.c b/liblfi/pal/arch/x64/regs.c index 4855320..b497b60 100644 --- a/liblfi/pal/arch/x64/regs.c +++ b/liblfi/pal/arch/x64/regs.c @@ -9,3 +9,15 @@ lfi_regs_init(struct TuxRegs* regs, struct LFIAddrSpace* as, struct LFIContext* regs->rsp = as->base; regs->r13 = (uintptr_t) ctx->sys; } + +uintptr_t* +lfi_regs_entry(struct TuxRegs* regs) +{ + return ®s->r11; +} + +uintptr_t* +lfi_regs_arg0(struct TuxRegs* regs) +{ + return ®s->rdi; +} diff --git a/liblfi/pal/ctx.c b/liblfi/pal/ctx.c index 0b9fa6c..2faef6f 100644 --- a/liblfi/pal/ctx.c +++ b/liblfi/pal/ctx.c @@ -7,8 +7,11 @@ #include "pal/platform.h" #include "pal/regs.h" +// context for injecting clone calls pthread_mutex_t lfi_clonectx_lk = PTHREAD_MUTEX_INITIALIZER; struct LFIContext* lfi_clonectx; +// for newly cloned thread contexts +_Thread_local struct LFIContext* lfi_newctx; _Thread_local struct LFIContext* lfi_myctx; @@ -154,8 +157,14 @@ pal_register_clonectx(struct LFIContext* ctx) lfi_clonectx = ctx; } -void -pal_register_myctx(struct LFIContext* ctx) +EXPORT void +lfi_thread_init(void* thread_create, void* pausefn) { - assert(!"unimplemented"); + // invoke sbx_thread_create(&_lfi_pause) with the clone context + LOCK_WITH_DEFER(&lfi_clonectx_lk, lk); + *lfi_regs_entry(&lfi_clonectx->regs) = (uintptr_t) thread_create; + *lfi_regs_arg0(&lfi_clonectx->regs) = (uintptr_t) pausefn; + lfi_ctx_run(lfi_clonectx, lfi_clonectx->as); + lfi_myctx = lfi_newctx; + lfi_newctx = NULL; } diff --git a/liblfi/pal/platform.h b/liblfi/pal/platform.h index 2974c52..1e355e9 100644 --- a/liblfi/pal/platform.h +++ b/liblfi/pal/platform.h @@ -54,6 +54,8 @@ gb(size_t x) _Thread_local extern struct LFIContext* lfi_myctx; -void pal_register_clonectx(struct LFIContext* ctx); +_Thread_local extern struct LFIContext* lfi_newctx; + +extern struct LFIContext* lfi_clonectx; -void pal_register_myctx(struct LFIContext* ctx); +void pal_register_clonectx(struct LFIContext* ctx); diff --git a/liblfi/pal/regs.h b/liblfi/pal/regs.h index 76531a6..8fb51ba 100644 --- a/liblfi/pal/regs.h +++ b/liblfi/pal/regs.h @@ -1,3 +1,7 @@ #include "lfi_arch.h" void lfi_regs_init(struct TuxRegs* regs, struct LFIAddrSpace* as, struct LFIContext* ctx); + +uintptr_t* lfi_regs_entry(struct TuxRegs* regs); + +uintptr_t* lfi_regs_arg0(struct TuxRegs* regs); diff --git a/liblfi/syscalls/sys_proc.c b/liblfi/syscalls/sys_proc.c index 0e5c0fb..0adc396 100644 --- a/liblfi/syscalls/sys_proc.c +++ b/liblfi/syscalls/sys_proc.c @@ -21,10 +21,11 @@ uintptr_t sys_exit(struct TuxThread* p, uint64_t code) { clearctid(p); - if (p->proc->tux->opts.pause_on_exit) + if (p->proc->tux->opts.pause_on_exit) { lfi_ctx_pause(p->p_ctx, code); - else + } else { lfi_ctx_exit(p->p_ctx, code); + } assert(!"unreachable"); } diff --git a/liblfi/syscalls/sys_thread.c b/liblfi/syscalls/sys_thread.c index 4766a69..d38d7ad 100644 --- a/liblfi/syscalls/sys_thread.c +++ b/liblfi/syscalls/sys_thread.c @@ -132,6 +132,11 @@ spawn(struct TuxThread* p, uint64_t flags, uint64_t stack, uint64_t ptidp, uint6 // was created so it can be reused when we need to spawn threads in the // future. pal_register_clonectx(p2->p_ctx); + } else if (p->p_ctx == lfi_clonectx) { + threadspawn(p2); + lfi_newctx = p2->p_ctx; + // does not return + lfi_ctx_pause(p->p_ctx, 0); } else { // Actually create a new thread. pthread_t thread;