757 lines · 21.1 KB · C
RawDownload
/* SPDX-License-Identifier: LGPL-2.1 *//* * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> * */#ifndef _PARSE_EVENTS_H#define _PARSE_EVENTS_H #include <stdbool.h>#include <stdarg.h>#include <stdio.h>#include <regex.h>#include <string.h> #include "trace-seq.h" #ifndef __maybe_unused#define __maybe_unused __attribute__((unused))#endif #ifndef DEBUG_RECORD#define DEBUG_RECORD 0#endif struct tep_record {	unsigned long long	ts;	unsigned long long	offset;	long long		missed_events;	/* buffer dropped events before */	int			record_size;	/* size of binary record */	int			size;		/* size of data */	void			*data;	int			cpu;	int			ref_count;	int			locked;		/* Do not free, even if ref_count is zero */	void			*priv;#if DEBUG_RECORD	struct tep_record	*prev;	struct tep_record	*next;	long			alloc_addr;#endif}; /* ----------------------- tep ----------------------- */ struct tep_handle;struct tep_event; typedef int (*tep_event_handler_func)(struct trace_seq *s,				      struct tep_record *record,				      struct tep_event *event,				      void *context); typedef int (*tep_plugin_load_func)(struct tep_handle *tep);typedef int (*tep_plugin_unload_func)(struct tep_handle *tep); struct tep_plugin_option {	struct tep_plugin_option	*next;	void				*handle;	char				*file;	char				*name;	char				*plugin_alias;	char				*description;	const char			*value;	void				*priv;	int				set;}; /* * Plugin hooks that can be called: * * TEP_PLUGIN_LOADER:  (required) *   The function name to initialized the plugin. * *   int TEP_PLUGIN_LOADER(struct tep_handle *tep) * * TEP_PLUGIN_UNLOADER:  (optional) *   The function called just before unloading * *   int TEP_PLUGIN_UNLOADER(struct tep_handle *tep) * * TEP_PLUGIN_OPTIONS:  (optional) *   Plugin options that can be set before loading * *   struct tep_plugin_option TEP_PLUGIN_OPTIONS[] = { *	{ *		.name = "option-name", *		.plugin_alias = "override-file-name", (optional) *		.description = "description of option to show users", *	}, *	{ *		.name = NULL, *	}, *   }; * *   Array must end with .name = NULL; * * *   .plugin_alias is used to give a shorter name to access *   the vairable. Useful if a plugin handles more than one event. * *   If .value is not set, then it is considered a boolean and only *   .set will be processed. If .value is defined, then it is considered *   a string option and .set will be ignored. * * TEP_PLUGIN_ALIAS: (optional) *   The name to use for finding options (uses filename if not defined) */#define TEP_PLUGIN_LOADER tep_plugin_loader#define TEP_PLUGIN_UNLOADER tep_plugin_unloader#define TEP_PLUGIN_OPTIONS tep_plugin_options#define TEP_PLUGIN_ALIAS tep_plugin_alias#define _MAKE_STR(x)	#x#define MAKE_STR(x)	_MAKE_STR(x)#define TEP_PLUGIN_LOADER_NAME MAKE_STR(TEP_PLUGIN_LOADER)#define TEP_PLUGIN_UNLOADER_NAME MAKE_STR(TEP_PLUGIN_UNLOADER)#define TEP_PLUGIN_OPTIONS_NAME MAKE_STR(TEP_PLUGIN_OPTIONS)#define TEP_PLUGIN_ALIAS_NAME MAKE_STR(TEP_PLUGIN_ALIAS) enum tep_format_flags {	TEP_FIELD_IS_ARRAY	= 1,	TEP_FIELD_IS_POINTER	= 2,	TEP_FIELD_IS_SIGNED	= 4,	TEP_FIELD_IS_STRING	= 8,	TEP_FIELD_IS_DYNAMIC	= 16,	TEP_FIELD_IS_LONG	= 32,	TEP_FIELD_IS_FLAG	= 64,	TEP_FIELD_IS_SYMBOLIC	= 128,}; struct tep_format_field {	struct tep_format_field	*next;	struct tep_event	*event;	char			*type;	char			*name;	char			*alias;	int			offset;	int			size;	unsigned int		arraylen;	unsigned int		elementsize;	unsigned long		flags;}; struct tep_format {	int			nr_common;	int			nr_fields;	struct tep_format_field	*common_fields;	struct tep_format_field	*fields;}; struct tep_print_arg_atom {	char			*atom;}; struct tep_print_arg_string {	char			*string;	int			offset;}; struct tep_print_arg_bitmask {	char			*bitmask;	int			offset;}; struct tep_print_arg_field {	char			*name;	struct tep_format_field	*field;}; struct tep_print_flag_sym {	struct tep_print_flag_sym	*next;	char				*value;	char				*str;}; struct tep_print_arg_typecast {	char 			*type;	struct tep_print_arg	*item;}; struct tep_print_arg_flags {	struct tep_print_arg		*field;	char				*delim;	struct tep_print_flag_sym	*flags;}; struct tep_print_arg_symbol {	struct tep_print_arg		*field;	struct tep_print_flag_sym	*symbols;}; struct tep_print_arg_hex {	struct tep_print_arg	*field;	struct tep_print_arg	*size;}; struct tep_print_arg_int_array {	struct tep_print_arg	*field;	struct tep_print_arg	*count;	struct tep_print_arg	*el_size;}; struct tep_print_arg_dynarray {	struct tep_format_field	*field;	struct tep_print_arg	*index;}; struct tep_print_arg; struct tep_print_arg_op {	char			*op;	int			prio;	struct tep_print_arg	*left;	struct tep_print_arg	*right;}; struct tep_function_handler; struct tep_print_arg_func {	struct tep_function_handler	*func;	struct tep_print_arg		*args;}; enum tep_print_arg_type {	TEP_PRINT_NULL,	TEP_PRINT_ATOM,	TEP_PRINT_FIELD,	TEP_PRINT_FLAGS,	TEP_PRINT_SYMBOL,	TEP_PRINT_HEX,	TEP_PRINT_INT_ARRAY,	TEP_PRINT_TYPE,	TEP_PRINT_STRING,	TEP_PRINT_BSTRING,	TEP_PRINT_DYNAMIC_ARRAY,	TEP_PRINT_OP,	TEP_PRINT_FUNC,	TEP_PRINT_BITMASK,	TEP_PRINT_DYNAMIC_ARRAY_LEN,	TEP_PRINT_HEX_STR,}; struct tep_print_arg {	struct tep_print_arg		*next;	enum tep_print_arg_type		type;	union {		struct tep_print_arg_atom	atom;		struct tep_print_arg_field	field;		struct tep_print_arg_typecast	typecast;		struct tep_print_arg_flags	flags;		struct tep_print_arg_symbol	symbol;		struct tep_print_arg_hex	hex;		struct tep_print_arg_int_array	int_array;		struct tep_print_arg_func	func;		struct tep_print_arg_string	string;		struct tep_print_arg_bitmask	bitmask;		struct tep_print_arg_op		op;		struct tep_print_arg_dynarray	dynarray;	};}; struct tep_print_parse; struct tep_print_fmt {	char			*format;	struct tep_print_arg	*args;	struct tep_print_parse	*print_cache;}; struct tep_event {	struct tep_handle	*tep;	char			*name;	int			id;	int			flags;	struct tep_format	format;	struct tep_print_fmt	print_fmt;	char			*system;	tep_event_handler_func	handler;	void			*context;}; enum {	TEP_EVENT_FL_ISFTRACE	= 0x01,	TEP_EVENT_FL_ISPRINT	= 0x02,	TEP_EVENT_FL_ISBPRINT	= 0x04,	TEP_EVENT_FL_ISFUNCENT	= 0x10,	TEP_EVENT_FL_ISFUNCRET	= 0x20,	TEP_EVENT_FL_NOHANDLE	= 0x40,	TEP_EVENT_FL_PRINTRAW	= 0x80, 	TEP_EVENT_FL_FAILED	= 0x80000000}; enum tep_event_sort_type {	TEP_EVENT_SORT_ID,	TEP_EVENT_SORT_NAME,	TEP_EVENT_SORT_SYSTEM,}; enum tep_event_type {	TEP_EVENT_ERROR,	TEP_EVENT_NONE,	TEP_EVENT_SPACE,	TEP_EVENT_NEWLINE,	TEP_EVENT_OP,	TEP_EVENT_DELIM,	TEP_EVENT_ITEM,	TEP_EVENT_DQUOTE,	TEP_EVENT_SQUOTE,}; typedef unsigned long long (*tep_func_handler)(struct trace_seq *s,					       unsigned long long *args); enum tep_func_arg_type {	TEP_FUNC_ARG_VOID,	TEP_FUNC_ARG_INT,	TEP_FUNC_ARG_LONG,	TEP_FUNC_ARG_STRING,	TEP_FUNC_ARG_PTR,	TEP_FUNC_ARG_MAX_TYPES}; enum tep_flag {	TEP_NSEC_OUTPUT		= 1,	/* output in NSECS */	TEP_DISABLE_SYS_PLUGINS	= 1 << 1,	TEP_DISABLE_PLUGINS	= 1 << 2,}; #define TEP_ERRORS 							      \	_PE(MEM_ALLOC_FAILED,	"failed to allocate memory"),		      \	_PE(PARSE_EVENT_FAILED,	"failed to parse event"),		      \	_PE(READ_ID_FAILED,	"failed to read event id"),		      \	_PE(READ_FORMAT_FAILED,	"failed to read event format"),		      \	_PE(READ_PRINT_FAILED,	"failed to read event print fmt"), 	      \	_PE(OLD_FTRACE_ARG_FAILED,"failed to allocate field name for ftrace"),\	_PE(INVALID_ARG_TYPE,	"invalid argument type"),		      \	_PE(INVALID_EXP_TYPE,	"invalid expression type"),		      \	_PE(INVALID_OP_TYPE,	"invalid operator type"),		      \	_PE(INVALID_EVENT_NAME,	"invalid event name"),			      \	_PE(EVENT_NOT_FOUND,	"no event found"),			      \	_PE(SYNTAX_ERROR,	"syntax error"),			      \	_PE(ILLEGAL_RVALUE,	"illegal rvalue"),			      \	_PE(ILLEGAL_LVALUE,	"illegal lvalue for string comparison"),      \	_PE(INVALID_REGEX,	"regex did not compute"),		      \	_PE(ILLEGAL_STRING_CMP,	"illegal comparison for string"), 	      \	_PE(ILLEGAL_INTEGER_CMP,"illegal comparison for integer"), 	      \	_PE(REPARENT_NOT_OP,	"cannot reparent other than OP"),	      \	_PE(REPARENT_FAILED,	"failed to reparent filter OP"),	      \	_PE(BAD_FILTER_ARG,	"bad arg in filter tree"),		      \	_PE(UNEXPECTED_TYPE,	"unexpected type (not a value)"),	      \	_PE(ILLEGAL_TOKEN,	"illegal token"),			      \	_PE(INVALID_PAREN,	"open parenthesis cannot come here"), 	      \	_PE(UNBALANCED_PAREN,	"unbalanced number of parenthesis"),	      \	_PE(UNKNOWN_TOKEN,	"unknown token"),			      \	_PE(FILTER_NOT_FOUND,	"no filter found"),			      \	_PE(NOT_A_NUMBER,	"must have number field"),		      \	_PE(NO_FILTER,		"no filters exists"),			      \	_PE(FILTER_MISS,	"record does not match to filter") #undef _PE#define _PE(__code, __str) TEP_ERRNO__ ## __codeenum tep_errno {	TEP_ERRNO__SUCCESS			= 0,	TEP_ERRNO__FILTER_MATCH			= TEP_ERRNO__SUCCESS, 	/*	 * Choose an arbitrary negative big number not to clash with standard	 * errno since SUS requires the errno has distinct positive values.	 * See 'Issue 6' in the link below.	 *	 * https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html	 */	__TEP_ERRNO__START			= -100000, 	TEP_ERRORS, 	__TEP_ERRNO__END,};#undef _PE struct tep_plugin_list; #define INVALID_PLUGIN_LIST_OPTION	((char **)((unsigned long)-1)) enum tep_plugin_load_priority {	TEP_PLUGIN_FIRST,	TEP_PLUGIN_LAST,}; int tep_add_plugin_path(struct tep_handle *tep, char *path,			enum tep_plugin_load_priority prio);struct tep_plugin_list *tep_load_plugins(struct tep_handle *tep);void tep_unload_plugins(struct tep_plugin_list *plugin_list,			struct tep_handle *tep);void tep_load_plugins_hook(struct tep_handle *tep, const char *suffix,			   void (*load_plugin)(struct tep_handle *tep,					       const char *path,					       const char *name,					       void *data),			   void *data);char **tep_plugin_list_options(void);void tep_plugin_free_options_list(char **list);int tep_plugin_add_options(const char *name,			   struct tep_plugin_option *options);int tep_plugin_add_option(const char *name, const char *val);void tep_plugin_remove_options(struct tep_plugin_option *options);void tep_plugin_print_options(struct trace_seq *s);void tep_print_plugins(struct trace_seq *s,			const char *prefix, const char *suffix,			const struct tep_plugin_list *list); /* tep_handle */typedef char *(tep_func_resolver_t)(void *priv,				    unsigned long long *addrp, char **modp);void tep_set_flag(struct tep_handle *tep, int flag);void tep_clear_flag(struct tep_handle *tep, enum tep_flag flag);bool tep_test_flag(struct tep_handle *tep, enum tep_flag flags); static inline int tep_is_bigendian(void){	unsigned char str[] = { 0x1, 0x2, 0x3, 0x4 };	unsigned int val; 	memcpy(&val, str, 4);	return val == 0x01020304;} /* taken from kernel/trace/trace.h */enum trace_flag_type {	TRACE_FLAG_IRQS_OFF		= 0x01,	TRACE_FLAG_IRQS_NOSUPPORT	= 0x02,	TRACE_FLAG_NEED_RESCHED		= 0x04,	TRACE_FLAG_HARDIRQ		= 0x08,	TRACE_FLAG_SOFTIRQ		= 0x10,}; int tep_set_function_resolver(struct tep_handle *tep,			      tep_func_resolver_t *func, void *priv);void tep_reset_function_resolver(struct tep_handle *tep);int tep_register_comm(struct tep_handle *tep, const char *comm, int pid);int tep_override_comm(struct tep_handle *tep, const char *comm, int pid);int tep_register_function(struct tep_handle *tep, char *name,			  unsigned long long addr, char *mod);int tep_register_print_string(struct tep_handle *tep, const char *fmt,			      unsigned long long addr);bool tep_is_pid_registered(struct tep_handle *tep, int pid); struct tep_event *tep_get_event(struct tep_handle *tep, int index); #define TEP_PRINT_INFO		"INFO"#define TEP_PRINT_INFO_RAW	"INFO_RAW"#define TEP_PRINT_COMM		"COMM"#define TEP_PRINT_LATENCY	"LATENCY"#define TEP_PRINT_NAME		"NAME"#define TEP_PRINT_PID		1U#define TEP_PRINT_TIME		2U#define TEP_PRINT_CPU		3U void tep_print_event(struct tep_handle *tep, struct trace_seq *s,		     struct tep_record *record, const char *fmt, ...)	__attribute__ ((format (printf, 4, 5))); int tep_parse_header_page(struct tep_handle *tep, char *buf, unsigned long size,			  int long_size); enum tep_errno tep_parse_event(struct tep_handle *tep, const char *buf,			       unsigned long size, const char *sys);enum tep_errno tep_parse_format(struct tep_handle *tep,				struct tep_event **eventp,				const char *buf,				unsigned long size, const char *sys); void *tep_get_field_raw(struct trace_seq *s, struct tep_event *event,			const char *name, struct tep_record *record,			int *len, int err); int tep_get_field_val(struct trace_seq *s, struct tep_event *event,		      const char *name, struct tep_record *record,		      unsigned long long *val, int err);int tep_get_common_field_val(struct trace_seq *s, struct tep_event *event,			     const char *name, struct tep_record *record,			     unsigned long long *val, int err);int tep_get_any_field_val(struct trace_seq *s, struct tep_event *event,			  const char *name, struct tep_record *record,			  unsigned long long *val, int err); int tep_print_num_field(struct trace_seq *s, const char *fmt,			struct tep_event *event, const char *name,			struct tep_record *record, int err); int tep_print_func_field(struct trace_seq *s, const char *fmt,			 struct tep_event *event, const char *name,			 struct tep_record *record, int err); enum tep_reg_handler {	TEP_REGISTER_SUCCESS = 0,	TEP_REGISTER_SUCCESS_OVERWRITE,}; int tep_register_event_handler(struct tep_handle *tep, int id,

Lines 1–500 of 757.