【php】使用phpdbg来调试php程序
PHPDBG是一个PHP的SAPI模块,可以在不用修改代码和不影响性能的情况下控制PHP的运行环境
可以在PHP5.4和之上版本中使用。在PHP5.6和之上版本将内部集成
功能
- 单步调试
- 灵活的下断点方式(类方法、函数、文件:行、内存地址、opcode)
- 可直接调用php的eval
- 可以查看当前执行的代码
- 用户空间API(userland/user space)
- 方便集成
- 支持指定php配置文件
- JIT全局变量
- readline支持(可选),终端操作更方便
- 远程debug,使用java GUI
- 操作简便(具体看help)
安装
如果是PHP56一下
cd /usr/src/php-src/sapi
git clone https://github.com/krakjoe/phpdbg
cd ../
./buildconf --force
./config.nice
make -j8
make install-phpdbg
PHP56的话直接启用phpdbg就可以了
注意: php 配置中可以启用 --with-readline for phpdbg to support history, autocompletion, tab-listing etc
phpdbginit
Setting up your debugging session automatically
phpdbg -imy.phpdbginit
In addition, .phpdbginit can contain embedded code, allowing, for example
- the setup of auto completion
- the registration of functions
- the acquisition and pre-compilation of code
- bootstrapping a web application
The default .phpdbginit
##########################################################
# .phpdbginit
#
# Lines starting with # are ignored
# Code must start and end with <: and :> respectively
##########################################################
# Place initialization commands one per line
##########################################################
# exec sapi/phpdbg/test.php ##########################################################
# Embedding code in .phpdbginit
##########################################################
<:
/*
If readline is loaded, you might want to setup completion:
*/
if (function_exists('readline_completion_function')) {
readline_completion_function(function(){
return array_merge(
get_defined_functions()['user'],
array_keys(get_defined_constants())
);
});
}
:>
##########################################################
# Now carry on initializing phpdbg ...
##########################################################
# R my_debugging_function ##########################################################
# PHP has many functions that might be useful
# ... you choose ...
##########################################################
# R touch
# R unlink
# R scandir
# R glob ##########################################################
# Remember: *you have access to the shell*
##########################################################
# The output of registered function calls is not,
# by default, very pretty (unless you implement
# and register a new implementation for phpdbg)
# The output of shell commands will usually be more
# readable on the console
##########################################################
# TLDR; if you have a good shell, use it ...
##########################################################
查看版本号
[root@localhost ~]# php -v
PHP 5.6.16 (cli) (built: Dec 8 2015 09:10:23) (DEBUG)
Copyright (c) 1997-2015 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2015 Zend Technologies
with Xdebug v2.3.3, Copyright (c) 2002-2015, by Derick Rethans
[root@localhost ~]# phpdbg -V
phpdbg 0.4.0 (built: Dec 8 2015 09:10:43)
PHP 5.6.16, Copyright (c) 1997-2015 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2015 Zend Technologies
with Xdebug v2.3.3, Copyright (c) 2002-2015, by Derick Rethans
查看help
[root@localhost ~]# phpdbg
[Welcome to phpdbg, the interactive PHP debugger, v0.4.0]
To get help using phpdbg type "help" and press enter
[Please report bugs to <http://github.com/krakjoe/phpdbg/issues>]
phpdbg> help phpdbg is a lightweight, powerful and easy to use debugging platform for PHP5.4+
It supports the following commands: Information
list list PHP source
info displays information on the debug session
print show opcodes
frame select a stack frame and print a stack frame summary
back shows the current backtrace
help provide help on a topic Starting and Stopping Execution
exec set execution context
run attempt execution
step continue execution until other line is reached
continue continue execution
until continue execution up to the given location
finish continue up to end of the current execution frame
leave continue up to end of the current execution frame and halt after the calling instruction
break set a breakpoint at the specified target
watch set a watchpoint on $variable
clear clear one or all breakpoints
clean clean the execution environment Miscellaneous
set set the phpdbg configuration
source execute a phpdbginit script
register register a phpdbginit function as a command alias
sh shell a command
ev evaluate some code
quit exit phpdbg Type help <command> or (help alias) to get detailed help on any of the above commands, for example help list or h l. Note that help will also match partial commands if unique (and list
out options if not unique), so help clea will give help on the clean command, but help cl will list the summary for clean and clear. Type help aliases to show a full alias list, including any registered phpdginit functions
Type help syntax for a general introduction to the command syntax.
Type help options for a list of phpdbg command line options.
Type help phpdbginit to show how to customise the debugger environment.
phpdbg> help list
Command: list Alias: l lists some code The list command displays source code for the given argument. The target type is specficied by a second subcommand keyword: Type Alias Purpose
lines l List N lines from the current execution point
func f List the complete source for a specified function
method m List the complete source for a specified class::method
class c List the complete source for a specified class Note that the context of lines, func and method can be determined by parsing the argument, so these subcommands are optional. However, you must specify the class keyword to list off a
class. Examples phpdbg> list 2
phpdbg> l l 2
List the next 2 lines from the current file phpdbg> list my_function
phpdbg> l f my_function
List the source of the function my_function phpdbg> list func .mine
phpdbg> l f .mine
List the source of the method mine from the active class in scope phpdbg> list m my::method
phpdbg> l my::method
List the source of my::method phpdbg> list c myClass
phpdbg> l c myClass
List the source of myClass Note that functions and classes can only be listed if the corresponding classes and functions table in the Zend executor has a corresponding entry. You can use the compile command to
populate these tables for a given execution context.
phpdbg> help break
Command: break Alias: b set breakpoint Breakpoints can be set at a range of targets within the execution environment. Execution will be paused if the program flow hits a breakpoint. The break target can be one of the
following types: Target Alias Purpose
at A specify breakpoint by location and condition
del d delete breakpoint by breakpoint identifier number Break at takes two arguments. The first is any valid target. The second is a valid PHP expression which will trigger the break in execution, if evaluated as true in a boolean context at
the specified target. Note that breakpoints can also be disabled and re-enabled by the set break command. Examples phpdbg> break test.php:100
phpdbg> b test.php:100
Break execution at line 100 of test.php phpdbg> break 200
phpdbg> b 200
Break execution at line 200 of the currently PHP script file phpdbg> break \mynamespace\my_function
phpdbg> b \mynamespace\my_function
Break execution on entry to \mynamespace\my_function phpdbg> break classX::method
phpdbg> b classX::method
Break execution on entry to classX::method phpdbg> break 0x7ff68f570e08
phpdbg> b 0x7ff68f570e08
Break at the opline at the address 0x7ff68f570e08 phpdbg> break my_function#14
phpdbg> b my_function#14
Break at the opline #14 of the function my_function phpdbg> break \my\class::method#2
phpdbg> b \my\class::method#2
Break at the opline #2 of the method \my\class::method phpdbg> break test.php:#3
phpdbg> b test.php:#3
Break at opline #3 in test.php phpdbg> break if $cnt > 10
phpdbg> b if $cnt > 10
Break when the condition ($cnt > 10) evaluates to true phpdbg> break at phpdbg::isGreat if $opt == 'S'
phpdbg> break @ phpdbg::isGreat if $opt == 'S'
Break at any opcode in phpdbg::isGreat when the condition ($opt == 'S') is true phpdbg> break at test.php:20 if !isset($x)
Break at every opcode on line 20 of test.php when the condition evaluates to true phpdbg> break ZEND_ADD
phpdbg> b ZEND_ADD
Break on any occurence of the opcode ZEND_ADD phpdbg> break del 2
phpdbg> b ~ 2
Remove breakpoint 2 Note: Conditional breaks are costly in terms of runtime overhead. Use them only when required as they significantly slow execution. Note: An address is only valid for the current compilation.
phpdbg> help watch
Command: watch Alias: w set watchpoint Sets watchpoints on variables as long as they are defined
Passing no parameter to watch, lists all actually active watchpoints Format for $variable $var Variable $var
$var[] All array elements of $var
$var-> All properties of $var
$var->a Property $var->a
$var[b] Array element with key b in array $var Subcommands of watch: Type Alias Purpose
array a Sets watchpoint on array/object to observe if an entry is added or removed
recursive r Watches variable recursively and automatically adds watchpoints if some entry is added to an array/object
delete d Removes watchpoint Note when recursive watchpoints are removed, watchpoints on all the children are removed too Examples phpdbg> watch
List currently active watchpoints phpdbg> watch $array
phpdbg> w $array
Set watchpoint on $array phpdbg> watch recursive $obj->
phpdbg> w r $obj->
Set recursive watchpoint on $obj-> phpdbg> watch delete $obj->a
phpdbg> w d $obj->a
Remove watchpoint $obj->a Technical note: If using this feature with a debugger, you will get many segmentation faults, each time when a memory page containing a watched address is hit.
You then you can continue, phpdbg will remove the write protection, so that the program can continue.
If phpdbg could not handle that segfault, the same segfault is triggered again and this time phpdbg will abort.
这些帮助文档足够了
示例代码 testb 与 testa的输出为什么是这样?
<?php ini_set("memory_limit","-1"); class test{ public function testa(){ $a=1;
$b = &$a;
return 0 + (++$a) + (++$a); } public function testb(){ $a=1;
$b = &$a;
return ++$a + (++$a); } public function convert($size)
{
$unit=array('b','kb','mb','gb','tb','pb');
return @round($size/pow(1024,($i=floor(log($size,1024)))),2).' '.$unit[$i];
} public function allsort($arr){
sort($arr);
$len = count($arr)-1;
$rs = array();
$rs[] = $arr;
$x = $len; while($x > 0){
$y = $x --;
if($arr[$x] < $arr[$y]){
$z = $len;
while($arr[$x] > $arr[$z]){
$z--;
}
list($arr[$x],$arr[$z]) = array($arr[$z],$arr[$x]); for($i=$len;$i>$y;$i--,$y++){
list($arr[$i],$arr[$y]) = array($arr[$y],$arr[$i]);
}
$x = $len;
$rs[] = $arr;
} }
return $rs;
}
} $s = new test();
$resa = $s->testa();
$resb = $s->testb();
$resc = $s->allsort([1,2,3]);
echo $resa,"\n",$resb,"\n";
#print_r($resb);
开始调试
[root@localhost ~]# phpdbg -e kk.php
[Welcome to phpdbg, the interactive PHP debugger, v0.4.0]
To get help using phpdbg type "help" and press enter
[Please report bugs to <http://github.com/krakjoe/phpdbg/issues>]
[Attempting compilation of /root/kk.php]
[Success]
查看一些当前类的opcode
phpdbg> p c test
[User Class: test]
Methods (4):
L7-13 test::testa() /root/kk.php
L7 0xb77b553c ZEND_EXT_NOP <unused> <unused> <unused>
L9 0xb77b5558 ZEND_EXT_STMT <unused> <unused> <unused>
L9 0xb77b5574 ZEND_ASSIGN $a C0 @0
L10 0xb77b5590 ZEND_EXT_STMT <unused> <unused> <unused>
L10 0xb77b55ac ZEND_ASSIGN_REF $b $a @1
L11 0xb77b55c8 ZEND_EXT_STMT <unused> <unused> <unused>
L11 0xb77b55e4 ZEND_PRE_INC $a <unused> @2
L11 0xb77b5600 ZEND_ADD C1 @2 @3
L11 0xb77b561c ZEND_PRE_INC $a <unused> @4
L11 0xb77b5638 ZEND_ADD @3 @4 @5
L11 0xb77b5654 ZEND_RETURN @5 <unused> <unused>
L13 0xb77b5670 ZEND_EXT_STMT <unused> <unused> <unused>
L13 0xb77b568c ZEND_RETURN C2 <unused> <unused>
L15-21 test::testb() /root/kk.php
L15 0xb77b656c ZEND_EXT_NOP <unused> <unused> <unused>
L17 0xb77b6588 ZEND_EXT_STMT <unused> <unused> <unused>
L17 0xb77b65a4 ZEND_ASSIGN $a C0 @0
L18 0xb77b65c0 ZEND_EXT_STMT <unused> <unused> <unused>
L18 0xb77b65dc ZEND_ASSIGN_REF $b $a @1
L19 0xb77b65f8 ZEND_EXT_STMT <unused> <unused> <unused>
L19 0xb77b6614 ZEND_PRE_INC $a <unused> @2
L19 0xb77b6630 ZEND_PRE_INC $a <unused> @3
L19 0xb77b664c ZEND_ADD @2 @3 @4
L19 0xb77b6668 ZEND_RETURN @4 <unused> <unused>
L21 0xb77b6684 ZEND_EXT_STMT <unused> <unused> <unused>
L21 0xb77b66a0 ZEND_RETURN C1 <unused> <unused>
L23-27 test::convert() /root/kk.php
L23 0xb77b66ec ZEND_EXT_NOP <unused> <unused> <unused>
L23 0xb77b6708 ZEND_RECV <unused> <unused> $size
L25 0xb77b6724 ZEND_EXT_STMT <unused> <unused> <unused>
L25 0xb77b6740 ZEND_INIT_ARRAY C0 <unused> @0
L25 0xb77b675c ZEND_ADD_ARRAY_ELEMENT C1 <unused> @0
L25 0xb77b6778 ZEND_ADD_ARRAY_ELEMENT C2 <unused> @0
L25 0xb77b6794 ZEND_ADD_ARRAY_ELEMENT C3 <unused> @0
L25 0xb77b67b0 ZEND_ADD_ARRAY_ELEMENT C4 <unused> @0
L25 0xb77b67cc ZEND_ADD_ARRAY_ELEMENT C5 <unused> @0
L25 0xb77b67e8 ZEND_ASSIGN $unit @0 @1
L26 0xb77b6804 ZEND_EXT_STMT <unused> <unused> <unused>
L26 0xb77b6820 ZEND_BEGIN_SILENCE <unused> <unused> @2
L26 0xb77b683c ZEND_EXT_FCALL_BEGIN <unused> <unused> <unused>
L26 0xb77b6858 ZEND_EXT_FCALL_BEGIN <unused> <unused> <unused>
L26 0xb77b6874 ZEND_SEND_VAL C6 <unused> <unused>
L26 0xb77b6890 ZEND_EXT_FCALL_BEGIN <unused> <unused> <unused>
L26 0xb77b68ac ZEND_EXT_FCALL_BEGIN <unused> <unused> <unused>
L26 0xb77b68c8 ZEND_SEND_VAR $size <unused> <unused>
L26 0xb77b68e4 ZEND_SEND_VAL C7 <unused> <unused>
L26 0xb77b6900 ZEND_DO_FCALL C8 <unused> @3
L26 0xb77b691c ZEND_EXT_FCALL_END <unused> <unused> <unused>
L26 0xb77b6938 ZEND_SEND_VAR_NO_REF @3 <unused> <unused>
L26 0xb77b6954 ZEND_DO_FCALL C9 <unused> @4
L26 0xb77b6970 ZEND_EXT_FCALL_END <unused> <unused> <unused>
L26 0xb77b698c ZEND_ASSIGN $i @4 @5
L26 0xb77b69a8 ZEND_SEND_VAR_NO_REF @5 <unused> <unused>
L26 0xb77b69c4 ZEND_DO_FCALL C10 <unused> @6
L26 0xb77b69e0 ZEND_EXT_FCALL_END <unused> <unused> <unused>
L26 0xb77b69fc ZEND_DIV $size @6 @7
L26 0xb77b6a18 ZEND_SEND_VAL @7 <unused> <unused>
L26 0xb77b6a34 ZEND_SEND_VAL C11 <unused> <unused>
L26 0xb77b6a50 ZEND_DO_FCALL C12 <unused> @8
L26 0xb77b6a6c ZEND_EXT_FCALL_END <unused> <unused> <unused>
L26 0xb77b6a88 ZEND_END_SILENCE @2 <unused> <unused>
L26 0xb77b6aa4 ZEND_CONCAT @8 C13 @9
L26 0xb77b6ac0 ZEND_FETCH_DIM_R $unit $i @10
L26 0xb77b6adc ZEND_CONCAT @9 @10 @11
L26 0xb77b6af8 ZEND_RETURN @11 <unused> <unused>
L27 0xb77b6b14 ZEND_EXT_STMT <unused> <unused> <unused>
L27 0xb77b6b30 ZEND_RETURN C14 <unused> <unused>
L29-54 test::allsort() /root/kk.php
L29 0xb77b818c ZEND_EXT_NOP <unused> <unused> <unused>
L29 0xb77b81a8 ZEND_RECV <unused> <unused> $arr
L30 0xb77b81c4 ZEND_EXT_STMT <unused> <unused> <unused>
L30 0xb77b81e0 ZEND_EXT_FCALL_BEGIN <unused> <unused> <unused>
L30 0xb77b81fc ZEND_SEND_REF $arr <unused> <unused>
L30 0xb77b8218 ZEND_DO_FCALL C0 <unused> @0
L30 0xb77b8234 ZEND_EXT_FCALL_END <unused> <unused> <unused>
L31 0xb77b8250 ZEND_EXT_STMT <unused> <unused> <unused>
L31 0xb77b826c ZEND_EXT_FCALL_BEGIN <unused> <unused> <unused>
L31 0xb77b8288 ZEND_SEND_VAR $arr <unused> <unused>
L31 0xb77b82a4 ZEND_DO_FCALL C1 <unused> @1
L31 0xb77b82c0 ZEND_EXT_FCALL_END <unused> <unused> <unused>
L31 0xb77b82dc ZEND_SUB @1 C2 @2
L31 0xb77b82f8 ZEND_ASSIGN $len @2 @3
L32 0xb77b8314 ZEND_EXT_STMT <unused> <unused> <unused>
L32 0xb77b8330 ZEND_INIT_ARRAY <unused> <unused> @4
L32 0xb77b834c ZEND_ASSIGN $rs @4 @5
L33 0xb77b8368 ZEND_EXT_STMT <unused> <unused> <unused>
L33 0xb77b8384 ZEND_ASSIGN_DIM $rs <unused> @6
L33 0xb77b83a0 UNKNOWN $arr @7 <unused>
L34 0xb77b83bc ZEND_EXT_STMT <unused> <unused> <unused>
L34 0xb77b83d8 ZEND_ASSIGN $x $len @8
L36 0xb77b83f4 ZEND_EXT_STMT <unused> <unused> <unused>
L36 0xb77b8410 ZEND_IS_SMALLER C3 $x @9
L36 0xb77b842c ZEND_JMPZ @9 J86 <unused>
L37 0xb77b8448 ZEND_EXT_STMT <unused> <unused> <unused>
L37 0xb77b8464 ZEND_POST_DEC $x <unused> @10
L37 0xb77b8480 ZEND_ASSIGN $y @10 @11
L38 0xb77b849c ZEND_EXT_STMT <unused> <unused> <unused>
L38 0xb77b84b8 ZEND_FETCH_DIM_R $arr $x @12
L38 0xb77b84d4 ZEND_FETCH_DIM_R $arr $y @13
L38 0xb77b84f0 ZEND_IS_SMALLER @12 @13 @14
L38 0xb77b850c ZEND_JMPZ @14 J85 <unused>
L39 0xb77b8528 ZEND_EXT_STMT <unused> <unused> <unused>
L39 0xb77b8544 ZEND_ASSIGN $z $len @15
L40 0xb77b8560 ZEND_EXT_STMT <unused> <unused> <unused>
L40 0xb77b857c ZEND_FETCH_DIM_R $arr $x @16
L40 0xb77b8598 ZEND_FETCH_DIM_R $arr $z @17
L40 0xb77b85b4 ZEND_IS_SMALLER @17 @16 @18
L40 0xb77b85d0 ZEND_JMPZ @18 J44 <unused>
L41 0xb77b85ec ZEND_EXT_STMT <unused> <unused> <unused>
L41 0xb77b8608 ZEND_POST_DEC $z <unused> @19
L41 0xb77b8624 ZEND_FREE @19 <unused> <unused>
L42 0xb77b8640 ZEND_JMP J36
L43 0xb77b865c ZEND_EXT_STMT <unused> <unused> <unused>
L43 0xb77b8678 ZEND_FETCH_DIM_R $arr $z @20
L43 0xb77b8694 ZEND_INIT_ARRAY @20 <unused> @21
L43 0xb77b86b0 ZEND_FETCH_DIM_R $arr $x @22
L43 0xb77b86cc ZEND_ADD_ARRAY_ELEMENT @22 <unused> @21
L43 0xb77b86e8 ZEND_FETCH_DIM_TMP_VAR @21 C4 @23
L43 0xb77b8704 ZEND_ASSIGN_DIM $arr $z @24
L43 0xb77b8720 UNKNOWN @23 @25 <unused>
L43 0xb77b873c ZEND_FETCH_DIM_TMP_VAR @21 C5 @26
L43 0xb77b8758 ZEND_ASSIGN_DIM $arr $x @27
L43 0xb77b8774 UNKNOWN @26 @28 <unused>
L43 0xb77b8790 ZEND_FREE @21 <unused> <unused>
L45 0xb77b87ac ZEND_EXT_STMT <unused> <unused> <unused>
L45 0xb77b87c8 ZEND_ASSIGN $i $len @29
L45 0xb77b87e4 ZEND_IS_SMALLER $y $i @30
L45 0xb77b8800 ZEND_EXT_STMT <unused> <unused> <unused>
L45 0xb77b881c ZEND_JMPZNZ @30 J79 or J66 <unused>
L45 0xb77b8838 ZEND_POST_DEC $i <unused> @31
L45 0xb77b8854 ZEND_FREE @31 <unused> <unused>
L45 0xb77b8870 ZEND_POST_INC $y <unused> @32
L45 0xb77b888c ZEND_FREE @32 <unused> <unused>
L45 0xb77b88a8 ZEND_JMP J58
L46 0xb77b88c4 ZEND_EXT_STMT <unused> <unused> <unused>
L46 0xb77b88e0 ZEND_FETCH_DIM_R $arr $y @33
L46 0xb77b88fc ZEND_INIT_ARRAY @33 <unused> @34
L46 0xb77b8918 ZEND_FETCH_DIM_R $arr $i @35
L46 0xb77b8934 ZEND_ADD_ARRAY_ELEMENT @35 <unused> @34
L46 0xb77b8950 ZEND_FETCH_DIM_TMP_VAR @34 C6 @36
L46 0xb77b896c ZEND_ASSIGN_DIM $arr $y @37
L46 0xb77b8988 UNKNOWN @36 @38 <unused>
L46 0xb77b89a4 ZEND_FETCH_DIM_TMP_VAR @34 C7 @39
L46 0xb77b89c0 ZEND_ASSIGN_DIM $arr $i @40
L46 0xb77b89dc UNKNOWN @39 @41 <unused>
L46 0xb77b89f8 ZEND_FREE @34 <unused> <unused>
L47 0xb77b8a14 ZEND_JMP J61
L48 0xb77b8a30 ZEND_EXT_STMT <unused> <unused> <unused>
L48 0xb77b8a4c ZEND_ASSIGN $x $len @42
L49 0xb77b8a68 ZEND_EXT_STMT <unused> <unused> <unused>
L49 0xb77b8a84 ZEND_ASSIGN_DIM $rs <unused> @43
L49 0xb77b8aa0 UNKNOWN $arr @44 <unused>
L50 0xb77b8abc ZEND_JMP J85
L52 0xb77b8ad8 ZEND_JMP J23
L53 0xb77b8af4 ZEND_EXT_STMT <unused> <unused> <unused>
L53 0xb77b8b10 ZEND_RETURN $rs <unused> <unused>
L54 0xb77b8b2c ZEND_EXT_STMT <unused> <unused> <unused>
L54 0xb77b8b48 ZEND_RETURN C8 <unused> <unused>
phpdbg>
加断点,开始调试
phpdbg> b test::testa
[Breakpoint #0 added at test::testa]
phpdbg> b test::testb
[Breakpoint #1 added at test::testb]
phpdbg> b 0xb77b6614
[Breakpoint #2 added at 0xb77b6614]
phpdbg> b 0xb77b6630
[Breakpoint #3 added at 0xb77b6630]
运行、查看代码
phpdbg> r
[Breakpoint #0 in test::testa() at /root/kk.php:7, hits: 1]
00006:
>00007: public function testa(){
00008:
00009: $a=1;
phpdbg> l test::testa
00007: public function testa(){
00008:
00009: $a=1;
00010: $b = &$a;
00011: return 0 + (++$a) + (++$a);
00012:
00013: }
00014:
phpdbg> p s
[Stack in test::testa()]
L7-13 test::testa() /root/kk.php
L7 0xb77b553c ZEND_EXT_NOP <unused> <unused> <unused>
L9 0xb77b5558 ZEND_EXT_STMT <unused> <unused> <unused>
L9 0xb77b5574 ZEND_ASSIGN $a C0 @0
L10 0xb77b5590 ZEND_EXT_STMT <unused> <unused> <unused>
L10 0xb77b55ac ZEND_ASSIGN_REF $b $a @1
L11 0xb77b55c8 ZEND_EXT_STMT <unused> <unused> <unused>
L11 0xb77b55e4 ZEND_PRE_INC $a <unused> @2
L11 0xb77b5600 ZEND_ADD C1 @2 @3
L11 0xb77b561c ZEND_PRE_INC $a <unused> @4
L11 0xb77b5638 ZEND_ADD @3 @4 @5
L11 0xb77b5654 ZEND_RETURN @5 <unused> <unused>
L13 0xb77b5670 ZEND_EXT_STMT <unused> <unused> <unused>
L13 0xb77b568c ZEND_RETURN C2 <unused> <unused>
继续执行
和gdb一样,phpdbg的继续执行命令也是continue,简写形式为c
查看断点
phpdbg> info b
------------------------------------------------
Method Breakpoints:
#0 test::testa
#1 test::testb
------------------------------------------------
Opline Breakpoints:
#2 0xb77b6614
#3 0xb77b6630
eval操作
可以执行任意的PHP代码
我们可以看到上面例子 testa 与 testb的区别
L7-13 test::testa() /root/kk.php
L11 0xb77b55e4 ZEND_PRE_INC $a <unused> @2
L11 0xb77b5600 ZEND_ADD C1 @2 @3
L11 0xb77b561c ZEND_PRE_INC $a <unused> @4
L11 0xb77b5638 ZEND_ADD @3 @4 @5
L15-21 test::testb() /root/kk.php
L19 0xb77b6614 ZEND_PRE_INC $a <unused> @2
L19 0xb77b6630 ZEND_PRE_INC $a <unused> @3
L19 0xb77b664c ZEND_ADD @2 @3 @4
区别在于这里 ZEND_PRE_INC 这一个opcode不同,这个opcode就是 ++$a
testb中当引用存在的时候, $a 先自增了两次,然后再加,所以结果为6,这里应该是PHP本身的问题
这个工具比vld丰富多了,PHP会越来越强大的
参考文章
https://github.com/krakjoe/phpdbg
http://phpdbg.com/docs/initializing
【php】使用phpdbg来调试php程序的更多相关文章
- 使用VS+VisualGDB编译调试Linux程序
Linux程序开发变得越来越多,越来越多的程序.产品需要跨平台,甚至有些开源项目只支持Linux平台,所以掌握Linux开发变得越来越重要. 但是对于习惯了Windows下的开发,使用了VS这个宇宙第 ...
- 使用未付费的账号真机调试 iOS 程序,过几天后程序一打开就会闪退
使用未付费的苹果开发者账号真机调试 iOS 程序,过几天后程序一打开就会闪退. 解决办法: 删除 Provisioning Profile,重新配置一次. 终极解决办法:花钱购买苹果开发者账号. ...
- Gdb调试多进程程序
Gdb调试多进程程序 程序经常使用fork/exec创建多进程程序.多进程程序有自己独立的地址空间,这是多进程调试首要注意的地方.Gdb功能强大,对调试多线程提供很多支持. 方法1:调试多进程最土的办 ...
- 利用 PhpStorm、Idea 等 IDE 如何 运行/调试 Go 程序 ?
以自己常用的 PhpStorm 为例 第一步:下载安装 Go插件 File -> Settings -> Plugins -> 输入关键字:Go 第二步:新建 Go项目 File - ...
- PDB调试Python程序
pdb是python内置的调试工具, 它可以在终端中调试Python程序, 这允许pdb在很多无法安装IDE的服务器上使用. 虽然远程调试使用广泛, 但在必要的时候(比如难以在本地搭建运行环境)pdb ...
- VS2010 win7 QT4.8.0,实现VS2010编译调试Qt程序,QtCreator静态发布程序
下载源代码,注意一定是源码压缩包如qt-everywhere-opensource-src-4.8.0.zip, 不是Qt发布的已编译的不同版本的标准库如qt-win-opensource-4.8.0 ...
- 【php】使用gdb调试php程序
1.简介 GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具.如果你是在 UNIX平台下做软件,你会发现GDB这个调试工具有比VC.BCB的图形化调试器更强大的功能.同时GDB也具有例如d ...
- 使用 GDB 调试多进程程序
使用 GDB 调试多进程程序 GDB 是 linux 系统上常用的调试工具,本文介绍了使用 GDB 调试多进程程序的几种方法,并对各种方法进行比较. 3 评论 田 强 (tianq@cn.ibm.co ...
- 使用webstorm调试node程序
前言 相信大家接触过不少node代码了,如果你应用的比较初级或者针对你的项目不需要接触过深的node代码,也许你仅仅需要简单的console.log('your variable')就完全满足你的需要 ...
随机推荐
- iOS 9.2新增API
CloudKit 新增CKFetchWebAuthTokenOperation类 CKFetchWebAuthTokenOperation对象从使用指定的cloudkit中的APIToken获取一个w ...
- Node.js爬虫抓取数据 -- HTML 实体编码处理办法
cheerio DOM化并解析的时候 1.假如使用了 .text()方法,则一般不会有html实体编码的问题出现 2.如果使用了 .html()方法,则很多情况下(多数是非英文的时候)都会出现,这时, ...
- js验证电话号码的正则表达式
在做程序时遇到js验证电话号码的问题,使用正则表达式来操作很简单的.一起来看一下吧. 1,这种是比较简单的验证号码: 电话号码只能包含”(“.“)”.“-”和数字 <input type=t ...
- WdatePicker.js的使用方法
WdatePicker.js的使用方法 摘自:http://www.cnblogs.com/wuchao/archive/2012/07/19/2599209.html 4. 日期范围限制 静态限制 ...
- 将C1Chart数据导出到Excel
大多数情况下,当我们说将图表导出到Excel时,意思是将Chart当成图片导出到Excel中.如果是这样,你可以参考帮助文档中保存和导出C1Chart章节. 不过,也有另一种情况,当你想把图表中的数据 ...
- MyEclipse+Mysql (二)
上一节介绍了如何在Myeclipse中连接mysql 这一节介绍如何在java程序中访问mysql数据库中的数据b并进行简单的操作 创建一个javaProject,并输入如下java代码: packa ...
- javascript实现排序算法
准备好好学习js了,js写的第一个排序 先推荐一个js在线编辑工具,RunJS,还不错. 冒泡排序 var arr = [2,4,1,5,3]; function handle(arr){ for(v ...
- ASP.NET Web API 路由
路由系统是请求消息进入ASP.NET Web API消息处理管道的第一道屏障,其根本目的是利用注册的路由表(RouteTable)对请求的URI进行解析以确定目标HttpController和Acti ...
- J2EE分布式架构及MySQL交流群
J2EE分布式架构及MySQL交流群:577913057
- 通过GPS数据反向地理信息编码, 得到当前位置信息
检查可用性 这属于基础知识, 不赘述, 总的来说,你的设备的支持要打开, 添加CoreLocation的framework, 引用头文件, 添加委托,然后, 好的实践是在使用前编程检查相关可用性: - ...