Commit | Line | Data |
---|---|---|
b2441318 | 1 | // SPDX-License-Identifier: GPL-2.0 |
770cb243 SR |
2 | /* |
3 | * trace_export.c - export basic ftrace utilities to user space | |
4 | * | |
5 | * Copyright (C) 2009 Steven Rostedt <srostedt@redhat.com> | |
6 | */ | |
7 | #include <linux/stringify.h> | |
8 | #include <linux/kallsyms.h> | |
9 | #include <linux/seq_file.h> | |
770cb243 SR |
10 | #include <linux/uaccess.h> |
11 | #include <linux/ftrace.h> | |
12 | #include <linux/module.h> | |
13 | #include <linux/init.h> | |
770cb243 SR |
14 | |
15 | #include "trace_output.h" | |
16 | ||
3dd80953 SRV |
17 | /* Stub function for events with triggers */ |
18 | static int ftrace_event_register(struct trace_event_call *call, | |
19 | enum trace_reg type, void *data) | |
20 | { | |
21 | return 0; | |
22 | } | |
23 | ||
4e5292ea SR |
24 | #undef TRACE_SYSTEM |
25 | #define TRACE_SYSTEM ftrace | |
da4d0302 | 26 | |
e59a0bff JO |
27 | /* |
28 | * The FTRACE_ENTRY_REG macro allows ftrace entry to define register | |
29 | * function and thus become accesible via perf. | |
30 | */ | |
31 | #undef FTRACE_ENTRY_REG | |
02aa3162 JO |
32 | #define FTRACE_ENTRY_REG(name, struct_name, id, tstruct, print, \ |
33 | filter, regfn) \ | |
34 | FTRACE_ENTRY(name, struct_name, id, PARAMS(tstruct), PARAMS(print), \ | |
35 | filter) | |
e59a0bff | 36 | |
4e5292ea SR |
37 | /* not needed for this file */ |
38 | #undef __field_struct | |
39 | #define __field_struct(type, item) | |
da4d0302 | 40 | |
05ffa2d0 LZ |
41 | #undef __field |
42 | #define __field(type, item) type item; | |
43 | ||
44 | #undef __field_desc | |
45 | #define __field_desc(type, container, item) type item; | |
46 | ||
47 | #undef __array | |
48 | #define __array(type, item, size) type item[size]; | |
49 | ||
50 | #undef __array_desc | |
51 | #define __array_desc(type, container, item, size) type item[size]; | |
52 | ||
53 | #undef __dynamic_array | |
54 | #define __dynamic_array(type, item) type item[]; | |
55 | ||
56 | #undef F_STRUCT | |
57 | #define F_STRUCT(args...) args | |
58 | ||
59 | #undef F_printk | |
60 | #define F_printk(fmt, args...) fmt, args | |
61 | ||
62 | #undef FTRACE_ENTRY | |
02aa3162 JO |
63 | #define FTRACE_ENTRY(name, struct_name, id, tstruct, print, filter) \ |
64 | struct ____ftrace_##name { \ | |
65 | tstruct \ | |
66 | }; \ | |
67 | static void __always_unused ____ftrace_check_##name(void) \ | |
68 | { \ | |
69 | struct ____ftrace_##name *__entry = NULL; \ | |
70 | \ | |
71 | /* force compile-time check on F_printk() */ \ | |
72 | printk(print); \ | |
05ffa2d0 LZ |
73 | } |
74 | ||
75 | #undef FTRACE_ENTRY_DUP | |
02aa3162 JO |
76 | #define FTRACE_ENTRY_DUP(name, struct_name, id, tstruct, print, filter) \ |
77 | FTRACE_ENTRY(name, struct_name, id, PARAMS(tstruct), PARAMS(print), \ | |
78 | filter) | |
05ffa2d0 LZ |
79 | |
80 | #include "trace_entries.h" | |
81 | ||
4e5292ea SR |
82 | #undef __field |
83 | #define __field(type, item) \ | |
84 | ret = trace_define_field(event_call, #type, #item, \ | |
85 | offsetof(typeof(field), item), \ | |
86 | sizeof(field.item), \ | |
02aa3162 | 87 | is_signed_type(type), filter_type); \ |
4e5292ea SR |
88 | if (ret) \ |
89 | return ret; | |
90 | ||
91 | #undef __field_desc | |
92 | #define __field_desc(type, container, item) \ | |
93 | ret = trace_define_field(event_call, #type, #item, \ | |
94 | offsetof(typeof(field), \ | |
95 | container.item), \ | |
96 | sizeof(field.container.item), \ | |
02aa3162 | 97 | is_signed_type(type), filter_type); \ |
4e5292ea SR |
98 | if (ret) \ |
99 | return ret; | |
100 | ||
101 | #undef __array | |
102 | #define __array(type, item, len) \ | |
04295780 | 103 | do { \ |
87291347 | 104 | char *type_str = #type"["__stringify(len)"]"; \ |
04295780 | 105 | BUILD_BUG_ON(len > MAX_FILTER_STR_VAL); \ |
87291347 | 106 | ret = trace_define_field(event_call, type_str, #item, \ |
4e5292ea | 107 | offsetof(typeof(field), item), \ |
fb7ae981 | 108 | sizeof(field.item), \ |
02aa3162 | 109 | is_signed_type(type), filter_type); \ |
04295780 SR |
110 | if (ret) \ |
111 | return ret; \ | |
112 | } while (0); | |
4e5292ea SR |
113 | |
114 | #undef __array_desc | |
115 | #define __array_desc(type, container, item, len) \ | |
116 | BUILD_BUG_ON(len > MAX_FILTER_STR_VAL); \ | |
117 | ret = trace_define_field(event_call, #type "[" #len "]", #item, \ | |
118 | offsetof(typeof(field), \ | |
119 | container.item), \ | |
fb7ae981 | 120 | sizeof(field.container.item), \ |
02aa3162 | 121 | is_signed_type(type), filter_type); \ |
4e5292ea SR |
122 | if (ret) \ |
123 | return ret; | |
124 | ||
125 | #undef __dynamic_array | |
809826a3 | 126 | #define __dynamic_array(type, item) \ |
af3dcb53 | 127 | ret = trace_define_field(event_call, #type "[]", #item, \ |
809826a3 | 128 | offsetof(typeof(field), item), \ |
02aa3162 | 129 | 0, is_signed_type(type), filter_type);\ |
809826a3 LJ |
130 | if (ret) \ |
131 | return ret; | |
4e5292ea SR |
132 | |
133 | #undef FTRACE_ENTRY | |
02aa3162 | 134 | #define FTRACE_ENTRY(name, struct_name, id, tstruct, print, filter) \ |
7e4f44b1 | 135 | static int __init \ |
2425bcb9 | 136 | ftrace_define_fields_##name(struct trace_event_call *event_call) \ |
e45f2e2b | 137 | { \ |
4e5292ea | 138 | struct struct_name field; \ |
e45f2e2b | 139 | int ret; \ |
02aa3162 | 140 | int filter_type = filter; \ |
e45f2e2b | 141 | \ |
4e5292ea | 142 | tstruct; \ |
e45f2e2b TZ |
143 | \ |
144 | return ret; \ | |
145 | } | |
146 | ||
4e5292ea SR |
147 | #include "trace_entries.h" |
148 | ||
509e760c LJ |
149 | #undef __entry |
150 | #define __entry REC | |
151 | ||
4e5292ea SR |
152 | #undef __field |
153 | #define __field(type, item) | |
154 | ||
155 | #undef __field_desc | |
156 | #define __field_desc(type, container, item) | |
157 | ||
158 | #undef __array | |
159 | #define __array(type, item, len) | |
160 | ||
161 | #undef __array_desc | |
162 | #define __array_desc(type, container, item, len) | |
163 | ||
164 | #undef __dynamic_array | |
165 | #define __dynamic_array(type, item) | |
166 | ||
509e760c | 167 | #undef F_printk |
01de982a | 168 | #define F_printk(fmt, args...) __stringify(fmt) ", " __stringify(args) |
509e760c | 169 | |
e59a0bff | 170 | #undef FTRACE_ENTRY_REG |
02aa3162 JO |
171 | #define FTRACE_ENTRY_REG(call, struct_name, etype, tstruct, print, filter,\ |
172 | regfn) \ | |
770cb243 | 173 | \ |
2425bcb9 | 174 | struct trace_event_class __refdata event_class_ftrace_##call = { \ |
2e33af02 SR |
175 | .system = __stringify(TRACE_SYSTEM), \ |
176 | .define_fields = ftrace_define_fields_##call, \ | |
ffb9f995 | 177 | .fields = LIST_HEAD_INIT(event_class_ftrace_##call.fields),\ |
e59a0bff | 178 | .reg = regfn, \ |
2e33af02 SR |
179 | }; \ |
180 | \ | |
2425bcb9 | 181 | struct trace_event_call __used event_##call = { \ |
2e33af02 | 182 | .class = &event_class_ftrace_##call, \ |
abb43f69 MD |
183 | { \ |
184 | .name = #call, \ | |
185 | }, \ | |
186 | .event.type = etype, \ | |
509e760c | 187 | .print_fmt = print, \ |
754cb007 | 188 | .flags = TRACE_EVENT_FL_IGNORE_ENABLE, \ |
e1112b4d | 189 | }; \ |
2425bcb9 | 190 | struct trace_event_call __used \ |
e4a9ea5e | 191 | __attribute__((section("_ftrace_events"))) *__event_##call = &event_##call; |
e1112b4d | 192 | |
e59a0bff | 193 | #undef FTRACE_ENTRY |
02aa3162 | 194 | #define FTRACE_ENTRY(call, struct_name, etype, tstruct, print, filter) \ |
e59a0bff | 195 | FTRACE_ENTRY_REG(call, struct_name, etype, \ |
02aa3162 | 196 | PARAMS(tstruct), PARAMS(print), filter, NULL) |
e59a0bff | 197 | |
c6650b2e | 198 | bool ftrace_event_is_function(struct trace_event_call *call) |
ced39002 JO |
199 | { |
200 | return call == &event_function; | |
201 | } | |
202 | ||
4e5292ea | 203 | #include "trace_entries.h" |