utools Tcl support (#2005)

* Add perl* utools man page links

Matches other languages, related to commit 9162be4.

* uthreads: explicitly list C as supported

uthreads supports C (pthreads) thread tracing, make this explicit.

Earlier use of -l java and -l none unchanged.

Add the corresponding man page and usage examples.

* Add Tcl support for ucalls / uflow / uobjnew / ustat

For some reason we need to use proc__args instead of proc__entry
in uflow.py to get similar results as with e.g. Python.
diff --git a/man/man8/cthreads.8 b/man/man8/cthreads.8
new file mode 120000
index 0000000..baf8205
--- /dev/null
+++ b/man/man8/cthreads.8
@@ -0,0 +1 @@
+uthreads.8
\ No newline at end of file
diff --git a/man/man8/perlcalls.8 b/man/man8/perlcalls.8
new file mode 120000
index 0000000..a9a6054
--- /dev/null
+++ b/man/man8/perlcalls.8
@@ -0,0 +1 @@
+ucalls.8
\ No newline at end of file
diff --git a/man/man8/perlflow.8 b/man/man8/perlflow.8
new file mode 120000
index 0000000..84ccb94
--- /dev/null
+++ b/man/man8/perlflow.8
@@ -0,0 +1 @@
+uflow.8
\ No newline at end of file
diff --git a/man/man8/perlstat.8 b/man/man8/perlstat.8
new file mode 120000
index 0000000..e3a3a29
--- /dev/null
+++ b/man/man8/perlstat.8
@@ -0,0 +1 @@
+ustat.8
\ No newline at end of file
diff --git a/man/man8/tclcalls.8 b/man/man8/tclcalls.8
new file mode 120000
index 0000000..a9a6054
--- /dev/null
+++ b/man/man8/tclcalls.8
@@ -0,0 +1 @@
+ucalls.8
\ No newline at end of file
diff --git a/man/man8/tclflow.8 b/man/man8/tclflow.8
new file mode 120000
index 0000000..84ccb94
--- /dev/null
+++ b/man/man8/tclflow.8
@@ -0,0 +1 @@
+uflow.8
\ No newline at end of file
diff --git a/man/man8/tclobjnew.8 b/man/man8/tclobjnew.8
new file mode 120000
index 0000000..b384265
--- /dev/null
+++ b/man/man8/tclobjnew.8
@@ -0,0 +1 @@
+uobjnew.8
\ No newline at end of file
diff --git a/man/man8/tclstat.8 b/man/man8/tclstat.8
new file mode 120000
index 0000000..e3a3a29
--- /dev/null
+++ b/man/man8/tclstat.8
@@ -0,0 +1 @@
+ustat.8
\ No newline at end of file
diff --git a/man/man8/ucalls.8 b/man/man8/ucalls.8
index cadb3e0..dfc4b8b 100644
--- a/man/man8/ucalls.8
+++ b/man/man8/ucalls.8
@@ -1,6 +1,6 @@
-.TH ucalls 8  "2016-11-07" "USER COMMANDS"
+.TH ucalls 8  "2018-10-09" "USER COMMANDS"
 .SH NAME
-ucalls, javacalls, perlcalls, phpcalls, pythoncalls, rubycalls \- Summarize method calls
+ucalls, javacalls, perlcalls, phpcalls, pythoncalls, rubycalls, tclcalls \- Summarize method calls
 from high-level languages and Linux syscalls.
 .SH SYNOPSIS
 .B javacalls [-h] [-T TOP] [-L] [-S] [-v] [-m] pid [interval]
@@ -13,17 +13,19 @@
 .br
 .B rubycalls [-h] [-T TOP] [-L] [-S] [-v] [-m] pid [interval]
 .br
+.B tclcalls [-h] [-T TOP] [-L] [-S] [-v] [-m] pid [interval]
+.br
 .B ucalls [-l {java,perl,php,python,ruby}] [-h] [-T TOP] [-L] [-S] [-v] [-m] pid [interval]
 .SH DESCRIPTION
 This tool summarizes method calls from high-level languages such as Java, Perl,
-PHP, Python, and Ruby. It can also trace Linux system calls. Whenever a method
+PHP, Python, Ruby, and Tcl. It can also trace Linux system calls. Whenever a method
 is invoked, ucalls records the call count and optionally the method's execution
 time (latency) and displays a summary.
 
 This uses in-kernel eBPF maps to store per process summaries for efficiency.
 
 This tool relies on USDT probes embedded in many high-level languages, such as
-Java, Perl, PHP, Python, and Ruby. It requires a runtime instrumented with these
+Java, Perl, PHP, Python, Ruby, and Tcl. It requires a runtime instrumented with these
 probes, which in some cases requires building from source with a USDT-specific
 flag, such as "--enable-dtrace" or "--with-dtrace". For Java, method probes are
 not enabled by default, and can be turned on by running the Java process with
@@ -35,7 +37,7 @@
 CONFIG_BPF and bcc.
 .SH OPTIONS
 .TP
-\-l {java,perl,php,python,ruby}
+\-l {java,perl,php,python,ruby,tcl}
 The language to trace. If not provided, only syscalls are traced (when the \-S
 option is used).
 .TP
diff --git a/man/man8/uflow.8 b/man/man8/uflow.8
index b6d160e..1d0951c 100644
--- a/man/man8/uflow.8
+++ b/man/man8/uflow.8
@@ -1,6 +1,6 @@
-.TH uflow 8  "2016-11-07" "USER COMMANDS"
+.TH uflow 8  "2018-10-09" "USER COMMANDS"
 .SH NAME
-uflow, javaflow, perlflow, phpflow, pythonflow, rubyflow \- Print a flow graph of method
+uflow, javaflow, perlflow, phpflow, pythonflow, rubyflow, tclflow \- Print a flow graph of method
 calls in high-level languages.
 .SH SYNOPSIS
 .B javaflow [-h] [-M METHOD] [-C CLAZZ] [-v] pid
@@ -13,13 +13,15 @@
 .br
 .B rubyflow [-h] [-M METHOD] [-C CLAZZ] [-v] pid
 .br
-.B uflow [-h] [-M METHOD] [-C CLAZZ] [-v] [-l {java,perl,php,python,ruby}] pid
+.B tclflow [-h] [-M METHOD] [-C CLAZZ] [-v] pid
+.br
+.B uflow [-h] [-M METHOD] [-C CLAZZ] [-v] [-l {java,perl,php,python,ruby,tcl}] pid
 .SH DESCRIPTION
 uflow traces method calls and prints them in a flow graph that can facilitate
 debugging and diagnostics by following the program's execution (method flow).
 
 This tool relies on USDT probes embedded in many high-level languages, such as
-Java, Perl, PHP, Python, and Ruby. It requires a runtime instrumented with these
+Java, Perl, PHP, Python, Ruby, and Tcl. It requires a runtime instrumented with these
 probes, which in some cases requires building from source with a USDT-specific
 flag, such as "--enable-dtrace" or "--with-dtrace". For Java processes, the
 startup flag "-XX:+ExtendedDTraceProbes" is required. For PHP processes, the
@@ -41,7 +43,7 @@
 \-v
 Print the resulting BPF program, for debugging purposes.
 .TP
-{java,perl,php,python,ruby}
+{java,perl,php,python,ruby,tcl}
 The language to trace.
 .TP
 pid
diff --git a/man/man8/ugc.8 b/man/man8/ugc.8
index a4a7448..782ae63 100644
--- a/man/man8/ugc.8
+++ b/man/man8/ugc.8
@@ -1,24 +1,24 @@
-.TH ugc 8  "2016-11-07" "USER COMMANDS"
+.TH ugc 8  "2018-10-09" "USER COMMANDS"
 .SH NAME
-ugc, javagc, pythongc, rubygc, nodegc \- Trace garbage collection events in
+ugc, javagc, nodegc, pythongc, rubygc \- Trace garbage collection events in
 high-level languages.
 .SH SYNOPSIS
 .B javagc [-h] [-v] [-m] [-M MINIMUM] [-F FILTER] pid
 .br
+.B nodegc [-h] [-v] [-m] [-M MINIMUM] [-F FILTER] pid
+.br
 .B pythongc [-h] [-v] [-m] [-M MINIMUM] [-F FILTER] pid
 .br
 .B rubygc [-h] [-v] [-m] [-M MINIMUM] [-F FILTER] pid
 .br
-.B nodegc [-h] [-v] [-m] [-M MINIMUM] [-F FILTER] pid
-.br
-.B ugc [-h] [-v] [-m] [-M MINIMUM] [-F FILTER] [-l {java,python,ruby,node}] pid
+.B ugc [-h] [-v] [-m] [-M MINIMUM] [-F FILTER] [-l {java,node,python,ruby}] pid
 .SH DESCRIPTION
 This traces garbage collection events as they occur, including their duration
 and any additional information (such as generation collected or type of GC)
 provided by the respective language's runtime.
 
 This tool relies on USDT probes embedded in many high-level languages, such as
-Node, Java, Python, and Ruby. It requires a runtime instrumented with these 
+Java, Node, Python, and Ruby. It requires a runtime instrumented with these
 probes, which in some cases requires building from source with a USDT-specific
 flag, such as "--enable-dtrace" or "--with-dtrace".
 
@@ -45,7 +45,7 @@
 reduce the amount of data that has to be transferred from the BPF program to
 the user-space script.
 .TP
-{java,python,ruby,node}
+{java,node,python,ruby}
 The language to trace.
 .TP
 pid
diff --git a/man/man8/uobjnew.8 b/man/man8/uobjnew.8
index dcb459a..f4a9c74 100644
--- a/man/man8/uobjnew.8
+++ b/man/man8/uobjnew.8
@@ -1,22 +1,24 @@
-.TH uobjnew 8  "2016-11-07" "USER COMMANDS"
+.TH uobjnew 8  "2018-10-09" "USER COMMANDS"
 .SH NAME
-uobjnew, javaobjnew, rubyobjnew, cobjnew \- Summarize object allocations in
+uobjnew, cobjnew, javaobjnew, rubyobjnew, tclobjnew \- Summarize object allocations in
 high-level languages.
 .SH SYNOPSIS
+.B cobjnew [-h] [-C TOP_COUNT] [-S TOP_SIZE] [-v] pid [interval]
+.br
 .B javaobjnew [-h] [-C TOP_COUNT] [-S TOP_SIZE] [-v] pid [interval]
 .br
 .B rubyobjnew [-h] [-C TOP_COUNT] [-S TOP_SIZE] [-v] pid [interval]
 .br
-.B cobjnew [-h] [-C TOP_COUNT] [-S TOP_SIZE] [-v] pid [interval]
+.B tclobjnew [-h] [-C TOP_COUNT] [-S TOP_SIZE] [-v] pid [interval]
 .br
-.B uobjnew [-h] [-C TOP_COUNT] [-S TOP_SIZE] [-v] [-l {java,ruby,c}] pid [interval]
+.B uobjnew [-h] [-C TOP_COUNT] [-S TOP_SIZE] [-v] [-l {c,java,ruby,tcl}] pid [interval]
 .SH DESCRIPTION
 uobjnew traces object allocations in high-level languages (including "malloc")
-and prints summaries of the most frequently allocated types by number of 
+and prints summaries of the most frequently allocated types by number of
 objects or number of bytes.
 
 This tool relies on USDT probes embedded in many high-level languages, such as
-Node, Java, Python, and Ruby. It requires a runtime instrumented with these 
+C, Java, Ruby, and Tcl. It requires a runtime instrumented with these
 probes, which in some cases requires building from source with a USDT-specific
 flag, such as "--enable-dtrace" or "--with-dtrace". For Java, the Java process
 must be started with the "-XX:+ExtendedDTraceProbes" flag.
@@ -35,7 +37,7 @@
 \-v
 Print the resulting BPF program, for debugging purposes.
 .TP
-{java,ruby,c}
+{c,java,ruby,tcl}
 The language to trace.
 .TP
 pid
diff --git a/man/man8/ustat.8 b/man/man8/ustat.8
index 6dd6f12..371d855 100644
--- a/man/man8/ustat.8
+++ b/man/man8/ustat.8
@@ -1,6 +1,6 @@
-.TH ustat 8  "2016-11-07" "USER COMMANDS"
+.TH ustat 8  "2018-10-09" "USER COMMANDS"
 .SH NAME
-ustat, javastat, nodestat, perlstat, phpstat, pythonstat, rubystat \- Activity stats from
+ustat, javastat, nodestat, perlstat, phpstat, pythonstat, rubystat, tclstat \- Activity stats from
 high-level languages.
 .SH SYNOPSIS
 .B javastat [-C] [-S {cload,excp,gc,method,objnew,thread}] [-r MAXROWS] [-d] [interval [count]]
@@ -15,7 +15,9 @@
 .br
 .B rubystat [-C] [-S {cload,excp,gc,method,objnew,thread}] [-r MAXROWS] [-d] [interval [count]]
 .br
-.B ustat [-l {java,perl,python,ruby,node,php}] [-C] [-S {cload,excp,gc,method,objnew,thread}] [-r MAXROWS] [-d] [interval [count]]
+.B tclstat [-C] [-S {cload,excp,gc,method,objnew,thread}] [-r MAXROWS] [-d] [interval [count]]
+.br
+.B ustat [-l {java,node,perl,php,python,ruby,tcl}] [-C] [-S {cload,excp,gc,method,objnew,thread}] [-r MAXROWS] [-d] [interval [count]]
 .SH DESCRIPTION
 This is "top" for high-level language events, such as garbage collections,
 exceptions, thread creations, object allocations, method calls, and more. The
@@ -26,7 +28,7 @@
 This uses in-kernel eBPF maps to store per process summaries for efficiency.
 
 This tool relies on USDT probes embedded in many high-level languages, such as
-Java, Node, Perl, PHP, Python, and Ruby. It requires a runtime instrumented with
+Java, Node, Perl, PHP, Python, Ruby, and Tcl. It requires a runtime instrumented with
 these probes, which in some cases requires building from source with a
 USDT-specific flag, such as "--enable-dtrace" or "--with-dtrace". For Java,
 some probes are not enabled by default, and can be turned on by running the Java
@@ -43,7 +45,7 @@
 CONFIG_BPF and bcc.
 .SH OPTIONS
 .TP
-\-l {java,node,perl,php,python,ruby}
+\-l {java,node,perl,php,python,ruby,tcl}
 The language to trace. By default, all languages are traced.
 .TP
 \-C
@@ -107,10 +109,10 @@
 Count of threads created during interval.
 .SH OVERHEAD
 When using this tool with high-frequency events, such as method calls, a very
-significant slow-down can be expected. However, many of the high-level 
+significant slow-down can be expected. However, many of the high-level
 languages covered by this tool already have a fairly high per-method invocation
-cost, especially when running in interpreted mode. For the lower-frequency 
-events, such as garbage collections or thread creations, the overhead should 
+cost, especially when running in interpreted mode. For the lower-frequency
+events, such as garbage collections or thread creations, the overhead should
 not be significant. Specifically, when probing Java processes and not using the
 "-XX:+ExtendedDTraceProbes" flag, the most expensive probes are not emitted,
 and the overhead should be acceptable.
diff --git a/man/man8/uthreads.8 b/man/man8/uthreads.8
index 76f0602..6acffa5 100644
--- a/man/man8/uthreads.8
+++ b/man/man8/uthreads.8
@@ -1,10 +1,12 @@
-.TH uthreads 8  "2016-11-07" "USER COMMANDS"
+.TH uthreads 8  "2018-10-09" "USER COMMANDS"
 .SH NAME
-uthreads, javathreads \- Trace thread creation events in Java or pthreads.
+uthreads, cthreads, javathreads \- Trace thread creation events in Java or pthreads.
 .SH SYNOPSIS
+.B cthreads [-h] [-v] pid
+.BR
 .B javathreads [-h] [-v] pid
 .BR
-.B uthreads [-h] [-l {java}] [-v] pid
+.B uthreads [-h] [-l {c,java,none}] [-v] pid
 .SH DESCRIPTION
 This traces thread creation events in Java processes, or pthread creation
 events in any process. When a thread is created, its name or start address
@@ -15,9 +17,9 @@
 CONFIG_BPF and bcc.
 .SH OPTIONS
 .TP
-\-l {java}
-The language to trace (currently only Java is supported). When no language is
-specified, only pthread creations are traced.
+\-l {c,java,none}
+The language to trace. C and none select tracing pthreads only, regardless
+of the runtime being traced.
 .TP
 \-v
 Print the resulting BPF program, for debugging purposes.
diff --git a/tools/cthreads_example.txt b/tools/cthreads_example.txt
new file mode 120000
index 0000000..4e678a8
--- /dev/null
+++ b/tools/cthreads_example.txt
@@ -0,0 +1 @@
+lib/uthreads_example.txt
\ No newline at end of file
diff --git a/tools/lib/ucalls.py b/tools/lib/ucalls.py
index 1a0fe21..18ca22c 100755
--- a/tools/lib/ucalls.py
+++ b/tools/lib/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,perl,php,python,ruby}] [-h] [-T TOP] [-L] [-S] [-v] [-m]
+# USAGE: ucalls [-l {java,perl,php,python,ruby,tcl}] [-h] [-T TOP] [-L] [-S] [-v] [-m]
 #        pid [interval]
 #
 # Copyright 2016 Sasha Goldshtein
