tracing: add size checks for exported ftrace internal structures
[safe/jmp/linux-2.6] / kernel / trace / trace_export.c
1 /*
2  * trace_export.c - export basic ftrace utilities to user space
3  *
4  * Copyright (C) 2009 Steven Rostedt <srostedt@redhat.com>
5  */
6 #include <linux/stringify.h>
7 #include <linux/kallsyms.h>
8 #include <linux/seq_file.h>
9 #include <linux/debugfs.h>
10 #include <linux/uaccess.h>
11 #include <linux/ftrace.h>
12 #include <linux/module.h>
13 #include <linux/init.h>
14 #include <linux/fs.h>
15
16 #include "trace_output.h"
17
18
19 #undef TRACE_STRUCT
20 #define TRACE_STRUCT(args...) args
21
22 extern void __bad_type_size(void);
23
24 #undef TRACE_FIELD
25 #define TRACE_FIELD(type, item, assign)                                 \
26         if (sizeof(type) != sizeof(field.item))                         \
27                 __bad_type_size();                                      \
28         ret = trace_seq_printf(s, "\tfield:" #type " " #item ";\t"      \
29                                "offset:%u;\tsize:%u;\n",                \
30                                (unsigned int)offsetof(typeof(field), item), \
31                                (unsigned int)sizeof(field.item));       \
32         if (!ret)                                                       \
33                 return 0;
34
35
36 #undef TRACE_FIELD_SPECIAL
37 #define TRACE_FIELD_SPECIAL(type_item, item, len, cmd)                  \
38         ret = trace_seq_printf(s, "\tfield special:" #type_item ";\t"   \
39                                "offset:%u;\tsize:%u;\n",                \
40                                (unsigned int)offsetof(typeof(field), item), \
41                                (unsigned int)sizeof(field.item));       \
42         if (!ret)                                                       \
43                 return 0;
44
45 #undef TRACE_FIELD_ZERO_CHAR
46 #define TRACE_FIELD_ZERO_CHAR(item)                                     \
47         ret = trace_seq_printf(s, "\tfield:char " #item ";\t"           \
48                                "offset:%u;\tsize:0;\n",                 \
49                                (unsigned int)offsetof(typeof(field), item)); \
50         if (!ret)                                                       \
51                 return 0;
52
53
54 #undef TP_RAW_FMT
55 #define TP_RAW_FMT(args...) args
56
57 #undef TRACE_EVENT_FORMAT
58 #define TRACE_EVENT_FORMAT(call, proto, args, fmt, tstruct, tpfmt)      \
59 static int                                                              \
60 ftrace_format_##call(struct trace_seq *s)                               \
61 {                                                                       \
62         struct args field;                                              \
63         int ret;                                                        \
64                                                                         \
65         tstruct;                                                        \
66                                                                         \
67         trace_seq_printf(s, "\nprint fmt: \"%s\"\n", tpfmt);            \
68                                                                         \
69         return ret;                                                     \
70 }
71
72 #undef TRACE_EVENT_FORMAT_NOFILTER
73 #define TRACE_EVENT_FORMAT_NOFILTER(call, proto, args, fmt, tstruct,    \
74                                     tpfmt)                              \
75 static int                                                              \
76 ftrace_format_##call(struct trace_seq *s)                               \
77 {                                                                       \
78         struct args field;                                              \
79         int ret;                                                        \
80                                                                         \
81         tstruct;                                                        \
82                                                                         \
83         trace_seq_printf(s, "\nprint fmt: \"%s\"\n", tpfmt);            \
84                                                                         \
85         return ret;                                                     \
86 }
87
88 #include "trace_event_types.h"
89
90 #undef TRACE_ZERO_CHAR
91 #define TRACE_ZERO_CHAR(arg)
92
93 #undef TRACE_FIELD
94 #define TRACE_FIELD(type, item, assign)\
95         entry->item = assign;
96
97 #undef TRACE_FIELD
98 #define TRACE_FIELD(type, item, assign)\
99         entry->item = assign;
100
101 #undef TP_CMD
102 #define TP_CMD(cmd...)  cmd
103
104 #undef TRACE_ENTRY
105 #define TRACE_ENTRY     entry
106
107 #undef TRACE_FIELD_SPECIAL
108 #define TRACE_FIELD_SPECIAL(type_item, item, len, cmd)  \
109         cmd;
110
111 #undef TRACE_EVENT_FORMAT
112 #define TRACE_EVENT_FORMAT(call, proto, args, fmt, tstruct, tpfmt)      \
113 int ftrace_define_fields_##call(void);                                  \
114 static int ftrace_raw_init_event_##call(void);                          \
115                                                                         \
116 struct ftrace_event_call __used                                         \
117 __attribute__((__aligned__(4)))                                         \
118 __attribute__((section("_ftrace_events"))) event_##call = {             \
119         .name                   = #call,                                \
120         .id                     = proto,                                \
121         .system                 = __stringify(TRACE_SYSTEM),            \
122         .raw_init               = ftrace_raw_init_event_##call,         \
123         .show_format            = ftrace_format_##call,                 \
124         .define_fields          = ftrace_define_fields_##call,          \
125 };                                                                      \
126 static int ftrace_raw_init_event_##call(void)                           \
127 {                                                                       \
128         INIT_LIST_HEAD(&event_##call.fields);                           \
129         init_preds(&event_##call);                                      \
130         return 0;                                                       \
131 }                                                                       \
132
133 #undef TRACE_EVENT_FORMAT_NOFILTER
134 #define TRACE_EVENT_FORMAT_NOFILTER(call, proto, args, fmt, tstruct,    \
135                                     tpfmt)                              \
136                                                                         \
137 struct ftrace_event_call __used                                         \
138 __attribute__((__aligned__(4)))                                         \
139 __attribute__((section("_ftrace_events"))) event_##call = {             \
140         .name                   = #call,                                \
141         .id                     = proto,                                \
142         .system                 = __stringify(TRACE_SYSTEM),            \
143         .show_format            = ftrace_format_##call,                 \
144 };
145
146 #include "trace_event_types.h"
147
148 #undef TRACE_FIELD
149 #define TRACE_FIELD(type, item, assign)                                 \
150         ret = trace_define_field(event_call, #type, #item,              \
151                                  offsetof(typeof(field), item),         \
152                                  sizeof(field.item));                   \
153         if (ret)                                                        \
154                 return ret;
155
156 #undef TRACE_FIELD_SPECIAL
157 #define TRACE_FIELD_SPECIAL(type, item, len, cmd)                       \
158         ret = trace_define_field(event_call, #type "[" #len "]", #item, \
159                                  offsetof(typeof(field), item),         \
160                                  sizeof(field.item));                   \
161         if (ret)                                                        \
162                 return ret;
163
164 #undef TRACE_FIELD_ZERO_CHAR
165 #define TRACE_FIELD_ZERO_CHAR(item)
166
167 #undef TRACE_EVENT_FORMAT
168 #define TRACE_EVENT_FORMAT(call, proto, args, fmt, tstruct, tpfmt)      \
169 int                                                                     \
170 ftrace_define_fields_##call(void)                                       \
171 {                                                                       \
172         struct ftrace_event_call *event_call = &event_##call;           \
173         struct args field;                                              \
174         int ret;                                                        \
175                                                                         \
176         __common_field(unsigned char, type);                            \
177         __common_field(unsigned char, flags);                           \
178         __common_field(unsigned char, preempt_count);                   \
179         __common_field(int, pid);                                       \
180         __common_field(int, tgid);                                      \
181                                                                         \
182         tstruct;                                                        \
183                                                                         \
184         return ret;                                                     \
185 }
186
187 #undef TRACE_EVENT_FORMAT_NOFILTER
188 #define TRACE_EVENT_FORMAT_NOFILTER(call, proto, args, fmt, tstruct,    \
189                                     tpfmt)
190
191 #include "trace_event_types.h"