php扩展调试

.gdbinit文件如下:

set $zts = 0


define ____executor_globals
	if $zts
		set $eg = ((zend_executor_globals) (*((void ***) tsrm_ls))[executor_globals_id-1])
	else
		set $eg = executor_globals
	end
end


document ____executor_globals
	portable way of accessing executor_globals
	ZTS detection is automatically based on ext/standard module struct
end


define dump_bt
	set $t = $arg0
	while $t
		printf "[0x%08x] ", $t
		if $t->function_state.function->common.function_name
			printf "%s() ", $t->function_state.function->common.function_name
		else
			printf "??? "
		end
		if $t->op_array != 0
			printf "%s:%d ", $t->op_array->filename, $t->opline->lineno
		end
		set $t = $t->prev_execute_data
		printf "\n"
	end
end


document dump_bt
	dumps the current execution stack. usage: dump_bt executor_globals.current_execute_data
end


define printzv
	set $ind = 1
	____printzv $arg0 0 
end


document printzv
	prints zval contents
end


define ____printzv_contents
	set $zvalue = $arg0
	set $type = $zvalue->type


	printf "(refcount=%d", $zvalue->refcount
	if $zvalue->is_ref
		printf ",is_ref"
	end
	printf ") "
	if $type == 0
		printf "NULL"
	end
	if $type == 1
		printf "long: %ld", $zvalue->value.lval
	end
	if $type == 2
		printf "double: %lf", $zvalue->value.dval
	end
	if $type == 3
		printf "bool: "
		if $zvalue->value.lval
			printf "true"
		else
			printf "false"
		end
	end
	if $type == 4
		printf "array(%d): ", $zvalue->value.ht->nNumOfElements
		if ! $arg1
			printf "{\n"
			set $ind = $ind + 1
			____print_ht $zvalue->value.ht 1
			set $ind = $ind - 1
			set $i = $ind
			while $i > 0
				printf "  "
				set $i = $i - 1
			end
			printf "}"
		end
		set $type = 0
	end
	if $type == 5
		printf "object"
		____executor_globals
		set $handle = $zvalue->value.obj.handle
		set $handlers = $zvalue->value.obj.handlers
		if $zts
			set $zobj = zend_objects_get_address($zvalue, $tsrm_ls)
		else
			set $zobj = zend_objects_get_address($zvalue)
		end
		if $handlers->get_class_entry == &zend_std_object_get_class
			set $cname = $zobj->ce.name
		else
			set $cname = "Unknown"
		end
		printf "(%s) #%d", $cname, $handle
		if ! $arg1
			if $handlers->get_properties == &zend_std_get_properties
				set $ht = $zobj->properties
				if $ht
					printf "(%d): ", $ht->nNumOfElements
					printf "{\n"
					set $ind = $ind + 1
					____print_ht $ht 1
					set $ind = $ind - 1
					set $i = $ind
					while $i > 0
						printf "  "
						set $i = $i - 1
					end
					printf "}"
				else
					echo "no properties found"
				end
			end
		end
		set $type = 0
	end
	if $type == 6
		printf "string(%d): ", $zvalue->value.str.len
		____print_str $zvalue->value.str.val $zvalue->value.str.len
	end
	if $type == 7
		printf "resource: #%d", $zvalue->value.lval
	end
	if $type == 8 
		printf "constant"
	end
	if $type == 9
		printf "const_array"
	end
	if $type > 9
		printf "unknown type %d", $type
	end
	printf "\n"
end


define ____printzv
	____executor_globals
	set $zvalue = $arg0


	printf "[0x%08x] ", $zvalue


	if $zvalue == $eg.uninitialized_zval_ptr
		printf "*uninitialized* "
	end


	set $zcontents = (zval*) $zvalue
	if $arg1
		____printzv_contents $zcontents $arg1
	else
		____printzv_contents $zcontents 0 
	end
end


define ____print_const_table
	set $ht = $arg0
	set $p = $ht->pListHead


	while $p != 0
		set $const = (zend_constant *) $p->pData


		set $i = $ind
		while $i > 0
			printf "  "
			set $i = $i - 1
		end


		if $p->nKeyLength > 0
			____print_str $p->arKey $p->nKeyLength
			printf " => "
		else
			printf "%d => ", $p->h
		end


		____printzv_contents &$const->value 0
		set $p = $p->pListNext
	end
