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 tep_handle *pevent = tep_alloc(); 32 33 if (pevent) { 34 t->plugin_list = tep_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 = tep_is_bigendian(); 44 struct tep_handle *pevent; 45 46 if (trace_event__init(&tevent)) 47 return -1; 48 49 pevent = tevent.pevent; 50 tep_set_flag(pevent, TEP_NSEC_OUTPUT); 51 tep_set_file_bigendian(pevent, be); 52 tep_set_local_bigendian(pevent, be); 53 tevent_initialized = true; 54 return 0; 55 } 56 57 int trace_event__register_resolver(struct machine *machine, 58 tep_func_resolver_t *func) 59 { 60 if (!tevent_initialized && trace_event__init2()) 61 return -1; 62 63 return tep_set_function_resolver(tevent.pevent, func, machine); 64 } 65 66 void trace_event__cleanup(struct trace_event *t) 67 { 68 tep_unload_plugins(t->plugin_list, t->pevent); 69 tep_free(t->pevent); 70 } 71 72 /* 73 * Returns pointer with encoded error via <linux/err.h> interface. 74 */ 75 static struct tep_event* 76 tp_format(const char *sys, const char *name) 77 { 78 char *tp_dir = get_events_file(sys); 79 struct tep_handle *pevent = tevent.pevent; 80 struct tep_event *event = NULL; 81 char path[PATH_MAX]; 82 size_t size; 83 char *data; 84 int err; 85 86 if (!tp_dir) 87 return ERR_PTR(-errno); 88 89 scnprintf(path, PATH_MAX, "%s/%s/format", tp_dir, name); 90 put_events_file(tp_dir); 91 92 err = filename__read_str(path, &data, &size); 93 if (err) 94 return ERR_PTR(err); 95 96 tep_parse_format(pevent, &event, data, size, sys); 97 98 free(data); 99 return event; 100 } 101 102 /* 103 * Returns pointer with encoded error via <linux/err.h> interface. 104 */ 105 struct tep_event* 106 trace_event__tp_format(const char *sys, const char *name) 107 { 108 if (!tevent_initialized && trace_event__init2()) 109 return ERR_PTR(-ENOMEM); 110 111 return tp_format(sys, name); 112 } 113 114 struct tep_event *trace_event__tp_format_id(int id) 115 { 116 if (!tevent_initialized && trace_event__init2()) 117 return ERR_PTR(-ENOMEM); 118 119 return tep_find_event(tevent.pevent, id); 120 } 121