summary refs log tree commit diff
path: root/ripple/tools/driver.pl
blob: 7a8d164caa27c38d5d9992c1d50713f32972938b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#! /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]";
die "bpftrace does not support spaces in argv" if grep {/ /} @ARGV;

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',
        join(' ', @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();
}