存储opline的内存地址可以实时跟踪opcode的执行

static intphp_handler(request_rec *r) { /* Initiliaze the context */ php_struct * volatile ctx; void *conf; apr_bucket_brigade * volatile brigade; apr_bucket *bucket; apr_status_t rv; request_rec * volatile parent_req = NULL; TSRMLS_FETCH(); ...... zend_file_handle zfd; zfd.type = ZEND_HANDLE_FILENAME; zfd.filename = (char *) r->filename; zfd.free_filename = 0; zfd.opened_path = NULL; zend_execute_scripts(ZEND_INCLUDE TSRMLS_CC, NULL, 1, &zfd); ...... } ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval **retval, int file_count, ...) /* {{{ */ { ...... EG(active_op_array) = \ zend_compile_file(file_handle, type TSRMLS_CC); ...... zend_execute(EG(active_op_array) TSRMLS_CC); ...... } ZEND_API void execute(zend_op_array *op_array TSRMLS_DC) { // 初始化执行上下文 zend_execute_data execute_data; // 如果有异常就退出执行 if (EG(exception)) { return; } /* Initialize execute_data */ EX(fbc) = NULL; // 初始化正在调用的函数 EX(object) = NULL; // 初始化正在调用的对象 EX(old_error_reporting) = NULL; // 初始化错误报告变量 // 为执行栈分配空间 if (op_array->T T); } else { EX(Ts) = (temp_variable *) safe_emalloc(sizeof(temp_variable), op_array->T, 0); } // 为临时变量分配空间并初始化这些空间 EX(CVs) = (zval***)do_alloca(sizeof(zval**) * op_array->last_var); memset(EX(CVs), 0, sizeof(zval**) * op_array->last_var); EX(op_array) = op_array; // 切换执行上下文 EX(original_in_execution) = EG(in_execution); EX(symbol_table) = EG(active_symbol_table); EX(prev_execute_data) = EG(current_execute_data); // 将当前全局变量中的执行数据压栈 EG(current_execute_data) = &execute_data; // 将当前执行上下文压栈 EG(in_execution) = 1; // 初始化第一个指令(opcode) /* #define ZEND_VM_SET_OPCODE(new_op) \ CHECK_SYMBOL_TABLES() \ EX(opline) = new_op execute_data.opline 为当前执行的 opcode */ if (op_array->start_op) { ZEND_VM_SET_OPCODE(op_array->start_op); } else { ZEND_VM_SET_OPCODE(op_array->opcodes); } if (op_array->uses_this && EG(This)) { EG(This)->refcount++; /* For $this pointer */ if (zend_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), NULL)==FAILURE) { EG(This)->refcount--; } } // 将存储opline的内存地址赋给 executor_globals.online_ptr ,可以实时跟踪opcode的执行 EG(opline_ptr) = &EX(opline); EX(function_state).function = (zend_function *) op_array; EG(function_state_ptr) = &EX(function_state); #if ZEND_DEBUG /* function_state.function_symbol_table is saved as-is to a stack, * which is an intentional UMR. Shut it up if we‘re in DEBUG. */ EX(function_state).function_symbol_table = NULL; #endif while (1) { #ifdef ZEND_WIN32 if (EG(timed_out)) { zend_timeout(0); } #endif // 循环调用每个opline的 handler 函数,如果是推出函数的话,返回值大于0,就退出 if (EX(opline)->handler(&execute_data TSRMLS_CC) > 0) { return; } } zend_error_noreturn(E_ERROR, "Arrived at end of main loop which shouldn‘t happen"); 2881064151}

时间: 2024-08-08 05:38:03

存储opline的内存地址可以实时跟踪opcode的执行的相关文章

C语言:内存地址分析 & sizeof和strlen用法总结

还是在大学时代接触的C语言,当时学习数组.指针等概念时,怎一个"晕"字了得.最近在学习之余,疯狂地恶补了相关知识,故总结之,如有错误,请大家多多指点. 一. 内存地址分析 1) 先来看一个最基础的例子: int a[4]; 提问:&a[0],  a,  &a,  a+1,  &(a+1),  &a+1 分别表示什么? 咋一看,真的不知所措: 我们可以图解来分析它(假设下面的操作均在32为系统上面). 先来对上图进行简单的说明工作: 1. 紫色区域就是数组

关于内存地址和内存空间的理解。

1.内存地址用4位16进制和8位16进制表示的区别.例如经常可以看到某些书籍上写的内存地址0x0001,在另外一些书籍上写的内存地址又变成了0x00000001.都是表示的编号为1的内存地址,为什么一个是4位16进制表示,另外一个又是用8位16进制表示呢? 首先,必须要知道内存地址只是一个编号,代表一个内存空间.那么这个空间是多大呢?原来在计算机中存储器的容量是以字节为基本单位的.也就是说一个内存地址代表一个字节(8bit)的存储空间. 例如经常说32位的操作系统最多支持4GB的内存空间,也就是