end


define print_const_table
	set $ind = 1
	printf "[0x%08x] {\n", $arg0
	____print_const_table $arg0
	printf "}\n"
end


define ____print_ht
	set $ht = (HashTable*)$arg0
	set $p = $ht->pListHead


	while $p != 0
		set $i = $ind
		while $i > 0
			printf "  "
			set $i = $i - 1
		end


		if $p->nKeyLength > 0
			____print_str $p->arKey $p->nKeyLength
			printf " => "
		else
			printf "%d => ", $p->h
		end
		
		if $arg1 == 0
			printf "%p\n", (void*)$p->pData
		end
		if $arg1 == 1
			set $zval = *(zval **)$p->pData
			____printzv $zval 1
		end
		if $arg1 == 2
			printf "%s\n", (char*)$p->pData
		end


		set $p = $p->pListNext
	end
end


define print_ht
	set $ind = 1_
	printf "[0x%08x] {\n", $arg0
	____print_ht $arg0 1
	printf "}\n"
end


document print_ht
	dumps elements of HashTable made of zval
end


define print_htptr
	set $ind = 1
	printf "[0x%08x] {\n", $arg0
	____print_ht $arg0 0
	printf "}\n"
end


document print_htptr
	dumps elements of HashTable made of pointers
end


define print_htstr
	set $ind = 1
	printf "[0x%08x] {\n", $arg0
	____print_ht $arg0 2
	printf "}\n"
end


document print_htstr
	dumps elements of HashTable made of strings
end


define ____print_ft
	set $ht = $arg0
	set $p = $ht->pListHead


	while $p != 0
		set $func = (zend_function*)$p->pData


		set $i = $ind
		while $i > 0
			printf "  "
			set $i = $i - 1
		end


		if $p->nKeyLength > 0
			____print_str $p->arKey $p->nKeyLength
			printf " => "
		else
			printf "%d => ", $p->h
		end


		printf "\"%s\"\n", $func->common.function_name
		set $p = $p->pListNext
	end
end


define print_ft
	set $ind = 1
	printf "[0x%08x] {\n", $arg0
	____print_ft $arg0
	printf "}\n"
end


document print_ft
	dumps a function table (HashTable)
end


define ____print_inh_class
	set $ce = $arg0
	if $ce->ce_flags & 0x10 || $ce->ce_flags & 0x20
		printf "abstract "
	else
		if $ce->ce_flags & 0x40
			printf "final "
		end
	end
	printf "class %s", $ce->name
	if $ce->parent != 0
		printf " extends %s", $ce->parent->name
	end
	if $ce->num_interfaces != 0
		printf " implements"
		set $tmp = 0
		while $tmp < $ce->num_interfaces
			printf " %s", $ce->interfaces[$tmp]->name
			set $tmp = $tmp + 1
			if $tmp < $ce->num_interfaces
				printf ","
			end
		end
	end
	set $ce = $ce->parent
end


define ____print_inh_iface
	set $ce = $arg0
	printf "interface %s", $ce->name
	if $ce->num_interfaces != 0
		set $ce = $ce->interfaces[0]
		printf " extends %s", $ce->name
	else
		set $ce = 0
	end
end


define print_inh
	set $ce = $arg0
	set $depth = 0
	while $ce != 0
		set $tmp = $depth
		while $tmp != 0
			printf " "
			set $tmp = $tmp - 1
		end
		set $depth = $depth + 1
		if $ce->ce_flags & 0x80
			____print_inh_iface $ce
		else
			____print_inh_class $ce
		end
		printf " {\n"
	end
	while $depth != 0
		set $tmp = $depth
		while $tmp != 1
			printf " "
			set $tmp = $tmp - 1
		end
		printf "}\n"
		set $depth = $depth - 1
	end
end


define print_pi
	set $pi = $arg0
	printf "[0x%08x] {\n", $pi
	printf "    h     = %lu\n", $pi->h
	printf "    flags = %d (", $pi->flags
	if $pi->flags & 0x100n
		printf "ZEND_ACC_PUBLIC"
	else
		if $pi->flags & 0x200
			printf "ZEND_ACC_PROTECTED"
		else
			if $pi->flags & 0x400
				printf "ZEND_ACC_PRIVATE"
			else
				if $pi->flags & 0x800
					printf "ZEND_ACC_CHANGED"
				end
			end
		end
	end
	printf ")\n"
	printf "    name  = "
	____print_str $pi->name $pi->name_length
	printf "\n}\n"
