tracefs_kprobe_alloc(3) — Linux manual page

NAME | SYNOPSIS | DESCRIPTION | RETURN VALUE | ERRORS | EXAMPLE | FILES | SEE ALSO | AUTHOR | REPORTING BUGS | LICENSE | RESOURCES | COPYING | NOTES | COLOPHON

LIBTRACEFS(3)               libtracefs Manual              LIBTRACEFS(3)

NAME         top

       tracefs_kprobe_alloc, tracefs_kretprobe_alloc,
       tracefs_kprobe_raw, tracefs_kretprobe_raw, tracefs_kprobe_destroy
       - Allocate, get, create, and remove kprobes

SYNOPSIS         top

       #include <tracefs.h>

       struct tracefs_dynevent *
       tracefs_kprobe_alloc(const char *system, const char *event,
                              const char *addr, const char *format);
       struct tracefs_dynevent *
       tracefs_kretprobe_alloc(const char *system, const char *event,
                                 const char *addr, const char *format, unsigned int max);
       int tracefs_kprobe_raw(const char *system, const char *event,
                                const char *addr, const char *format);
       int tracefs_kretprobe_raw(const char *system, const char *event,
                                   const char *addr, const char *format);
       int tracefs_kprobe_destroy(const char *system, const char *event,
                                  const char *addr, const char *format, bool force);

DESCRIPTION         top

       tracefs_kprobe_alloc() allocates a new kprobe context. The kbrobe
       is not configured in the system. The kprobe can be added to the
       system by passing in the returned descriptor into
       tracefs_dynevent_create(3). The new kprobe will be in the system
       group (or kprobes if system is NULL) and have the name of event
       (or addr if event is NULL). The kprobe will be inserted to addr
       (function name, with or without offset, or a address), and the
       format will define the format of the kprobe. See the Linux
       documentation file under: Documentation/trace/kprobetrace.rst

       tracefs_kretprobe_alloc() is the same as tracefs_kprobe_alloc,
       but allocates context for kretprobe. It has one additional
       parameter, which is optional, max - maxactive count. See
       description of kretprobes in the
       Documentation/trace/kprobetrace.rst file.

       tracefs_kprobe_raw() will create a kprobe event. If system is
       NULL, then the default "kprobes" is used for the group (event
       system). Otherwise if system is specified then the kprobe will be
       created under the group by that name. The event is the name of
       the kprobe event to create. The addr can be a function, a
       function and offset, or a kernel address. This is where the
       location of the kprobe will be inserted in the kernel. The format
       is the kprobe format as specified as FETCHARGS in the Linux
       kernel source in the Documentation/trace/kprobetrace.rst
       document.

       tracefs_kretprobe_raw() is the same as tracefs_kprobe_raw(),
       except that it creates a kretprobe instead of a kprobe. The
       difference is also described in the Linux kernel source in the
       Documentation/trace/kprobetrace.rst file.

       tracefs_kprobe_destroy() will destroy a specific kprobe or
       kretprobe created by tracefs_kprobe_raw() or
       tracefs_kretprobe_raw() with the same parameters.

RETURN VALUE         top

       tracefs_kprobe_raw() and tracefs_kretprobe_raw() return 0 on
       success, or -1 on error. If a parsing error occurs on
       tracefs_kprobe_raw() or tracefs_kretprobe_raw() then
       tracefs_error_last(3) may be used to retrieve the error message
       explaining the parsing issue.

       The tracefs_kprobe_alloc() and tracefs_kretprobe_alloc() APIs
       return a pointer to an allocated tracefs_dynevent structure,
       describing the probe. This pointer must be freed by
       tracefs_dynevent_free(3). Note, this only allocates a descriptor
       representing the kprobe. It does not modify the running system.

       The tracefs_kprobe_destroy() returns 0 on success or -1 on error
       if it was not able to successful destory (or find) the kprobe or
       kretprobe.

ERRORS         top

       The following errors are for all the above calls:

       EPERM Not run as root user

       ENODEV Kprobe events are not configured for the running kernel.

       ENOMEM Memory allocation error.

       tracefs_kprobe_raw(), tracefs_kretprobe_raw(),
       tracefs_kprobe_alloc(), and tracefs_kretprobe_alloc() can fail
       with the following errors:

       EBADMSG if addr is NULL.

       EINVAL Most likely a parsing error occurred (use
       tracefs_error_last(3) to possibly see what that error was).

       Other errors may also happen caused by internal system calls.

