linux/include/trace/trace_custom_events.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2/*
   3 * This is similar to the trace_events.h file, but is to only
   4 * create custom trace events to be attached to existing tracepoints.
   5 * Where as the TRACE_EVENT() macro (from trace_events.h) will create
   6 * both the trace event and the tracepoint it will attach the event to,
   7 * TRACE_CUSTOM_EVENT() is to create only a custom version of an existing
   8 * trace event (created by TRACE_EVENT() or DEFINE_EVENT()), and will
   9 * be placed in the "custom" system.
  10 */
  11
  12#include <linux/trace_events.h>
  13
  14/* All custom events are placed in the custom group */
  15#undef TRACE_SYSTEM
  16#define TRACE_SYSTEM custom
  17
  18#ifndef TRACE_SYSTEM_VAR
  19#define TRACE_SYSTEM_VAR TRACE_SYSTEM
  20#endif
  21
  22/* The init stage creates the system string and enum mappings */
  23
  24#include "stages/init.h"
  25
  26#undef TRACE_CUSTOM_EVENT
  27#define TRACE_CUSTOM_EVENT(name, proto, args, tstruct, assign, print) \
  28        DECLARE_CUSTOM_EVENT_CLASS(name,                              \
  29                             PARAMS(proto),                    \
  30                             PARAMS(args),                     \
  31                             PARAMS(tstruct),                  \
  32                             PARAMS(assign),                   \
  33                             PARAMS(print));                   \
  34        DEFINE_CUSTOM_EVENT(name, name, PARAMS(proto), PARAMS(args));
  35
  36/* Stage 1 creates the structure of the recorded event layout */
  37
  38#include "stages/stage1_struct_define.h"
  39
  40#undef DECLARE_CUSTOM_EVENT_CLASS
  41#define DECLARE_CUSTOM_EVENT_CLASS(name, proto, args, tstruct, assign, print) \
  42        struct trace_custom_event_raw_##name {                          \
  43                struct trace_entry      ent;                            \
  44                tstruct                                                 \
  45                char                    __data[];                       \
  46        };                                                              \
  47                                                                        \
  48        static struct trace_event_class custom_event_class_##name;
  49
  50#undef DEFINE_CUSTOM_EVENT
  51#define DEFINE_CUSTOM_EVENT(template, name, proto, args)        \
  52        static struct trace_event_call  __used                  \
  53        __attribute__((__aligned__(4))) custom_event_##name
  54
  55#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
  56
  57/* Stage 2 creates the custom class */
  58
  59#include "stages/stage2_data_offsets.h"
  60
  61#undef DECLARE_CUSTOM_EVENT_CLASS
  62#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print)   \
  63        struct trace_custom_event_data_offsets_##call {                 \
  64                tstruct;                                                \
  65        };
  66
  67#undef DEFINE_CUSTOM_EVENT
  68#define DEFINE_CUSTOM_EVENT(template, name, proto, args)
  69
  70#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
  71
  72/* Stage 3 create the way to print the custom event */
  73
  74#include "stages/stage3_trace_output.h"
  75
  76#undef DECLARE_CUSTOM_EVENT_CLASS
  77#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
  78static notrace enum print_line_t                                        \
  79trace_custom_raw_output_##call(struct trace_iterator *iter, int flags,  \
  80                        struct trace_event *trace_event)                \
  81{                                                                       \
  82        struct trace_seq *s = &iter->seq;                               \
  83        struct trace_seq __maybe_unused *p = &iter->tmp_seq;            \
  84        struct trace_custom_event_raw_##call *field;                    \
  85        int ret;                                                        \
  86                                                                        \
  87        field = (typeof(field))iter->ent;                               \
  88                                                                        \
  89        ret = trace_raw_output_prep(iter, trace_event);                 \
  90        if (ret != TRACE_TYPE_HANDLED)                                  \
  91                return ret;                                             \
  92                                                                        \
  93        trace_event_printf(iter, print);                                \
  94                                                                        \
  95        return trace_handle_return(s);                                  \
  96}                                                                       \
  97static struct trace_event_functions trace_custom_event_type_funcs_##call = { \
  98        .trace                  = trace_custom_raw_output_##call,       \
  99};
 100
 101#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
 102
 103/* Stage 4 creates the offset layout for the fields */
 104
 105#include "stages/stage4_event_fields.h"
 106
 107#undef DECLARE_CUSTOM_EVENT_CLASS
 108#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, func, print)     \
 109static struct trace_event_fields trace_custom_event_fields_##call[] = { \
 110        tstruct                                                         \
 111        {} };
 112
 113#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
 114
 115/* Stage 5 creates the helper function for dynamic fields */
 116
 117#include "stages/stage5_get_offsets.h"
 118
 119#undef DECLARE_CUSTOM_EVENT_CLASS
 120#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
 121static inline notrace int trace_custom_event_get_offsets_##call(        \
 122        struct trace_custom_event_data_offsets_##call *__data_offsets, proto) \
 123{                                                                       \
 124        int __data_size = 0;                                            \
 125        int __maybe_unused __item_length;                               \
 126        struct trace_custom_event_raw_##call __maybe_unused *entry;     \
 127                                                                        \
 128        tstruct;                                                        \
 129                                                                        \
 130        return __data_size;                                             \
 131}
 132
 133#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
 134
 135/* Stage 6 creates the probe function that records the event */
 136
 137#include "stages/stage6_event_callback.h"
 138
 139#undef DECLARE_CUSTOM_EVENT_CLASS
 140#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
 141                                                                        \
 142static notrace void                                                     \
 143trace_custom_event_raw_event_##call(void *__data, proto)                \
 144{                                                                       \
 145        struct trace_event_file *trace_file = __data;                   \
 146        struct trace_custom_event_data_offsets_##call __maybe_unused __data_offsets; \
 147        struct trace_event_buffer fbuffer;                              \
 148        struct trace_custom_event_raw_##call *entry;                    \
 149        int __data_size;                                                \
 150                                                                        \
 151        if (trace_trigger_soft_disabled(trace_file))                    \
 152                return;                                                 \
 153                                                                        \
 154        __data_size = trace_custom_event_get_offsets_##call(&__data_offsets, args); \
 155                                                                        \
 156        entry = trace_event_buffer_reserve(&fbuffer, trace_file,        \
 157                                 sizeof(*entry) + __data_size);         \
 158                                                                        \
 159        if (!entry)                                                     \
 160                return;                                                 \
 161                                                                        \
 162        tstruct                                                         \
 163                                                                        \
 164        { assign; }                                                     \
 165                                                                        \
 166        trace_event_buffer_commit(&fbuffer);                            \
 167}
 168/*
 169 * The ftrace_test_custom_probe is compiled out, it is only here as a build time check
 170 * to make sure that if the tracepoint handling changes, the ftrace probe will
 171 * fail to compile unless it too is updated.
 172 */
 173
 174#undef DEFINE_CUSTOM_EVENT
 175#define DEFINE_CUSTOM_EVENT(template, call, proto, args)                \
 176static inline void ftrace_test_custom_probe_##call(void)                \
 177{                                                                       \
 178        check_trace_callback_type_##call(trace_custom_event_raw_event_##template); \
 179}
 180
 181#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
 182
 183/* Stage 7 creates the actual class and event structure for the custom event */
 184
 185#include "stages/stage7_class_define.h"
 186
 187#undef DECLARE_CUSTOM_EVENT_CLASS
 188#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
 189static char custom_print_fmt_##call[] = print;                                  \
 190static struct trace_event_class __used __refdata custom_event_class_##call = { \
 191        .system                 = TRACE_SYSTEM_STRING,                  \
 192        .fields_array           = trace_custom_event_fields_##call,             \
 193        .fields                 = LIST_HEAD_INIT(custom_event_class_##call.fields),\
 194        .raw_init               = trace_event_raw_init,                 \
 195        .probe                  = trace_custom_event_raw_event_##call,  \
 196        .reg                    = trace_event_reg,                      \
 197};
 198
 199#undef DEFINE_CUSTOM_EVENT
 200#define DEFINE_CUSTOM_EVENT(template, call, proto, args)                \
 201                                                                        \
 202static struct trace_event_call __used custom_event_##call = {           \
 203        .name                   = #call,                                \
 204        .class                  = &custom_event_class_##template,       \
 205        .event.funcs            = &trace_custom_event_type_funcs_##template, \
 206        .print_fmt              = custom_print_fmt_##template,          \
 207        .flags                  = TRACE_EVENT_FL_CUSTOM,                \
 208};                                                                      \
 209static inline int trace_custom_event_##call##_update(struct tracepoint *tp) \
 210{                                                                       \
 211        if (tp->name && strcmp(tp->name, #call) == 0) {                 \
 212                custom_event_##call.tp = tp;                            \
 213                custom_event_##call.flags = TRACE_EVENT_FL_TRACEPOINT;  \
 214                return 1;                                               \
 215        }                                                               \
 216        return 0;                                                       \
 217}                                                                       \
 218static struct trace_event_call __used                                   \
 219__section("_ftrace_events") *__custom_event_##call = &custom_event_##call
 220
 221#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
 222