]> granicus.if.org Git - php/commitdiff
Added API function to call VM opcode handler in a portable way
authorDmitry Stogov <dmitry@zend.com>
Fri, 13 Mar 2015 08:29:43 +0000 (11:29 +0300)
committerDmitry Stogov <dmitry@zend.com>
Fri, 13 Mar 2015 08:29:43 +0000 (11:29 +0300)
Zend/zend_vm.h
Zend/zend_vm_execute.h
Zend/zend_vm_gen.php
sapi/phpdbg/phpdbg_prompt.c

index 15a269e0a7963fe8732146f5dc72a896ac5315b7..5a5c9fa96ee5c122f856283fceec7bcabf35280a 100644 (file)
@@ -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()
 
index 189555891dfa7ab4e30093df8c6486f473b32d66..af085f6b271aa1d673d7d6f835596a02e3fa8b66 100644 (file)
@@ -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;
+}
+
index a972784283cc587ff0868e58a912e0b2fa8c6c8a..7fc7902ae64129a84aaefd662889d6bbdabfe713 100644 (file)
@@ -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) {
index 72cb2e018c46161150bd3638533d8c59882d672d..b9228aa922d2f4d449ea8184855ac2109f562984 100644 (file)
@@ -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) {