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