summaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace_export.c
blob: 0cb1a142c74fd88971befdb7d7d3a234ac8f6231 (plain)
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
/*
 * trace_export.c - export basic ftrace utilities to user space
 *
 * Copyright (C) 2009 Steven Rostedt <srostedt@redhat.com>
 */
#include <linux/stringify.h>
#include <linux/kallsyms.h>
#include <linux/seq_file.h>
#include <linux/debugfs.h>
#include <linux/uaccess.h>
#include <linux/ftrace.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>

#include "trace_output.h"


#undef TRACE_STRUCT
#define TRACE_STRUCT(args...) args

extern void __bad_type_size(void);

#undef TRACE_FIELD
#define TRACE_FIELD(type, item, assign)					\
	if (sizeof(type) != sizeof(field.item))				\
		__bad_type_size();					\
	ret = trace_seq_printf(s, "\tfield:" #type " " #item ";\t"	\
			       "offset:%u;\tsize:%u;\n",		\
			       (unsigned int)offsetof(typeof(field), item), \
			       (unsigned int)sizeof(field.item));	\
	if (!ret)							\
		return 0;


#undef TRACE_FIELD_SPECIAL
#define TRACE_FIELD_SPECIAL(type_item, item, len, cmd)			\
	ret = trace_seq_printf(s, "\tfield special:" #type_item ";\t"	\
			       "offset:%u;\tsize:%u;\n",		\
			       (unsigned int)offsetof(typeof(field), item), \
			       (unsigned int)sizeof(field.item));	\
	if (!ret)							\
		return 0;

#undef TRACE_FIELD_ZERO_CHAR
#define TRACE_FIELD_ZERO_CHAR(item)					\
	ret = trace_seq_printf(s, "\tfield:char " #item ";\t"		\
			       "offset:%u;\tsize:0;\n",			\
			       (unsigned int)offsetof(typeof(field), item)); \
	if (!ret)							\
		return 0;


#undef TP_RAW_FMT
#define TP_RAW_FMT(args...) args

#undef TRACE_EVENT_FORMAT
#define TRACE_EVENT_FORMAT(call, proto, args, fmt, tstruct, tpfmt)	\
static int								\
ftrace_format_##call(struct trace_seq *s)				\
{									\
	struct args field;						\
	int ret;							\
									\
	tstruct;							\
									\
	trace_seq_printf(s, "\nprint fmt: \"%s\"\n", tpfmt);		\
									\
	return ret;							\
}

#undef TRACE_EVENT_FORMAT_NOFILTER
#define TRACE_EVENT_FORMAT_NOFILTER(call, proto, args, fmt, tstruct,	\
				    tpfmt)				\
static int								\
ftrace_format_##call(struct trace_seq *s)				\
{									\
	struct args field;						\
	int ret;							\
									\
	tstruct;							\
									\
	trace_seq_printf(s, "\nprint fmt: \"%s\"\n", tpfmt);		\
									\
	return ret;							\
}

#include "trace_event_types.h"

#undef TRACE_ZERO_CHAR
#define TRACE_ZERO_CHAR(arg)

#undef TRACE_FIELD
#define TRACE_FIELD(type, item, assign)\
	entry->item = assign;

#undef TRACE_FIELD
#define TRACE_FIELD(type, item, assign)\
	entry->item = assign;

#undef TP_CMD
#define TP_CMD(cmd...)	cmd

#undef TRACE_ENTRY
#define TRACE_ENTRY	entry

#undef TRACE_FIELD_SPECIAL
#define TRACE_FIELD_SPECIAL(type_item, item, len, cmd)	\
	cmd;

#undef TRACE_EVENT_FORMAT
#define TRACE_EVENT_FORMAT(call, proto, args, fmt, tstruct, tpfmt)	\
int ftrace_define_fields_##call(void);					\
static int ftrace_raw_init_event_##call(void);				\
									\
struct ftrace_event_call __used						\
__attribute__((__aligned__(4)))						\
__attribute__((section("_ftrace_events"))) event_##call = {		\
	.name			= #call,				\
	.id			= proto,				\
	.system			= __stringify(TRACE_SYSTEM),		\
	.raw_init		= ftrace_raw_init_event_##call,		\
	.show_format		= ftrace_format_##call,			\
	.define_fields		= ftrace_define_fields_##call,		\
};									\
static int ftrace_raw_init_event_##call(void)				\
{									\
	INIT_LIST_HEAD(&event_##call.fields);				\
	init_preds(&event_##call);					\
	return 0;							\
}									\

#undef TRACE_EVENT_FORMAT_NOFILTER
#define TRACE_EVENT_FORMAT_NOFILTER(call, proto, args, fmt, tstruct,	\
				    tpfmt)				\
									\
struct ftrace_event_call __used						\
__attribute__((__aligned__(4)))						\
__attribute__((section("_ftrace_events"))) event_##call = {		\
	.name			= #call,				\
	.id			= proto,				\
	.system			= __stringify(TRACE_SYSTEM),		\
	.show_format		= ftrace_format_##call,			\
};

#include "trace_event_types.h"

#undef TRACE_FIELD
#define TRACE_FIELD(type, item, assign)					\
	ret = trace_define_field(event_call, #type, #item,		\
				 offsetof(typeof(field), item),		\
				 sizeof(field.item));			\
	if (ret)							\
		return ret;

#undef TRACE_FIELD_SPECIAL
#define TRACE_FIELD_SPECIAL(type, item, len, cmd)			\
	ret = trace_define_field(event_call, #type "[" #len "]", #item,	\
				 offsetof(typeof(field), item),		\
				 sizeof(field.item));			\
	if (ret)							\
		return ret;

#undef TRACE_FIELD_ZERO_CHAR
#define TRACE_FIELD_ZERO_CHAR(item)

#undef TRACE_EVENT_FORMAT
#define TRACE_EVENT_FORMAT(call, proto, args, fmt, tstruct, tpfmt)	\
int									\
ftrace_define_fields_##call(void)					\
{									\
	struct ftrace_event_call *event_call = &event_##call;		\
	struct args field;						\
	int ret;							\
									\
	__common_field(unsigned char, type);				\
	__common_field(unsigned char, flags);				\
	__common_field(unsigned char, preempt_count);			\
	__common_field(int, pid);					\
	__common_field(int, tgid);					\
									\
	tstruct;							\
									\
	return ret;							\
}

#undef TRACE_EVENT_FORMAT_NOFILTER
#define TRACE_EVENT_FORMAT_NOFILTER(call, proto, args, fmt, tstruct,	\
				    tpfmt)

#include "trace_event_types.h"