117 lines
3.7 KiB
C
117 lines
3.7 KiB
C
|
/* 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
|