u* tools: PHP support

Introduce PHP support to ucalls, uflow, and ustat. The PHP probes
used are for function entry and exit, file compile (~ class load),
and exception throw. This requires a PHP runtime built with the
`--enable-dtrace` configure switch. Some probes also require
USE_ZEND_DTRACE=1.

Resolves #945.
diff --git a/tools/ucalls.py b/tools/ucalls.py
index ed476cd..90b2d47 100755
--- a/tools/ucalls.py
+++ b/tools/ucalls.py
@@ -4,7 +4,7 @@
 # ucalls  Summarize method calls in high-level languages and/or system calls.
 #         For Linux, uses BCC, eBPF.
 #
-# USAGE: ucalls [-l {java,python,ruby}] [-h] [-T TOP] [-L] [-S] [-v] [-m]
+# USAGE: ucalls [-l {java,python,ruby,php}] [-h] [-T TOP] [-L] [-S] [-v] [-m]
 #        pid [interval]
 #
 # Copyright 2016 Sasha Goldshtein
@@ -24,7 +24,7 @@
     ./ucalls 6712 -S            # trace only syscall counts
     ./ucalls -l ruby 1344 -T 10 # trace top 10 Ruby method calls
     ./ucalls -l ruby 1344 -L    # trace Ruby calls including latency
