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