end


define ____print_str
	set $tmp = 0
	set $str = $arg0
	printf "\""
	while $tmp < $arg1
		if $str[$tmp] > 32 && $str[$tmp] < 127
			printf "%c", $str[$tmp]
		else
			printf "\\%o", $str[$tmp]
		end
		set $tmp = $tmp + 1
	end
	printf "\""
end


define printzn
	____executor_globals
	set $ind = 0
	set $znode = $arg0
	if $znode->op_type == 1
		set $optype = "IS_CONST"
	end
	if $znode->op_type == 2 
		set $optype = "IS_TMP_VAR"
	end
	if $znode->op_type == 4 
		set $optype = "IS_VAR"
	end
	if $znode->op_type == 8
		set $optype = "IS_UNUSED"
	end


	printf "[0x%08x] %s", $znode, $optype


	if $znode->op_type == 1
		printf ": "
		____printzv &$znode->u.constant 0
	end
	if $znode->op_type == 2
		printf ": "
		set $tvar = (union _temp_variable *)((char *)$eg.current_execute_data->Ts + $znode->u.var)
		____printzv ((union _temp_variable *)$tvar)->tmp_var 0
	end
	if $znode->op_type == 4
		printf ": "
		set $tvar = (union _temp_variable *)((char *)$eg.current_execute_data->Ts + $znode->u.var)
		____printzv *$tvar->var.ptr_ptr 0
	end
	if $znode->op_type == 8
		printf "\n"
	end
end


document printzn
	print type and content of znode.
	usage: printzn &opline->op1 
end


define printzops
	printf "op1 => " 
	printzn &execute_data->opline.op1
	printf "op2 => "
	printzn &execute_data->opline.op2
	printf "result => "
	printzn &execute_data->opline.result
end


document printzops
	dump operands of the current opline
end


define zbacktrace
	____executor_globals
	dump_bt $eg.current_execute_data
end


document zbacktrace
	prints backtrace.
	This command is almost a short cut for
	> (gdb) ____executor_globals
	> (gdb) dump_bt $eg.current_execute_data
end


define zmemcheck
	set $p = alloc_globals.head
	set $stat = "?"
	set $total_size = 0
	if $arg0 != 0
		set $not_found = 1
	else
		set $not_found = 0
	end
	printf " block      size      status file:line\n"
	printf "-------------------------------------------------------------------------------\n"
	while $p
		set $aptr = $p + sizeof(struct _zend_mem_header) + sizeof(align_test)
		if $arg0 == 0 || (void *)$aptr == (void *)$arg0
			if $p->magic == 0x7312f8dc 
				set $stat = "OK"
			end
			if $p->magic == 0x99954317
				set $stat = "FREED"
			end
			if $p->magic == 0xfb8277dc
				set $stat = "CACHED"
			end
			set $filename = strrchr($p->filename, '/')
			if !$filename
				set $filename = $p->filename
			else
				set $filename = $filename + 1
			end
			printf " 0x%08x ", $aptr
			if $p->size == sizeof(struct _zval_struct) && ((struct _zval_struct *)$aptr)->type >= 0 && ((struct _zval_struct *)$aptr)->type < 10
				printf "ZVAL?(%-2d) ", $p->size
			else
				printf "%-9d ", $p->size
			end
			set $total_size = $total_size + $p->size
			printf "%-06s %s:%d", $stat, $filename, $p->lineno
			if $p->orig_filename
				set $orig_filename = strrchr($p->orig_filename, '/')
				if !$orig_filename
					set $orig_filename = $p->orig_filename
				else
					set $orig_filename = $orig_filename + 1
				end
				printf " <= %s:%d\n", $orig_filename, $p->orig_lineno
			else
				printf "\n"
			end
			if $arg0 != 0
				set $p = 0
				set $not_found = 0
			else
				set $p = $p->pNext
			end
		else
			set $p = $p->pNext
		end
	end
	if $not_found
		printf "no such block that begins at 0x%08x.\n", $aptr 
	end
	if $arg0 == 0
		printf "-------------------------------------------------------------------------------\n"
		printf "     total: %d bytes\n", $total_size
	end
end


document zmemcheck
	show status of a memory block.
	usage: zmemcheck [ptr].
	if ptr is 0, all blocks will be listed.