EXAMPLE         top

           #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 struct tep_event *openret_event;
           static struct tep_format_field *ret_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");
                   } else if (event->id == openret_event->id) {
                           unsigned long long ret;
                           tep_read_number_field(ret_field, record->data, &ret);
                           trace_seq_printf(&seq, "open ret=%lld\n", ret);
                   } else {
                           goto out;
                   }

                   trace_seq_terminate(&seq);
                   trace_seq_do_printf(&seq);
           out:
                   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 *mykprobe = "my_kprobes";

           enum kprobe_type {
                   KPROBE,
                   KRETPROBE,
           };

           static void __kprobe_create(enum kprobe_type type, const char *event,
                                       const char *addr, const char *fmt)
           {
                   char *err;
                   int r;

                   if (type == KPROBE)
                           r = tracefs_kprobe_raw(mykprobe, event, addr, fmt);
                   else
                           r = tracefs_kretprobe_raw(mykprobe, event, addr, fmt);
                   if (r < 0) {
                           err = tracefs_error_last(NULL);
                           perror("Failed to create kprobe:");
                           if (err && strlen(err))
                                   fprintf(stderr, "%s\n", err);
                   }
           }

           static void kprobe_create(const char *event, const char *addr,
                                     const char *fmt)
           {
                   __kprobe_create(KPROBE, event, addr, fmt);
           }

           static void kretprobe_create(const char *event, const char *addr,
                                        const char *fmt)
           {
                   __kprobe_create(KRETPROBE, event, addr, fmt);
           }

           int main (int argc, char **argv, char **env)
           {
                   struct tracefs_instance *instance;
                   struct tep_handle *tep;
                   const char *sysnames[] = { mykprobe, 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_KPROBE | TRACEFS_DYNEVENT_KRETPROBE, true);

                   kprobe_create("open", "do_sys_openat2",
                                 "file=+0($arg2):ustring flags=+0($arg3):x64 mode=+8($arg3):x64\n");

                   kretprobe_create("openret", "do_sys_openat2", "ret=%ax");

                   tep = tracefs_local_events_system(NULL, sysnames);
                   if (!tep) {
                           perror("reading events");
                           exit(-1);
                   }
                   open_event = tep_find_event_by_name(tep, mykprobe, "open");
                   file_field = tep_find_field(open_event, "file");

                   openret_event = tep_find_event_by_name(tep, mykprobe, "openret");
                   ret_field = tep_find_field(openret_event, "ret");

                   tracefs_event_enable(instance, mykprobe, NULL);
                   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_all(TRACEFS_DYNEVENT_KPROBE | TRACEFS_DYNEVENT_KRETPROBE, true);
                   tracefs_instance_destroy(instance);
                   tep_free(tep);

                   return 0;
           }

FILES         top

           tracefs.h
                   Header file to include in order to have access to the library APIs.
           -ltracefs
                   Linker switch to add when building a program that uses the library.

SEE ALSO         top

       libtracefs(3), libtraceevent(3), trace-cmd(1)

AUTHOR         top

           Steven Rostedt <rostedt@goodmis.org[1]>
           Tzvetomir Stoyanov <tz.stoyanov@gmail.com[2]>
           sameeruddin shaik <sameeruddin.shaik8@gmail.com[3]>

REPORTING BUGS         top

       Report bugs to <linux-trace-devel@vger.kernel.org[4]>

LICENSE         top

       libtracefs is Free Software licensed under the GNU LGPL 2.1

RESOURCES         top

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

COPYING         top

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

NOTES         top

        1. rostedt@goodmis.org
           mailto:rostedt@goodmis.org

        2. tz.stoyanov@gmail.com
           mailto:tz.stoyanov@gmail.com

        3. sameeruddin.shaik8@gmail.com
           mailto:sameeruddin.shaik8@gmail.com

        4. linux-trace-devel@vger.kernel.org
           mailto:linux-trace-devel@vger.kernel.org

COLOPHON         top

       This page is part of the libtracefs (Linux kernel trace file
       system library) project.  Information about the project can be
       found at ⟨https://www.trace-cmd.org/⟩.  If you have a bug report
       for this manual page, see ⟨https://www.trace-cmd.org/⟩.  This
       page was obtained from the project's upstream Git repository
       ⟨https://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git⟩ on
       2023-12-22.  (At that time, the date of the most recent commit
       that was found in the repository was 2023-07-05.)  If you
       discover any rendering problems in this HTML version of the page,
       or you believe there is a better or more up-to-date source for
       the page, or you have corrections or improvements to the
       information in this COLOPHON (which is not part of the original
       manual page), send a mail to man-pages@man7.org

libtracefs 1.7.0               12/22/2023                  LIBTRACEFS(3)