LIBTRACEFS(3)

πŸ’… LIBTRACEFS(3) β€” libtracefs manual, but make it a group chat

okay so this is the libtracefs(3) page, bestie, and today we're deep-diving tracefs_eprobe_alloc. yes it's a mouthful, no you're not going to pronounce it right the first time, and yes it slays anyway. let's go 🫢


✨ NAME ✨

tracefs_eprobe_alloc β€” allocate a new event probe (eprobe). that's it. that's the whole name section. iconic brevity πŸ’…


πŸ¦‹ SYNOPSIS πŸ¦‹

#include <tracefs.h>

struct tracefs_dynevent *
tracefs_eprobe_alloc(const char *system, const char *event,
                       const char *target_system, const char *target_event,
                       const char *fetchargs);

five arguments, one struct pointer coming back, zero drama. drink water before you type it though πŸ’–


🌸 DESCRIPTION 🌸

so tracefs_eprobe_alloc() allocates a brand-new eprobe context for you. and like β€” key thing β€” the eprobe is not configured in the system yet. it's just a descriptor chillin'. nothing has actually happened to your kernel. we love a low-commitment queen ✨

the new eprobe will live in the system group β€” or, if system is NULL, it goes in eprobes (nice, a sensible default, we stan). its name will be event.

the eprobe gets attached to target_event, which is located in target_system. and the list of arguments described in fetchargs gets fetched from target_event. so like, you're pulling data out of the target event and stuffing it into your new probe. very "borrowing your bestie's notes" energy ngl πŸŽ€

heads up: the pointer you get back must be freed with tracefs_dynevent_free(). don't just ghost it, free it. 😭

πŸ”₯ RETURN VALUE πŸ”₯

tracefs_eprobe_alloc() returns a pointer to an allocated tracefs_dynevent structure that describes the event probe. that pointer must be freed by tracefs_dynevent_free(3). periodt.

note β€” and this is the important bit β€” this function only allocates a descriptor representing the eprobe. it does not modify the running system. it's giving "draft in your notes app," not "posted to the group chat." πŸ“

on error, NULL is returned. so check it. always check it. i'm literally begging πŸ™ˆ


πŸ’œ EXAMPLE πŸ’œ

here's the whole thing, verbatim, no cap β€” a full program that sets up an eprobe on sys_enter_openat2, runs a command, and prints out which files got opened:

#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

#include <tracefs.h>

static struct tep_event *open_event;
static struct tep_format_field *file_field;

static int callback(struct tep_event *event, struct tep_record *record,
                    int cpu, void *data)
{
        struct trace_seq seq;

        trace_seq_init(&seq);
        tep_print_event(event->tep, &seq, record, "%d-%s: ", TEP_PRINT_PID, TEP_PRINT_COMM);

        if (event->id == open_event->id) {
                trace_seq_puts(&seq, "open file='");
                tep_print_field(&seq, record->data, file_field);
                trace_seq_puts(&seq, "'\n");
        }

        trace_seq_terminate(&seq);
        trace_seq_do_printf(&seq);
        trace_seq_destroy(&seq);

        return 0;
}

static pid_t run_exec(char **argv, char **env)
{
        pid_t pid;

        pid = fork();
        if (pid)
                return pid;

        execve(argv[0], argv, env);
        perror("exec");
        exit(-1);
}

const char *myprobe = "my_eprobes";

int main (int argc, char **argv, char **env)
{
        struct tracefs_dynevent *eprobe;
        struct tracefs_instance *instance;
        struct tep_handle *tep;
        const char *sysnames[] = { myprobe, NULL };
        pid_t pid;

        if (argc < 2) {
                printf("usage: %s command\n", argv[0]);
                exit(-1);
        }

        instance = tracefs_instance_create("exec_open");
        if (!instance) {
                perror("creating instance");
                exit(-1);
        }

        tracefs_dynevent_destroy_all(TRACEFS_DYNEVENT_EPROBE, true);

        eprobe = tracefs_eprobe_alloc(myprobe, "sopen", "syscalls", "sys_enter_openat2",
                                      "file=+0($filename):ustring");
        if (!eprobe) {
                perror("allocating event probe");
                exit(-1);
        }

        if (tracefs_dynevent_create(eprobe)) {
                perror("creating event probe");
                exit(-1);
        }

        tep = tracefs_local_events_system(NULL, sysnames);
        if (!tep) {
                perror("reading events");
                exit(-1);
        }

        open_event = tep_find_event_by_name(tep, myprobe, "sopen");
        file_field = tep_find_field(open_event, "file");

        tracefs_event_enable(instance, myprobe, "sopen");
        pid = run_exec(&argv[1], env);

        /* Let the child start to run */
        sched_yield();

        do {
                tracefs_load_cmdlines(NULL, tep);
                tracefs_iterate_raw_events(tep, instance, NULL, 0, callback, NULL);
        } while (waitpid(pid, NULL, WNOHANG) != pid);

        /* Will disable the events */
        tracefs_dynevent_destroy(eprobe, true);
        tracefs_dynevent_free(eprobe);
        tracefs_instance_destroy(instance);
        tep_free(tep);

        return 0;
}

notice the "file=+0($filename):ustring" fetcharg β€” that's the "pull the filename out of the target event" part, main character energy honestly πŸ‘‘


πŸŽ€ FILES πŸŽ€

  • tracefs.h β€” the header file you include to get access to the library APIs. include it, don't fight it.
  • -ltracefs β€” the linker switch you add when building a program that uses the library. yes, it goes at the end, you know this πŸ’…

🌈 SEE ALSO 🌈

go read those too, i'm not joking, they're literally right there πŸ¦‹


πŸ‘‘ AUTHOR πŸ‘‘

  • Steven Rostedt <rostedt@goodmis.org[1]>
  • Tzvetomir Stoyanov <tz.stoyanov@gmail.com[2]>

legends. both of them. 🫢


πŸ’€ REPORTING BUGS πŸ’€

report bugs to <linux-trace-devel@vger.kernel.org[3]>

not me, bestie, i just write the vibes 😭


⭐ LICENSE ⭐

libtracefs is Free Software licensed under the GNU LGPL 2.1. read it, respect it, love it 🧚


πŸ“ RESOURCES πŸ“

https://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git/

the source. the mothership. go touch it 🌸


🌸 COPYING 🌸

Copyright (C) 2021 VMware, Inc. Free use of this software is granted under the terms of the GNU Public License (GPL).


πŸ“Ž NOTES πŸ“Ž

  1. rostedt@goodmis.org β€” mailto:rostedt@goodmis.org
  2. tz.stoyanov@gmail.com β€” mailto:tz.stoyanov@gmail.com
  3. linux-trace-devel@vger.kernel.org β€” mailto:linux-trace-devel@vger.kernel.org

and that's the whole page!! πŸŽ‰ this was libtracefs 1.8.4, dated 10/21/2026 β€” screenshot it, bookmark it, tattoo it on your forearm, whatever you need to do. mwah πŸ’‹βœ¨

πŸ“¦ where this page comes from