[DTrace-devel] [PATCH] examples: add script fcalls.d
eugene.loh at oracle.com
eugene.loh at oracle.com
Mon Aug 4 23:42:43 UTC 2025
From: Ruud van der Pas <ruud.vanderpas at oracle.com>
This is a script to list and count function calls.
dtrace/ChangeLog
2025-08-01 Ruud van der Pas <ruud.vanderpas at oracle.com>
* examples/fcalls.d: List and count function calls.
Signed-off-by: Ruud van der Pas <ruud.vanderpas at oracle.com>
---
examples/fcalls.d | 88 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 88 insertions(+)
create mode 100755 examples/fcalls.d
diff --git a/examples/fcalls.d b/examples/fcalls.d
new file mode 100755
index 000000000..8116ecc6f
--- /dev/null
+++ b/examples/fcalls.d
@@ -0,0 +1,88 @@
+#!/usr/sbin/dtrace -s
+
+/*
+ * NAME
+ * fcalls.d - list the functions executed by an application
+ *
+ * SYNOPSIS
+ * sudo ./fcalls.d -c "<name-of-application> [app options]"
+ *
+ * DESCRIPTION
+ * This program lists the functions executed by the target
+ * application. In addition to this, the number of calls to
+ * each function is printed. This information is given on a
+ * per-thread basis, as well as aggregated over all threads.
+ *
+ * NOTES
+ * - Since a.out is used in the probe definitions, library calls
+ * are excluded. If a library like libc should be included,
+ * duplicate the probe definitions and in the copied lines
+ * replace a.out by libc.so.
+ * For example:
+ * pid$target:a.out::entry,pid$target:libc.so::entry
+ * { ... }
+ * - It is assumed that a function called main is executed.
+ * If this is not the case, this is not a critical error.
+ * The first probe is used to capture the name of the executable,
+ * but this is not critical. The probe and printf statement
+ * can safely be removed, or replaced by a suitable alternative.
+ */
+
+/*
+ * Suppress the default output from the dtrace command and
+ * have printa() print the data sorted by the first field.
+ */
+#pragma D option quiet
+#pragma D option aggsortkey=1
+#pragma D option aggsortkeypos=0
+
+/*
+ * Store the name of the target application. The probe
+ * is restricted to main only, because the exec name needs
+ * to be captured only once.
+ */
+pid$target:a.out:main:entry
+{
+ executable_name = execname;
+}
+/*
+ * Use 4 aggregations to store the total number of function
+ * calls, the counts per function and per thread, both
+ * seperately and differentiated by thread and function.
+ */
+pid$target:a.out::entry
+{
+ @total_call_counts = count();
+ @call_counts_per_function[probefunc] = count();
+ @call_counts_per_thr[tid] = count();
+ @counts_per_thr_and_function[tid,probefunc] = count();
+}
+/*
+ * Print the results. Use format strings to create a
+ * table lay-out.
+ */
+END {
+ printf("===========================================\n");
+ printf(" Function Call Count Statistics\n");
+ printf("===========================================\n");
+ printf("Name of the executable: %s\n" ,executable_name);
+ printa("Total function calls : %@d\n", at total_call_counts);
+
+ printf("\n===========================================\n");
+ printf(" Aggregated Function Call Counts\n");
+ printf("===========================================\n");
+ printf("%-25s %12s\n\n","Function name","Count");
+ printa("%-25s %@12d\n", at call_counts_per_function);
+
+ printf("\n===========================================\n");
+ printf(" Function Call Counts Per Thread\n");
+ printf("===========================================\n");
+ printf("%-7s %12s\n\n", "TID","Count");
+ printa("%-7d %@12d\n", at call_counts_per_thr);
+
+ printf("\n===========================================\n");
+ printf(" Thread Level Function Call Counts\n");
+ printf("===========================================\n");
+ printf("%-7s %-25s %8s\n\n","TID","Function name","Count");
+ printa("%-7d %-25s %@8d\n", at counts_per_thr_and_function);
+}
--
2.43.5
More information about the DTrace-devel
mailing list