Provided by: libtracefs-doc_1.4.2-1_all bug

NAME

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

SYNOPSIS

       #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);

DESCRIPTION

       tracefs_kprobe_alloc() allocates a new kprobe context. The kbrobe is not configured in the
       system. 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.

RETURN VALUE

       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.

ERRORS

       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

           #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

           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

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

AUTHOR

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

REPORTING BUGS

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

LICENSE

       libtracefs is Free Software licensed under the GNU LGPL 2.1

RESOURCES

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

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. sameeruddin.shaik8@gmail.com
           mailto:sameeruddin.shaik8@gmail.com

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