TRACE_EVENT_FL_TRACEPOINT_BIT,
TRACE_EVENT_FL_KPROBE_BIT,
TRACE_EVENT_FL_UPROBE_BIT,
+ TRACE_EVENT_FL_MAP_BIT,
};
/*
* TRACEPOINT - Event is a tracepoint
* KPROBE - Event is a kprobe
* UPROBE - Event is a uprobe
+ * MAP - Event maps to a tracepoint as an alias
*/
enum {
TRACE_EVENT_FL_FILTERED = (1 << TRACE_EVENT_FL_FILTERED_BIT),
TRACE_EVENT_FL_TRACEPOINT = (1 << TRACE_EVENT_FL_TRACEPOINT_BIT),
TRACE_EVENT_FL_KPROBE = (1 << TRACE_EVENT_FL_KPROBE_BIT),
TRACE_EVENT_FL_UPROBE = (1 << TRACE_EVENT_FL_UPROBE_BIT),
+ TRACE_EVENT_FL_MAP = (1 << TRACE_EVENT_FL_MAP_BIT),
};
#define TRACE_EVENT_FL_UKPROBE (TRACE_EVENT_FL_KPROBE | TRACE_EVENT_FL_UPROBE)
+struct trace_event_map {
+ struct tracepoint *tp;
+ char *name;
+};
+
struct trace_event_call {
struct list_head list;
struct trace_event_class *class;
char *name;
/* Set TRACE_EVENT_FL_TRACEPOINT flag when using "tp" */
struct tracepoint *tp;
+ /* Set TRACE_EVENT_FL_MAP flag when using "map" instead */
+ struct trace_event_map *map;
};
struct trace_event event;
char *print_fmt;
static inline const char *
trace_event_name(struct trace_event_call *call)
{
- if (call->flags & TRACE_EVENT_FL_TRACEPOINT)
+ if (call->flags & TRACE_EVENT_FL_MAP)
+ return call->map->name;
+ else if (call->flags & TRACE_EVENT_FL_TRACEPOINT)
return call->tp ? call->tp->name : NULL;
else
return call->name;
#define DEFINE_TRACE_FN(name, reg, unreg)
#define DEFINE_TRACE(name)
+#define DEFINE_TRACE_MAP(name, map)
#define EXPORT_TRACEPOINT_SYMBOL_GPL(name)
#define EXPORT_TRACEPOINT_SYMBOL(name)
*
* A set of (un)registration functions can be passed to the variant
* TRACE_EVENT_FN to perform any (un)registration work.
+ *
+ * TRACE_EVENT_MAP can be used to create alternate versions of a
+ * TRACE_EVENT without modifying the instrumented code. It connects
+ * a different probe to an existing tracepoint, so other fields can be
+ * extracted. The "name" field is the name of the original TRACE_EVENT,
+ * the "map" field is the name of the alias. They can be enabled
+ * independently.
*/
#define DECLARE_EVENT_CLASS(name, proto, args, tstruct, assign, print)
struct, assign, print) \
DECLARE_TRACE_CONDITION(name, PARAMS(proto), \
PARAMS(args), PARAMS(cond))
-
#define TRACE_EVENT_FLAGS(event, flag)
#define TRACE_EVENT_PERF_PERM(event, expr...)
+#define TRACE_EVENT_MAP(name, map, proto, args, struct, assign, print)
+
#endif /* ifdef TRACE_EVENT (see note above) */
#define TRACE_EVENT(name, proto, args, tstruct, assign, print) \
DEFINE_TRACE(name)
+#undef TRACE_EVENT_MAP
+#define TRACE_EVENT_MAP(name, map, proto, args, tstruct, assign, print)
+
#undef TRACE_EVENT_CONDITION
#define TRACE_EVENT_CONDITION(name, proto, args, cond, tstruct, assign, print) \
TRACE_EVENT(name, \
#undef TRACE_EVENT_FN
#undef TRACE_EVENT_FN_COND
#undef TRACE_EVENT_CONDITION
+#undef TRACE_EVENT_MAP
#undef DECLARE_EVENT_CLASS
#undef DEFINE_EVENT
#undef DEFINE_EVENT_FN
#define DEFINE_EVENT_PRINT(template, name, proto, args, print) \
DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args))
+#undef DEFINE_EVENT_MAP
+#define DEFINE_EVENT_MAP(template, call, map, proto, args) \
+static inline void perf_test_probe_##map(void) \
+{ \
+ check_trace_callback_type_##call(perf_trace_##template); \
+}
+
#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
#endif /* CONFIG_PERF_EVENTS */
PARAMS(print)); \
DEFINE_EVENT(name, name, PARAMS(proto), PARAMS(args));
+#undef TRACE_EVENT_MAP
+#define TRACE_EVENT_MAP(name, map, proto, args, tstruct, assign, print) \
+ DECLARE_EVENT_CLASS(map, \
+ PARAMS(proto), \
+ PARAMS(args), \
+ PARAMS(tstruct), \
+ PARAMS(assign), \
+ PARAMS(print)); \
+ DEFINE_EVENT_MAP(map, name, map, PARAMS(proto), PARAMS(args));
#undef __field
#define __field(type, item) type item;
static struct trace_event_call __used \
__attribute__((__aligned__(4))) event_##name
+#undef DEFINE_EVENT_MAP
+#define DEFINE_EVENT_MAP(template, name, map, proto, args) \
+ static struct trace_event_call __used \
+ __attribute__((__aligned__(4))) event_##map
+
#undef DEFINE_EVENT_FN
#define DEFINE_EVENT_FN(template, name, proto, args, reg, unreg) \
DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args))
#undef DEFINE_EVENT
#define DEFINE_EVENT(template, name, proto, args)
+#undef DEFINE_EVENT_MAP
+#define DEFINE_EVENT_MAP(template, name, map, proto, args)
+
#undef DEFINE_EVENT_PRINT
#define DEFINE_EVENT_PRINT(template, name, proto, args, print) \
DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args))
#undef DEFINE_EVENT
#define DEFINE_EVENT(template, name, proto, args)
+#undef DEFINE_EVENT_MAP
+#define DEFINE_EVENT_MAP(template, name, map, proto, args)
+
#undef DEFINE_EVENT_PRINT
#define DEFINE_EVENT_PRINT(template, name, proto, args, print) \
DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args))
#undef DEFINE_EVENT
#define DEFINE_EVENT(template, name, proto, args)
+#undef DEFINE_EVENT_MAP
+#define DEFINE_EVENT_MAP(template, name, map, proto, args)
+
#undef DEFINE_EVENT_PRINT
#define DEFINE_EVENT_PRINT(template, name, proto, args, print) \
DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args))
check_trace_callback_type_##call(trace_event_raw_event_##template); \
}
+#undef DEFINE_EVENT_MAP
+#define DEFINE_EVENT_MAP(template, call, map, proto, args) \
+static inline void ftrace_test_probe_##map(void) \
+{ \
+ check_trace_callback_type_##call(trace_event_raw_event_##template); \
+}
+
#undef DEFINE_EVENT_PRINT
#define DEFINE_EVENT_PRINT(template, name, proto, args, print)
static struct trace_event_call __used \
__attribute__((section("_ftrace_events"))) *__event_##call = &event_##call
+#undef DEFINE_EVENT_MAP
+#define DEFINE_EVENT_MAP(_template, _call, _map, _proto, _args) \
+ \
+static struct trace_event_map event_map_##_map = { \
+ .tp = &__tracepoint_##_call, \
+ .name = #_map, \
+}; \
+ \
+static struct trace_event_call __used event_##_map = { \
+ .class = &event_class_##_template, \
+ { \
+ .map = &event_map_##_map, \
+ }, \
+ .event.funcs = &trace_event_type_funcs_##_template, \
+ .print_fmt = print_fmt_##_template, \
+ .flags = TRACE_EVENT_FL_TRACEPOINT | TRACE_EVENT_FL_MAP,\
+}; \
+static struct trace_event_call __used \
+__attribute__((section("_ftrace_events"))) *__event_##_map = &event_##_map
+
#undef DEFINE_EVENT_PRINT
#define DEFINE_EVENT_PRINT(template, call, proto, args, print) \
\
enum trace_reg type, void *data)
{
struct trace_event_file *file = data;
+ struct tracepoint *tp;
WARN_ON(!(call->flags & TRACE_EVENT_FL_TRACEPOINT));
+
+ if (call->flags & TRACE_EVENT_FL_MAP)
+ tp = call->map->tp;
+ else
+ tp = call->tp;
+
switch (type) {
case TRACE_REG_REGISTER:
- return tracepoint_probe_register(call->tp,
+ return tracepoint_probe_register(tp,
call->class->probe,
file);
case TRACE_REG_UNREGISTER:
- tracepoint_probe_unregister(call->tp,
+ tracepoint_probe_unregister(tp,
call->class->probe,
file);
return 0;
#ifdef CONFIG_PERF_EVENTS
case TRACE_REG_PERF_REGISTER:
- return tracepoint_probe_register(call->tp,
+ return tracepoint_probe_register(tp,
call->class->perf_probe,
call);
case TRACE_REG_PERF_UNREGISTER:
- tracepoint_probe_unregister(call->tp,
+ tracepoint_probe_unregister(tp,
call->class->perf_probe,
call);
return 0;