end


php调试:

gdb /usr/local/php/bin/php


set args test.php


break ***


source /home/xulei-ps/.gdbinit 

run


查找对象

 
 
  1. (gdb) p ((zval *)0x2a95de7840)->value.obj.handle
  2. $6 = 1
  3. //注意, 下面用到了这个$6的值:1
  4. (gdb) p (zend_object*) executor_globals->objects_store.object_buckets[1].bucket.obj.object
  5. $7 = (struct _zend_object *) 0x2a95de3ec0
  6. (gdb) p $9->ce->name
  7. $8 = 0x2a95e200b0 "Test

1. print_cvs 打印当前执行环境中已编译的PHP变量, 如:


2. printzv 打印指定的PHP变量, 需要指定地址, 如:

(gdb) printzv 0x9543f98
[0x9543f98] (refcount=1) string(3): “MMM”
(gdb)

3. 打印PHP的函数调用栈, 如:
(gdb) zbacktrace 
[0x95770a4] sleep(1) /usr/home/junjie2/a.php:11
[0x9576fe0] test(“phpor”) /usr/home/junjie2/a.php:7
(gdb)

4. print_ft 打印函数表( HashTable )
(gdb) set $eg = executor_globals
(gdb) print $eg.function_table  

$6 = (HashTable *) 0xa5bd450
(gdb) print_ft $eg.function_table 
[0xa5bd450] {
“zend_version\0″ => “zend_version”
“func_num_args\0″ => “func_num_args”
“func_get_arg\0″ => “func_get_arg”
“func_get_args\0″ => “func_get_args”
“strlen\0″ => “strlen”
“strcmp\0″ => “strcmp”
“strncmp\0″ => “strncmp”
“strcasecmp\0″ => “strcasecmp”
“strncasecmp\0″ => “strncasecmp”
“each\0″ => “each”

学习
1. 通过阅读 print_cvs 命令的实现,可以知道可以通过prev_execute_data来打印上一执行空间的PHP变量,如:
(gdb) printzv *executor_globals.current_execute_data->prev_execute_data->CVs[1]  
[0x9543408] (refcount=1) string(3): “AAA”
(gdb) printzv *executor_globals.current_execute_data->prev_execute_data->CVs[2]  
[0x95433ec] (refcount=1) string(3): “BBB”
(gdb)

2. 通过 op_array->vars 来找到对应的变量的名字
(gdb) printf “%s\n” ,executor_globals.current_execute_data->prev_execute_data->op_array->vars[1].name  
a
(gdb) printf “%s\n” ,executor_globals.current_execute_data->prev_execute_data->op_array->vars[2].name  
b

3. 修改了一下 print_cvs 命令,通过参数来获取每个执行空间的PHP的已编译变量


 

使用方法:
———————
(gdb) zbacktrace  #查看PHP的调用栈
[0x8ce2078] sleep(1) /usr/home/junjie2/a.php:9
[0x8ce1fe0] test(“phpor”) /usr/home/junjie2/a.php:5
(gdb) print_cvs #查看当前执行空间中的PHP变量
Compiled variables count: 3
0 = name
[0x8cae3d0] (refcount=2) string(5): “phpor”
1 = m
[0x8cae93c] (refcount=1) string(3): “MMM”
2 = n
[0x8cae958] (refcount=1) string(3): “NNN”
(gdb) print_cvs 2 # 查看指定执行空间中的PHP变量, 这个参数给大了也没关系,最多打印最外层的PHP变量
Compiled variables count: 2
0 = a
[0x8cae408] (refcount=1) string(3): “AAA”
1 = b
[0x8cae3ec] (refcount=1) string(3): “BBB”
(gdb)
———————

4. 有时候需要借助环境变量,如:
(gdb) print_ft (HashTable *)0xa5bd450
A syntax error in expression, near `’.
(gdb) set $phpor=(HashTable *)0xa5bd450
(gdb) print_ft $phpor
[0xa5bd450] {
“zend_version\0″ => “zend_version”
“func_num_args\0″ => “func_num_args”
“func_get_arg\0″ => “func_get_arg”
“func_get_args\0″ => “func_get_args”
“strlen\0″ => “strlen”
“strcmp\0″ => “strcmp”
“strncmp\0″ => “strncmp”

 

5. 打印指定的PHP变量

 



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值