43
Internal PHP and gdb php core [email protected]

Internal php and gdb php core

  • Upload
    alpha86

  • View
    1.247

  • Download
    10

Embed Size (px)

Citation preview

Page 1: Internal php and gdb php core

Internal PHP and gdb php core

[email protected]

Page 2: Internal php and gdb php core

Agenda

• Overview• PHP lifecycle• Zend Engine 2 & PHP Opcodes• PHP 变量• PHP 函数• PHP OO• Some Details• PHP extensions• gdb php core

Page 3: Internal php and gdb php core

Overview

Page 4: Internal php and gdb php core

Overview

• Php 5.2.x

– Zend Engine 2.0

• OO的改进

Page 5: Internal php and gdb php core

Overview –代码结构

• main – php的核心文件以及基础设施

• Zend– Zend engine2 – 词法语法分析,虚拟机,所有与”php”相关的

• ext– 扩展目录

• sapi– 服务器抽象层(mod_php,fastcgi,etc)

• TSRM– 线程安全相关

Page 6: Internal php and gdb php core

PHP lifecycle - CLI

Page 7: Internal php and gdb php core

PHP lifecycle – Apache Multiprocess

Individual process life cycle

Page 8: Internal php and gdb php core

PHP lifecycle – Apache Multiprocess

Multiprocess life cycles

Page 9: Internal php and gdb php core

PHP lifecycle –扩展

• PHP_MINIT_FUNCTION(mysqli);

• PHP_MSHUTDOWN_FUNCTION(mysqli);

• PHP_RINIT_FUNCTION(mysqli);

• PHP_RSHUTDOWN_FUNCTION(mysqli);

Page 10: Internal php and gdb php core

PHP lifecycle – execute PHP

• Lexical Analysis

• Syntax Analysis

• Opcodes Generation

• Opcodes Execution

Page 11: Internal php and gdb php core

PHP lifecycle – PHP Execution

*.php

lex

Exprs

yacc

opcodesZendvm

zend_language_scanner.l

zend_language_parser.y

eAccelerator(eacc)

eaccelerator.c, PHP_MINIT_FUNCTION(eaccelerator)

Page 12: Internal php and gdb php core

PHP lifecycle – tokens

zend_language_scanner.l 中有所有token的定义,php的token_get_all函数可以获得一段php代码的token

Page 13: Internal php and gdb php core

Opcodeszend_op_array

Zend Engine 2 & PHP Opcodes

php_execute_script()

zend_execute_scripts()

zend_execute()

user call

(function/method)

包括定义在php中的函数和扩展里的函数

include/require

zend_compile_file()

函数指针

Zend engine 整体流程

Page 14: Internal php and gdb php core

Zend Engine 2 - execute_scripts

• PHPAPI int php_execute_script(zend_file_handle *primary_file TSRMLS_DC) (main/main.c)

• ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval **retval, intfile_count, ...) (Zend/zend.c)

• php_execute_script把auto_prepend_file,primary_file,auto_prepend_file这三个文件传给zend_execute_scripts

Page 15: Internal php and gdb php core

Zend Engine 2 - zend_compile_file

• Zend/zend.c zend_startup

• 默认指向compile_file() in zend_language_scanner.c

• ZEND_API zend_op_array *compile_file(zend_file_handle*file_handle, int type TSRMLS_DC)

• Lexical Analysis -> Syntax Analysis -> Opcodes Generation

Page 16: Internal php and gdb php core

PHP Opcodes

<?phpecho "hello world!";

通过vld扩展可以查看opcode,space@bb-space-test000/home/space/php5/bin/php -dvld.active=1 test3.php

Page 17: Internal php and gdb php core

PHP Opcodes

<?phpfunction testHello(){

return "hello world";}echo testHello();

Page 18: Internal php and gdb php core