LMA(装载内存地址)与VMA(虚拟内存地址)

      关于LMA和VMA,这个问题,有点点小复杂,不过,此处,我会把我的理解,尽量通过通俗的方式解释出来,以方便理解.当然,鄙人水平有限,难免有错,希望各位批评指正.       一般提及LMA和VMA,多数情况都是和ld,链接器相关的.在了解这两个名词的详细含义之前,有些基本知识和前提要说一下: [基础知识] 1.从你写的源代码到执行你的程序,一般经历了这几个过程:源代码编辑 -> 编译 -> 链接 -> 装载 -> 执行 2.编译,简单说就是用编译工具,将你的源码,变成可

C语言精要总结-内存地址对齐与struct大小判断篇

在笔试时,经常会遇到结构体大小的问题,实际就是在考内存地址对齐.在实际开发中,如果一个结构体会在内存中高频地分配创建,那么掌握内存地址对齐规则,通过简单地自定义对齐方式,或者调整结构体成员的顺序,可以有效地减少内存使用.另外,一些不用边界对齐.可以在任何地址(包括奇数地址)引用任何数据类型的的机器,不在本文讨论范围之内. 什么是地址对齐 计算机读取或者写入存储器地址时,一般以字(因系统而异,32位系统为4个字节)大小(N)的块来执行操作.数据对齐就是将数据存储区的首地址对齐字大小(N)的某个整数

c语言中通过指针将数值赋值到制定内存地址

1.一种直观的方法 假设现在需要往内存0x12ff7c地址上存入一个整型数0x100.我们怎么才能做到呢? 我们知道可以通过一个指针向其指向的内存地址写入数据,那么这里的内存地址0x12ff7c其本质不就是一个指针嘛.所以我们可以用下面的方法: int *p = (int *)0x12ff7c; *p = 0x100; 需要注意的是将地址0x12ff7c赋值给指针变量p的时候必须强制转换. 1.1 为什么在此处,我们敢往0x12ff7c这个地址赋值呢? 至于这里为什么选择内存地址0x12ff7c

python的变量,对象的内存地址以及参数传递过程

作为一个由c/c++转过来的菜鸟,刚接触Python的变量的时候很不适应,应为他的行为很像指针,void* ,不知道大家有没有这样的感觉.其实Python是以数据为本,变量可以理解为标签.作为c/c++的菜鸟,把跟踪变量地址的习惯带入Python,举个小例子说明Python的变量,对象,及参数传递. 1 '''例子1''' 2 x = 1 3 def fun(x): 4 x = 2 5 return None 6 7 fun(x) 8 print(x) 其实不打印也可以,我们用pycharm单步

字节与内存地址

存储单元一般以八个二进制单位也就是一个字节为单位,字节是最小的存储单位.比如说一个八位二进制数是一个字节,也就是一个存储单位,我们常说的0x56000050很多时候只是内存的虚拟地址,CPU能直接操作的也是这个,内存常常是已经有的固定的,对于地址我们能操作的是映射提供给用户那一部分,比如我们映射了如下四个地址0x56000050.0x56000054.0x56000058.0x5600005c,这4段内存,每一部分里面可以存储的内容大小是4k,我们看到0x56000050~0x56000054之

汇编语言学习第七章-更灵活的定位内存地址的方法

本博文系列参考自<<汇编语言>>第三版,作者:王爽 前面已经通过类似[0]和[bx]的方法进行了内存定位了.本章将涉及更多内存地址定位和编程的方法. 7.1 and 和 or 指令 (1) and指令,逻辑按位与指令 例如: mov al,01100011B and al,00111011B 执行后 al=00100011B and指令可以用来将某个数的位置为零. 比如我们要将al的第二位置为零,则: and al,11111101B 依次类推. (2) or指令,逻辑按位或指令

一个可以实时跟踪分析iOS App视图的小工具

一个可以实时跟踪分析iOS App视图的小工具(已开源) GitHub入口:https://github.com/sx1989827/RunTrace 前言 作为iOS的开发者,常常为了UI界面搞得头破血流,你是不是经常遇到这样的痛点:这个view是从哪里来的,它的父视图是什么,它的子视图有哪些,它的frame会发生什么样的变化,它怎么突然隐藏了,它什么时候会被释放掉,对于像自动布局,错误常常如潮水般的涌来,我想动态获取一个view的约束怎么办,我想知道这个view此时此刻和其他哪些view产生