diff --git a/src/koffi/src/abi_x86.cc b/src/koffi/src/abi_x86.cc index f2f74bbcc8..6e7bc519b9 100644 --- a/src/koffi/src/abi_x86.cc +++ b/src/koffi/src/abi_x86.cc @@ -44,12 +44,37 @@ struct BackRegisters { int ret_pop; }; -extern "C" uint64_t ForwardCallG(const void *func, uint8_t *sp, uint8_t **out_old_sp); -extern "C" float ForwardCallF(const void *func, uint8_t *sp, uint8_t **out_old_sp); -extern "C" double ForwardCallD(const void *func, uint8_t *sp, uint8_t **out_old_sp); -extern "C" uint64_t ForwardCallRG(const void *func, uint8_t *sp, uint8_t **out_old_sp); -extern "C" float ForwardCallRF(const void *func, uint8_t *sp, uint8_t **out_old_sp); -extern "C" double ForwardCallRD(const void *func, uint8_t *sp, uint8_t **out_old_sp); +extern "C" uint64_t ForwardCallG(const void *func, uint8_t *sp, uint8_t **out_old_sp, Size len); +extern "C" float ForwardCallF(const void *func, uint8_t *sp, uint8_t **out_old_sp, Size len); +extern "C" double ForwardCallD(const void *func, uint8_t *sp, uint8_t **out_old_sp, Size len); +extern "C" uint64_t ForwardCallRG(const void *func, uint8_t *sp, uint8_t **out_old_sp, Size len); +extern "C" float ForwardCallRF(const void *func, uint8_t *sp, uint8_t **out_old_sp, Size len); +extern "C" double ForwardCallRD(const void *func, uint8_t *sp, uint8_t **out_old_sp, Size len); +extern "C" void ForwardCall(const void* func, Size len) +{ + __try + { + __asm + { + sub esp, 12 + sub esp, len + mov edi, esp + mov esi, ebp + add esi, 24 + mov ecx, len + shr ecx, 2 + cld + rep movsd + call func + add esp, len + add esp, 12 + } + } + __except (UnhandledExceptionFilter(GetExceptionInformation())) + { + ExitProcess(GetExceptionCode()); + } +} extern "C" napi_value CallSwitchStack(Napi::Function *func, size_t argc, napi_value *argv, uint8_t *old_sp, Span *new_stack, @@ -134,6 +159,8 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info) uint32_t *args_ptr = nullptr; uint32_t *fast_ptr = nullptr; + uint8_t* sp = mem->stack.end(); + // Pass return value in register or through memory if (!AllocStack(func->args_size, 16, &args_ptr)) [[unlikely]] return false; @@ -316,6 +343,7 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info) #undef PUSH_INTEGER_32 new_sp = mem->stack.end(); + len = sp - new_sp; return true; } @@ -355,8 +383,8 @@ void CallData::Execute(const FunctionInfo *func, void *native) #define PERFORM_CALL(Suffix) \ ([&]() { \ - auto ret = (func->fast ? ForwardCallR ## Suffix(native, new_sp, &old_sp) \ - : ForwardCall ## Suffix(native, new_sp, &old_sp)); \ + auto ret = (func->fast ? ForwardCallR ## Suffix(native, new_sp, &old_sp, len) \ + : ForwardCall ## Suffix(native, new_sp, &old_sp, len)); \ return ret; \ })() diff --git a/src/koffi/src/abi_x86_asm.asm b/src/koffi/src/abi_x86_asm.asm index a783264c81..2ab6cf53b2 100644 --- a/src/koffi/src/abi_x86_asm.asm +++ b/src/koffi/src/abi_x86_asm.asm @@ -30,6 +30,10 @@ public ForwardCallRF public ForwardCallRD .model flat, C + +.data +extern ForwardCall:proc + .code ; Copy function pointer to EAX, in order to save it through argument forwarding. @@ -38,16 +42,18 @@ public ForwardCallRD prologue macro endbr32 push ebp + push esi mov ebp, esp - mov eax, dword ptr [esp+16] + mov eax, dword ptr [esp+20] mov dword ptr [eax+0], esp - mov eax, dword ptr [esp+8] - mov esp, dword ptr [esp+12] + mov eax, dword ptr [esp+12] + mov esi, dword ptr [esp+24] + mov esp, dword ptr [esp+16] endm fastcall macro - mov ecx, dword ptr [esp+0] - mov edx, dword ptr [esp+4] + mov ecx, dword ptr [esp+4] + mov edx, dword ptr [esp+8] add esp, 16 endm @@ -55,8 +61,13 @@ endm ; Once done, restore normal stack pointer and return. ; The return value is passed back untouched. epilogue macro - call eax + sub esp, 8 + push esi + push eax + call ForwardCall + add esp, 16 mov esp, ebp + pop esi pop ebp ret endm diff --git a/src/koffi/src/call.hh b/src/koffi/src/call.hh index 51e82cbc54..ef23f49bd3 100644 --- a/src/koffi/src/call.hh +++ b/src/koffi/src/call.hh @@ -63,6 +63,7 @@ class alignas(8) CallData { uint8_t *new_sp; uint8_t *old_sp; + Size len; union { int8_t i8;