【php】使用gdb调试php程序
1、簡介
GDB是GNU開源組織發布的一個強大的UNIX下的程序調試工具。如果你是在 UNIX平臺下做軟件,你會發現GDB這個調試工具有比VC、BCB的圖形化調試器更強大的功能。同時GDB也具有例如ddd這樣的圖形化的調試端
2、調試C/C++程序
直接上代碼了
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #include<iostream> using?namespace?std; long?factorial(int?n); ?? int?main() { ????int?n(0); ????cin>>n; ????long?val=factorial(n); ????cout<<val<<endl; ????cin.get(); ????return?0; } ?? long?factorial(int?n) { ????long?result(1); ????while(n--) ????{?? ????????result*=n; ????}?? ????return?result; } |
編譯
| 1 | g++ k.cpp -g -Wall -Werror -o main |
開始調試
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | [root@localhost code]# gdb ./main GNU gdb (GDB) Red Hat Enterprise Linux (7.2-83.el6) Copyright (C) 2010 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is?free?software: you are?free?to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.? Type?"show copying" and?"show warranty"?for?details. This GDB was configured as?"i686-redhat-linux-gnu". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>... Reading symbols from /code/main...done. (gdb) l warning: Source file is more recent than executable. 1?????? #include<iostream> 2???????using?namespace?std; 3???????long?factorial(int?n); 4 5???????int?main() 6?????? { 7???????????int?n(0); 8?????????? cin>>n; 9???????????long?val=factorial(n); 10????????? cout<<val<<endl; (gdb) |
設置斷點 break linenumber
| 1 2 3 4 5 6 7 8 | (gdb) b 9 Breakpoint 1 at 0x80486f9: file k.cpp, line 9. (gdb) r Starting program: /code/main 4 ? Breakpoint 1, main () at k.cpp:9 9???????????long?val=factorial(n); |
設置觀察點 watch var
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | (gdb) s factorial (n=4) at k.cpp:17 17??????????long?result(1); (gdb) l 12??????????return?0; 13????? } 14 15??????long?factorial(int?n) 16????? { 17??????????long?result(1); 18??????????while(n--) 19????????? { 20????????????? result*=n; 21????????? } (gdb) watch n Hardware watchpoint 2: n (gdb) watch result Hardware watchpoint 3: result (gdb) c Continuing. Hardware watchpoint 3: result ? Old value = 0 New value = 1 factorial (n=4) at k.cpp:18 18??????????while(n--) (gdb) Continuing. Hardware watchpoint 2: n ? Old value = 4 New value = 3 0x08048764 in factorial (n=3) at k.cpp:18 18??????????while(n--) (gdb) Continuing. Hardware watchpoint 3: result ? Old value = 1 New value = 3 factorial (n=3) at k.cpp:18 18??????????while(n--) (gdb) Continuing. Hardware watchpoint 2: n ? Old value = 3 New value = 2 0x08048764 in factorial (n=2) at k.cpp:18 18??????????while(n--) (gdb) Continuing. Hardware watchpoint 3: result ? Old value = 3 New value = 6 factorial (n=2) at k.cpp:18 18??????????while(n--) (gdb) Continuing. Hardware watchpoint 2: n ? Old value = 2 New value = 1 0x08048764 in factorial (n=1) at k.cpp:18 18??????????while(n--) (gdb) Continuing. Hardware watchpoint 2: n ? Old value = 1 New value = 0 0x08048764 in factorial (n=0) at k.cpp:18 18??????????while(n--) (gdb) Continuing. ? Watchpoint 2 deleted because the program has left the block in which its expression is valid. ? Watchpoint 3 deleted because the program has left the block in which its expression is valid. 0x08048705 in main () at k.cpp:9 9???????????long?val=factorial(n); (gdb) p val $1 = 11476980 (gdb) |
可以看到是while那里,導致n越界了,fix
| 1 2 3 4 5 | while(n>0)?//doesn't let n reach 0 { ??result*=n; ??n--;????????//decrements only after the evaluation } |
一些快捷命令
| 1 2 3 4 5 6 7 8 9 | l – list p – print print {variable} c –?continue s – step b -?break??break?line_number/break?[file_name]:line_number/break?[file_name]:func_name r - run set <var> = <value> watch <var> ENTER: pressing enter key would execute the previously executed command again. |
c/n/s的區別
- c or continue: Debugger will continue executing until the next break point.
- n or next: Debugger will execute the next line as single instruction.
- s or step: Same as next, but does not treats function as a single instruction, instead goes into the function and executes it line by line
3、調試PHP程序
PHP代碼
| 1 2 3 4 5 6 7 8 9 10 | <?php.?? for($i = 0; $i < 10; $i++){ ????echo $i."\n"; ????sleep(3); ????if(in_array($i,[1,9,20])){ ????????print_r($i*$i); ????????var_dump($i*$i);????????????????????????????????????????????????????????????????????????????????????????????????????????????? ????????print $i*$i; ????}?????? } |
開始調試,加上斷點
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | [root@localhost code]# gdb php??? GNU gdb (GDB) Red Hat Enterprise Linux (7.2-83.el6) Copyright (C) 2010 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is?free?software: you are?free?to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.? Type?"show copying" and?"show warranty"?for?details. This GDB was configured as?"i686-redhat-linux-gnu". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>... Reading symbols from /usr/bin/php...done. (gdb) b zif_sleep Breakpoint 1 at 0x8435180: file /usr/local/src/php-5.5.23/ext/standard/basic_functions.c, line 4449. (gdb) b zif_in_array Breakpoint 2 at 0x8426923: file /usr/local/src/php-5.5.23/ext/standard/array.c, line 1215. (gdb) b zif_print_r Breakpoint 3 at 0x8438273: file /usr/local/src/php-5.5.23/ext/standard/basic_functions.c, line 5553. (gdb) b zif_var_dump Breakpoint 4 at 0x847d296: file /usr/local/src/php-5.5.23/ext/standard/var.c, line 178. (gdb) b zif_printf Function?"zif_printf"?not defined. Make breakpoint pending on future shared library load? (y or [n]) n (gdb) b zif_sprintf Function?"zif_sprintf"?not defined. Make breakpoint pending on future shared library load? (y or [n]) n (gdb) b?printf Breakpoint 5 at 0x806a390 (gdb) b?memcpy Breakpoint 6 at 0x8069390 (gdb) b zif_print Function?"zif_print"?not defined. Make breakpoint pending on future shared library load? (y or [n]) n (gdb) b zif_echo Function?"zif_echo"?not defined. Make breakpoint pending on future shared library load? (y or [n]) n (gdb) info b Num???? Type?????????? Disp Enb Address??? What 1?????? breakpoint???? keep y?? 0x08435180 in zif_sleep at /usr/local/src/php-5.5.23/ext/standard/basic_functions.c:4449 2?????? breakpoint???? keep y?? 0x08426923 in zif_in_array at /usr/local/src/php-5.5.23/ext/standard/array.c:1215 3?????? breakpoint???? keep y?? 0x08438273 in zif_print_r at /usr/local/src/php-5.5.23/ext/standard/basic_functions.c:5553 4?????? breakpoint???? keep y?? 0x0847d296 in zif_var_dump at /usr/local/src/php-5.5.23/ext/standard/var.c:178 5?????? breakpoint???? keep y?? 0x0806a390 <printf@plt> 6?????? breakpoint???? keep y?? 0x08069390 <memcpy@plt> (gdb) |
加幾個斷點測試一下 syntax:break [file_name]:func_name,這里大致可以看一下 echo print等不是函數了
然后開始調試
| 1 2 3 4 5 6 7 8 9 | (gdb) run kk.php ( or set args ./kk.php && r) Starting program: /usr/bin/php kk.php [Thread debugging?using?libthread_db enabled] 0 ? Breakpoint 3, zif_sleep (ht=1, return_value=0xb7fbd6f0, return_value_ptr=0x0, this_ptr=0x0, return_value_used=0) ????at /usr/local/src/php-5.5.23/ext/standard/basic_functions.c:4449 4449????????????if?(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,?"l", &num) == FAILURE) { (gdb) |
這里我們可以看一下zif_sleep 函數 return_value 返回的是什么
| 1 2 3 4 5 6 7 8 | (gdb) p *return_value $1 = {value = {lval = 1515870810, dval = 1.7838867517321418e+127, str = {val = 0x5a5a5a5a <Address 0x5a5a5a5a out of bounds>, ??????len = 1515870810}, ht = 0x5a5a5a5a, obj = {handle = 1515870810, handlers = 0x5a5a5a5a}}, refcount__gc = 1, type = 0?'\000', is_ref__gc = 0?'\000'} (gdb) p return_value->value $2 = {lval = 1515870810, dval = 1.7838867517321418e+127, str = {val = 0x5a5a5a5a <Address 0x5a5a5a5a out of bounds>, ????len = 1515870810}, ht = 0x5a5a5a5a, obj = {handle = 1515870810, handlers = 0x5a5a5a5a}} (gdb) p return_value->value->lval $3 = 1515870810 |
我們還可以使用內置的gdbinit來調試
| 1 2 3 | (gdb) source /usr/local/src/php-5.5.23/.gdbinit (gdb) zbacktrace [0xb7fa1144] sleep(3) /code/kk.php:4 |
查看當前堆棧,PHP內核的執行過程
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | (gdb) bt #0? zif_sleep (ht=1, return_value=0xb7fbd6f0, return_value_ptr=0x0, this_ptr=0x0, return_value_used=0) ????at /usr/local/src/php-5.5.23/ext/standard/basic_functions.c:4449 #1? 0x085f6870 in execute_internal (execute_data_ptr=0xb7fa1144, fci=0x0, return_value_used=0) ????at /usr/local/src/php-5.5.23/Zend/zend_execute.c:1484 #2? 0x085aea5f in dtrace_execute_internal (execute_data_ptr=0xb7fa1144, fci=0x0, return_value_used=0) ????at /usr/local/src/php-5.5.23/Zend/zend_dtrace.c:97 #3? 0x00935c33 in pt_execute_core (internal=1, execute_data=0xb7fa1144, fci=0x0, rvu=0) ????at /usr/local/src/trace-0.3.0/extension/trace.c:941 #4? 0x00935e49 in pt_execute_internal (execute_data=0xb7fa1144, fci=0x0, return_value_used=0) ????at /usr/local/src/trace-0.3.0/extension/trace.c:1005 #5? 0x085f7523 in zend_do_fcall_common_helper_SPEC (execute_data=0xb7fa1144) at /usr/local/src/php-5.5.23/Zend/zend_vm_execute.h:552 #6? 0x085fb2a9 in ZEND_DO_FCALL_SPEC_CONST_HANDLER (execute_data=0xb7fa1144) at /usr/local/src/php-5.5.23/Zend/zend_vm_execute.h:2332 #7? 0x085f6deb in execute_ex (execute_data=0xb7fa1144) at /usr/local/src/php-5.5.23/Zend/zend_vm_execute.h:363 #8? 0x085ae9dc in dtrace_execute_ex (execute_data=0xb7fa1144) at /usr/local/src/php-5.5.23/Zend/zend_dtrace.c:73 #9? 0x00935c5e in pt_execute_core (internal=0, execute_data=0xb7fa1144, fci=0x0, rvu=0) ????at /usr/local/src/trace-0.3.0/extension/trace.c:946 #10 0x00935e10 in pt_execute_ex (execute_data=0xb7fa1144) at /usr/local/src/trace-0.3.0/extension/trace.c:1000 #11 0x085f6e4a in zend_execute (op_array=0xb7fbc7b4) at /usr/local/src/php-5.5.23/Zend/zend_vm_execute.h:388 #12 0x085c1cf2 in zend_execute_scripts (type=8, retval=0x0, file_count=3) at /usr/local/src/php-5.5.23/Zend/zend.c:1327 #13 0x085470f9 in php_execute_script (primary_file=0xbffff4a4) at /usr/local/src/php-5.5.23/main/main.c:2525 #14 0x0865af46 in do_cli (argc=2, argv=0x8b9b908) at /usr/local/src/php-5.5.23/sapi/cli/php_cli.c:994 #15 0x0865bff3 in main (argc=2, argv=0x8b9b908) at /usr/local/src/php-5.5.23/sapi/cli/php_cli.c:1378 |
查看代碼段
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | (gdb) l 4444?????? Delay?for?a given number of seconds */ 4445??? PHP_FUNCTION(sleep) 4446??? { 4447????????????long?num; 4448 4449????????????if?(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,?"l", &num) == FAILURE) { 4450??????????????????? RETURN_FALSE; 4451??????????? } 4452????????????if?(num < 0) { 4453??????????????????? php_error_docref(NULL TSRMLS_CC, E_WARNING,?"Number of seconds must be greater than or equal to 0"); (gdb) l 4450 4445??? PHP_FUNCTION(sleep) 4446??? { 4447????????????long?num; 4448 4449????????????if?(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,?"l", &num) == FAILURE) { 4450??????????????????? RETURN_FALSE; 4451??????????? } 4452????????????if?(num < 0) { 4453??????????????????? php_error_docref(NULL TSRMLS_CC, E_WARNING,?"Number of seconds must be greater than or equal to 0"); 4454??????????????????? RETURN_FALSE; (gdb) l zif_usleep 4463????/* }}} */ 4464 4465????/* {{{ proto void usleep(int micro_seconds) 4466?????? Delay for a given number of micro seconds */ 4467??? PHP_FUNCTION(usleep) 4468??? { 4469??? #if?HAVE_USLEEP 4470????????????long?num; 4471 4472????????????if?(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,?"l", &num) == FAILURE) { |
繼續執行
| 1 2 3 4 5 6 7 8 9 10 11 | (gdb) n 4452????????????if?(num < 0) { (gdb) p num $6 = 3 (gdb) n 4457??????????? RETURN_LONG(php_sleep(num)); (gdb) n 4462??? } (gdb) n execute_internal (execute_data_ptr=0xb7fa1144, fci=0x0, return_value_used=0) at /usr/local/src/php-5.5.23/Zend/zend_execute.c:1488 1488??? } |
到了execute_internal ,可以查看一下當前函數的一個狀態
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | (gdb) p execute_data_ptr $7 = (zend_execute_data *) 0xb7fa1144 (gdb) p *execute_data_ptr $8 = {opline = 0xb7fbcacc, function_state = {function = 0x8bcf3e8, arguments = 0xb7fa119c}, op_array = 0xb7fbc7b4, object = 0x0, ??symbol_table = 0x8b99cdc, prev_execute_data = 0x0, old_error_reporting = 0x0, nested = 0?'\000', ??original_return_value = 0x38b4ac9, current_scope = 0x49, current_called_scope = 0x45, current_this = 0x0, fast_ret = 0x0, ??call_slots = 0xb7fa1188, call = 0xb7fa1188} (gdb) p *execute_data_ptr->function_state.function->common->function_name $9 = 115?'s' (gdb) p execute_data_ptr->function_state.function->common->function_name $10 = 0x8af03c9?"sleep" (gdb) p execute_data_ptr->op_array->filename $11 = 0xb7fbc8e8?"/code/kk.php" |
查看當前hashtable
| 1 2 3 4 | (gdb) p *execute_data_ptr->symbol_table $16 = {nTableSize = 64, nTableMask = 63, nNumOfElements = 8, nNextFreeElement = 0, pInternalPointer = 0xb7fb924c, ??pListHead = 0xb7fb924c, pListTail = 0xb7fbd228, arBuckets = 0xb7fb9120, pDestructor = 0x85bf06f <_zval_ptr_dtor_wrapper>, ??persistent = 0?'\000', nApplyCount = 0?'\000', bApplyProtection = 1?'\001', inconsistent = 0} |
繼續執行輸出c之后,回車即可,同樣可以看到in_array的執行信息
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | (gdb) p *execute_data_ptr->function_state.function $24 = {type = 1?'\001', common = {type = 1?'\001', function_name = 0x8af1841?"in_array", scope = 0x0, fn_flags = 256, ????prototype = 0x0, num_args = 3, required_num_args = 2, arg_info = 0x8ae7554}, op_array = {type = 1?'\001', ????function_name = 0x8af1841?"in_array", scope = 0x0, fn_flags = 256, prototype = 0x0, num_args = 3, required_num_args = 2, ????arg_info = 0x8ae7554, refcount = 0x842691d, opcodes = 0x8bcf120, last = 0, vars = 0x0, last_var = 0, T = 1, ????nested_calls = 3086618796, used_stack = 0, brk_cont_array = 0x0, last_brk_cont = 1, try_catch_array = 0xb7fa10dd, ????last_try_catch = 96, has_finally_block = 160?'\240', static_variables = 0x0, this_var = 11482064, ????filename = 0xaf1ff4?"|\035\257", line_start = 11482016, line_end = 146381272, ????doc_comment = 0xbffff238?"x\362\377\277\244\aY\b\021", doc_comment_len = 10305959, early_binding = 11085989, ????literals = 0x8b7a0a0, last_literal = 140062666, run_time_cache = 0xb7fa10d4, last_cache_slot = 90, reserved = {0x9, 0x8b5f7ac, ??????0x796, 0x0}}, internal_function = {type = 1?'\001', function_name = 0x8af1841?"in_array", scope = 0x0, fn_flags = 256, ????prototype = 0x0, num_args = 3, required_num_args = 2, arg_info = 0x8ae7554, handler = 0x842691d <zif_in_array>, ????module = 0x8bcf120}} (gdb) p execute_data_ptr->function_state.function->common->function_name $26 = 0x8af1841?"in_array" (gdb) p execute_data_ptr->op_array->filename?????????????????????? $27 = 0xb7fbc8e8?"/code/kk.php" |
還可以加一下監控watch、設置一些調試變量set 等等
其他的調試工具還有?strace 查看系統調用、ltrace 查看類庫的調用、vld查看opcode
?
參考文章
http://www.cprogramming.com/gcc.html
http://www.thegeekstuff.com/2010/03/debug-c-program-using-gdb/
http://www.cprogramming.com/gdb.html
http://www.laruence.com/2011/06/23/2057.html
http://derickrethans.nl/what-is-php-doing.html
來源:https://www.cnblogs.com/chenpingzhao/p/5027984.html
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的【php】使用gdb调试php程序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 为什么你应该学习Go语言?
- 下一篇: 网商贷贷款额度是多少