diff --git a/.github/workflows/test-eunomia.yaml b/.github/workflows/test-eunomia.yaml index a44976d9..81a709ac 100644 --- a/.github/workflows/test-eunomia.yaml +++ b/.github/workflows/test-eunomia.yaml @@ -79,3 +79,7 @@ jobs: run: | ./ecc src/25-signal/signal.bpf.c src/25-signal/signal.h sudo timeout -s 2 3 ./ecli run src/25-signal/package.json || if [ $? = 124 ]; then exit 0; else exit $?; fi + - name: test 31 goroutine + run: | + ./ecc src/31-goroutine/goroutine.bpf.c src/31-signal/goroutine.h + # todo diff --git a/.github/workflows/test-libbpf.yml b/.github/workflows/test-libbpf.yml index 8da0881d..acc884f4 100644 --- a/.github/workflows/test-libbpf.yml +++ b/.github/workflows/test-libbpf.yml @@ -61,6 +61,10 @@ jobs: run: | make -C src/30-sslsniff sudo timeout -s 2 3 src/30-sslsniff/sslsniff || if [ $? = 124 ]; then exit 0; else exit $?; fi + + - name: test 33 funclatency + run: | + make -C src/33-funclatency - name: test 35-user-ringbuf run: | make -C src/35-user-ringbuf diff --git a/src/31-goroutine/goroutine.bpf.c b/src/31-goroutine/goroutine.bpf.c index 6d1b7c6d..8ea21b9d 100644 --- a/src/31-goroutine/goroutine.bpf.c +++ b/src/31-goroutine/goroutine.bpf.c @@ -38,7 +38,7 @@ struct { SEC("uprobe/./go-server-http/main:runtime.casgstatus") int uprobe_runtime_casgstatus(struct pt_regs *ctx) { int newval = ctx->cx; - void *gp = ctx->ax; + void *gp = (void*)ctx->ax; struct goroutine_execute_data *data; u64 goid; if (bpf_probe_read_user(&goid, sizeof(goid), gp + GOID_OFFSET) == 0) { diff --git a/src/31-goroutine/goroutine.c b/src/31-goroutine/goroutine.c deleted file mode 100644 index 89c9ee90..00000000 --- a/src/31-goroutine/goroutine.c +++ /dev/null @@ -1,172 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include -#include -#include -#include -#include -#include -#include "goroutine.h" -#include "goroutine.skel.h" - -static struct env { - bool verbose; - long min_duration_ms; -} env; - -const char *argp_program_version = "goroutine 0.0"; -const char *argp_program_bug_address = ""; -const char argp_program_doc[] = -"BPF goroutine demo application.\n" -"\n" -"It traces process start and exits and shows associated \n" -"information (filename, process duration, PID and PPID, etc).\n" -"\n" -"USAGE: ./goroutine [-d ] [-v]\n"; - -static const struct argp_option opts[] = { - { "verbose", 'v', NULL, 0, "Verbose debug output" }, - { "duration", 'd', "DURATION-MS", 0, "Minimum process duration (ms) to report" }, - {}, -}; - -static error_t parse_arg(int key, char *arg, struct argp_state *state) -{ - switch (key) { - case 'v': - env.verbose = true; - break; - case 'd': - errno = 0; - env.min_duration_ms = strtol(arg, NULL, 10); - if (errno || env.min_duration_ms <= 0) { - fprintf(stderr, "Invalid duration: %s\n", arg); - argp_usage(state); - } - break; - case ARGP_KEY_ARG: - argp_usage(state); - break; - default: - return ARGP_ERR_UNKNOWN; - } - return 0; -} - -static const struct argp argp = { - .options = opts, - .parser = parse_arg, - .doc = argp_program_doc, -}; - -static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args) -{ - if (level == LIBBPF_DEBUG && !env.verbose) - return 0; - return vfprintf(stderr, format, args); -} - -static volatile bool exiting = false; - -static void sig_handler(int sig) -{ - exiting = true; -} - -static int handle_event(void *ctx, void *data, size_t data_sz) -{ - const struct event *e = data; - struct tm *tm; - char ts[32]; - time_t t; - - time(&t); - tm = localtime(&t); - strftime(ts, sizeof(ts), "%H:%M:%S", tm); - - if (e->exit_event) { - printf("%-8s %-5s %-16s %-7d %-7d [%u]", - ts, "EXIT", e->comm, e->pid, e->ppid, e->exit_code); - if (e->duration_ns) - printf(" (%llums)", e->duration_ns / 1000000); - printf("\n"); - } else { - printf("%-8s %-5s %-16s %-7d %-7d %s\n", - ts, "EXEC", e->comm, e->pid, e->ppid, e->filename); - } - - return 0; -} - -int main(int argc, char **argv) -{ - struct ring_buffer *rb = NULL; - struct goroutine_bpf *skel; - int err; - - /* Parse command line arguments */ - err = argp_parse(&argp, argc, argv, 0, NULL, NULL); - if (err) - return err; - - /* Set up libbpf errors and debug info callback */ - libbpf_set_print(libbpf_print_fn); - - /* Cleaner handling of Ctrl-C */ - signal(SIGINT, sig_handler); - signal(SIGTERM, sig_handler); - - /* Load and verify BPF application */ - skel = goroutine_bpf__open(); - if (!skel) { - fprintf(stderr, "Failed to open and load BPF skeleton\n"); - return 1; - } - - /* Parameterize BPF code with minimum duration parameter */ - skel->rodata->min_duration_ns = env.min_duration_ms * 1000000ULL; - - /* Load & verify BPF programs */ - err = goroutine_bpf__load(skel); - if (err) { - fprintf(stderr, "Failed to load and verify BPF skeleton\n"); - goto cleanup; - } - - /* Attach tracepoints */ - err = goroutine_bpf__attach(skel); - if (err) { - fprintf(stderr, "Failed to attach BPF skeleton\n"); - goto cleanup; - } - - /* Set up ring buffer polling */ - rb = ring_buffer__new(bpf_map__fd(skel->maps.rb), handle_event, NULL, NULL); - if (!rb) { - err = -1; - fprintf(stderr, "Failed to create ring buffer\n"); - goto cleanup; - } - - /* Process events */ - printf("%-8s %-5s %-16s %-7s %-7s %s\n", - "TIME", "EVENT", "COMM", "PID", "PPID", "FILENAME/EXIT CODE"); - while (!exiting) { - err = ring_buffer__poll(rb, 100 /* timeout, ms */); - /* Ctrl-C will cause -EINTR */ - if (err == -EINTR) { - err = 0; - break; - } - if (err < 0) { - printf("Error polling perf buffer: %d\n", err); - break; - } - } - -cleanup: - /* Clean up */ - ring_buffer__free(rb); - goroutine_bpf__destroy(skel); - - return err < 0 ? -err : 0; -}