、初始化 opcode处理器列表

// main实现在文件“php-5.6.26\sapi\cgi\cgi_main.c”
int main(int argc, char *argv[])
{
if (cgi_sapi_module.startup(&cgi_sapi_module){
// php_cgi_startup实现在文件“php-5.6.26\sapi\cgi\cgi_main.c”
static int php_cgi_startup(sapi_module_struct *sapi_module)
{
if (php_module_startup(sapi_module, &cgi_module_entry, ){ // zend_startup实现在文件“php-5.6.26\sapi\cgi\cgi_main.c”
int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_modules, uint num_additional_modules)
{
// zend_startup实现在文件“php-5.6.26\Zend\zend.c”
zend_startup(&zuf, NULL TSRMLS_CC); // !!!!
{
int zend_startup(zend_utility_functions *utility_functions, char **extensions TSRMLS_DC)
{
...
// zend_init_opcodes_handlers实现在文件php-7.2.3\Zend\zend_vm_execute.h
zend_init_opcodes_handlers(); // !!! 初始化“opcodes处理器”列表 ------------ 初始化
{
static const opcode_handler_t labels[] = {
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
ZEND_NOP_SPEC_HANDLER,
...
ZEND_ASSIGN_POW_SPEC_CV_TMP_HANDLER,
ZEND_ASSIGN_POW_SPEC_CV_VAR_HANDLER,
ZEND_ASSIGN_POW_SPEC_CV_UNUSED_HANDLER,
ZEND_ASSIGN_POW_SPEC_CV_CV_HANDLER,
ZEND_NULL_HANDLER
};
zend_opcode_handlers = (opcode_handler_t*)labels;
}
...
}
}
}
} == FAILURE) {
return FAILURE;
}
return SUCCESS; }
} == FAILURE) { // startup ---> php_cgi_startup ---> php_module_startup
#ifdef ZTS ---
tsrm_shutdown();
#endif
return FAILURE;
}
} 、注入opcode处理器 & 执行opcode处理器 // 在文件 php-5.6.26\main\main.c
PHPAPI int php_execute_script(zend_file_handle *primary_file TSRMLS_DC)
{
...
/*
If cli primary file has shabang line and there is a prepend file,
the `start_lineno` will be used by prepend file but not primary file,
save it and restore after prepend file been executed.
*/
if (CG(start_lineno) && prepend_file_p) {
int orig_start_lineno = CG(start_lineno); CG(start_lineno) = ;
if (zend_execute_scripts(ZEND_REQUIRE TSRMLS_CC, NULL, , prepend_file_p) == SUCCESS) {
CG(start_lineno) = orig_start_lineno;
retval = (zend_execute_scripts(ZEND_REQUIRE TSRMLS_CC, NULL, , primary_file, append_file_p) == SUCCESS);
}
} else {
// 在文件 php-5.6.26\Zend\zend.c
retval = (zend_execute_scripts(ZEND_REQUIRE TSRMLS_CC, NULL, , prepend_file_p, primary_file, append_file_p) == SUCCESS); // 执行primary_file的php脚本
{
...
EG(active_op_array) = zend_compile_file(file_handle, type TSRMLS_CC); // 编译PHP文件成操作码 op_code ,zend_compile_file == compile_file
{
// 在文件 php-5.6.26\Zend\zend_language_scanner.c !!!编译文件,编译出opcode
ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type TSRMLS_DC)
{
...
if (retval) {
CG(active_op_array) = original_active_op_array; // 还原原来 op_code 现场(还原现场)
if (compilation_successful) { // !!!汇编成功 // 在文件 php-5.6.26\Zend\zend_opcode.c
pass_two(op_array TSRMLS_CC); // !!!! 给每个op_code注册“op_code处理器”
{
...
while (opline < end) { // 迭代所有操作码
if (opline->op1_type == IS_CONST) { // 如果是是常量
opline->op1.zv = &op_array->literals[opline->op1.constant].constant;
}
if (opline->op2_type == IS_CONST) {
opline->op2.zv = &op_array->literals[opline->op2.constant].constant;
}
switch (opline->opcode) {
case ZEND_GOTO:
if (Z_TYPE_P(opline->op2.zv) != IS_LONG) {
zend_resolve_goto_label(op_array, opline, TSRMLS_CC);
}
/* break omitted intentionally */
case ZEND_JMP:
case ZEND_FAST_CALL:
opline->op1.jmp_addr = &op_array->opcodes[opline->op1.opline_num];
break;
case ZEND_JMPZ:
case ZEND_JMPNZ:
case ZEND_JMPZ_EX:
case ZEND_JMPNZ_EX:
case ZEND_JMP_SET:
case ZEND_JMP_SET_VAR:
opline->op2.jmp_addr = &op_array->opcodes[opline->op2.opline_num];
break;
case ZEND_RETURN:
case ZEND_RETURN_BY_REF:
if (op_array->fn_flags & ZEND_ACC_GENERATOR) {
if (opline->op1_type != IS_CONST || Z_TYPE_P(opline->op1.zv) != IS_NULL) {
CG(zend_lineno) = opline->lineno;
zend_error_noreturn(E_COMPILE_ERROR, "Generators cannot return values using \"return\"");
} opline->opcode = ZEND_GENERATOR_RETURN;
}
break;
}
ZEND_VM_SET_OPCODE_HANDLER(opline); // 设置“opcode处理器” ------------ 注入
{
// 宏定义在文件 “php-5.6.26\Zend\zend_vm.h ”
#define ZEND_VM_SET_OPCODE_HANDLER(opline) zend_vm_set_opcode_handler(opline)
{
// zend_vm_set_opcode_handler 实现在文件“php-5.6.26\Zend\zend_vm_execute.h”,
ZEND_API void zend_vm_set_opcode_handler(zend_op* op) // 获取“opcode处理器”
{
op->handler = zend_vm_get_opcode_handler(zend_user_opcodes[op->opcode], op);
{
// zend_vm_get_opcode_handler实现在文件“php-5.6.26\Zend\zend_vm_execute.h”,
static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, zend_op* op) // 获取“opcode处理器”
{
static const int zend_vm_decode[] = {
_UNUSED_CODE, /* 0 */
_CONST_CODE, /* 1 = IS_CONST */
_TMP_CODE, /* 2 = IS_TMP_VAR */
_UNUSED_CODE, /* 3 */
_VAR_CODE, /* 4 = IS_VAR */
_UNUSED_CODE, /* 5 */
_UNUSED_CODE, /* 6 */
_UNUSED_CODE, /* 7 */
_UNUSED_CODE, /* 8 = IS_UNUSED */
_UNUSED_CODE, /* 9 */
_UNUSED_CODE, /* 10 */
_UNUSED_CODE, /* 11 */
_UNUSED_CODE, /* 12 */
_UNUSED_CODE, /* 13 */
_UNUSED_CODE, /* 14 */
_UNUSED_CODE, /* 15 */
_CV_CODE /* 16 = IS_CV */
};
return zend_opcode_handlers[opcode * + zend_vm_decode[op->op1_type] * + zend_vm_decode[op->op2_type]];
}
}
}
}
}
opline++;
} op_array->fn_flags |= ZEND_ACC_DONE_PASS_TWO;
return ;
...
}
zend_release_labels( TSRMLS_CC);
} else {
efree(op_array);
retval = NULL;
}
}
...
} // !!! 执行 opcode 列表
if (EG(active_op_array)) { // “操作码”数组
EG(return_value_ptr_ptr) = retval ? retval : NULL; // 在文件 php-5.6.26\Zend\zend_vm_execute.c
zend_execute(EG(active_op_array) TSRMLS_CC); // 执行编译后的操作码 op_code , zend_execute == execute_ex
{ if (EG(exception)) {
return;
} // 在文件 php-5.6.26\Zend\zend_vm_execute.c
zend_execute_ex(i_create_execute_data_from_op_array(op_array, TSRMLS_CC) TSRMLS_CC); // zend_execute_ex = execute_ex
{
DCL_OPLINE
zend_bool original_in_execution; original_in_execution = EG(in_execution); // 保存现场
EG(in_execution) = ; // 正在执行中 if () {
zend_vm_enter:
execute_data = i_create_execute_data_from_op_array(EG(active_op_array), TSRMLS_CC);
} LOAD_REGS();
LOAD_OPLINE(); while () {
int ret;
#ifdef ZEND_WIN32
if (EG(timed_out)) {
zend_timeout();
}
#endif /*
OPLINE->handler(execute_data TSRMLS_CC)
EX(opline)->handler(execute_data TSRMLS_CC)
execute_data.opline->handler(execute_data TSRMLS_CC)
*/
if ((ret = OPLINE->handler(execute_data TSRMLS_CC)) > ) { // execute_data.opline->handler(execute_data TSRMLS_CC) // 调用“opcode对应的处理函数” ------------调用
switch (ret) {
case :
EG(in_execution) = original_in_execution; // 还原现场
return;
case :
goto zend_vm_enter; // 进入虚拟机
break;
case :
execute_data = EG(current_execute_data); // 当前正在执行的数据
break;
default:
break;
}
} }
zend_error_noreturn(E_ERROR, "Arrived at end of main loop which shouldn't happen");
}
}
...
}
...
}
...
}
}
...
}

