Nic Hubbard
Nic Hubbard

Reputation: 42173

Using valgrind to debug a PHP cli segmentation fault

I have a third-party PHP script that I am running in the cli and it is throwing a segmentation fault, which I am trying now to debug.

Just learned about the valgrind tool, but most of the guides I can find seem to be for PHP running in Apache, not the cli.

How can I use valgrind to debug my cli script and figure out what is causing this segmentation fault?

EDIT:

Using help from @sudowned it gave me the following, but not sure what it is telling me:

==32363== Invalid read of size 8
==32363==    at 0x6A459A: _zend_mm_alloc_canary_int (in /usr/bin/php5)
==32363==    by 0x6A4CFD: _zend_mm_realloc_canary_int (in /usr/bin/php5)
==32363==    by 0x690CC3: zend_hash_do_resize (in /usr/bin/php5)
==32363==    by 0x6925C7: _zend_hash_add_or_update (in /usr/bin/php5)
==32363==    by 0x68EA1F: add_assoc_zval_ex (in /usr/bin/php5)
==32363==    by 0x69729D: zif_get_defined_constants (in /usr/bin/php5)
==32363==    by 0xE393B63: ??? (in /usr/lib/php5/20090626/suhosin.so)
==32363==    by 0x6D4B15: zend_do_fcall_common_helper_SPEC (in /usr/bin/php5)
==32363==    by 0x6ABD8F: execute (in /usr/bin/php5)
==32363==    by 0xE394115: ??? (in /usr/lib/php5/20090626/suhosin.so)
==32363==    by 0x6D4805: zend_do_fcall_common_helper_SPEC (in /usr/bin/php5)
==32363==    by 0x6ABD8F: execute (in /usr/bin/php5)
==32363==  Address 0x1c486147 is not stack'd, malloc'd or (recently) free'd
==32363== 
==32363== 
==32363== Process terminating with default action of signal 11 (SIGSEGV)
==32363==  Access not within mapped region at address 0x1C486147
==32363==    at 0x6A459A: _zend_mm_alloc_canary_int (in /usr/bin/php5)
==32363==    by 0x6A4CFD: _zend_mm_realloc_canary_int (in /usr/bin/php5)
==32363==    by 0x690CC3: zend_hash_do_resize (in /usr/bin/php5)
==32363==    by 0x6925C7: _zend_hash_add_or_update (in /usr/bin/php5)
==32363==    by 0x68EA1F: add_assoc_zval_ex (in /usr/bin/php5)
==32363==    by 0x69729D: zif_get_defined_constants (in /usr/bin/php5)
==32363==    by 0xE393B63: ??? (in /usr/lib/php5/20090626/suhosin.so)
==32363==    by 0x6D4B15: zend_do_fcall_common_helper_SPEC (in /usr/bin/php5)
==32363==    by 0x6ABD8F: execute (in /usr/bin/php5)
==32363==    by 0xE394115: ??? (in /usr/lib/php5/20090626/suhosin.so)
==32363==    by 0x6D4805: zend_do_fcall_common_helper_SPEC (in /usr/bin/php5)
==32363==    by 0x6ABD8F: execute (in /usr/bin/php5)
==32363==  If you believe this happened as a result of a stack
==32363==  overflow in your program's main thread (unlikely but
==32363==  possible), you can try to increase the size of the
==32363==  main thread stack using the --main-stacksize= flag.
==32363==  The main thread stack size used in this run was 8388608.
==32363== 
==32363== HEAP SUMMARY:
==32363==     in use at exit: 180,903,362 bytes in 27,691 blocks
==32363==   total heap usage: 11,144,829 allocs, 11,117,138 frees, 2,198,841,176 bytes allocated
==32363== 
==32363== LEAK SUMMARY:
==32363==    definitely lost: 0 bytes in 0 blocks
==32363==    indirectly lost: 0 bytes in 0 blocks
==32363==      possibly lost: 0 bytes in 0 blocks
==32363==    still reachable: 180,903,362 bytes in 27,691 blocks
==32363==         suppressed: 0 bytes in 0 blocks
==32363== Reachable blocks (those to which a pointer was found) are not shown.
==32363== To see them, rerun with: --leak-check=full --show-reachable=yes
==32363== 
==32363== For counts of detected and suppressed errors, rerun with: -v
==32363== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 37 from 10)

Upvotes: 3

Views: 3032

Answers (1)

Winfield Trail
Winfield Trail

Reputation: 5695

You can, as laid out in the Valgrind quick-start guide, chain your PHP CLI command as follows:

valgrind --leak-check=yes php -f filename.php args

In order to glean useful information from the output, you may need to recompile PHP with debug symbols.:

./configure --enable-debug

Edit: In response to your comments, please keep in mind that when you are using Valgrind you are not debugging your PHP script: you are debugging the PHP interpreter, which is the underlying C executable.

This is not a task for the lighthearted.

Without a strong understanding of C (and debugging it) you are going to have a hard time gleaning useful information about the situation from a stack trace.

Valgrind has told you exactly what function in the interpreter caused the segmentation fault. The next step would be to isolate the variables passed to the function at the time of the segfault. From there deep knowledge of how PHP code maps to the underlying C will be necessary before you can even identify what PHP instruction caused it.

The simple answer is to start commenting out lines of PHP until your segfault ceases to occur, and then play with the guilty line until you determine what not to do. Low tech? Sure. Effective, equally sure. You could also use xdebug, discussed here, which could provide more targeted information about the interpreted code.

Upvotes: 4

Related Questions