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 #ifndef __GENKSYMS__ 11 #include <linux/tracepoint.h> 12 #endif 13 14 #if defined(CONFIG_TRACEPOINTS) && defined(CONFIG_ANDROID_VENDOR_HOOKS) 15 16 #define DECLARE_HOOK DECLARE_TRACE 17 18 int android_rvh_probe_register(struct tracepoint *tp, void *probe, void *data); 19 20 #ifdef TRACE_HEADER_MULTI_READ 21 22 #define DEFINE_HOOK_FN(_name, _reg, _unreg, proto, args) \ 23 static const char __tpstrtab_##_name[] \ 24 __section("__tracepoints_strings") = #_name; \ 25 extern struct static_call_key STATIC_CALL_KEY(tp_func_##_name); \ 26 int __traceiter_##_name(void *__data, proto); \ 27 struct tracepoint __tracepoint_##_name __used \ 28 __section("__tracepoints") = { \ 29 .name = __tpstrtab_##_name, \ 30 .key = STATIC_KEY_INIT_FALSE, \ 31 .static_call_key = &STATIC_CALL_KEY(tp_func_##_name), \ 32 .static_call_tramp = STATIC_CALL_TRAMP_ADDR(tp_func_##_name), \ 33 .iterator = &__traceiter_##_name, \ 34 .regfunc = _reg, \ 35 .unregfunc = _unreg, \ 36 .funcs = NULL }; \ 37 __TRACEPOINT_ENTRY(_name); \ 38 int __traceiter_##_name(void *__data, proto) \ 39 { \ 40 struct tracepoint_func *it_func_ptr; \ 41 void *it_func; \ 42 \ 43 it_func_ptr = (&__tracepoint_##_name)->funcs; \ 44 it_func = (it_func_ptr)->func; \ 45 do { \ 46 __data = (it_func_ptr)->data; \ 47 ((void(*)(void *, proto))(it_func))(__data, args); \ 48 it_func = READ_ONCE((++it_func_ptr)->func); \ 49 } while (it_func); \ 50 return 0; \ 51 } \ 52 DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name); 53 54 #undef DECLARE_RESTRICTED_HOOK 55 #define DECLARE_RESTRICTED_HOOK(name, proto, args, cond) \ 56 DEFINE_HOOK_FN(name, NULL, NULL, PARAMS(proto), PARAMS(args)) 57 58 /* prevent additional recursion */ 59 #undef TRACE_HEADER_MULTI_READ 60 #else /* TRACE_HEADER_MULTI_READ */ 61 62 #define DO_HOOK(name, proto, args, cond) \ 63 do { \ 64 struct tracepoint_func *it_func_ptr; \ 65 void *__data; \ 66 \ 67 if (!(cond)) \ 68 return; \ 69 \ 70 it_func_ptr = (&__tracepoint_##name)->funcs; \ 71 if (it_func_ptr) { \ 72 __data = (it_func_ptr)->data; \ 73 __DO_TRACE_CALL(name)(args); \ 74 } \ 75 } while (0) 76 77 #define __DECLARE_HOOK(name, proto, args, cond, data_proto, data_args) \ 78 extern int __traceiter_##name(data_proto); \ 79 DECLARE_STATIC_CALL(tp_func_##name, __traceiter_##name); \ 80 extern struct tracepoint __tracepoint_##name; \ 81 static inline void __nocfi trace_##name(proto) \ 82 { \ 83 if (static_key_false(&__tracepoint_##name.key)) \ 84 DO_HOOK(name, \ 85 TP_PROTO(data_proto), \ 86 TP_ARGS(data_args), \ 87 TP_CONDITION(cond)); \ 88 } \ 89 static inline bool \ 90 trace_##name##_enabled(void) \ 91 { \ 92 return static_key_false(&__tracepoint_##name.key); \ 93 } \ 94 static inline int \ 95 register_trace_##name(void (*probe)(data_proto), void *data) \ 96 { \ 97 return android_rvh_probe_register(&__tracepoint_##name, \ 98 (void *)probe, data); \ 99 } \ 100 /* vendor hooks cannot be unregistered */ \ 101 102 #undef DECLARE_RESTRICTED_HOOK 103 #define DECLARE_RESTRICTED_HOOK(name, proto, args, cond) \ 104 __DECLARE_HOOK(name, PARAMS(proto), PARAMS(args), \ 105 cond, \ 106 PARAMS(void *__data, proto), \ 107 PARAMS(__data, args)) 108 109 #endif /* TRACE_HEADER_MULTI_READ */ 110 111 #else /* !CONFIG_TRACEPOINTS || !CONFIG_ANDROID_VENDOR_HOOKS */ 112 /* suppress trace hooks */ 113 #define DECLARE_HOOK DECLARE_EVENT_NOP 114 #define DECLARE_RESTRICTED_HOOK(name, proto, args, cond) \ 115 DECLARE_EVENT_NOP(name, PARAMS(proto), PARAMS(args)) 116 #endif 117