PHP Opcodesstruct _zend_op {

opcode_handler_t handler; //每一个opcode对应的回调znode result;znode op1;znode op2;ulong extended_value;uint lineno;zend_uchar opcode; // opcode值

};typedef int (*opcode_handler_t) (ZEND_OPCODE_HANDLER_ARGS);typedef unsigned char zend_uchar;//zend_compile.h( _zend_op_array 也在这里)

Page 19: Internal php and gdb php core

PHP Opcodes

• Opcodes由zend_execute来执行

• 默认情况,zend_execute指向zend_vm_execute.h的ZEND_API void execute(zend_op_array *op_arrayTSRMLS_DC)

• 每个opcode的回调都存在全局变量zend_opcode_handlers中,初始化在zend_init_opcodes_handlers()

• 回调命名规则ZEND_[opcode]_SPEC_(变量类型1)_(变量类型2)_HANDLER

Page 20: Internal php and gdb php core

PHP 变量

• 弱类型

typedef union _zvalue_value {long lval; /* long value */double dval; /* double value */struct {

char *val;int len;

} str;HashTable *ht; /* hash table value */zend_object_value obj;

} zvalue_value;

//zend.htypedef struct _zval_struct zval;struct _zval_struct {

/* Variable information */zvalue_value value; /* value */zend_uint refcount;zend_uchar type; /* active type */zend_uchar is_ref;

};

Page 21: Internal php and gdb php core

PHP 变量 - type

/* data types */ // zval.type/* All data types <= IS_BOOL have their constructor/destructors

skipped */#define IS_NULL 0#define IS_LONG 1#define IS_DOUBLE 2#define IS_BOOL 3#define IS_ARRAY 4#define IS_OBJECT 5#define IS_STRING 6#define IS_RESOURCE 7#define IS_CONSTANT 8#define IS_CONSTANT_ARRAY 9

Page 22: Internal php and gdb php core

PHP 变量 - HashTable

• 整个zend engine最核心的数据结构

• 不仅仅是php中的array,ze中大量采用HashTable来实现自己的逻辑,比如OO的逻辑,全局大变量等等

• zend_hash.h

Page 23: Internal php and gdb php core

PHP 函数

<?phpfcrypt_hstr_2id("space","aaaa");strstr("abcde","abc");echo "done";

PHP中的user_function和扩展中的函数都是DO_FCALL指令,echo是指令不是函数

Page 24: Internal php and gdb php core

PHP 函数

• DO_FCALL最终调到static intzend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)// zend_vm_execute.h

Page 25: Internal php and gdb php core

zend_do_fcall_common_helper_SPEC

Page 26: Internal php and gdb php core

PHP 函数

• 两种类型函数

– User function(写在php代码中的函数)

– Internal function(扩展中的函数)

• Php代码的函数栈会在zend vm中也体现出来!

–就是zend_do_fcall_common_helper_SPEC形成的栈(还包括execute,zend_execute_internal等)

• abc

Page 27: Internal php and gdb php core

PHP 函数 –函数类型

#define ZEND_INTERNAL_FUNCTION 1#define ZEND_USER_FUNCTION 2#define ZEND_OVERLOADED_FUNCTION 3#define ZEND_EVAL_CODE 4#define ZEND_OVERLOADED_FUNCTION_TEMPORARY 5

typedef union _zend_function {zend_uchar type; /* MUST be the first element of this struct! */

struct {zend_uchar type; /* never used */char *function_name;zend_class_entry *scope;zend_uint fn_flags;union _zend_function *prototype;zend_uint num_args;zend_uint required_num_args;zend_arg_info *arg_info;zend_bool pass_rest_by_reference;unsigned char return_reference;

} common;

zend_op_array op_array;zend_internal_function internal_function;

} zend_function;

Page 28: Internal php and gdb php core

