# tracefs_dynevent_create

## NAME



           tracefs_dynevent_create, tracefs_dynevent_destroy,
           tracefs_dynevent_destroy_all, tracefs_dynevent_free,
           tracefs_dynevent_list_free, tracefs_dynevent_get,
           tracefs_dynevent_get_all, tracefs_dynevent_info,
           tracefs_dynevent_get_event - Create, destroy, free and get dynamic
           events.
    


## SYNOPSIS



           **#include <tracefs.h>**
    
           struct **tracefs_dynevent** ;
           enum **tracefs_dynevent_type** ;
           int **tracefs_dynevent_create**(struct tracefs_dynevent *_devent_);
           int **tracefs_dynevent_destroy**(struct tracefs_dynevent *_devent_ , bool _force_);
           int **tracefs_dynevent_destroy_all**(unsigned int _types_ , bool _force_);
           void **tracefs_dynevent_free**(struct tracefs_dynevent *_devent_);
           void **tracefs_dynevent_list_free**(struct tracefs_dynevent **_events_);
           struct tracefs_dynevent * **tracefs_dynevent_get**(enum tracefs_dynevent_type _type_ , const char *_system_ , const char *_event_);
           struct tracefs_dynevent ** **tracefs_dynevent_get_all**(unsigned int _types_ , const char *_system_);
           enum tracefs_dynevent_type **tracefs_dynevent_info**(struct tracefs_dynevent *_dynevent_ , char **_system_ , char **_event_ , char **_prefix_ , char **_addr_ , char **_format_);
           struct tep_event * **tracefs_dynevent_get_event**(struct tep_handle *_tep_ , struct tracefs_dynevent *_dynevent_);
    


## DESCRIPTION



           The **tracefs_dynevent_create**() function creates dynamic event
           _devent_ in the system.
    
           The **tracefs_dynevent_destroy**() function removes dynamic event
           _devent_ from the system. If _force_ is true, the function will
           attempt to disable all events in all trace instances, before
           removing the dynamic event. The _devent_ context is not freed, use
           **tracefs_dynevent_free**() to free it.
    
           The **tracefs_dynevent_destroy_all**() function removes all dynamic
           events of given types from the system. The _types_ parameter is a
           type of specific dynamic event, or a bitmask of dynamic events
           types **tracefs_dynevent_type** , that will be removed. If _types_ is 0,
           dynamic events from all types will be removed. If _force_ is true,
           the function will attempt to disable all events in all trace
           instances, before removing the dynamic events.
    
           The **tracefs_dynevent_get**() function allocates and returns a single
           instance of a dynamic event that matches the given **type** , **system**
           and **event** that is passed to it. NULL is returned if there is no
           match. The returned event is what is found in the system, and must
           be freed with **tracefs_dynevent_free**(). If **system** is NULL, then the
           first **event** of any system of the given type that has the name of
           **event** will be returned.
    
           The **tracefs_dynevent_get_all**() function allocates and returns an
           array of pointers to dynamic events of given types that exist in
           the system. The last element of the array is a NULL pointer. The
           array must be freed with **tracefs_dynevent_list_free**(). If there
           are no events a NULL pointer is returned. The _types_ parameter is a
           type of specific dynamic event, or a bitmask of dynamic events
           types **tracefs_dynevent_type** , that will be retrieved. If _types_ is
           0, dynamic events from all types will be retrieved.
    
           The **tracefs_dynevent_free**() function frees a dynamic event context
           _devent_.
    
           The **tracefs_dynevent_list_free**() function frees an array of
           pointers to dynamic event, returned by **tracefs_dynevent_get_all()**
           API.
    
           The **tracefs_dynevent_info**() function returns the type and
           information of a given dynamic event _dynevent_. If any of the
           _system_ , _event_ , _prefix_ , _addr_ or _format_ arguments are not NULL, then
           strings are allocated and returned back via these arguments. The
           _system_ and _event_ holds the system and the name of the dynamic
           event. If _prefix_ is non NULL, then it will hold an allocated
           string that holds the prefix portion of the dynamic event (the
           content up to the ":", exluding it). If _addr_ is non NULL, it will
           hold the address or function that the dynamic event is attached
           to, if relevant for this event type. If _format_ is non NULL, it
           will hold the format string of the dynamic event. Note, that the
           content in _group_ , _event_ , _prefix_ , _addr_ , and _format_ must be freed
           with free(3) if they are set.
    
           The **tracefs_dynevent_get_event**() function returns a tep event,
           describing the given dynamic event. The API detects any newly
           created or removed dynamic events. The returned pointer to tep
           event is controlled by @tep and must not be freed.
    


## RETURN VALUE



           **tracefs_dynevent_create**() returns 0 on success, or -1 on error. If
           a parsing error occurs then tracefs_error_last(3) may be used to
           retrieve the error message explaining the parsing issue.
    
           **tracefs_dynevent_destroy**() and **tracefs_dynevent_destroy_all**()
           return 0 on success, or -1 on error. If _force_ is enabled, the
           functions may fail on disabling the events.
    
           **tracefs_dynevent_get**() function returns an allocated dynamic event
           from the system that matches the type, system and event given.
    
           **tracefs_dynevent_get_all**() function returns allocated array of
           pointers to dynamic events, or NULL in case of an error or in case
           there are no events in the system. That array must be freed by
           **tracefs_dynevent_list_free**().
    
           **tracefs_dynevent_info**() returns the type of the given dynamic
           event or TRACEFS_DYNEVENT_UNKNOWN on error. If _system_ , _event_ ,
           _prefix_ , _addr_ , or _format_ are non NULL, they will contain allocated
           strings that must be freed by free(3).
    
           The **tracefs_dynevent_get_event**() function returns a pointer to a
           tep event or NULL in case of an error or if the requested dynamic
           event is missing. The returned pointer to tep event is controlled
           by @tep and must not be freed.
    


## ERRORS



           The following errors are for all the above calls:
    
           **ENODEV** dynamic events of requested type are not configured for the
           running kernel.
    
           **ENOMEM** Memory allocation error.
    
           **tracefs_dynevent_create**() can fail with the following errors:
    
           **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";
    
               int main (int argc, char **argv, char **env)
               {
                       struct tracefs_dynevent *kprobe, *kretprobe;
                       const char *sysnames[] = { mykprobe, NULL };
                       struct tracefs_instance *instance;
                       struct tep_handle *tep;
                       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 = tracefs_kprobe_alloc(mykprobe, "open", "do_sys_openat2",
                                                     "file=+0($arg2):ustring flags=+0($arg3):x64 mode=+8($arg3):x64\n");
                       kretprobe = tracefs_kretprobe_alloc(mykprobe, "openret", "do_sys_openat2", "ret=%ax", 0);
                       if (!kprobe || !kretprobe) {
                               perror("allocating dynamic events");
                               exit(-1);
                       }
    
                       if (tracefs_dynevent_create(kprobe) || tracefs_dynevent_create(kretprobe)){
                               char *err = tracefs_error_last(NULL);
                               perror("Failed to create kprobes:");
                               if (err && strlen(err))
                                       fprintf(stderr, "%s\n", err);
                               exit(-1);
                       }
    
                       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_dynevent_free(kprobe);
                       tracefs_dynevent_free(kretprobe);
                       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.
    


## 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. y.karadz@gmail.com
               mailto:y.karadz@gmail.com
    
            4. linux-trace-devel@vger.kernel.org
               mailto:linux-trace-devel@vger.kernel.org
    


* * *