Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 
0003 #include <stdio.h>
0004 #include <unistd.h>
0005 #include <stdlib.h>
0006 #include <errno.h>
0007 #include <sys/types.h>
0008 #include <sys/stat.h>
0009 #include <fcntl.h>
0010 #include <linux/kernel.h>
0011 #include <linux/err.h>
0012 #include <traceevent/event-parse.h>
0013 #include <api/fs/tracing_path.h>
0014 #include <api/fs/fs.h>
0015 #include "trace-event.h"
0016 #include "machine.h"
0017 
0018 /*
0019  * global trace_event object used by trace_event__tp_format
0020  *
0021  * TODO There's no cleanup call for this. Add some sort of
0022  * __exit function support and call trace_event__cleanup
0023  * there.
0024  */
0025 static struct trace_event tevent;
0026 static bool tevent_initialized;
0027 
0028 int trace_event__init(struct trace_event *t)
0029 {
0030     struct tep_handle *pevent = tep_alloc();
0031 
0032     if (pevent) {
0033         t->plugin_list = tep_load_plugins(pevent);
0034         t->pevent  = pevent;
0035     }
0036 
0037     return pevent ? 0 : -1;
0038 }
0039 
0040 static int trace_event__init2(void)
0041 {
0042     int be = tep_is_bigendian();
0043     struct tep_handle *pevent;
0044 
0045     if (trace_event__init(&tevent))
0046         return -1;
0047 
0048     pevent = tevent.pevent;
0049     tep_set_flag(pevent, TEP_NSEC_OUTPUT);
0050     tep_set_file_bigendian(pevent, be);
0051     tep_set_local_bigendian(pevent, be);
0052     tevent_initialized = true;
0053     return 0;
0054 }
0055 
0056 int trace_event__register_resolver(struct machine *machine,
0057                    tep_func_resolver_t *func)
0058 {
0059     if (!tevent_initialized && trace_event__init2())
0060         return -1;
0061 
0062     return tep_set_function_resolver(tevent.pevent, func, machine);
0063 }
0064 
0065 void trace_event__cleanup(struct trace_event *t)
0066 {
0067     tep_unload_plugins(t->plugin_list, t->pevent);
0068     tep_free(t->pevent);
0069 }
0070 
0071 /*
0072  * Returns pointer with encoded error via <linux/err.h> interface.
0073  */
0074 static struct tep_event*
0075 tp_format(const char *sys, const char *name)
0076 {
0077     char *tp_dir = get_events_file(sys);
0078     struct tep_handle *pevent = tevent.pevent;
0079     struct tep_event *event = NULL;
0080     char path[PATH_MAX];
0081     size_t size;
0082     char *data;
0083     int err;
0084 
0085     if (!tp_dir)
0086         return ERR_PTR(-errno);
0087 
0088     scnprintf(path, PATH_MAX, "%s/%s/format", tp_dir, name);
0089     put_events_file(tp_dir);
0090 
0091     err = filename__read_str(path, &data, &size);
0092     if (err)
0093         return ERR_PTR(err);
0094 
0095     tep_parse_format(pevent, &event, data, size, sys);
0096 
0097     free(data);
0098     return event;
0099 }
0100 
0101 /*
0102  * Returns pointer with encoded error via <linux/err.h> interface.
0103  */
0104 struct tep_event*
0105 trace_event__tp_format(const char *sys, const char *name)
0106 {
0107     if (!tevent_initialized && trace_event__init2())
0108         return ERR_PTR(-ENOMEM);
0109 
0110     return tp_format(sys, name);
0111 }
0112 
0113 struct tep_event *trace_event__tp_format_id(int id)
0114 {
0115     if (!tevent_initialized && trace_event__init2())
0116         return ERR_PTR(-ENOMEM);
0117 
0118     return tep_find_event(tevent.pevent, id);
0119 }