php-5.6.26源代码 - opcode处理器的注入
、初始化 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处理器的注入的更多相关文章
- 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 ...
- php-5.6.26源代码 - opcode处理器,“乘法opcode”处理器
// opcode处理器 - 运算符怎么执行: “*” 乘法opcode处理器 static int ZEND_FASTCALL ZEND_MUL_SPEC_CONST_CONST_HANDLER(Z ...
- 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 ...
- 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 ...
- 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 ...
- 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 ...
- php-5.6.26源代码 - 扩展模块的种类,扩展模块的执行埋点
模块种类(两种) 类型一:zend的模块:(类似zend_extension=test.so) 识别方法: php.ini中以zend_extension开头的配置,如zend_extension=t ...
- monkey源代码分析之事件注入方法变化
在上一篇文章<Monkey源代码分析之事件注入>中.我们看到了monkey在注入事件的时候用到了<Monkey源代码分析番外篇之Android注入事件的三种方法比較>中的第一种 ...
- 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 ...
随机推荐
- textarea输入框显隐文字
html: <textarea class="dxtd_text"></textarea> javascript: //管理端短信 var textarea ...
- springmvc实现文件下载到Android手机设备pda端
1:首先要添加相关得jar文件,在pom.xml中 <dependency> <groupId>commons-fileupload</groupId> <a ...
- 移动端适配(1)——viewport设置与初始化css
<meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=0 ...
- SublimeText插件vue Syntax Highlight : vue语法高亮
参考:http://www.cnblogs.com/cosnyang/p/6290950.html Vue.js 的单文件组件(*.vue)在 sublime 编辑器中是不被识别的.若要想高亮显示,需 ...
- 织梦channelartlist标签内使用currentstyle
找到文件\include\taglib\channelartlist.lib.php 找到代码 $pv->Fields['typeurl'] = GetOneTypeUrlA($typeids[ ...
- Android Studio 小技巧(2):AS中Button文字默认大写的问题
问题类型 设置Layout中添加一个Button <Button android:id="@+id/bt_showerror" android:layout_width=&q ...
- Object in Java same as pointer
到目前为止,读者应对对象的“传递”有了一个较为深刻的认识,记住实际传递的只是一个句柄. 然而准确地说,Java是有指针的!事实上,Java中每个对象(除基本数据类型以外)的标识符都属于指针的一种.但它 ...
- One special dictionary
由于项目一个功能需要,可以将关键字的值叠加加来,最终可以获取对这些关键字都做了些什么操作. Generic Programming is very powerful. /// <summary& ...
- 随便讲讲自己了解的ajax在JQ中的应用
首先jQuery 库拥有完整的 Ajax 兼容套件.其中的函数和方法允许我们在不刷新浏览器的情况下从服务器加载数据. 定义和用法 ajax() 方法通过 HTTP 请求加载远程数据. 该方法是 jQu ...
- 使用extentreports美化testng报告2,增加监听
有兴趣研究了extentreports报告美化插件,但是因为发现插件有很多内容不能自定义,所以放弃了这个插件,我扩充了官方代码的demo,在testng中增加了监听,并打印了一些测试用例,现在我把两个 ...