概述
😐 本来是看看 WordPress。没想到越看需要看的就越多,遂记录一下。虽然现在 AI 已经很好用了,但是该记还是得记,这种比较杂的知识点,AI 也不能一次性涉及到。本文涉及 PHP 从源码到逆向、关键函数、关键变量、zend 等相关概念。
文章目录无先后顺序,根据学习进度随手记录
[toc]
相关参考
php 源码
这一部分涉及源码的下载、编译部分。
下载
-
可以从 PHP 的 Github 页面下载历史版本
-
也可以在 Windows.php.NET 页面下载
编译
编译部分开源官方已经提供了脚本文件,直接运行编译即可,流程相对比较简单。
编译部分可以参考文章:PHP 源码编译
相关变量
CG 和 EG
这一部分参考了部分网上的文章,主要是理解这两个全局宏,对了解 zend 框架来说是关键的一步。
**CG **
CG 的含义是 compiler_globals,Zend 编译器相关的全局变量,并且,在 PHP 内核中,会通过 CG 宏来获取函数的句柄结构体。compiler_globals.function_table 里面存 储了所有我们可以在 PHP 页面里面调用的函数,包括 Zend 内建函数、PHP 标准库函数、模块导出的函数以及用户使用 PHP 代码定义的函数。
定义如下所示:
// zend_globals_macros.h
#define CG(v) (compiler_globals.v)直接访问_zend_compiler_globals 结构体实例,该结构体在 zend_compile.c 中定义为全局变量:
ZEND_API zend_compiler_globals compiler_globals;zend_compiler_globals 对应的结构体如下所示,其中 HashTable 就是接下来要查找对应函数需要用到的函数表:
struct _zend_compiler_globals {
zend_stack loop_var_stack;
zend_class_entry *active_class_entry;
zend_string *compiled_filename;
int zend_lineno;
zend_op_array *active_op_array;
HashTable *function_table; /* function symbol table */
HashTable *class_table; /* class table */
HashTable filenames_table;
HashTable *auto_globals;
zend_bool parse_error;
zend_bool in_compilation;
zend_bool short_tags;
zend_bool unclean_shutdown;
zend_bool ini_parser_unbuffered_errors;
zend_llist open_files;
struct _zend_ini_parser_param *ini_parser_param;
uint32_t start_lineno;
zend_bool increment_lineno;
zend_string *doc_comment;
uint32_t extra_fn_flags;
uint32_t compiler_options; /* set of ZEND_COMPILE_* constants */
zend_oparray_context context;
zend_file_context file_context;
zend_arena *arena;
HashTable interned_strings;
const zend_encoding **script_encoding_list;
size_t script_encoding_list_size;
zend_bool multibyte;
zend_bool detect_unicode;
zend_bool encoding_declared;
zend_ast *ast;
zend_arena *ast_arena;
zend_stack delayed_oplines_stack;
#ifdef ZTS
zval **static_members_table;
int last_static_member;
#endif
};最核心的一点就是,Zend 引擎会通过 compiler_globals(CG 宏)访问编译器全局符号表,如下所示:
// 伪代码示例
zend_function *func = zend_hash_str_find_ptr(
&CG(function_table), // 编译器函数符号表
"exec", // 目标函数名
strlen("exec") // 函数名长度
);返回的 zend_function 结构体包含函数指针、参数信息等关键数据。
compiler_globals 的核心作用
- 存储编译阶段的全局状态,包括:
function_table:所有已定义函数的哈希表class_table:类定义表auto_globals:自动全局变量
- 通过 CG()宏快速访问(如
CG(function_table))
EG
EG 的含义是 executor_globals。Zend 执行器相关的全局变量。Zend 引擎在执行 Opcode 的时候,需要记录一些执行过程中的状态。如,当前执行的类作用域,当前已经加载了那些文件等。
另外的,EG 和 CG 有一些数据是共用的。如,function_table (存储方法信息) , class_table (存储类信息) 。
相关代码在 Zend/zend_execute_API.c 的 init_executor 方法中发现如下代码:
void init_executor(void) /* {{{ */
{
zend_init_fpu();
ZVAL_NULL(&EG(uninitialized_zval));
ZVAL_ERROR(&EG(error_zval));
/* destroys stack frame, therefore makes core dumps worthless */
#if 0&&ZEND_DEBUG
original_sigsegv_handler = signal(SIGSEGV, zend_handle_sigsegv);
#endif
EG(symtable_cache_ptr) = EG(symtable_cache) - 1;
EG(symtable_cache_limit) = EG(symtable_cache) + SYMTABLE_CACHE_SIZE - 1;
EG(no_extensions) = 0;
EG(function_table) = CG(function_table);
EG(class_table) = CG(class_table);
...
EG(active) = 1;
}sapi
全局结构体
sapi 中一个很重要的结构体,也是全局变量
/* {{{ sapi_module_struct cgi_sapi_module
*/
static sapi_module_struct cgi_sapi_module = {
"cgi-fcgi", /* name */
"CGI/FastCGI", /* pretty name */
php_cgi_startup, /* startup */
php_module_shutdown_wrapper, /* shutdown */
sapi_cgi_activate, /* activate */
sapi_cgi_deactivate, /* deactivate */
sapi_cgi_ub_write, /* unbuffered write */
sapi_cgi_flush, /* flush */
NULL, /* get uid */
sapi_cgi_getenv, /* getenv */
php_error, /* error handler */
NULL, /* header handler */
sapi_cgi_send_headers, /* send headers handler */
NULL, /* send header handler */
sapi_cgi_read_post, /* read POST data */
sapi_cgi_read_cookies, /* read Cookies */
sapi_cgi_register_variables, /* register server variables */
sapi_cgi_log_message, /* Log message */
NULL, /* Get request time */
NULL, /* Child terminate */
STANDARD_SAPI_MODULE_PROPERTIES
};