@@ -18,7 +18,7 @@
 from time import sleep
 import os
 
-languages = ["java", "perl", "php", "python", "ruby"]
+languages = ["java", "perl", "php", "python", "ruby", "tcl"]
 
 examples = """examples:
     ./ucalls -l java 185        # trace Java calls and print statistics on ^C
@@ -94,6 +94,12 @@
     return_probe = "method__return"
     read_class = "bpf_usdt_readarg(1, ctx, &clazz);"
     read_method = "bpf_usdt_readarg(2, ctx, &method);"
+elif language == "tcl":
+    # TODO Also consider probe cmd__entry and cmd__return with same arguments
+    entry_probe = "proc__entry"
+    return_probe = "proc__return"
+    read_class = ""  # no class/file info available
+    read_method = "bpf_usdt_readarg(1, ctx, &method);"
 elif not language or language == "none":
     if not args.syscalls:
         print("Nothing to do; use -S to trace syscalls.")
diff --git a/tools/lib/ucalls_example.txt b/tools/lib/ucalls_example.txt
index 69d401a..7191fb8 100644
--- a/tools/lib/ucalls_example.txt
+++ b/tools/lib/ucalls_example.txt
@@ -2,8 +2,8 @@
 
 
 ucalls summarizes method calls in various high-level languages, including Java,
-Perl, PHP, Python, Ruby, and Linux system calls. It displays statistics on the
-most frequently called methods, as well as the latency (duration) of these
+Perl, PHP, Python, Ruby, Tcl, 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 
@@ -61,7 +61,7 @@
 USAGE message:
 
 # ./ucalls.py -h
-usage: ucalls.py [-h] [-l {java,perl,php,python,ruby,none}] [-T TOP] [-L] [-S] [-v]
+usage: ucalls.py [-h] [-l {java,perl,php,python,ruby,tcl,none}] [-T TOP] [-L] [-S] [-v]
                  [-m]
                  pid [interval]
 
@@ -73,7 +73,7 @@
 
 optional arguments:
   -h, --help            show this help message and exit
-  -l {java,perl,php,python,ruby,none}, --language {java,perl,php,python,ruby,none}
+  -l {java,perl,php,python,ruby,tcl,none}, --language {java,perl,php,python,ruby,tcl,none}
                         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
diff --git a/tools/lib/uflow.py b/tools/lib/uflow.py
index f2a458d..02cad55 100755
--- a/tools/lib/uflow.py
+++ b/tools/lib/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,perl,php,python,ruby} pid
+# USAGE: uflow [-C CLASS] [-M METHOD] [-v] {java,perl,php,python,ruby,tcl} pid
 #
 # Copyright 2016 Sasha Goldshtein
 # Licensed under the Apache License, Version 2.0 (the "License")
@@ -18,7 +18,7 @@
 import time
 import os
 
-languages = ["java", "perl", "php", "python", "ruby"]
+languages = ["java", "perl", "php", "python", "ruby", "tcl"]
 
 examples = """examples:
     ./uflow -l java 185                # trace Java method calls in process 185
