summary refs log tree commit diff
path: root/ripple/driver.pl
diff options
context:
space:
mode:
authoredef <edef@unfathomable.blue>2021-05-26 11:16:14 +0000
committeredef <edef@unfathomable.blue>2021-05-26 11:29:35 +0000
commite109ea262d2059115c2069f32f420a9d3af71803 (patch)
treecb7ae9827db6a413c9b70f71febbf71774030e5c /ripple/driver.pl
parentf5c8a8537a336b60fd28af003572fa8883fc8354 (diff)
downloadunf-legacy-e109ea262d2059115c2069f32f420a9d3af71803.tar.zst
ripple/driver.pl: a basic syscall tracing driver
This program spawns a child in a new cgroup (using systemd-run) under
bpftrace and counts syscall invocations for each (syscall, comm) pair.

It outputs a TSV of (syscall, comm, count) tuples to STDERR.

This makes it easy to assess which system calls a build process uses,
segmented by a useful approximation of the invoking programs.

Change-Id: I9ab7a34fda82245d3fa22b47840de16d1decf719
Diffstat (limited to 'ripple/driver.pl')
-rwxr-xr-xripple/driver.pl68
1 files changed, 68 insertions, 0 deletions
diff --git a/ripple/driver.pl b/ripple/driver.pl
new file mode 100755
index 0000000..07be06f
--- /dev/null
+++ b/ripple/driver.pl
@@ -0,0 +1,68 @@
+#! /usr/bin/perl
+# SPDX-FileCopyrightText: edef <edef@unfathomable.blue>
+# SPDX-License-Identifier: OSL-3.0
+
+use strict;
+use POSIX qw(mkfifo);
+
+@ARGV or die "Usage: $0 PROGRAM [ARG]... 2> [LOG FILE]";
+
+unlink(my $fifo = "tracepipe");
+mkfifo($fifo, 0600) or die;
+
+my $script = do { local $/; <DATA> };
+defined(my $pid = fork) or die;
+
+if (!$pid) {
+    open(STDERR, ">&", STDOUT) or die;
+    exec(
+        'systemd-run', '--user', '--scope', '--',
+        # NOTE: this expects bpftrace to be SUID-root,
+        # and relies on shells dropping euid
+        'bpftrace', '-o', $fifo, '-e', $script, '-c',
+        @ARGV
+    ) or die;
+}
+
+my %count;
+
+# TODO(edef): if bpftrace fails, the FIFO will never open
+open(TRACE, '<', $fifo) or die;
+while (<TRACE>) {
+    chomp;
+    next if /^Attaching \d+ probes[.][.][.]$/ or /^$/;
+    /^@\[tracepoint:syscalls:sys_enter_(\w+), (.+)\]: (\d+)$/ or die $_;
+    $count{$1}{$2} += $3;
+}
+
+waitpid $pid, 0;
+
+foreach my $comm (sort keys %count) {
+    die "unhandled: $comm" if $comm =~ /\s/;
+    my $comm_count = $count{$comm};
+    foreach my $sys (sort keys %$comm_count) {
+        my $n = $comm_count->{$sys};
+        print STDERR "$comm\t$sys\t$n\n";
+    }
+}
+
+__DATA__
+BEGIN {
+    @cgroup = cgroup;
+    @self = pid;
+}
+
+tracepoint:syscalls:sys_enter_* /cgroup == @cgroup && pid != @self/ {
+    @[probe, comm] = count();
+}
+
+interval:s:1 {
+    print(@);
+    clear(@);
+}
+
+tracepoint:sched:sched_process_exit /tid == cpid/ {
+    clear(@cgroup);
+    clear(@self);
+    exit();
+}