-    ./ucalls -l ruby 1344 -LS   # trace Ruby calls and syscalls with latency
+    ./ucalls -l php 443 -LS     # trace PHP calls and syscalls with latency
     ./ucalls -l python 2020 -mL # trace Python calls including latency in ms
 """
 parser = argparse.ArgumentParser(
@@ -34,7 +34,8 @@
 parser.add_argument("pid", type=int, help="process id to attach to")
 parser.add_argument("interval", type=int, nargs='?',
     help="print every specified number of seconds")
-parser.add_argument("-l", "--language", choices=["java", "python", "ruby"],
+parser.add_argument("-l", "--language",
+    choices=["java", "python", "ruby", "php"],
     help="language to trace (if none, trace syscalls only)")
 parser.add_argument("-T", "--top", type=int,
     help="number of most frequent/slow calls to print")
@@ -49,8 +50,8 @@
 args = parser.parse_args()
 
 # We assume that the entry and return probes have the same arguments. This is
-# the case for Java, Python, and Ruby. If there's a language where it's not the
-# case, we will need to build a custom correlator from entry to exit.
+# the case for Java, Python, Ruby, and PHP. If there's a language where it's
+# not the case, we will need to build a custom correlator from entry to exit.
 if args.language == "java":
     # TODO for JVM entries, we actually have the real length of the class
     #      and method strings in arg3 and arg5 respectively, so we can insert
@@ -70,6 +71,11 @@
     return_probe = "method__return"
     read_class = "bpf_usdt_readarg(1, ctx, &clazz);"
     read_method = "bpf_usdt_readarg(2, ctx, &method);"
+elif args.language == "php":
+    entry_probe = "function__entry"
+    return_probe = "function__return"
+    read_class = "bpf_usdt_readarg(4, ctx, &clazz);"
+    read_method = "bpf_usdt_readarg(1, ctx, &method);"
 elif not args.language:
     if not args.syscalls:
         print("Nothing to do; use -S to trace syscalls.")
diff --git a/tools/ucalls_example.txt b/tools/ucalls_example.txt
index 7410f88..75d35cd 100644
--- a/tools/ucalls_example.txt
+++ b/tools/ucalls_example.txt
@@ -2,7 +2,7 @@
 
 
 ucalls summarizes method calls in various high-level languages, including Java,
-Python, Ruby, and Linux system calls. It displays statistics on the most 
+Python, Ruby, PHP, and Linux system calls. It displays statistics on the most 
 frequently called methods, as well as the latency (duration) of these methods.
 
 Through the syscalls support, ucalls can provide basic information on a 
@@ -60,7 +60,7 @@
 USAGE message:
 
 # ./ucalls.py -h
-usage: ucalls.py [-h] [-l {java,python,ruby}] [-T TOP] [-L] [-S] [-v] [-m]
+usage: ucalls.py [-h] [-l {java,python,ruby,php}] [-T TOP] [-L] [-S] [-v] [-m]
                  pid [interval]
 
 Summarize method calls in high-level languages.
@@ -71,7 +71,7 @@
 
 optional arguments:
   -h, --help            show this help message and exit
-  -l {java,python,ruby}, --language {java,python,ruby}
+  -l {java,python,ruby,php}, --language {java,python,ruby,php}
                         language to trace (if none, trace syscalls only)
   -T TOP, --top TOP     number of most frequent/slow calls to print
   -L, --latency         record method latency from enter to exit (except
@@ -88,5 +88,5 @@
     ./ucalls 6712 -S            # trace only syscall counts
     ./ucalls -l ruby 1344 -T 10 # trace top 10 Ruby method calls
     ./ucalls -l ruby 1344 -L    # trace Ruby calls including latency
-    ./ucalls -l ruby 1344 -LS   # trace Ruby calls and syscalls with latency
+    ./ucalls -l php 443 -LS     # trace PHP calls and syscalls with latency
     ./ucalls -l python 2020 -mL # trace Python calls including latency in ms
diff --git a/tools/uflow.py b/tools/uflow.py
index 6bf8b53..361f220 100755
--- a/tools/uflow.py
+++ b/tools/uflow.py
@@ -4,7 +4,7 @@
 # uflow  Trace method execution flow in high-level languages.
 #        For Linux, uses BCC, eBPF.
 #
-# USAGE: uflow [-C CLASS] [-M METHOD] [-v] {java,python,ruby} pid
+# USAGE: uflow [-C CLASS] [-M METHOD] [-v] {java,python,ruby,php} pid
 #
 # Copyright 2016 Sasha Goldshtein
 # Licensed under the Apache License, Version 2.0 (the "License")
@@ -27,7 +27,7 @@
     description="Trace method execution flow in high-level languages.",
     formatter_class=argparse.RawDescriptionHelpFormatter,
     epilog=examples)
-parser.add_argument("language", choices=["java", "python", "ruby"],
+parser.add_argument("language", choices=["java", "python", "ruby", "php"],
     help="language to trace")
 parser.add_argument("pid", type=int, help="process id to attach to")
 parser.add_argument("-M", "--method",
@@ -140,6 +140,13 @@
     enable_probe("cmethod__return", "ruby_creturn",
                  "bpf_usdt_readarg(1, ctx, &clazz);",
                  "bpf_usdt_readarg(2, ctx, &method);", is_return=True)
+elif args.language == "php":
+    enable_probe("function__entry", "php_entry",
+                 "bpf_usdt_readarg(4, ctx, &clazz);",
+                 "bpf_usdt_readarg(1, ctx, &method);", is_return=False)
+    enable_probe("function__return", "php_return",
+                 "bpf_usdt_readarg(4, ctx, &clazz);",
+                 "bpf_usdt_readarg(1, ctx, &method);", is_return=True)
 
 if args.verbose:
     print(usdt.get_text())
diff --git a/tools/uflow_example.txt b/tools/uflow_example.txt
index 34dd533..b2bb519 100644
--- a/tools/uflow_example.txt
+++ b/tools/uflow_example.txt
@@ -4,8 +4,8 @@
 uflow traces method entry and exit events and prints a visual flow graph that
 shows how methods are entered and exited, similar to a tracing debugger with
 breakpoints. This can be useful for understanding program flow in high-level
-languages such as Java, Python, and Ruby, which provide USDT probes for method
-invocations.
+languages such as Java, Python, Ruby, and PHP, which provide USDT probes for
+method invocations.
 
 
 For example, trace all Ruby method calls in a specific process:
@@ -88,12 +88,13 @@
 USAGE message:
 
 # ./uflow -h
-usage: uflow.py [-h] [-M METHOD] [-C CLAZZ] [-v] {java,python,ruby} pid
+usage: uflow.py [-h] [-M METHOD] [-C CLAZZ] [-v] {java,python,ruby,php} pid
 
 Trace method execution flow in high-level languages.
 
 positional arguments:
-  {java,python,ruby}    language to trace
+  {java,python,ruby,php}
+			language to trace
   pid                   process id to attach to
 
 optional arguments:
diff --git a/tools/ustat.py b/tools/ustat.py
index 1c85ea0..aa026e1 100755
--- a/tools/ustat.py
+++ b/tools/ustat.py
@@ -5,7 +5,7 @@
 #        method calls, class loads, garbage collections, and more.
 #        For Linux, uses BCC, eBPF.
 #
-# USAGE: ustat [-l {java,python,ruby,node}] [-C]
+# USAGE: ustat [-l {java,python,ruby,node,php}] [-C]
 #        [-S {cload,excp,gc,method,objnew,thread}] [-r MAXROWS] [-d]
 #        [interval [count]]
 #
@@ -132,7 +132,7 @@
             formatter_class=argparse.RawDescriptionHelpFormatter,
             epilog=examples)
         parser.add_argument("-l", "--language",
-            choices=["java", "python", "ruby", "node"],
+            choices=["java", "python", "ruby", "node", "php"],
             help="language to trace (default: all languages)")
         parser.add_argument("-C", "--noclear", action="store_true",
             help="don't clear the screen")
@@ -158,6 +158,11 @@
                     "function__entry": Category.METHOD,
                     "gc__start": Category.GC
                     }),
+                "php": Probe("php", ["php"], {
+                    "function__entry": Category.METHOD,
+                    "compile__file__entry": Category.CLOAD,
+                    "exception__thrown": Category.EXCP
+                    }),
                 "ruby": Probe("ruby", ["ruby", "irb"], {
                     "method__entry": Category.METHOD,
                     "cmethod__entry": Category.METHOD,
diff --git a/tools/ustat_example.txt b/tools/ustat_example.txt
index 7da01e6..79f67fd 100644
--- a/tools/ustat_example.txt
+++ b/tools/ustat_example.txt
@@ -4,7 +4,7 @@
 ustat is a "top"-like tool for monitoring events in high-level languages. It 
 prints statistics about garbage collections, method calls, object allocations,
 and various other events for every process that it recognizes with a Java,
-Python, Ruby, or Node runtime.
+Python, Ruby, Node, or PHP runtime.
 
 For example:
 
@@ -48,7 +48,7 @@
 USAGE message:
 
 # ./ustat.py -h
-usage: ustat.py [-h] [-l {java,python,ruby,node}] [-C]
+usage: ustat.py [-h] [-l {java,python,ruby,node,php}] [-C]
                 [-S {cload,excp,gc,method,objnew,thread}] [-r MAXROWS] [-d]
                 [interval] [count]
 
@@ -60,7 +60,7 @@
 
 optional arguments:
   -h, --help            show this help message and exit
-  -l {java,python,ruby,node}, --language {java,python,ruby,node}
+  -l {java,python,ruby,node,php}, --language {java,python,ruby,node,php}
                         language to trace (default: all languages)
   -C, --noclear         don't clear the screen
   -S {cload,excp,gc,method,objnew,thread}, --sort {cload,excp,gc,method,objnew,thread}