@@ -161,6 +161,13 @@
     enable_probe("cmethod__return", "ruby_creturn",
                  "bpf_usdt_readarg(1, ctx, &clazz);",
                  "bpf_usdt_readarg(2, ctx, &method);", is_return=True)
+elif language == "tcl":
+    enable_probe("proc__args", "tcl_entry",
+                 "",  # no class/file info available
+                 "bpf_usdt_readarg(1, ctx, &method);", is_return=False)
+    enable_probe("proc__return", "tcl_return",
+                 "",  # no class/file info available
+                 "bpf_usdt_readarg(1, ctx, &method);", is_return=True)
 else:
     print("No language detected; use -l to trace a language.")
     exit(1)
diff --git a/tools/lib/uflow_example.txt b/tools/lib/uflow_example.txt
index fae52f3..5dccb8f 100644
--- a/tools/lib/uflow_example.txt
+++ b/tools/lib/uflow_example.txt
@@ -4,7 +4,7 @@
 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, Perl, PHP, Python, and Ruby, which provide USDT
+languages such as Java, Perl, PHP, Python, Ruby, and Tcl which provide USDT
 probes for method invocations.
 
 
@@ -88,7 +88,7 @@
 USAGE message:
 
 # ./uflow -h
-usage: uflow.py [-h] [-l {java,perl,php,python,ruby}] [-M METHOD] [-C CLAZZ] [-v]
+usage: uflow.py [-h] [-l {java,perl,php,python,ruby,tcl}] [-M METHOD] [-C CLAZZ] [-v]
                 pid
 
 Trace method execution flow in high-level languages.