PHP OOstruct _zend_class_entry {

char type;char *name;zend_uint name_length;struct _*parent;int refcozend_class_entry unt;HashTable function_table;HashTable default_properties;HashTable properties_info;HashTable default_static_members;HashTable *static_members;HashTable constants_table;struct _zend_function_entry *builtin_functions;union _zend_function *constructor;union _zend_function *destructor;union _zend_function *clone;union _zend_function *__get;union _zend_function *serialize_func;union _zend_function *unserialize_func;……..

Page 29: Internal php and gdb php core

Some Details

• 大量的宏

– # define EG(v) (executor_globals.v) //Zend/zend_globals_macros.h

– #define EX(element) execute_data->element

Page 30: Internal php and gdb php core

比较重要的全局变量

• ZEND_API zend_compiler_globalscompiler_globals;

• ZEND_API zend_executor_globalsexecutor_globals;

• 尤其对于executor_globals会有大量的运行时数据

Page 31: Internal php and gdb php core

PHP extensions(学习hack php的一些思路)

• eAccelerator

• Xdebug

• Xphrof

Page 32: Internal php and gdb php core

PHP extensions - eAccelerator

• PHP_MINIT_FUNCTION(eaccelerator) 中zend_compile_file = eaccelerator_compile_file;

• eaccelerator_compile_file会首先从cache中读opcode,没有cache才会重新生成,cache

• 来实现opcode cache

Page 33: Internal php and gdb php core

PHP extensions - xdebug

• 函数调用的性能分析

// PHP_MINIT_FUNCTION old_compile_file = zend_compile_file;zend_compile_file = xdebug_compile_file;xdebug_old_execute = zend_execute;zend_execute = xdebug_execute;

xdebug_orig_header_handler = sapi_module.header_handler;sapi_module.header_handler = xdebug_header_handler;

xdebug_execute做完一堆

事情后,再调回xdebug_old_execute

Page 34: Internal php and gdb php core

PHP extensions - xdebug

• 代码覆盖率分析

// PHP_MINIT_FUNCTIONif (XG(coverage_enable)) {

XDEBUG_SET_OPCODE_OVERRIDE_COMMON(ZEND_JMP);XDEBUG_SET_OPCODE_OVERRIDE_COMMON(ZEND_JMPZ);XDEBUG_SET_OPCODE_OVERRIDE_COMMON(ZEND_JMPZ_EX);XDEBUG_SET_OPCODE_OVERRIDE_COMMON(ZEND_JMPNZ);

#define XDEBUG_SET_OPCODE_OVERRIDE_COMMON(oc) \zend_set_user_opcode_handler(oc, xdebug_common_override_handler);

Page 35: Internal php and gdb php core

PHP extensions - Xphrof

• PHP_FUNCTION(xhprof_enable) 中进行

_zend_compile_file = zend_compile_file;zend_compile_file = hp_compile_file;/* Replace zend_execute with our proxy */_zend_execute = zend_execute;zend_execute = hp_execute;

Page 36: Internal php and gdb php core

gdb php core

类似于下面这种,需要了解php的逻辑来排查问题的

Page 37: Internal php and gdb php core

gdb php core

• source ~/php-5.2.10/.gdbinit 初始化一些gdb命令(方便查询hashtable)

• 如果获取当前执行在php的那个函数?

Page 38: Internal php and gdb php core

gdb php core –在哪个类?

Page 39: Internal php and gdb php core

gdb php core –获取php中的全局变量

• $_SERVER,$_GET,$_POST 等这些php代码中的大变量如何获取?

• executor_globals

• executor_globals->symbol_table 全局的变量在这个符号表里

Page 40: Internal php and gdb php core
Page 41: Internal php and gdb php core

这次没有涉及到的

• PHP SAPI架构• PHP HashTable细节• PHP内存管理• PHP ZTS & TSRM等线程安全机制• OO的更多细节以及如何编写OO扩展• 变量的作用域• Zend vm更深入的分析• 等等• 这些内容也期待大家共同参与

Page 42: Internal php and gdb php core

参考资料

• Php.net

• Extending and Embedding PHP

• http://www.php-internal.com/

• http://www.laruence.com/

Page 43: Internal php and gdb php core

Thank you!