1<?php $this->extends('layout.php', ['title' => 'Generating a gdb backtrace']) ?> 2 3<?php $this->start('content') ?> 4 5<p> 6<strong>Unix</strong> | <a href="/bugs-generating-backtrace-win32.php">Windows</a> 7</p> 8 9<h1>Generating a gdb backtrace</h1> 10 11<h3>Noticing PHP crashes</h3> 12 13There's no absolute way to know that PHP is crashing, but there may be signs. 14Typically, if you access a page that is always supposed to generate output (has 15a leading HTML block, for example), and suddenly get "Document contains no data" 16from your browser, it may mean that PHP crashes somewhere along the execution of 17the script. Another way to tell that PHP is crashing is by looking at the Apache 18error logs, and looking for SEGV (Apache 1.2) or Segmentation Fault (Apache 191.3). 20 21<h3>Important!</h3> 22To get a backtrace with correct information you must have 23a non stripped PHP binary! 24 25<h3>If you don't have a core file yet:</h3> 26 27<ul> 28 <li> 29 Remove any limits you may have on core dump size from your shell: 30 <ul> 31 <li>tcsh: unlimit coredumpsize</li> 32 <li>bash/sh: ulimit -c unlimited</li> 33 </ul> 34 </li> 35 <li> 36 Ensure that the directory in which you're running PHP, or the 37 PHP-enabled httpd, has write permissions for the user who's running PHP. 38 </li> 39 <li> 40 Cause PHP to crash: 41 <ul> 42 <li>PHP CGI: Simply run php with the script that crashes it</li> 43 <li>PHP Apache Module: Run httpd -X, and access the script that crashes PHP</li> 44 </ul> 45 </li> 46</ul> 47 48<h3>Generic way to get a core on Linux</h3> 49 50<ul> 51 <li> 52 Set up the core pattern (run this command as <i>root</i>): 53 <ul> 54 <li>echo "<cores dir>/core-%e.%p" > /proc/sys/kernel/core_pattern</li> 55 <li>make sure the directory is writable by PHP</li> 56 </ul> 57 </li> 58 <li>Set the ulimit (see above how to do it).</li> 59 <li>Restart/rerun PHP.</li> 60</ul> 61 62<p>After that any process crashing in your system, including PHP, will leave its 63core file in the directory you've specified in <i>core_pattern</i>.</p> 64 65<h3>Once you have the core file:</h3> 66 67<ul> 68 <li> 69 Run gdb with the path to the PHP or PHP-enabled httpd binary, and path 70 to the core file. Some examples: 71 <ul> 72 <li><code>gdb /usr/local/apache/sbin/httpd /usr/local/apache/sbin/core</code></li> 73 <li><code>gdb /home/user/dev/php-snaps/sapi/cli/php /home/user/dev/testing/core</code></li> 74 </ul> 75 </li> 76 <li> 77 At the gdb prompt, run: 78 <ul> 79 <li><code>(gdb) bt</code></li> 80 </ul> 81 </li> 82</ul> 83 84<h3>If you can't get a core file:</h3> 85<ul> 86 <li> 87 Run httpd -X under gdb with something like: 88 <ul> 89 <li><code>gdb /usr/local/apache/sbin/httpd</code></li> 90 <li>(gdb) run -X</li> 91 </ul> 92 </li> 93 <li> 94 Then use your web browser and access your server to force the crash. You 95 should see a gdb prompt appear and some message indicating that there 96 was a crash. At this gdb prompt, type: 97 <ul> 98 <li><code>(gdb) bt</code></li> 99 </ul> 100 <ul> 101 <li> 102 or, running from the commandline 103 <ul> 104 <li> 105 gdb /home/user/dev/php-snaps/sapi/cli/php 106 <ul> 107 <li><code>(gdb) run /path/to/script.php</code></li> 108 <li><code>(gdb) bt</code></li> 109 </ul> 110 </li> 111 </ul> 112 </li> 113 </ul> 114 </li> 115</ul> 116 117<p>This should generate a backtrace, that you should submit in the bug report, 118along with any other details you can give us about your setup, and offending 119script.</p> 120 121<h3>Locating which function call caused a segfault:</h3> 122 123<p>You can locate the function call that caused a segfault, easily, with gdb. 124First, you need a core file or to generate a segfault under gdb as described 125above.</p> 126 127<p>In PHP, each function is executed by an internal function called 128<b><code>execute()</code></b> and has its own stack. Each line generated by the 129<b><code>bt</code></b> command represents a function call stack. Typically, you 130will see several <b><code>execute()</code></b> lines when you issue 131<b><code>bt</code></b>. You are interested in the last 132<b><code>execute()</code></b> stack (i.e. smallest frame number). You can move 133the current working stack with the <b><code>up</code></b>, <code>down</code> or 134<b><code>frame</code></b> commands. Below is an example gdb session that can be 135used as a guideline on how to handle your segfault.</p> 136 137<ul> 138 <li>Sample gdb session</li> 139 <pre><code> 140(gdb) bt 141#0 0x080ca21b in _efree (ptr=0xbfffdb9b) at zend_alloc.c:240 142#1 0x080d691a in _zval_dtor (zvalue=0x8186b94) at zend_variables.c:44 143#2 0x080cfab3 in _zval_ptr_dtor (zval_ptr=0xbfffdbfc) at zend_execute_API.c:274 144#3 0x080f1cc4 in execute (op_array=0x816c670) at ./zend_execute.c:1605 145#4 0x080f1e06 in execute (op_array=0x816c530) at ./zend_execute.c:1638 146#5 0x080f1e06 in execute (op_array=0x816c278) at ./zend_execute.c:1638 147#6 0x080f1e06 in execute (op_array=0x8166eec) at ./zend_execute.c:1638 148#7 0x080d7b93 in zend_execute_scripts (type=8, retval=0x0, file_count=3) at zend.c:810 149#8 0x0805ea75 in php_execute_script (primary_file=0xbffff650) at main.c:1310 150#9 0x0805cdb3 in main (argc=2, argv=0xbffff6fc) at cgi_main.c:753 151#10 0x400c91be in __libc_start_main (main=0x805c580 <main>, argc=2, ubp_av=0xbffff6fc, 152 init=0x805b080 <_init>, fini=0x80f67b4 <_fini>, rtld_fini=0x4000ddd0 <_dl_fini>, 153 stack_end=0xbffff6ec) at ../sysdeps/generic/libc-start.c:129 154(gdb) frame 3 155#3 0x080f1cc4 in execute (op_array=0x816c670) at ./zend_execute.c:1605 156(gdb) print (char *)(executor_globals.function_state_ptr->function)->common.function_name 157$14 = 0x80fa6fa "pg_result_error" 158(gdb) print (char *)executor_globals.active_op_array->function_name 159$15 = 0x816cfc4 "result_error" 160(gdb) print (char *)executor_globals.active_op_array->filename 161$16 = 0x816afbc "/home/yohgaki/php/DEV/segfault.php" 162(gdb) 163 </code></pre> 164</ul> 165 166<p>In this session, frame 3 is the last <b><code>execute()</code></b> call. The 167<b><code>frame 3</code></b> command moves the current working stack to the 168proper frame.<br> 169<b><code>print (char *)(executor_globals.function_state_ptr->function)->common.function_name</code></b><br> 170prints the function name. In the sample gdb session, the 171<code>pg_result_error()</code> call is causing the segfault. You can print any 172internal data that you like, if you know the internal data structure. Please do 173not ask how to use gdb or about the internal data structure. Refer to gdb manual 174for gdb usage and to the PHP source for the internal data structure.</p> 175 176<p>You may not see <b><code>execute</code></b> if the segfault happens without 177calling any functions.</p> 178 179<?php $this->end('content') ?> 180