php-5.6.26源代码 - opcode处理器的注入的更多相关文章

  1. php-5.6.26源代码 - opcode处理器,“函数调用opcode”处理器,如何调用扩展模块的函数

    // opcode处理器 --- ZEND_DO_FCALL_SPEC_CONST_HANDLER实现在 php-5.6.26\Zend\zend_vm_execute.h static int ZE ...

  2. php-5.6.26源代码 - opcode处理器,“乘法opcode”处理器

    // opcode处理器 - 运算符怎么执行: “*” 乘法opcode处理器 static int ZEND_FASTCALL ZEND_MUL_SPEC_CONST_CONST_HANDLER(Z ...

  3. php-5.6.26源代码 - opcode列表

    文件 php-5.6.26/Zend/zend_vm_opcodes.h #ifndef ZEND_VM_OPCODES_H #define ZEND_VM_OPCODES_H BEGIN_EXTER ...

  4. php-5.6.26源代码 - opcode执行

    文件 php-5.6.26/Zend/zend_vm_execute.h ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS ...

  5. php-7.2.3源代码和php-5.6.26源代码摘录,对比 “汇编php文件”和“执行opcode代码”

    php-7.2.3 在“汇编php文件”和“执行opcode代码”上做了大量改变php-5.6.26 没见到支持抽象语法树的相关代码,php-7.2.3 见到支持抽象语法树的相关代码php-5.6.2 ...

  6. php-5.6.26源代码 - PHP文件汇编成opcode(require、include的差异)

    文件 php-5.6.26/Zend/zend_language_scanner.c ZEND_API zend_op_array *compile_file(zend_file_handle *fi ...

  7. php-5.6.26源代码 - 扩展模块的种类,扩展模块的执行埋点

    模块种类(两种) 类型一:zend的模块:(类似zend_extension=test.so) 识别方法: php.ini中以zend_extension开头的配置,如zend_extension=t ...

  8. monkey源代码分析之事件注入方法变化

    在上一篇文章<Monkey源代码分析之事件注入>中.我们看到了monkey在注入事件的时候用到了<Monkey源代码分析番外篇之Android注入事件的三种方法比較>中的第一种 ...

  9. php-5.6.26源代码 - include_once、require_once、include、require、eval 的opcode处理器

    # ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER 实现在文件 php-\Zend\zend_vm_execute.h static int ZEND_FASTCALL ...

随机推荐

  1. java实现两个整数相除保留一位小数

    //整数相除 保留一位小数 public static String division(int a ,int b){ String result = ""; float num = ...

  2. EasyUI 数据网格 - 设置排序并自定义排序

    数据网格(DataGrid)的所有列可以通过点击列表头来排序.您可以定义哪列可以排序.默认的,列是不能排序的,除非您设置 sortable 属性为 true. 当排序时,数据网格(DataGrid)将 ...

  3. 转:解决Arcsde用户锁定的问题

    采用arcgis平台做GIS应用的人,可能偶尔碰到sde用户锁定(Arccatalog 或应用程序异常退出的时比较多)的问题,往往咱们解决的办法是重启sde服务.如果一个服务器上有多个连接时,重启服务 ...

  4. Gremlin--一种支持对图表操作的语言

    Gremlin 是操作图表的一个非常有用的图灵完备的编程语言.它是一种Java DSL语言,对图表进行查询.分析和操作时使用了大量的XPath. Gremlin可用于创建多关系图表.因为图表.顶点和边 ...

  5. python 生成随机图片验证码

    1.安装pillow模块 pip install pillow (1)创建图片 from PIL import Image #定义使用Image类实例化一个长为400px,宽为400px,基于RGB的 ...

  6. Linux 查看CPU、Memory等资源占用情况

    linux下获取占用CPU资源最多的10个进程,可以使用如下命令组合: ps aux|head -1;ps aux|grep -v PID|sort -rn -k +3|head linux下获取占用 ...

  7. SPICE简史

    如今每一天都有不知其数的半导体芯片设计公司与设计验证工程师,在用着电路仿真软件SPICE.SPICE广泛应用在仿真模拟电路(例如运放Op Amp,能隙基准稳压电源Bandgap Reference,数 ...

  8. 来自NVIDIA开源的pix2pixHD,将Image-to-Image Translation带到了另一个境界

    Kuo Ming Lin 分享了 Learning By Hacking 的动图 最近討論最火熱的project之一,來自NVIDIA開源的pix2pixHD,將Image-to-Image Tran ...

  9. CRM WebClient UI里的文件是如何上传到Netweaver后台的

    使用Chrome开发者工具调试CRM WebClient UI里附件上传的功能: 从本地选择一个文件,断点触发: 前端取得用户选中上传的文件名: Jerry.txt 点Attach按钮后,触发ABAP ...

  10. RF脚本中的坑1: SyntaxError: invalid token

    话不多说,直接上调试脚本: 执行后${b}=8:没问题.然后${a}改成08继续: 执行后居然报错了: 经过多次尝试08或者09时,都会报SyntaxError错误:后来查阅语法,才恍然大悟:Pyth ...