@@ -98,7 +98,7 @@
 
 optional arguments:
   -h, --help            show this help message and exit
-  -l {java,perl,php,python,ruby}, --language {java,perl,php,python,ruby}
+  -l {java,perl,php,python,ruby,tcl}, --language {java,perl,php,python,ruby,tcl}
                         language to trace
   -M METHOD, --method METHOD
                         trace only calls to methods starting with this prefix
diff --git a/tools/lib/uobjnew.py b/tools/lib/uobjnew.py
index e3b61ff..85f5768 100755
--- a/tools/lib/uobjnew.py
+++ b/tools/lib/uobjnew.py
@@ -4,7 +4,7 @@
 # uobjnew  Summarize object allocations in high-level languages.
 #          For Linux, uses BCC, eBPF.
 #
-# USAGE: uobjnew [-h] [-T TOP] [-v] {c,java,ruby} pid [interval]
+# USAGE: uobjnew [-h] [-T TOP] [-v] {c,java,ruby,tcl} pid [interval]
 #
 # Copyright 2016 Sasha Goldshtein
 # Licensed under the Apache License, Version 2.0 (the "License")
@@ -18,7 +18,7 @@
 import os
 
 # C needs to be the last language.
-languages = ["c", "java", "ruby"]
+languages = ["c", "java", "ruby", "tcl"]
 
 examples = """examples:
     ./uobjnew -l java 145         # summarize Java allocations in process 145
@@ -137,7 +137,20 @@
         program += create_template.replace("THETHING", thing)
         usdt.enable_probe_or_bail("%s__create" % thing,
                                   "%s_alloc_entry" % thing)
-
+#
+# Tcl
+#
+elif language == "tcl":
+    program += """
+int alloc_entry(struct pt_regs *ctx) {
+    struct key_t key = { .name = "<ALL>" };
+    struct val_t *valp, zero = {};
+    valp = allocs.lookup_or_init(&key, &zero);
+    valp->num_allocs += 1;
+    return 0;
+}
+    """
+    usdt.enable_probe_or_bail("obj__create", "alloc_entry")
 else:
     print("No language detected; use -l to trace a language.")
     exit(1)
@@ -173,7 +186,7 @@
         data = data[-args.top_size:]
     else:
         data = sorted(data.items(), key=lambda kv: kv[1].total_size)
-    print("%-30s %8s %12s" % ("TYPE", "# ALLOCS", "# BYTES"))
+    print("%-30s %8s %12s" % ("NAME/TYPE", "# ALLOCS", "# BYTES"))
     for key, value in data:
         if language == "c":
             obj_type = "block size %d" % key.size
diff --git a/tools/lib/uobjnew_example.txt b/tools/lib/uobjnew_example.txt
index 4863321..fcb2d21 100644
--- a/tools/lib/uobjnew_example.txt
+++ b/tools/lib/uobjnew_example.txt
@@ -48,7 +48,7 @@
 USAGE message:
 
 # ./uobjnew -h
-usage: uobjnew.py [-h] [-l {java,ruby,c}] [-C TOP_COUNT] [-S TOP_SIZE] [-v]
+usage: uobjnew.py [-h] [-l {c,java,ruby,tcl}] [-C TOP_COUNT] [-S TOP_SIZE] [-v]
                   pid [interval]
 
 Summarize object allocations in high-level languages.
@@ -59,7 +59,7 @@
 
 optional arguments:
   -h, --help            show this help message and exit
-  -l {java,ruby,c}, --language {java,ruby,c}
+  -l {c,java,ruby,tcl}, --language {c,java,ruby,tcl}
                         language to trace
   -C TOP_COUNT, --top-count TOP_COUNT
                         number of most frequently allocated types to print
diff --git a/tools/lib/ustat.py b/tools/lib/ustat.py
index 7ac0967..3661a14 100755
--- a/tools/lib/ustat.py
+++ b/tools/lib/ustat.py
@@ -5,7 +5,7 @@
 #        method calls, class loads, garbage collections, and more.
 #        For Linux, uses BCC, eBPF.
 #
-# USAGE: ustat [-l {java,node,perl,php,python,ruby}] [-C]
+# USAGE: ustat [-l {java,node,perl,php,python,ruby,tcl}] [-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", "node", "perl", "php", "python", "ruby"],
+            choices=["java", "node", "perl", "php", "python", "ruby", "tcl"],
             help="language to trace (default: all languages)")
         parser.add_argument("-C", "--noclear", action="store_true",
             help="don't clear the screen")
@@ -190,6 +190,10 @@
                     "load__entry": Category.CLOAD,
                     "raise": Category.EXCP
                     }),
+                "tcl": Probe("tcl", ["tclsh", "wish"], {
+                    "proc__entry": Category.METHOD,
+                    "obj__create": Category.OBJNEW
+                    }),
                 }
 
         if self.args.language:
diff --git a/tools/lib/ustat_example.txt b/tools/lib/ustat_example.txt
index 8a9ee87..11ee2de 100644
--- a/tools/lib/ustat_example.txt
+++ b/tools/lib/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,
-Node, Perl, PHP, Python, and Ruby runtime.
+Node, Perl, PHP, Python, Ruby, and Tcl runtime.
 
 For example:
 
@@ -48,7 +48,7 @@
 USAGE message:
 
 # ./ustat.py -h
-usage: ustat.py [-h] [-l {java,node,perl,php,python,ruby}] [-C]
+usage: ustat.py [-h] [-l {java,node,perl,php,python,ruby,tcl}] [-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,node,perl,php,python,ruby}}, --language {java,node,perl,php,python,ruby}
+  -l {java,node,perl,php,python,ruby,tcl}, --language {java,node,perl,php,python,ruby,tcl}
                         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}
diff --git a/tools/lib/uthreads.py b/tools/lib/uthreads.py
index fb54599..71e9c6a 100755
--- a/tools/lib/uthreads.py
+++ b/tools/lib/uthreads.py
@@ -4,7 +4,7 @@
 # uthreads  Trace thread creation/destruction events in high-level languages.
 #           For Linux, uses BCC, eBPF.
 #
-# USAGE: uthreads [-l {java}] [-v] pid
+# USAGE: uthreads [-l {c,java,none}] [-v] pid
 #
 # Copyright 2016 Sasha Goldshtein
 # Licensed under the Apache License, Version 2.0 (the "License")
@@ -18,11 +18,11 @@
 import time
 import os
 
-languages = ["java"]
+languages = ["c", "java"]
 
 examples = """examples:
