1 // SPDX-License-Identifier: GPL-2.0 2 3 #include <stdio.h> 4 #include <unistd.h> 5 #include <stdlib.h> 6 #include <errno.h> 7 #include <sys/types.h> 8 #include <sys/stat.h> 9 #include <fcntl.h> 10 #include <linux/kernel.h> 11 #include <linux/err.h> 12 #include <traceevent/event-parse.h> 13 #include <api/fs/tracing_path.h> 14 #include <api/fs/fs.h> 15 #include "trace-event.h" 16 #include "machine.h" 17 #include "util.h" 18 19 /* 20 * global trace_event object used by trace_event__tp_format 21 * 22 * TODO There's no cleanup call for this. Add some sort of 23 * __exit function support and call trace_event__cleanup 24 * there. 25 */ 26 static struct trace_event tevent; 27 static bool tevent_initialized; 28 29 int trace_event__init(struct trace_event *t) 30 { 31 struct pevent *pevent = pevent_alloc(); 32 33 if (pevent) { 34 t->plugin_list = traceevent_load_plugins(pevent); 35 t->pevent = pevent; 36 } 37 38 return pevent ? 0 : -1; 39 } 40 41 static int trace_event__init2(void) 42 { 43 int be = traceevent_host_bigendian(); 44 struct pevent *pevent; 45 46 if (trace_event__init(&tevent)) 47 return -1; 48 49 pevent = tevent.pevent; 50 pevent_set_flag(pevent, PEVENT_NSEC_OUTPUT); 51 pevent_set_file_bigendian(pevent, be); 52 pevent_set_host_bigendian(pevent, be); 53 tevent_initialized = true; 54 return 0; 55 } 56 57 int trace_event__register_resolver(struct machine *machine, 58 pevent_func_resolver_t *func) 59 { 60 if (!tevent_initialized && trace_event__init2()) 61 return -1; 62 63 return pevent_set_function_resolver(tevent.pevent, func, machine); 64 } 65 66 void trace_event__cleanup(struct trace_event *t) 67 { 68 traceevent_unload_plugins(t->plugin_list, t->pevent); 69 pevent_free(t->pevent); 70 } 71 72 /* 73 * Returns pointer with encoded error via <linux/err.h> interface. 74 */ 75 static struct event_format* 76 tp_format(const char *sys, const char *name) 77 { 78 struct pevent *pevent = tevent.pevent; 79 struct event_format *event = NULL; 80 char path[PATH_MAX]; 81 size_t size; 82 char *data; 83 int err; 84 85 scnprintf(path, PATH_MAX, "%s/%s/%s/format", 86 tracing_events_path, sys, name); 87 88 err = filename__read_str(path, &data, &size); 89 if (err) 90 return ERR_PTR(err); 91 92 pevent_parse_format(pevent, &event, data, size, sys); 93 94 free(data); 95 return event; 96 } 97 98 /* 99 * Returns pointer with encoded error via <linux/err.h> interface. 100 */ 101 struct event_format* 102 trace_event__tp_format(const char *sys, const char *name) 103 { 104 if (!tevent_initialized && trace_event__init2()) 105 return ERR_PTR(-ENOMEM); 106 107 return tp_format(sys, name); 108 } 109 110 struct event_format *trace_event__tp_format_id(int id) 111 { 112 if (!tevent_initialized && trace_event__init2()) 113 return ERR_PTR(-ENOMEM); 114 115 return pevent_find_event(tevent.pevent, id); 116 } 117