221 lines · 7.1 KB · C
RawDownload
/* SPDX-License-Identifier: GPL-2.0 *//* * This is similar to the trace_events.h file, but is to only * create custom trace events to be attached to existing tracepoints. * Where as the TRACE_EVENT() macro (from trace_events.h) will create * both the trace event and the tracepoint it will attach the event to, * TRACE_CUSTOM_EVENT() is to create only a custom version of an existing * trace event (created by TRACE_EVENT() or DEFINE_EVENT()), and will * be placed in the "custom" system. */ #include <linux/trace_events.h> /* All custom events are placed in the custom group */#undef TRACE_SYSTEM#define TRACE_SYSTEM custom #ifndef TRACE_SYSTEM_VAR#define TRACE_SYSTEM_VAR TRACE_SYSTEM#endif /* The init stage creates the system string and enum mappings */ #include "stages/init.h" #undef TRACE_CUSTOM_EVENT#define TRACE_CUSTOM_EVENT(name, proto, args, tstruct, assign, print) \	DECLARE_CUSTOM_EVENT_CLASS(name,			      \			     PARAMS(proto),		       \			     PARAMS(args),		       \			     PARAMS(tstruct),		       \			     PARAMS(assign),		       \			     PARAMS(print));		       \	DEFINE_CUSTOM_EVENT(name, name, PARAMS(proto), PARAMS(args)); /* Stage 1 creates the structure of the recorded event layout */ #include "stages/stage1_struct_define.h" #undef DECLARE_CUSTOM_EVENT_CLASS#define DECLARE_CUSTOM_EVENT_CLASS(name, proto, args, tstruct, assign, print) \	struct trace_custom_event_raw_##name {				\		struct trace_entry	ent;				\		tstruct							\		char			__data[];			\	};								\									\	static struct trace_event_class custom_event_class_##name; #undef DEFINE_CUSTOM_EVENT#define DEFINE_CUSTOM_EVENT(template, name, proto, args)	\	static struct trace_event_call	__used			\	__attribute__((__aligned__(4))) custom_event_##name #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) /* Stage 2 creates the custom class */ #include "stages/stage2_data_offsets.h" #undef DECLARE_CUSTOM_EVENT_CLASS#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print)	\	struct trace_custom_event_data_offsets_##call {			\		tstruct;						\	}; #undef DEFINE_CUSTOM_EVENT#define DEFINE_CUSTOM_EVENT(template, name, proto, args) #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) /* Stage 3 create the way to print the custom event */ #include "stages/stage3_trace_output.h" #undef DECLARE_CUSTOM_EVENT_CLASS#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \static notrace enum print_line_t					\trace_custom_raw_output_##call(struct trace_iterator *iter, int flags,	\			struct trace_event *trace_event)		\{									\	struct trace_seq *s = &iter->seq;				\	struct trace_seq __maybe_unused *p = &iter->tmp_seq;		\	struct trace_custom_event_raw_##call *field;			\	int ret;							\									\	field = (typeof(field))iter->ent;				\									\	ret = trace_raw_output_prep(iter, trace_event);			\	if (ret != TRACE_TYPE_HANDLED)					\		return ret;						\									\	trace_event_printf(iter, print);				\									\	return trace_handle_return(s);					\}									\static struct trace_event_functions trace_custom_event_type_funcs_##call = { \	.trace			= trace_custom_raw_output_##call,	\}; #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) /* Stage 4 creates the offset layout for the fields */ #include "stages/stage4_event_fields.h" #undef DECLARE_CUSTOM_EVENT_CLASS#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, func, print)	\static struct trace_event_fields trace_custom_event_fields_##call[] = {	\	tstruct								\	{} }; #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) /* Stage 5 creates the helper function for dynamic fields */ #include "stages/stage5_get_offsets.h" #undef DECLARE_CUSTOM_EVENT_CLASS#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \static inline notrace int trace_custom_event_get_offsets_##call(	\	struct trace_custom_event_data_offsets_##call *__data_offsets, proto) \{									\	int __data_size = 0;						\	int __maybe_unused __item_length;				\	struct trace_custom_event_raw_##call __maybe_unused *entry;	\									\	tstruct;							\									\	return __data_size;						\} #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) /* Stage 6 creates the probe function that records the event */ #include "stages/stage6_event_callback.h" #undef DECLARE_CUSTOM_EVENT_CLASS#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \									\static notrace void							\trace_custom_event_raw_event_##call(void *__data, proto)		\{									\	struct trace_event_file *trace_file = __data;			\	struct trace_custom_event_data_offsets_##call __maybe_unused __data_offsets; \	struct trace_event_buffer fbuffer;				\	struct trace_custom_event_raw_##call *entry;			\	int __data_size;						\									\	if (trace_trigger_soft_disabled(trace_file))			\		return;							\									\	__data_size = trace_custom_event_get_offsets_##call(&__data_offsets, args); \									\	entry = trace_event_buffer_reserve(&fbuffer, trace_file,	\				 sizeof(*entry) + __data_size);		\									\	if (!entry)							\		return;							\									\	tstruct								\									\	{ assign; }							\									\	trace_event_buffer_commit(&fbuffer);				\}/* * The ftrace_test_custom_probe is compiled out, it is only here as a build time check * to make sure that if the tracepoint handling changes, the ftrace probe will * fail to compile unless it too is updated. */ #undef DEFINE_CUSTOM_EVENT#define DEFINE_CUSTOM_EVENT(template, call, proto, args)		\static inline void ftrace_test_custom_probe_##call(void)		\{									\	check_trace_callback_type_##call(trace_custom_event_raw_event_##template); \} #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) /* Stage 7 creates the actual class and event structure for the custom event */ #include "stages/stage7_class_define.h" #undef DECLARE_CUSTOM_EVENT_CLASS#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \static char custom_print_fmt_##call[] = print;					\static struct trace_event_class __used __refdata custom_event_class_##call = { \	.system			= TRACE_SYSTEM_STRING,			\	.fields_array		= trace_custom_event_fields_##call,		\	.fields			= LIST_HEAD_INIT(custom_event_class_##call.fields),\	.raw_init		= trace_event_raw_init,			\	.probe			= trace_custom_event_raw_event_##call,	\	.reg			= trace_event_reg,			\}; #undef DEFINE_CUSTOM_EVENT#define DEFINE_CUSTOM_EVENT(template, call, proto, args)		\									\static struct trace_event_call __used custom_event_##call = {		\	.name			= #call,				\	.class			= &custom_event_class_##template,	\	.event.funcs		= &trace_custom_event_type_funcs_##template, \	.print_fmt		= custom_print_fmt_##template,		\	.flags			= TRACE_EVENT_FL_CUSTOM,		\};									\static inline int trace_custom_event_##call##_update(struct tracepoint *tp) \{									\	if (tp->name && strcmp(tp->name, #call) == 0) {			\		custom_event_##call.tp = tp;				\		custom_event_##call.flags = TRACE_EVENT_FL_TRACEPOINT;	\		return 1;						\	}								\	return 0;							\}									\static struct trace_event_call __used					\__section("_ftrace_events") *__custom_event_##call = &custom_event_##call #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)