From ae26a51f0f9967e2182197e0abbb8abb1ad4c79a Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 13 Mar 2015 11:29:43 +0300 Subject: [PATCH] Added API function to call VM opcode handler in a portable way --- Zend/zend_vm.h | 1 + Zend/zend_vm_execute.h | 25 +++++++++++++++++++++++++ Zend/zend_vm_gen.php | 28 ++++++++++++++++++++++++++++ sapi/phpdbg/phpdbg_prompt.c | 3 ++- 4 files changed, 56 insertions(+), 1 deletion(-) diff --git a/Zend/zend_vm.h b/Zend/zend_vm.h index 15a269e0a7..5a5c9fa96e 100644 --- a/Zend/zend_vm.h +++ b/Zend/zend_vm.h @@ -25,6 +25,7 @@ BEGIN_EXTERN_C() ZEND_API void zend_vm_use_old_executor(void); ZEND_API void zend_vm_set_opcode_handler(zend_op* opcode); +ZEND_API int zend_vm_call_opcode_handler(zend_execute_data *ex); END_EXTERN_C() diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 189555891d..af085f6b27 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -42835,3 +42835,28 @@ ZEND_API void zend_vm_set_opcode_handler(zend_op* op) op->handler = zend_vm_get_opcode_handler(zend_user_opcodes[op->opcode], op); } +ZEND_API int zend_vm_call_opcode_handler(zend_execute_data* ex) +{ + int ret; +#ifdef ZEND_VM_IP_GLOBAL_REG + const zend_op *orig_opline = opline; +#endif +#ifdef ZEND_VM_FP_GLOBAL_REG + zend_execute_data *orig_execute_data = execute_data; + execute_data = ex; +#else + zend_execute_data *execute_data = ex; +#endif + + LOAD_OPLINE(); + ret = ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + SAVE_OPLINE(); +#ifdef ZEND_VM_FP_GLOBAL_REG + execute_data = orig_execute_data; +#endif +#ifdef ZEND_VM_IP_GLOBAL_REG + opline = orig_opline; +#endif + return ret; +} + diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index a972784283..7fc7902ae6 100644 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -1468,6 +1468,34 @@ function gen_vm($def, $skel) { out($f, "\top->handler = zend_vm_get_opcode_handler(zend_user_opcodes[op->opcode], op);\n"); out($f, "}\n\n"); + // Generate zend_vm_call_opcode_handler() function + if (ZEND_VM_KIND == ZEND_VM_KIND_CALL) { + out($f, "ZEND_API int zend_vm_call_opcode_handler(zend_execute_data* ex)\n"); + out($f, "{\n"); + out($f, "\tint ret;\n"); + out($f, "#ifdef ZEND_VM_IP_GLOBAL_REG\n"); + out($f, "\tconst zend_op *orig_opline = opline;\n"); + out($f, "#endif\n"); + out($f, "#ifdef ZEND_VM_FP_GLOBAL_REG\n"); + out($f, "\tzend_execute_data *orig_execute_data = execute_data;\n"); + out($f, "\texecute_data = ex;\n"); + out($f, "#else\n"); + out($f, "\tzend_execute_data *execute_data = ex;\n"); + out($f, "#endif\n"); + out($f, "\n"); + out($f, "\tLOAD_OPLINE();\n"); + out($f, "\tret = ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n"); + out($f, "\tSAVE_OPLINE();\n"); + out($f, "#ifdef ZEND_VM_FP_GLOBAL_REG\n"); + out($f, "\texecute_data = orig_execute_data;\n"); + out($f, "#endif\n"); + out($f, "#ifdef ZEND_VM_IP_GLOBAL_REG\n"); + out($f, "\topline = orig_opline;\n"); + out($f, "#endif\n"); + out($f, "\treturn ret;\n"); + out($f, "}\n\n"); + } + // Export handlers and helpers if (count($export) > 0 && ZEND_VM_KIND != ZEND_VM_KIND_CALL) { diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c index 72cb2e018c..b9228aa922 100644 --- a/sapi/phpdbg/phpdbg_prompt.c +++ b/sapi/phpdbg/phpdbg_prompt.c @@ -23,6 +23,7 @@ #include "zend.h" #include "zend_compile.h" #include "zend_exceptions.h" +#include "zend_vm.h" #include "phpdbg.h" #include "phpdbg_help.h" @@ -1460,7 +1461,7 @@ next: execute_data->func->type == ZEND_USER_FUNCTION) { zend_execute_ex = execute_ex; } - PHPDBG_G(vmret) = execute_data->opline->handler(execute_data); + PHPDBG_G(vmret) = zend_vm_call_opcode_handler(execute_data); zend_execute_ex = phpdbg_execute_ex; if (PHPDBG_G(vmret) != 0) { -- 2.40.0