After two weeks of iteration, Deliverer is currently updated to 1.0.8 https://github.com/zhoumengkang/deliverer
Because it is to solve the problem of ancestral code, and I heard some voices from group friends, it is still necessary to support PHP5, so I have been working hard to solve the compatibility problem of this version during this period. I did not expect the problem to be much more difficult than I expected .
After recording the problems encountered in the development (mainly physical work) and want to share, are interested in fork
can get a copy of 060e02e2a5e8c1, and they are not so unfamiliar with the code, and I look forward to your PR .
In PHP7, the function or method when executed in zend_execute_data
structural body execute_data->call->fbc
, whereas in the corresponding field PHP5 get function is to invoke the function, a relatively large gap between the two.
Later, opline
zend_execute_data
, but there are still differences in the logic before and after PHP5.4, which needs to be treated differently (fortunately, the compiler prompts the error field)
#if PHP_VERSION_ID < 50400
#define OP1_FUNCTION_PTR(n) (&(n)->op1.u.constant)
#else
#define OP1_FUNCTION_PTR(n) ((n)->op1.zv)
#endif
The first call is resolved, and it is found that the embedded call is no opline
in 060e02e2a5e96d, and the version is different, the place to obtain it is different, and the judgment version number of the opline above is not the same, which can only be measured by physical strength .
#if PHP_VERSION_ID < 50500
if (execute_data->fbc != NULL)
{
fbc = execute_data->fbc;
}
#else
if (execute_data->call != NULL && execute_data->call->fbc != NULL)
{
fbc = execute_data->call->fbc;
}
#endif
The final access to function information is a multi-level judgment
zend_function *fbc;
#if PHP_VERSION_ID < 70000
#if PHP_VERSION_ID < 50500
if (execute_data->fbc != NULL)
{
fbc = execute_data->fbc;
}
#else
if (execute_data->call != NULL && execute_data->call->fbc != NULL)
{
fbc = execute_data->call->fbc;
}
#endif
if (fbc == NULL)
{
fbc = get_function_from_opline(execute_data->opline);
}
#else
if (execute_data->call != NULL && execute_data->call->func != NULL)
{
fbc = execute_data->call->fbc;
}
#endif
Only the name of the function can be queried from the opline. You need to find the corresponding function pointer in the global function table.
static zend_function *get_function_from_opline(zend_op *opline)
{
zend_function *fbc;
zval *function_name = OP1_FUNCTION_PTR(opline);
if (Z_STRVAL_P(function_name) == NULL)
{
return NULL;
}
if (zend_hash_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name) + 1, (void **)&fbc) ==
FAILURE)
{
return NULL;
}
return fbc;
}
Generally speaking, the processing of PHP5 is much more complicated than that of PHP7, which also shows that PHP7 is doing better. I like it.
These are the development work in the past few days. There may be many actual online environments that have not been encountered. If you are interested, you can use this tool to solve problems, or you can improve this gadget together.
Next week or next next week I will add the watch function to support function and method parameter printing. It is mainly analogous to Java's Arthas, because trace and watch functions are the most commonly used among them. Although PHP can directly modify and add logs online, it is not standardized after all, and the release process is too slow. I think this watch function is still very slow. Necessary, probably
$ ./bin/deliverer -w foo -n 3
It means that the monitor foo
function exits after 3 calls, and prints out deliverer-request-id
and its input parameters. You can then view the complete call stack deliverer-request-id
If you feel interested in this, give me a star, 160e02e2a5ea7b https://github.com/zhoumengkang/deliverer
If you have any problems with installation and use, please add me WeChat zhoumengkang to harass, the code: deliverer
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。