18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci 38c2ecf20Sopenharmony_ci#include <stdio.h> 48c2ecf20Sopenharmony_ci#include <unistd.h> 58c2ecf20Sopenharmony_ci#include <stdlib.h> 68c2ecf20Sopenharmony_ci#include <errno.h> 78c2ecf20Sopenharmony_ci#include <sys/types.h> 88c2ecf20Sopenharmony_ci#include <sys/stat.h> 98c2ecf20Sopenharmony_ci#include <fcntl.h> 108c2ecf20Sopenharmony_ci#include <linux/kernel.h> 118c2ecf20Sopenharmony_ci#include <linux/err.h> 128c2ecf20Sopenharmony_ci#include <traceevent/event-parse.h> 138c2ecf20Sopenharmony_ci#include <api/fs/tracing_path.h> 148c2ecf20Sopenharmony_ci#include <api/fs/fs.h> 158c2ecf20Sopenharmony_ci#include "trace-event.h" 168c2ecf20Sopenharmony_ci#include "machine.h" 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci/* 198c2ecf20Sopenharmony_ci * global trace_event object used by trace_event__tp_format 208c2ecf20Sopenharmony_ci * 218c2ecf20Sopenharmony_ci * TODO There's no cleanup call for this. Add some sort of 228c2ecf20Sopenharmony_ci * __exit function support and call trace_event__cleanup 238c2ecf20Sopenharmony_ci * there. 248c2ecf20Sopenharmony_ci */ 258c2ecf20Sopenharmony_cistatic struct trace_event tevent; 268c2ecf20Sopenharmony_cistatic bool tevent_initialized; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ciint trace_event__init(struct trace_event *t) 298c2ecf20Sopenharmony_ci{ 308c2ecf20Sopenharmony_ci struct tep_handle *pevent = tep_alloc(); 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci if (pevent) { 338c2ecf20Sopenharmony_ci t->plugin_list = tep_load_plugins(pevent); 348c2ecf20Sopenharmony_ci t->pevent = pevent; 358c2ecf20Sopenharmony_ci } 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci return pevent ? 0 : -1; 388c2ecf20Sopenharmony_ci} 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_cistatic int trace_event__init2(void) 418c2ecf20Sopenharmony_ci{ 428c2ecf20Sopenharmony_ci int be = tep_is_bigendian(); 438c2ecf20Sopenharmony_ci struct tep_handle *pevent; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci if (trace_event__init(&tevent)) 468c2ecf20Sopenharmony_ci return -1; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci pevent = tevent.pevent; 498c2ecf20Sopenharmony_ci tep_set_flag(pevent, TEP_NSEC_OUTPUT); 508c2ecf20Sopenharmony_ci tep_set_file_bigendian(pevent, be); 518c2ecf20Sopenharmony_ci tep_set_local_bigendian(pevent, be); 528c2ecf20Sopenharmony_ci tevent_initialized = true; 538c2ecf20Sopenharmony_ci return 0; 548c2ecf20Sopenharmony_ci} 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ciint trace_event__register_resolver(struct machine *machine, 578c2ecf20Sopenharmony_ci tep_func_resolver_t *func) 588c2ecf20Sopenharmony_ci{ 598c2ecf20Sopenharmony_ci if (!tevent_initialized && trace_event__init2()) 608c2ecf20Sopenharmony_ci return -1; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci return tep_set_function_resolver(tevent.pevent, func, machine); 638c2ecf20Sopenharmony_ci} 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_civoid trace_event__cleanup(struct trace_event *t) 668c2ecf20Sopenharmony_ci{ 678c2ecf20Sopenharmony_ci tep_unload_plugins(t->plugin_list, t->pevent); 688c2ecf20Sopenharmony_ci tep_free(t->pevent); 698c2ecf20Sopenharmony_ci} 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci/* 728c2ecf20Sopenharmony_ci * Returns pointer with encoded error via <linux/err.h> interface. 738c2ecf20Sopenharmony_ci */ 748c2ecf20Sopenharmony_cistatic struct tep_event* 758c2ecf20Sopenharmony_citp_format(const char *sys, const char *name) 768c2ecf20Sopenharmony_ci{ 778c2ecf20Sopenharmony_ci char *tp_dir = get_events_file(sys); 788c2ecf20Sopenharmony_ci struct tep_handle *pevent = tevent.pevent; 798c2ecf20Sopenharmony_ci struct tep_event *event = NULL; 808c2ecf20Sopenharmony_ci char path[PATH_MAX]; 818c2ecf20Sopenharmony_ci size_t size; 828c2ecf20Sopenharmony_ci char *data; 838c2ecf20Sopenharmony_ci int err; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci if (!tp_dir) 868c2ecf20Sopenharmony_ci return ERR_PTR(-errno); 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci scnprintf(path, PATH_MAX, "%s/%s/format", tp_dir, name); 898c2ecf20Sopenharmony_ci put_events_file(tp_dir); 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci err = filename__read_str(path, &data, &size); 928c2ecf20Sopenharmony_ci if (err) 938c2ecf20Sopenharmony_ci return ERR_PTR(err); 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci tep_parse_format(pevent, &event, data, size, sys); 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci free(data); 988c2ecf20Sopenharmony_ci return event; 998c2ecf20Sopenharmony_ci} 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci/* 1028c2ecf20Sopenharmony_ci * Returns pointer with encoded error via <linux/err.h> interface. 1038c2ecf20Sopenharmony_ci */ 1048c2ecf20Sopenharmony_cistruct tep_event* 1058c2ecf20Sopenharmony_citrace_event__tp_format(const char *sys, const char *name) 1068c2ecf20Sopenharmony_ci{ 1078c2ecf20Sopenharmony_ci if (!tevent_initialized && trace_event__init2()) 1088c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci return tp_format(sys, name); 1118c2ecf20Sopenharmony_ci} 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_cistruct tep_event *trace_event__tp_format_id(int id) 1148c2ecf20Sopenharmony_ci{ 1158c2ecf20Sopenharmony_ci if (!tevent_initialized && trace_event__init2()) 1168c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci return tep_find_event(tevent.pevent, id); 1198c2ecf20Sopenharmony_ci} 120