LIBTRACEEVENT(3)

πŸ“¦ version 1.9.0, in ubuntu stonking

πŸ’– LIBTRACEEVENT β€” tep_load_btf, tep_btf_print_args πŸ’–

okay bestie, sit down, hydrate, and let me tell you about the two little functions that make raw kernel numbers look cute: they load a BTF file and use it to pretty print function arguments. it's giving "I can read your structs" energy and honestly? iconic. ✨

(this is a page from the libtraceevent Manual, and it's your new fave, no cap.)


🌸 SYNOPSIS 🌸

#include <event-parse.h>

int tep_load_btf(struct tep_handle *tep, void *raw_data, size_t data_size);
int tep_btf_print_args(struct tep_handle *tep, struct trace_seq *s, void *args,
                       int nmem, int size, const char *func);

πŸ¦‹ DESCRIPTION πŸ¦‹

so first things first: if the Linux kernel has BTF configured, there's a whole binary file just sitting there at /sys/kernel/btf/vmlinux πŸ‘€. If you read that file into memory and hand it over to tep_load_btf(), then the library will use it to parse the arguments of a given function β€” as long as that function's data is actually found inside the BTF file. iykyk.

tep_load_btf() takes the tep handle and loads raw_data into it. and data_size? that's just the size of the content in raw_data. keep them matching, bestie, that's the vibe check. πŸ’…

tep_btf_print_args() takes:

  • a tep handle 🫢
  • a trace_seq s pointer β€” and heads up, this one needs to have been initialized by trace_seq_init(3) first, don't skip that step
  • an args array, which holds either 4 byte or 8 byte values (pick a lane, it's one size per array)
  • nmem, the number of values in the args parameter
  • size, which is either 4 or 8, telling it how big each value in args is
  • func, a string with the name of the function whose BTF info we wanna find and use for parsing

and here's the chill part: if BTF is not loaded, or the func name isn't found, it doesn't crash out 😌 β€” it just prints a hex value of all the args into the s descriptor. lowkey graceful.


✨ RETURN VALUE ✨

  • tep_load_btf() returns 0 on success. on failure it returns -1, and β€” important β€” the raw_data will need to be freed by the caller. that's on you, boo 🫡
  • tep_btf_print_args() returns 0 on success and -1 on failure. failure happens if the size is not valid, or if the BTF file that was loaded is corrupted πŸ’€.

πŸŽ€ EXAMPLE πŸŽ€

okay this is the part where it gets gorgeous. look at this whole setup:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <event-parse.h>

int print_args(const char *func, unsigned long *args, int nr)
{
        struct tep_handle *tep = tep_alloc();
        struct trace_seq s;
        struct stat st;
        void *buf;
        int fd;
        int ret;

        if (!tep)
                return -1;

        fd = open("/sys/kernel/btf/vmlinux", O_RDONLY);
        if (fd < 0)
                return -1;

        if (fstat(fd, &st) < 0) {
                close(fd);
                return -1;
        }

        buf = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
        if (buf == MAP_FAILED) {
                close(fd);
                return -1;
        }

        ret = tep_load_btf(tep, buf, st.st_size);
        munmap(buf, st.st_size);
        close(fd);

        if (ret < 0)
                return -1;

        trace_seq_init(&s);
        trace_seq_printf(&s, "%s(", func);

        tep_btf_print_args(tep, &s, args, nr, sizeof(long), func);

        trace_seq_puts(&s, ")\n");
        trace_seq_do_printf(&s);

        tep_free(tep);
        return 0;
}

int main(int argc, char **argv)
{
        unsigned long args[] = {0x7ffe7d33f3d0, 0, 0, 0, 0, 0};

        print_args("getname_flags", args, 6);
        return 0;
}

...

and the above may output:

  getname_flags(filename=0x7ffe7d33f3d0, flags=0)

if BTF is loaded and the function was found πŸ‘‘ β€” actual named arguments, so pretty, so demure.

or it may show:

  getname_flags(7ffe7d33f3d0, 0, 0, 0, 0, 0)

if it was not πŸ™ˆ β€” just the raw hex numbers, still valid, just less sparkly.

...


πŸ“ FILES πŸ“

  • event-parse.h β€” the header file you include to get access to the library APIs. include it or perish, bestie.
  • -ltraceevent β€” the linker switch you add when building a program that uses the library. don't forget it, the linker will simply not know you πŸ’€.

🌈 SEE ALSO 🌈

libtraceevent(3), trace-cmd(1)


πŸ’œ AUTHOR πŸ’œ

  • Steven Rostedt <rostedt@goodmis.org[1]>, author of libtraceevent. periodt.

πŸ“’ REPORTING BUGS πŸ“’

found a bug? don't gatekeep it, report bugs to <linux-trace-devel@vger.kernel.org[2]> 🫢


πŸ“œ LICENSE πŸ“œ

libtraceevent is Free Software licensed under the GNU LGPL 2.1


⭐ RESOURCES ⭐

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


🧚 NOTES 🧚

  1. rostedt@goodmis.org mailto:rostedt@goodmis.org
  2. linux-trace-devel@vger.kernel.org mailto:linux-trace-devel@vger.kernel.org

and that's the whole page, bestie πŸ’… this was libtraceevent 1.9.0, dated 06/15/2026, and yeah β€” it's LIBTRACEEVENT(3) in the flesh. go forth and pretty-print those args, you absolute main character πŸŽ€βœ¨

πŸ“¦ where this page comes from