-    ./uthreads -l java 185   # trace Java threads in process 185
-    ./uthreads 12245         # trace only pthreads in process 12245
+    ./uthreads -l java 185    # trace Java threads in process 185
+    ./uthreads -l none 12245  # trace only pthreads in process 12245
 """
 parser = argparse.ArgumentParser(
     description="Trace thread creation/destruction events in " +
@@ -68,7 +68,10 @@
 if not language:
     language = utils.detect_language(languages, args.pid)
 
-if language == "java":
+if language == "c":
+    # Nothing to add
+    pass
+elif language == "java":
     template = """
 int %s(struct pt_regs *ctx) {
     char type[] = "%s";
diff --git a/tools/lib/uthreads_example.txt b/tools/lib/uthreads_example.txt
index 0a6a039..9880926 100644
--- a/tools/lib/uthreads_example.txt
+++ b/tools/lib/uthreads_example.txt
@@ -1,7 +1,7 @@
 Demonstrations of uthreads.
 
 
-uthreads traces thread creation events in Java or raw pthreads, and prints
+uthreads traces thread creation events in Java or raw (C) pthreads, and prints
 details about the newly created thread. For Java threads, the thread name is
 printed; for pthreads, the thread's start function is printed, if there is
 symbol information to resolve it.
@@ -23,7 +23,7 @@
 Next, trace only pthread creation events in some native application:
 
 # ./uthreads 27450
-Tracing thread events in process 27450 (language: none)... Ctrl-C to quit.
+Tracing thread events in process 27450 (language: c)... Ctrl-C to quit.
 TIME     ID               TYPE     DESCRIPTION                   
 0.924    27462            pthread  primes_thread [primes]
 0.927    27463            pthread  primes_thread [primes]     
@@ -39,7 +39,7 @@
 USAGE message:
 
 # ./uthreads -h
-usage: uthreads.py [-h] [-l {java,none}] [-v] pid
+usage: uthreads.py [-h] [-l {c,java,none}] [-v] pid
 
 Trace thread creation/destruction events in high-level languages.
 
@@ -48,11 +48,11 @@
 
 optional arguments:
   -h, --help            show this help message and exit
-  -l {java,none}, --language {java,none}
+  -l {c,java,none}, --language {c,java,none}
                         language to trace (none for pthreads only)
   -v, --verbose         verbose mode: print the BPF program (for debugging
                         purposes)
 
 examples:
-    ./uthreads -l java 185   # trace Java threads in process 185
-    ./uthreads 12245         # trace only pthreads in process 12245
+    ./uthreads -l java 185    # trace Java threads in process 185
+    ./uthreads -l none 12245  # trace only pthreads in process 12245
diff --git a/tools/tclcalls.sh b/tools/tclcalls.sh
new file mode 100755
index 0000000..fafd550
--- /dev/null
+++ b/tools/tclcalls.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+lib=$(dirname $0)/lib
+$lib/ucalls.py -l tcl "$@"
diff --git a/tools/tclcalls_example.txt b/tools/tclcalls_example.txt
new file mode 120000
index 0000000..22b0fb3
--- /dev/null
+++ b/tools/tclcalls_example.txt
@@ -0,0 +1 @@
+lib/ucalls_example.txt
\ No newline at end of file
diff --git a/tools/tclflow.sh b/tools/tclflow.sh
new file mode 100755
index 0000000..8930466
--- /dev/null
+++ b/tools/tclflow.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+lib=$(dirname $0)/lib
+$lib/uflow.py -l tcl "$@"
diff --git a/tools/tclflow_example.txt b/tools/tclflow_example.txt
new file mode 120000
index 0000000..bc71efc
--- /dev/null
+++ b/tools/tclflow_example.txt
@@ -0,0 +1 @@
+lib/uflow_example.txt
\ No newline at end of file
diff --git a/tools/tclobjnew.sh b/tools/tclobjnew.sh
new file mode 100755
index 0000000..6aed1ac
--- /dev/null
+++ b/tools/tclobjnew.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+lib=$(dirname $0)/lib
+$lib/uobjnew.py -l tcl "$@"
diff --git a/tools/tclobjnew_example.txt b/tools/tclobjnew_example.txt
new file mode 120000
index 0000000..a8a83c3
--- /dev/null
+++ b/tools/tclobjnew_example.txt
@@ -0,0 +1 @@
+lib/uobjnew_example.txt
\ No newline at end of file
diff --git a/tools/tclstat.sh b/tools/tclstat.sh
new file mode 100755
index 0000000..f4291ab
--- /dev/null
+++ b/tools/tclstat.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+lib=$(dirname $0)/lib
+$lib/ustat.py -l tcl "$@"
diff --git a/tools/tclstat_example.txt b/tools/tclstat_example.txt
new file mode 120000
index 0000000..544e5ad
--- /dev/null
+++ b/tools/tclstat_example.txt
@@ -0,0 +1 @@
+lib/ustat_example.txt
\ No newline at end of file