129f5ffd3SJiri Olsa 297978b3eSJiri Olsa #include <stdio.h> 397978b3eSJiri Olsa #include <unistd.h> 497978b3eSJiri Olsa #include <stdlib.h> 597978b3eSJiri Olsa #include <errno.h> 697978b3eSJiri Olsa #include <sys/types.h> 797978b3eSJiri Olsa #include <sys/stat.h> 897978b3eSJiri Olsa #include <fcntl.h> 997978b3eSJiri Olsa #include <linux/kernel.h> 108dd2a131SJiri Olsa #include <linux/err.h> 1129f5ffd3SJiri Olsa #include <traceevent/event-parse.h> 12592d5a6bSJiri Olsa #include <api/fs/tracing_path.h> 13*607bfbd7SJiri Olsa #include <api/fs/fs.h> 1429f5ffd3SJiri Olsa #include "trace-event.h" 15c3168b0dSArnaldo Carvalho de Melo #include "machine.h" 1697978b3eSJiri Olsa #include "util.h" 1797978b3eSJiri Olsa 1897978b3eSJiri Olsa /* 1997978b3eSJiri Olsa * global trace_event object used by trace_event__tp_format 2097978b3eSJiri Olsa * 2197978b3eSJiri Olsa * TODO There's no cleanup call for this. Add some sort of 2297978b3eSJiri Olsa * __exit function support and call trace_event__cleanup 2397978b3eSJiri Olsa * there. 2497978b3eSJiri Olsa */ 2597978b3eSJiri Olsa static struct trace_event tevent; 26c3168b0dSArnaldo Carvalho de Melo static bool tevent_initialized; 2729f5ffd3SJiri Olsa 2829f5ffd3SJiri Olsa int trace_event__init(struct trace_event *t) 2929f5ffd3SJiri Olsa { 3029f5ffd3SJiri Olsa struct pevent *pevent = pevent_alloc(); 3129f5ffd3SJiri Olsa 3229f5ffd3SJiri Olsa if (pevent) { 3329f5ffd3SJiri Olsa t->plugin_list = traceevent_load_plugins(pevent); 3429f5ffd3SJiri Olsa t->pevent = pevent; 3529f5ffd3SJiri Olsa } 3629f5ffd3SJiri Olsa 3729f5ffd3SJiri Olsa return pevent ? 0 : -1; 3829f5ffd3SJiri Olsa } 3929f5ffd3SJiri Olsa 40c3168b0dSArnaldo Carvalho de Melo static int trace_event__init2(void) 41c3168b0dSArnaldo Carvalho de Melo { 42c3168b0dSArnaldo Carvalho de Melo int be = traceevent_host_bigendian(); 43c3168b0dSArnaldo Carvalho de Melo struct pevent *pevent; 44c3168b0dSArnaldo Carvalho de Melo 45c3168b0dSArnaldo Carvalho de Melo if (trace_event__init(&tevent)) 46c3168b0dSArnaldo Carvalho de Melo return -1; 47c3168b0dSArnaldo Carvalho de Melo 48c3168b0dSArnaldo Carvalho de Melo pevent = tevent.pevent; 49c3168b0dSArnaldo Carvalho de Melo pevent_set_flag(pevent, PEVENT_NSEC_OUTPUT); 50c3168b0dSArnaldo Carvalho de Melo pevent_set_file_bigendian(pevent, be); 51c3168b0dSArnaldo Carvalho de Melo pevent_set_host_bigendian(pevent, be); 52c3168b0dSArnaldo Carvalho de Melo tevent_initialized = true; 53c3168b0dSArnaldo Carvalho de Melo return 0; 54c3168b0dSArnaldo Carvalho de Melo } 55c3168b0dSArnaldo Carvalho de Melo 56959c2199SArnaldo Carvalho de Melo int trace_event__register_resolver(struct machine *machine, 57959c2199SArnaldo Carvalho de Melo pevent_func_resolver_t *func) 58c3168b0dSArnaldo Carvalho de Melo { 59c3168b0dSArnaldo Carvalho de Melo if (!tevent_initialized && trace_event__init2()) 60c3168b0dSArnaldo Carvalho de Melo return -1; 61c3168b0dSArnaldo Carvalho de Melo 62959c2199SArnaldo Carvalho de Melo return pevent_set_function_resolver(tevent.pevent, func, machine); 63c3168b0dSArnaldo Carvalho de Melo } 64c3168b0dSArnaldo Carvalho de Melo 6529f5ffd3SJiri Olsa void trace_event__cleanup(struct trace_event *t) 6629f5ffd3SJiri Olsa { 678d0c2224SNamhyung Kim traceevent_unload_plugins(t->plugin_list, t->pevent); 6829f5ffd3SJiri Olsa pevent_free(t->pevent); 6929f5ffd3SJiri Olsa } 7097978b3eSJiri Olsa 718dd2a131SJiri Olsa /* 728dd2a131SJiri Olsa * Returns pointer with encoded error via <linux/err.h> interface. 738dd2a131SJiri Olsa */ 7497978b3eSJiri Olsa static struct event_format* 7597978b3eSJiri Olsa tp_format(const char *sys, const char *name) 7697978b3eSJiri Olsa { 7797978b3eSJiri Olsa struct pevent *pevent = tevent.pevent; 7897978b3eSJiri Olsa struct event_format *event = NULL; 7997978b3eSJiri Olsa char path[PATH_MAX]; 8097978b3eSJiri Olsa size_t size; 8197978b3eSJiri Olsa char *data; 828dd2a131SJiri Olsa int err; 8397978b3eSJiri Olsa 8497978b3eSJiri Olsa scnprintf(path, PATH_MAX, "%s/%s/%s/format", 8597978b3eSJiri Olsa tracing_events_path, sys, name); 8697978b3eSJiri Olsa 878dd2a131SJiri Olsa err = filename__read_str(path, &data, &size); 888dd2a131SJiri Olsa if (err) 898dd2a131SJiri Olsa return ERR_PTR(err); 9097978b3eSJiri Olsa 9197978b3eSJiri Olsa pevent_parse_format(pevent, &event, data, size, sys); 9297978b3eSJiri Olsa 9397978b3eSJiri Olsa free(data); 9497978b3eSJiri Olsa return event; 9597978b3eSJiri Olsa } 9697978b3eSJiri Olsa 978dd2a131SJiri Olsa /* 988dd2a131SJiri Olsa * Returns pointer with encoded error via <linux/err.h> interface. 998dd2a131SJiri Olsa */ 10097978b3eSJiri Olsa struct event_format* 10197978b3eSJiri Olsa trace_event__tp_format(const char *sys, const char *name) 10297978b3eSJiri Olsa { 103c3168b0dSArnaldo Carvalho de Melo if (!tevent_initialized && trace_event__init2()) 1048dd2a131SJiri Olsa return ERR_PTR(-ENOMEM); 10597978b3eSJiri Olsa 10697978b3eSJiri Olsa return tp_format(sys, name); 10797978b3eSJiri Olsa } 108