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 ...
随机推荐
- C# 使用消息队列,包括远程访问
转:https://www.cnblogs.com/80X86/p/5557801.html 功能需求,用到了队列,用的时候出了很多问题,现在总结一下,希望能对有需要的人提供帮助. 我的需求很简单,就 ...
- angularjs ui-grid如何动态设置行高
自己开发的公众号,可以领取淘宝内部优惠券 在用ui-grid的时候我们可以用rowHeight设置行高,可是每一行的高度都是一样的,无法根据行内的内容进行自适应.如下图 为了解决这个问题,google ...
- DOS常见命令
dir: 显示一个目录中的文件和子目录 md: 创建目录 rd: 删除目录 cd: 进入指定目录 cd..: 退回到上级目录 cd\: 退回到根目录 del: 删除文件 set: 显示.设置.删除cm ...
- java-logic====吃货联盟
1.系统界面 2.功能一 3.查看餐袋 4.签收订单 5.删除订单 6.我要点赞 主要分在两个类中: 第一个类entity,主要的是一些共有的属性 主要代码: public class entity ...
- css的三个特性 背景透明设置
关于行内元素(补充一点) 行内元素只能容纳文本或其他行内元素.(a特殊a里面可以放块级元素) 例子: 关于行高tip: 选择器的嵌套层级不应大于3级,位置靠后的限定条件应尽可能的精确. 属性定义必须另 ...
- js获取农历日期【转】
var CalendarData=new Array(100); var madd=new Array(12); var tgString="甲乙丙丁戊己庚辛壬癸"; var dz ...
- 笨办法学Python(三十一)
习题 31: 作出决定 这本书的上半部分你打印了一些东西,而且调用了函数,不过一切都是直线式进行的.你的脚本从最上面一行开始,一路运行到结束,但其中并没有决定程序流向的分支点.现在你已经学了 if, ...
- MySQL入门很简单: 11 mysql函数
1. 数学函数 2. 字符串函数 3. 日期和时间函数 4. 条件判断函数 IF(expr, v1, v2) // 如果表达式expr成立,返回结果v1,否则返回v2: IFNULL(v1, v2) ...
- IOS 设置颜色的的详情
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typica ...
- ArcGIS License Server Administrator 10.2 无法启动许可的解决办法
刚刚重装了电脑,安装ArcGIS的时候,安装完desktop之后又安装了License Manager,结果把破解文件替换完之后,发现ArcGIS License Server Administrat ...