Flanders

Advanced debugging techniques for PHP

Debugging what?

  • PHP code execution: what happens internally in your application? (PHP specific tools)
  • How is your code interacting with the external world (I/O)? (Language agnostic tools)

Before we start...

One of the most powerful debugging technique is...

Rubber duck debugging!

  1. You have an issue!
  2. Decide to bring it on Stack Overflow
  3. Write down your question
  4. Realize that it doesn't make any sense
  5. Rethink how to ask it with enough information
  6. Realize that you are attacking the problem from a wrong perspective
  7. Start again from scratch and find your solution
Bat-duck
Giant duck
Real duck
Killed duck
Cooked duck
Iron duck

Ducks cannot solve everything (yet)

Debugging PHP

Quick and dirty

Do I enter that code?

die();

But why does it fail? What's in my $var?

var_dump($var);
die();

Xdebug

By far, the most used PHP debugger, by Derick Rethans.

PHPdbg

The newcomer, a super powerful and native PHP debugger, included by default as of PHP 5.6.

PHPdbg

function greetings() {
    $hello = "Hello ";
    $world = 'world';
    return "$hello$world";
}

echo greetings();

PHPdbg

$ phpdbg test.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>]
[Successful compilation of test.php]
prompt> 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
  next     continue execution up to the given location and halt on the first line after it
  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

prompt> list f greetings
 00003:     $hello = "Hello ";
 00004:     $world = 'world';
 00005:     return "$hello$world";
prompt> print f greetings
[User Function greetings (6 ops)]
L2-6 greetings() test.php - 0x7f498beb5300 + 6 ops
L3    #0     ASSIGN           $hello      "Hello "    @0
L4    #1     ASSIGN           $world      "world"     @1
L5    #2     NOP
L5    #3     FAST_CONCAT      $hello      $world      @2
L5    #4     RETURN           @2
L5    #5     RETURN           null
prompt> break 3
[Breakpoint #0 added at test.php:3]
prompt> break greetings#3
[Breakpoint #1 added at greetings#3]
prompt> run
[Breakpoint #0 at test.php:3, hits: 1]
>00003:     $hello = "Hello ";
 00004:     $world = 'world';
 00005:     return "$hello$world";
prompt> step
[L4      0x7f1cf3ba1880 ZEND_ASSIGN    $world   C1   @0     test.php]
 00003:     $hello = "Hello ";
>00004:     $world = 'world';
 00005:     return "$hello$world";
prompt> continue
[Breakpoint #1 at greetings#3, hits: 1]
 00003:     $hello = "Hello ";
 00004:     $world = 'world';
>00005:     return "$hello$world";
prompt> ev $hello
Hello

phptrace

Low overhead tracing tool composed of a PHP extension and a command line tool.

$ php -r 'for ($i = 0; $i < 100; $i++) usleep(10000);' &
$ ./phptrace -p $!
1431763911.194806      usleep(10000) at [Command line code:1]
1431763911.204932      usleep  =>  NULL   wt: 0.010126 ct: 0.000000
1431763911.204950      usleep(10000) at [Command line code:1]
1431763911.215045      usleep  =>  NULL   wt: 0.010095 ct: 0.000000
1431763911.215056      usleep(10000) at [Command line code:1]
1431763911.225177      usleep  =>  NULL   wt: 0.010121 ct: 0.000000
1431763911.225192      usleep(10000) at [Command line code:1]
$ ./phptrace status -p 3600
Memory
usage: 235320
peak_usage: 244072
real_usage: 262144
real_peak_usage: 262144

Request
request_script: sample.php
request_time: 1431682554.245320

Stack
#1    printf("hello world") at [sample.php:8]
#2    say("hello world") at [sample.php:3]
#3    run() at [sample.php:12]
https://pecl.php.net/package/trace

System debugging

strace

  • Trace any system calls done by a program.
$ strace <program to run>
$ strace -p <pid> [-f]
  • Use -e <category> to filter the type of syscall to catch.
  • Use -c for a summary of the system calls performed.

ltrace

  • Trace any library calls done by a program.
  • Watch out, this might be VERY verbose!
$ ltrace <program to run>
$ ltrace -p <pid> [-f]
  • Use -l <library_pattern> -l <library_pattern> to filter on a specific library.
  • Hint: use ldd to figure out the external libraries of a binary executable.

Inotify

Native Linux FS notification mechanism.

  • inotifywait: wait for changes to files using inotify
  • inotifywatch: gather filesystem access statistics using inotify

MySQL Proxy

  • Sits between a client and a server and let's you do what you want thanks to lua scripting.
  • Examples:
    • Printing:
      • all queries
      • the ones not using an index
      • the slow ones
    • Graphing the most frequent queries / used tables
    • Simulate a heavy loaded (read: “slow”) DB
  • https://github.com/patrickallaert/MySQL-Proxy-scripts-for-devs

Nethogs

  • "top"-like tool grouping bandwidth per process

Wireshark

  • Catches network traffic and analyze it
  • Hundreds of protocols

Questions?

Thanks

Don't forget to rate this talk on https://joind.in/talk/d1ac3

Stay in touch!

@patrick_allaert

patrickallaert@php.net