• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0 */
2 
3 /*
4  * Note: we intentionally omit include file ifdef protection
5  *  This is due to the way trace events work. If a file includes two
6  *  trace event headers under one "CREATE_TRACE_POINTS" the first include
7  *  will override the DECLARE_RESTRICTED_HOOK and break the second include.
8  */
9 
10 #include <linux/tracepoint.h>
11 
12 #if defined(CONFIG_TRACEPOINTS) && defined(CONFIG_ANDROID_VENDOR_HOOKS)
13 
14 #define DECLARE_HOOK DECLARE_TRACE
15 
16 int android_rvh_probe_register(struct tracepoint *tp, void *probe, void *data);
17 
18 #ifdef TRACE_HEADER_MULTI_READ
19 
20 #define DEFINE_HOOK_FN(_name, _reg, _unreg, proto, args)		\
21 	static const char __tpstrtab_##_name[]				\
22 	__section("__tracepoints_strings") = #_name;			\
23 	extern struct static_call_key STATIC_CALL_KEY(tp_func_##_name);	\
24 	int __traceiter_##_name(void *__data, proto);			\
25 	struct tracepoint __tracepoint_##_name	__used			\
26 	__section("__tracepoints") = {					\
27 		.name = __tpstrtab_##_name,				\
28 		.key = STATIC_KEY_INIT_FALSE,				\
29 		.static_call_key = &STATIC_CALL_KEY(tp_func_##_name),	\
30 		.static_call_tramp = STATIC_CALL_TRAMP_ADDR(tp_func_##_name), \
31 		.iterator = &__traceiter_##_name,			\
32 		.regfunc = _reg,					\
33 		.unregfunc = _unreg,					\
34 		.funcs = NULL };					\
35 	__TRACEPOINT_ENTRY(_name);					\
36 	int __nocfi __traceiter_##_name(void *__data, proto)			\
37 	{								\
38 		struct tracepoint_func *it_func_ptr;			\
39 		void *it_func;						\
40 									\
41 		it_func_ptr = (&__tracepoint_##_name)->funcs;		\
42 		it_func = (it_func_ptr)->func;				\
43 		do {							\
44 			__data = (it_func_ptr)->data;			\
45 			((void(*)(void *, proto))(it_func))(__data, args); \
46 			it_func = READ_ONCE((++it_func_ptr)->func);	\
47 		} while (it_func);					\
48 		return 0;						\
49 	}								\
50 	DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name);
51 
52 #undef DECLARE_RESTRICTED_HOOK
53 #define DECLARE_RESTRICTED_HOOK(name, proto, args, cond) \
54 	DEFINE_HOOK_FN(name, NULL, NULL, PARAMS(proto), PARAMS(args))
55 
56 /* prevent additional recursion */
57 #undef TRACE_HEADER_MULTI_READ
58 #else /* TRACE_HEADER_MULTI_READ */
59 
60 #define DO_HOOK(name, proto, args, cond)				\
61 	do {								\
62 		struct tracepoint_func *it_func_ptr;			\
63 		void *__data;						\
64 									\
65 		if (!(cond))						\
66 			return;						\
67 									\
68 		it_func_ptr = (&__tracepoint_##name)->funcs;		\
69 		if (it_func_ptr) {					\
70 			__data = (it_func_ptr)->data;			\
71 			__DO_TRACE_CALL(name)(args);			\
72 		}							\
73 	} while (0)
74 
75 #define __DECLARE_HOOK(name, proto, args, cond, data_proto, data_args)	\
76 	extern int __traceiter_##name(data_proto);			\
77 	DECLARE_STATIC_CALL(tp_func_##name, __traceiter_##name);	\
78 	extern struct tracepoint __tracepoint_##name;			\
79 	static inline void __nocfi trace_##name(proto)			\
80 	{								\
81 		if (static_key_false(&__tracepoint_##name.key))		\
82 			DO_HOOK(name,					\
83 				TP_PROTO(data_proto),			\
84 				TP_ARGS(data_args),			\
85 				TP_CONDITION(cond));			\
86 	}								\
87 	static inline bool						\
88 	trace_##name##_enabled(void)					\
89 	{								\
90 		return static_key_false(&__tracepoint_##name.key);	\
91 	}								\
92 	static inline int						\
93 	register_trace_##name(void (*probe)(data_proto), void *data) 	\
94 	{								\
95 		return android_rvh_probe_register(&__tracepoint_##name,	\
96 						  (void *)probe, data);	\
97 	}								\
98 	/* vendor hooks cannot be unregistered */			\
99 
100 #undef DECLARE_RESTRICTED_HOOK
101 #define DECLARE_RESTRICTED_HOOK(name, proto, args, cond)		\
102 	__DECLARE_HOOK(name, PARAMS(proto), PARAMS(args),		\
103 			cond,						\
104 			PARAMS(void *__data, proto),			\
105 			PARAMS(__data, args))
106 
107 #endif /* TRACE_HEADER_MULTI_READ */
108 
109 #else /* !CONFIG_TRACEPOINTS || !CONFIG_ANDROID_VENDOR_HOOKS */
110 /* suppress trace hooks */
111 #define DECLARE_HOOK DECLARE_EVENT_NOP
112 #define DECLARE_RESTRICTED_HOOK(name, proto, args, cond)		\
113 	DECLARE_EVENT_NOP(name, PARAMS(proto), PARAMS(args))
114 #endif
115