]>
Commit | Line | Data |
---|---|---|
f7d82350 SR |
1 | /* |
2 | * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> | |
3 | * | |
4 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
5 | * This program is free software; you can redistribute it and/or | |
6 | * modify it under the terms of the GNU Lesser General Public | |
7 | * License as published by the Free Software Foundation; | |
8 | * version 2.1 of the License (not later!) | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | * GNU Lesser General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU Lesser General Public | |
7b9f6b40 | 16 | * License along with this program; if not, see <http://www.gnu.org/licenses> |
f7d82350 SR |
17 | * |
18 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
19 | */ | |
20 | #ifndef _PARSE_EVENTS_H | |
21 | #define _PARSE_EVENTS_H | |
22 | ||
1b372ca5 | 23 | #include <stdbool.h> |
f7d82350 | 24 | #include <stdarg.h> |
402bb4e6 | 25 | #include <stdio.h> |
f7d82350 | 26 | #include <regex.h> |
91a058ad | 27 | #include <string.h> |
f7d82350 | 28 | |
1d037ca1 IT |
29 | #ifndef __maybe_unused |
30 | #define __maybe_unused __attribute__((unused)) | |
f7d82350 SR |
31 | #endif |
32 | ||
33 | /* ----------------------- trace_seq ----------------------- */ | |
34 | ||
35 | ||
36 | #ifndef TRACE_SEQ_BUF_SIZE | |
37 | #define TRACE_SEQ_BUF_SIZE 4096 | |
38 | #endif | |
39 | ||
40 | #ifndef DEBUG_RECORD | |
41 | #define DEBUG_RECORD 0 | |
42 | #endif | |
43 | ||
1c698186 | 44 | struct pevent_record { |
f7d82350 SR |
45 | unsigned long long ts; |
46 | unsigned long long offset; | |
47 | long long missed_events; /* buffer dropped events before */ | |
48 | int record_size; /* size of binary record */ | |
49 | int size; /* size of data */ | |
50 | void *data; | |
51 | int cpu; | |
52 | int ref_count; | |
53 | int locked; /* Do not free, even if ref_count is zero */ | |
ff1a70e7 | 54 | void *priv; |
f7d82350 | 55 | #if DEBUG_RECORD |
1c698186 SR |
56 | struct pevent_record *prev; |
57 | struct pevent_record *next; | |
f7d82350 SR |
58 | long alloc_addr; |
59 | #endif | |
60 | }; | |
61 | ||
3c6d8d84 NK |
62 | enum trace_seq_fail { |
63 | TRACE_SEQ__GOOD, | |
64 | TRACE_SEQ__BUFFER_POISONED, | |
65 | TRACE_SEQ__MEM_ALLOC_FAILED, | |
66 | }; | |
67 | ||
f7d82350 SR |
68 | /* |
69 | * Trace sequences are used to allow a function to call several other functions | |
70 | * to create a string of data to use (up to a max of PAGE_SIZE). | |
71 | */ | |
72 | ||
73 | struct trace_seq { | |
74 | char *buffer; | |
75 | unsigned int buffer_size; | |
76 | unsigned int len; | |
77 | unsigned int readpos; | |
3c6d8d84 | 78 | enum trace_seq_fail state; |
f7d82350 SR |
79 | }; |
80 | ||
81 | void trace_seq_init(struct trace_seq *s); | |
6a48aec3 | 82 | void trace_seq_reset(struct trace_seq *s); |
f7d82350 SR |
83 | void trace_seq_destroy(struct trace_seq *s); |
84 | ||
85 | extern int trace_seq_printf(struct trace_seq *s, const char *fmt, ...) | |
86 | __attribute__ ((format (printf, 2, 3))); | |
87 | extern int trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args) | |
88 | __attribute__ ((format (printf, 2, 0))); | |
89 | ||
90 | extern int trace_seq_puts(struct trace_seq *s, const char *str); | |
91 | extern int trace_seq_putc(struct trace_seq *s, unsigned char c); | |
92 | ||
93 | extern void trace_seq_terminate(struct trace_seq *s); | |
94 | ||
402bb4e6 | 95 | extern int trace_seq_do_fprintf(struct trace_seq *s, FILE *fp); |
f7d82350 SR |
96 | extern int trace_seq_do_printf(struct trace_seq *s); |
97 | ||
98 | ||
99 | /* ----------------------- pevent ----------------------- */ | |
100 | ||
101 | struct pevent; | |
102 | struct event_format; | |
103 | ||
104 | typedef int (*pevent_event_handler_func)(struct trace_seq *s, | |
1c698186 | 105 | struct pevent_record *record, |
f7d82350 SR |
106 | struct event_format *event, |
107 | void *context); | |
108 | ||
109 | typedef int (*pevent_plugin_load_func)(struct pevent *pevent); | |
8d0c2224 | 110 | typedef int (*pevent_plugin_unload_func)(struct pevent *pevent); |
f7d82350 | 111 | |
5827f2fa SR |
112 | struct pevent_plugin_option { |
113 | struct pevent_plugin_option *next; | |
f7d82350 SR |
114 | void *handle; |
115 | char *file; | |
116 | char *name; | |
117 | char *plugin_alias; | |
118 | char *description; | |
5dbcfd93 | 119 | const char *value; |
ff1a70e7 | 120 | void *priv; |
f7d82350 SR |
121 | int set; |
122 | }; | |
123 | ||
124 | /* | |
125 | * Plugin hooks that can be called: | |
126 | * | |
127 | * PEVENT_PLUGIN_LOADER: (required) | |
128 | * The function name to initialized the plugin. | |
129 | * | |
130 | * int PEVENT_PLUGIN_LOADER(struct pevent *pevent) | |
131 | * | |
132 | * PEVENT_PLUGIN_UNLOADER: (optional) | |
133 | * The function called just before unloading | |
134 | * | |
8d0c2224 | 135 | * int PEVENT_PLUGIN_UNLOADER(struct pevent *pevent) |
f7d82350 SR |
136 | * |
137 | * PEVENT_PLUGIN_OPTIONS: (optional) | |
138 | * Plugin options that can be set before loading | |
139 | * | |
5827f2fa | 140 | * struct pevent_plugin_option PEVENT_PLUGIN_OPTIONS[] = { |
f7d82350 SR |
141 | * { |
142 | * .name = "option-name", | |
505d3085 | 143 | * .plugin_alias = "override-file-name", (optional) |
f7d82350 SR |
144 | * .description = "description of option to show users", |
145 | * }, | |
146 | * { | |
147 | * .name = NULL, | |
148 | * }, | |
149 | * }; | |
150 | * | |
151 | * Array must end with .name = NULL; | |
152 | * | |
153 | * | |
154 | * .plugin_alias is used to give a shorter name to access | |
155 | * the vairable. Useful if a plugin handles more than one event. | |
156 | * | |
5dbcfd93 SR |
157 | * If .value is not set, then it is considered a boolean and only |
158 | * .set will be processed. If .value is defined, then it is considered | |
159 | * a string option and .set will be ignored. | |
160 | * | |
f7d82350 SR |
161 | * PEVENT_PLUGIN_ALIAS: (optional) |
162 | * The name to use for finding options (uses filename if not defined) | |
163 | */ | |
164 | #define PEVENT_PLUGIN_LOADER pevent_plugin_loader | |
165 | #define PEVENT_PLUGIN_UNLOADER pevent_plugin_unloader | |
166 | #define PEVENT_PLUGIN_OPTIONS pevent_plugin_options | |
167 | #define PEVENT_PLUGIN_ALIAS pevent_plugin_alias | |
168 | #define _MAKE_STR(x) #x | |
169 | #define MAKE_STR(x) _MAKE_STR(x) | |
170 | #define PEVENT_PLUGIN_LOADER_NAME MAKE_STR(PEVENT_PLUGIN_LOADER) | |
171 | #define PEVENT_PLUGIN_UNLOADER_NAME MAKE_STR(PEVENT_PLUGIN_UNLOADER) | |
172 | #define PEVENT_PLUGIN_OPTIONS_NAME MAKE_STR(PEVENT_PLUGIN_OPTIONS) | |
173 | #define PEVENT_PLUGIN_ALIAS_NAME MAKE_STR(PEVENT_PLUGIN_ALIAS) | |
174 | ||
f7d82350 SR |
175 | enum format_flags { |
176 | FIELD_IS_ARRAY = 1, | |
177 | FIELD_IS_POINTER = 2, | |
178 | FIELD_IS_SIGNED = 4, | |
179 | FIELD_IS_STRING = 8, | |
180 | FIELD_IS_DYNAMIC = 16, | |
181 | FIELD_IS_LONG = 32, | |
668fe01f SR |
182 | FIELD_IS_FLAG = 64, |
183 | FIELD_IS_SYMBOLIC = 128, | |
f7d82350 SR |
184 | }; |
185 | ||
186 | struct format_field { | |
187 | struct format_field *next; | |
188 | struct event_format *event; | |
189 | char *type; | |
190 | char *name; | |
d3542436 | 191 | char *alias; |
f7d82350 SR |
192 | int offset; |
193 | int size; | |
194 | unsigned int arraylen; | |
195 | unsigned int elementsize; | |
196 | unsigned long flags; | |
197 | }; | |
198 | ||
199 | struct format { | |
200 | int nr_common; | |
201 | int nr_fields; | |
202 | struct format_field *common_fields; | |
203 | struct format_field *fields; | |
204 | }; | |
205 | ||
206 | struct print_arg_atom { | |
207 | char *atom; | |
208 | }; | |
209 | ||
210 | struct print_arg_string { | |
211 | char *string; | |
212 | int offset; | |
213 | }; | |
214 | ||
473a778a SRRH |
215 | struct print_arg_bitmask { |
216 | char *bitmask; | |
217 | int offset; | |
218 | }; | |
219 | ||
f7d82350 SR |
220 | struct print_arg_field { |
221 | char *name; | |
222 | struct format_field *field; | |
223 | }; | |
224 | ||
225 | struct print_flag_sym { | |
226 | struct print_flag_sym *next; | |
227 | char *value; | |
228 | char *str; | |
229 | }; | |
230 | ||
231 | struct print_arg_typecast { | |
232 | char *type; | |
233 | struct print_arg *item; | |
234 | }; | |
235 | ||
236 | struct print_arg_flags { | |
237 | struct print_arg *field; | |
238 | char *delim; | |
239 | struct print_flag_sym *flags; | |
240 | }; | |
241 | ||
242 | struct print_arg_symbol { | |
243 | struct print_arg *field; | |
244 | struct print_flag_sym *symbols; | |
245 | }; | |
246 | ||
e080e6f1 NK |
247 | struct print_arg_hex { |
248 | struct print_arg *field; | |
249 | struct print_arg *size; | |
250 | }; | |
251 | ||
b839e1e8 JM |
252 | struct print_arg_int_array { |
253 | struct print_arg *field; | |
254 | struct print_arg *count; | |
255 | struct print_arg *el_size; | |
256 | }; | |
257 | ||
f7d82350 SR |
258 | struct print_arg_dynarray { |
259 | struct format_field *field; | |
260 | struct print_arg *index; | |
261 | }; | |
262 | ||
263 | struct print_arg; | |
264 | ||
265 | struct print_arg_op { | |
266 | char *op; | |
267 | int prio; | |
268 | struct print_arg *left; | |
269 | struct print_arg *right; | |
270 | }; | |
271 | ||
272 | struct pevent_function_handler; | |
273 | ||
274 | struct print_arg_func { | |
275 | struct pevent_function_handler *func; | |
276 | struct print_arg *args; | |
277 | }; | |
278 | ||
279 | enum print_arg_type { | |
280 | PRINT_NULL, | |
281 | PRINT_ATOM, | |
282 | PRINT_FIELD, | |
283 | PRINT_FLAGS, | |
284 | PRINT_SYMBOL, | |
e080e6f1 | 285 | PRINT_HEX, |
b839e1e8 | 286 | PRINT_INT_ARRAY, |
f7d82350 SR |
287 | PRINT_TYPE, |
288 | PRINT_STRING, | |
289 | PRINT_BSTRING, | |
290 | PRINT_DYNAMIC_ARRAY, | |
291 | PRINT_OP, | |
292 | PRINT_FUNC, | |
473a778a | 293 | PRINT_BITMASK, |
76055940 | 294 | PRINT_DYNAMIC_ARRAY_LEN, |
0fe05591 | 295 | PRINT_HEX_STR, |
f7d82350 SR |
296 | }; |
297 | ||
298 | struct print_arg { | |
299 | struct print_arg *next; | |
300 | enum print_arg_type type; | |
301 | union { | |
302 | struct print_arg_atom atom; | |
303 | struct print_arg_field field; | |
304 | struct print_arg_typecast typecast; | |
305 | struct print_arg_flags flags; | |
306 | struct print_arg_symbol symbol; | |
e080e6f1 | 307 | struct print_arg_hex hex; |
b839e1e8 | 308 | struct print_arg_int_array int_array; |
f7d82350 SR |
309 | struct print_arg_func func; |
310 | struct print_arg_string string; | |
473a778a | 311 | struct print_arg_bitmask bitmask; |
f7d82350 SR |
312 | struct print_arg_op op; |
313 | struct print_arg_dynarray dynarray; | |
314 | }; | |
315 | }; | |
316 | ||
317 | struct print_fmt { | |
318 | char *format; | |
319 | struct print_arg *args; | |
320 | }; | |
321 | ||
322 | struct event_format { | |
323 | struct pevent *pevent; | |
324 | char *name; | |
325 | int id; | |
326 | int flags; | |
327 | struct format format; | |
328 | struct print_fmt print_fmt; | |
329 | char *system; | |
330 | pevent_event_handler_func handler; | |
331 | void *context; | |
332 | }; | |
333 | ||
334 | enum { | |
335 | EVENT_FL_ISFTRACE = 0x01, | |
336 | EVENT_FL_ISPRINT = 0x02, | |
337 | EVENT_FL_ISBPRINT = 0x04, | |
338 | EVENT_FL_ISFUNCENT = 0x10, | |
339 | EVENT_FL_ISFUNCRET = 0x20, | |
c6c2b960 SR |
340 | EVENT_FL_NOHANDLE = 0x40, |
341 | EVENT_FL_PRINTRAW = 0x80, | |
f7d82350 SR |
342 | |
343 | EVENT_FL_FAILED = 0x80000000 | |
344 | }; | |
345 | ||
346 | enum event_sort_type { | |
347 | EVENT_SORT_ID, | |
348 | EVENT_SORT_NAME, | |
349 | EVENT_SORT_SYSTEM, | |
350 | }; | |
351 | ||
352 | enum event_type { | |
353 | EVENT_ERROR, | |
354 | EVENT_NONE, | |
355 | EVENT_SPACE, | |
356 | EVENT_NEWLINE, | |
357 | EVENT_OP, | |
358 | EVENT_DELIM, | |
359 | EVENT_ITEM, | |
360 | EVENT_DQUOTE, | |
361 | EVENT_SQUOTE, | |
362 | }; | |
363 | ||
364 | typedef unsigned long long (*pevent_func_handler)(struct trace_seq *s, | |
365 | unsigned long long *args); | |
366 | ||
367 | enum pevent_func_arg_type { | |
368 | PEVENT_FUNC_ARG_VOID, | |
369 | PEVENT_FUNC_ARG_INT, | |
370 | PEVENT_FUNC_ARG_LONG, | |
371 | PEVENT_FUNC_ARG_STRING, | |
372 | PEVENT_FUNC_ARG_PTR, | |
373 | PEVENT_FUNC_ARG_MAX_TYPES | |
374 | }; | |
375 | ||
4dc1024a SR |
376 | enum pevent_flag { |
377 | PEVENT_NSEC_OUTPUT = 1, /* output in NSECS */ | |
a7c3196c SRRH |
378 | PEVENT_DISABLE_SYS_PLUGINS = 1 << 1, |
379 | PEVENT_DISABLE_PLUGINS = 1 << 2, | |
4dc1024a SR |
380 | }; |
381 | ||
2f197b9d NK |
382 | #define PEVENT_ERRORS \ |
383 | _PE(MEM_ALLOC_FAILED, "failed to allocate memory"), \ | |
384 | _PE(PARSE_EVENT_FAILED, "failed to parse event"), \ | |
385 | _PE(READ_ID_FAILED, "failed to read event id"), \ | |
386 | _PE(READ_FORMAT_FAILED, "failed to read event format"), \ | |
387 | _PE(READ_PRINT_FAILED, "failed to read event print fmt"), \ | |
67ed939c | 388 | _PE(OLD_FTRACE_ARG_FAILED,"failed to allocate field name for ftrace"),\ |
605b8fda | 389 | _PE(INVALID_ARG_TYPE, "invalid argument type"), \ |
41e12e58 NK |
390 | _PE(INVALID_EXP_TYPE, "invalid expression type"), \ |
391 | _PE(INVALID_OP_TYPE, "invalid operator type"), \ | |
605b8fda | 392 | _PE(INVALID_EVENT_NAME, "invalid event name"), \ |
02d62d6d NK |
393 | _PE(EVENT_NOT_FOUND, "no event found"), \ |
394 | _PE(SYNTAX_ERROR, "syntax error"), \ | |
395 | _PE(ILLEGAL_RVALUE, "illegal rvalue"), \ | |
396 | _PE(ILLEGAL_LVALUE, "illegal lvalue for string comparison"), \ | |
397 | _PE(INVALID_REGEX, "regex did not compute"), \ | |
398 | _PE(ILLEGAL_STRING_CMP, "illegal comparison for string"), \ | |
7bb73553 NK |
399 | _PE(ILLEGAL_INTEGER_CMP,"illegal comparison for integer"), \ |
400 | _PE(REPARENT_NOT_OP, "cannot reparent other than OP"), \ | |
401 | _PE(REPARENT_FAILED, "failed to reparent filter OP"), \ | |
c8ea690d | 402 | _PE(BAD_FILTER_ARG, "bad arg in filter tree"), \ |
42d6194d NK |
403 | _PE(UNEXPECTED_TYPE, "unexpected type (not a value)"), \ |
404 | _PE(ILLEGAL_TOKEN, "illegal token"), \ | |
405 | _PE(INVALID_PAREN, "open parenthesis cannot come here"), \ | |
406 | _PE(UNBALANCED_PAREN, "unbalanced number of parenthesis"), \ | |
69c770a6 | 407 | _PE(UNKNOWN_TOKEN, "unknown token"), \ |
41e12e58 NK |
408 | _PE(FILTER_NOT_FOUND, "no filter found"), \ |
409 | _PE(NOT_A_NUMBER, "must have number field"), \ | |
410 | _PE(NO_FILTER, "no filters exists"), \ | |
411 | _PE(FILTER_MISS, "record does not match to filter") | |
2f197b9d NK |
412 | |
413 | #undef _PE | |
414 | #define _PE(__code, __str) PEVENT_ERRNO__ ## __code | |
bffddffd NK |
415 | enum pevent_errno { |
416 | PEVENT_ERRNO__SUCCESS = 0, | |
41e12e58 | 417 | PEVENT_ERRNO__FILTER_MATCH = PEVENT_ERRNO__SUCCESS, |
bffddffd NK |
418 | |
419 | /* | |
420 | * Choose an arbitrary negative big number not to clash with standard | |
421 | * errno since SUS requires the errno has distinct positive values. | |
422 | * See 'Issue 6' in the link below. | |
423 | * | |
424 | * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html | |
425 | */ | |
426 | __PEVENT_ERRNO__START = -100000, | |
427 | ||
2f197b9d | 428 | PEVENT_ERRORS, |
bffddffd NK |
429 | |
430 | __PEVENT_ERRNO__END, | |
431 | }; | |
2f197b9d | 432 | #undef _PE |
bffddffd | 433 | |
c877bbd8 JO |
434 | struct plugin_list; |
435 | ||
5827f2fa SR |
436 | #define INVALID_PLUGIN_LIST_OPTION ((char **)((unsigned long)-1)) |
437 | ||
c877bbd8 | 438 | struct plugin_list *traceevent_load_plugins(struct pevent *pevent); |
8d0c2224 NK |
439 | void traceevent_unload_plugins(struct plugin_list *plugin_list, |
440 | struct pevent *pevent); | |
5827f2fa SR |
441 | char **traceevent_plugin_list_options(void); |
442 | void traceevent_plugin_free_options_list(char **list); | |
443 | int traceevent_plugin_add_options(const char *name, | |
444 | struct pevent_plugin_option *options); | |
445 | void traceevent_plugin_remove_options(struct pevent_plugin_option *options); | |
446 | void traceevent_print_plugins(struct trace_seq *s, | |
447 | const char *prefix, const char *suffix, | |
448 | const struct plugin_list *list); | |
c877bbd8 | 449 | |
f7d82350 SR |
450 | struct cmdline; |
451 | struct cmdline_list; | |
452 | struct func_map; | |
453 | struct func_list; | |
454 | struct event_handler; | |
33a2471c ACM |
455 | struct func_resolver; |
456 | ||
457 | typedef char *(pevent_func_resolver_t)(void *priv, | |
458 | unsigned long long *addrp, char **modp); | |
f7d82350 SR |
459 | |
460 | struct pevent { | |
461 | int ref_count; | |
462 | ||
463 | int header_page_ts_offset; | |
464 | int header_page_ts_size; | |
465 | int header_page_size_offset; | |
466 | int header_page_size_size; | |
467 | int header_page_data_offset; | |
468 | int header_page_data_size; | |
469 | int header_page_overwrite; | |
470 | ||
471 | int file_bigendian; | |
472 | int host_bigendian; | |
473 | ||
474 | int latency_format; | |
475 | ||
476 | int old_format; | |
477 | ||
478 | int cpus; | |
479 | int long_size; | |
012ac692 | 480 | int page_size; |
f7d82350 SR |
481 | |
482 | struct cmdline *cmdlines; | |
483 | struct cmdline_list *cmdlist; | |
484 | int cmdline_count; | |
485 | ||
486 | struct func_map *func_map; | |
33a2471c | 487 | struct func_resolver *func_resolver; |
f7d82350 SR |
488 | struct func_list *funclist; |
489 | unsigned int func_count; | |
490 | ||
491 | struct printk_map *printk_map; | |
492 | struct printk_list *printklist; | |
493 | unsigned int printk_count; | |
494 | ||
4dc1024a | 495 | |
f7d82350 SR |
496 | struct event_format **events; |
497 | int nr_events; | |
498 | struct event_format **sort_events; | |
499 | enum event_sort_type last_type; | |
500 | ||
501 | int type_offset; | |
502 | int type_size; | |
503 | ||
504 | int pid_offset; | |
505 | int pid_size; | |
506 | ||
507 | int pc_offset; | |
508 | int pc_size; | |
509 | ||
510 | int flags_offset; | |
511 | int flags_size; | |
512 | ||
513 | int ld_offset; | |
514 | int ld_size; | |
515 | ||
516 | int print_raw; | |
517 | ||
518 | int test_filters; | |
519 | ||
4dc1024a SR |
520 | int flags; |
521 | ||
f7d82350 SR |
522 | struct format_field *bprint_ip_field; |
523 | struct format_field *bprint_fmt_field; | |
524 | struct format_field *bprint_buf_field; | |
525 | ||
526 | struct event_handler *handlers; | |
527 | struct pevent_function_handler *func_handlers; | |
528 | ||
529 | /* cache */ | |
530 | struct event_format *last_event; | |
1b372ca5 YY |
531 | |
532 | char *trace_clock; | |
f7d82350 SR |
533 | }; |
534 | ||
4dc1024a SR |
535 | static inline void pevent_set_flag(struct pevent *pevent, int flag) |
536 | { | |
537 | pevent->flags |= flag; | |
538 | } | |
539 | ||
f7d82350 SR |
540 | static inline unsigned short |
541 | __data2host2(struct pevent *pevent, unsigned short data) | |
542 | { | |
543 | unsigned short swap; | |
544 | ||
545 | if (pevent->host_bigendian == pevent->file_bigendian) | |
546 | return data; | |
547 | ||
548 | swap = ((data & 0xffULL) << 8) | | |
549 | ((data & (0xffULL << 8)) >> 8); | |
550 | ||
551 | return swap; | |
552 | } | |
553 | ||
554 | static inline unsigned int | |
555 | __data2host4(struct pevent *pevent, unsigned int data) | |
556 | { | |
557 | unsigned int swap; | |
558 | ||
559 | if (pevent->host_bigendian == pevent->file_bigendian) | |
560 | return data; | |
561 | ||
562 | swap = ((data & 0xffULL) << 24) | | |
563 | ((data & (0xffULL << 8)) << 8) | | |
564 | ((data & (0xffULL << 16)) >> 8) | | |
565 | ((data & (0xffULL << 24)) >> 24); | |
566 | ||
567 | return swap; | |
568 | } | |
569 | ||
570 | static inline unsigned long long | |
571 | __data2host8(struct pevent *pevent, unsigned long long data) | |
572 | { | |
573 | unsigned long long swap; | |
574 | ||
575 | if (pevent->host_bigendian == pevent->file_bigendian) | |
576 | return data; | |
577 | ||
578 | swap = ((data & 0xffULL) << 56) | | |
579 | ((data & (0xffULL << 8)) << 40) | | |
580 | ((data & (0xffULL << 16)) << 24) | | |
581 | ((data & (0xffULL << 24)) << 8) | | |
582 | ((data & (0xffULL << 32)) >> 8) | | |
583 | ((data & (0xffULL << 40)) >> 24) | | |
584 | ((data & (0xffULL << 48)) >> 40) | | |
585 | ((data & (0xffULL << 56)) >> 56); | |
586 | ||
587 | return swap; | |
588 | } | |
589 | ||
590 | #define data2host2(pevent, ptr) __data2host2(pevent, *(unsigned short *)(ptr)) | |
591 | #define data2host4(pevent, ptr) __data2host4(pevent, *(unsigned int *)(ptr)) | |
592 | #define data2host8(pevent, ptr) \ | |
593 | ({ \ | |
594 | unsigned long long __val; \ | |
595 | \ | |
596 | memcpy(&__val, (ptr), sizeof(unsigned long long)); \ | |
597 | __data2host8(pevent, __val); \ | |
598 | }) | |
599 | ||
91a058ad JO |
600 | static inline int traceevent_host_bigendian(void) |
601 | { | |
602 | unsigned char str[] = { 0x1, 0x2, 0x3, 0x4 }; | |
603 | unsigned int val; | |
604 | ||
605 | memcpy(&val, str, 4); | |
606 | return val == 0x01020304; | |
607 | } | |
608 | ||
f7d82350 SR |
609 | /* taken from kernel/trace/trace.h */ |
610 | enum trace_flag_type { | |
611 | TRACE_FLAG_IRQS_OFF = 0x01, | |
612 | TRACE_FLAG_IRQS_NOSUPPORT = 0x02, | |
613 | TRACE_FLAG_NEED_RESCHED = 0x04, | |
614 | TRACE_FLAG_HARDIRQ = 0x08, | |
615 | TRACE_FLAG_SOFTIRQ = 0x10, | |
616 | }; | |
617 | ||
33a2471c ACM |
618 | int pevent_set_function_resolver(struct pevent *pevent, |
619 | pevent_func_resolver_t *func, void *priv); | |
620 | void pevent_reset_function_resolver(struct pevent *pevent); | |
f7d82350 | 621 | int pevent_register_comm(struct pevent *pevent, const char *comm, int pid); |
99ad1417 | 622 | int pevent_register_trace_clock(struct pevent *pevent, const char *trace_clock); |
f7d82350 SR |
623 | int pevent_register_function(struct pevent *pevent, char *name, |
624 | unsigned long long addr, char *mod); | |
18900af8 | 625 | int pevent_register_print_string(struct pevent *pevent, const char *fmt, |
f7d82350 SR |
626 | unsigned long long addr); |
627 | int pevent_pid_is_registered(struct pevent *pevent, int pid); | |
628 | ||
a6745330 SR |
629 | void pevent_print_event_task(struct pevent *pevent, struct trace_seq *s, |
630 | struct event_format *event, | |
631 | struct pevent_record *record); | |
632 | void pevent_print_event_time(struct pevent *pevent, struct trace_seq *s, | |
633 | struct event_format *event, | |
634 | struct pevent_record *record, | |
635 | bool use_trace_clock); | |
636 | void pevent_print_event_data(struct pevent *pevent, struct trace_seq *s, | |
637 | struct event_format *event, | |
638 | struct pevent_record *record); | |
f7d82350 | 639 | void pevent_print_event(struct pevent *pevent, struct trace_seq *s, |
1b372ca5 | 640 | struct pevent_record *record, bool use_trace_clock); |
f7d82350 SR |
641 | |
642 | int pevent_parse_header_page(struct pevent *pevent, char *buf, unsigned long size, | |
643 | int long_size); | |
644 | ||
bffddffd NK |
645 | enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf, |
646 | unsigned long size, const char *sys); | |
71ad9583 JO |
647 | enum pevent_errno pevent_parse_format(struct pevent *pevent, |
648 | struct event_format **eventp, | |
649 | const char *buf, | |
2b29175d ACM |
650 | unsigned long size, const char *sys); |
651 | void pevent_free_format(struct event_format *event); | |
00ae1127 | 652 | void pevent_free_format_field(struct format_field *field); |
f7d82350 SR |
653 | |
654 | void *pevent_get_field_raw(struct trace_seq *s, struct event_format *event, | |
1c698186 | 655 | const char *name, struct pevent_record *record, |
f7d82350 SR |
656 | int *len, int err); |
657 | ||
658 | int pevent_get_field_val(struct trace_seq *s, struct event_format *event, | |
1c698186 | 659 | const char *name, struct pevent_record *record, |
f7d82350 SR |
660 | unsigned long long *val, int err); |
661 | int pevent_get_common_field_val(struct trace_seq *s, struct event_format *event, | |
1c698186 | 662 | const char *name, struct pevent_record *record, |
f7d82350 SR |
663 | unsigned long long *val, int err); |
664 | int pevent_get_any_field_val(struct trace_seq *s, struct event_format *event, | |
1c698186 | 665 | const char *name, struct pevent_record *record, |
f7d82350 SR |
666 | unsigned long long *val, int err); |
667 | ||
668 | int pevent_print_num_field(struct trace_seq *s, const char *fmt, | |
669 | struct event_format *event, const char *name, | |
1c698186 | 670 | struct pevent_record *record, int err); |
f7d82350 | 671 | |
6d862b8c SR |
672 | int pevent_print_func_field(struct trace_seq *s, const char *fmt, |
673 | struct event_format *event, const char *name, | |
674 | struct pevent_record *record, int err); | |
675 | ||
79d5adf0 NK |
676 | int pevent_register_event_handler(struct pevent *pevent, int id, |
677 | const char *sys_name, const char *event_name, | |
f7d82350 | 678 | pevent_event_handler_func func, void *context); |
ad13701d NK |
679 | int pevent_unregister_event_handler(struct pevent *pevent, int id, |
680 | const char *sys_name, const char *event_name, | |
681 | pevent_event_handler_func func, void *context); | |
f7d82350 SR |
682 | int pevent_register_print_function(struct pevent *pevent, |
683 | pevent_func_handler func, | |
684 | enum pevent_func_arg_type ret_type, | |
685 | char *name, ...); | |
20c7e5ab NK |
686 | int pevent_unregister_print_function(struct pevent *pevent, |
687 | pevent_func_handler func, char *name); | |
f7d82350 SR |
688 | |
689 | struct format_field *pevent_find_common_field(struct event_format *event, const char *name); | |
690 | struct format_field *pevent_find_field(struct event_format *event, const char *name); | |
691 | struct format_field *pevent_find_any_field(struct event_format *event, const char *name); | |
692 | ||
693 | const char *pevent_find_function(struct pevent *pevent, unsigned long long addr); | |
694 | unsigned long long | |
695 | pevent_find_function_address(struct pevent *pevent, unsigned long long addr); | |
696 | unsigned long long pevent_read_number(struct pevent *pevent, const void *ptr, int size); | |
697 | int pevent_read_number_field(struct format_field *field, const void *data, | |
698 | unsigned long long *value); | |
699 | ||
700 | struct event_format *pevent_find_event(struct pevent *pevent, int id); | |
701 | ||
702 | struct event_format * | |
703 | pevent_find_event_by_name(struct pevent *pevent, const char *sys, const char *name); | |
704 | ||
a6745330 SR |
705 | struct event_format * |
706 | pevent_find_event_by_record(struct pevent *pevent, struct pevent_record *record); | |
707 | ||
f7d82350 | 708 | void pevent_data_lat_fmt(struct pevent *pevent, |
1c698186 SR |
709 | struct trace_seq *s, struct pevent_record *record); |
710 | int pevent_data_type(struct pevent *pevent, struct pevent_record *rec); | |
f7d82350 | 711 | struct event_format *pevent_data_event_from_type(struct pevent *pevent, int type); |
1c698186 | 712 | int pevent_data_pid(struct pevent *pevent, struct pevent_record *rec); |
9c72fd0f | 713 | int pevent_data_preempt_count(struct pevent *pevent, struct pevent_record *rec); |
c52d9e4e | 714 | int pevent_data_flags(struct pevent *pevent, struct pevent_record *rec); |
f7d82350 | 715 | const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid); |
2771984c SRRH |
716 | struct cmdline; |
717 | struct cmdline *pevent_data_pid_from_comm(struct pevent *pevent, const char *comm, | |
718 | struct cmdline *next); | |
719 | int pevent_cmdline_pid(struct pevent *pevent, struct cmdline *cmdline); | |
720 | ||
be45d40e NK |
721 | void pevent_print_field(struct trace_seq *s, void *data, |
722 | struct format_field *field); | |
723 | void pevent_print_fields(struct trace_seq *s, void *data, | |
724 | int size __maybe_unused, struct event_format *event); | |
f7d82350 | 725 | void pevent_event_info(struct trace_seq *s, struct event_format *event, |
1c698186 | 726 | struct pevent_record *record); |
2f197b9d NK |
727 | int pevent_strerror(struct pevent *pevent, enum pevent_errno errnum, |
728 | char *buf, size_t buflen); | |
f7d82350 SR |
729 | |
730 | struct event_format **pevent_list_events(struct pevent *pevent, enum event_sort_type); | |
731 | struct format_field **pevent_event_common_fields(struct event_format *event); | |
732 | struct format_field **pevent_event_fields(struct event_format *event); | |
733 | ||
734 | static inline int pevent_get_cpus(struct pevent *pevent) | |
735 | { | |
736 | return pevent->cpus; | |
737 | } | |
738 | ||
739 | static inline void pevent_set_cpus(struct pevent *pevent, int cpus) | |
740 | { | |
741 | pevent->cpus = cpus; | |
742 | } | |
743 | ||
744 | static inline int pevent_get_long_size(struct pevent *pevent) | |
745 | { | |
746 | return pevent->long_size; | |
747 | } | |
748 | ||
749 | static inline void pevent_set_long_size(struct pevent *pevent, int long_size) | |
750 | { | |
751 | pevent->long_size = long_size; | |
752 | } | |
753 | ||
012ac692 NK |
754 | static inline int pevent_get_page_size(struct pevent *pevent) |
755 | { | |
756 | return pevent->page_size; | |
757 | } | |
758 | ||
759 | static inline void pevent_set_page_size(struct pevent *pevent, int _page_size) | |
760 | { | |
761 | pevent->page_size = _page_size; | |
762 | } | |
763 | ||
f7d82350 SR |
764 | static inline int pevent_is_file_bigendian(struct pevent *pevent) |
765 | { | |
766 | return pevent->file_bigendian; | |
767 | } | |
768 | ||
769 | static inline void pevent_set_file_bigendian(struct pevent *pevent, int endian) | |
770 | { | |
771 | pevent->file_bigendian = endian; | |
772 | } | |
773 | ||
774 | static inline int pevent_is_host_bigendian(struct pevent *pevent) | |
775 | { | |
776 | return pevent->host_bigendian; | |
777 | } | |
778 | ||
779 | static inline void pevent_set_host_bigendian(struct pevent *pevent, int endian) | |
780 | { | |
781 | pevent->host_bigendian = endian; | |
782 | } | |
783 | ||
784 | static inline int pevent_is_latency_format(struct pevent *pevent) | |
785 | { | |
786 | return pevent->latency_format; | |
787 | } | |
788 | ||
789 | static inline void pevent_set_latency_format(struct pevent *pevent, int lat) | |
790 | { | |
791 | pevent->latency_format = lat; | |
792 | } | |
793 | ||
794 | struct pevent *pevent_alloc(void); | |
795 | void pevent_free(struct pevent *pevent); | |
796 | void pevent_ref(struct pevent *pevent); | |
797 | void pevent_unref(struct pevent *pevent); | |
798 | ||
799 | /* access to the internal parser */ | |
800 | void pevent_buffer_init(const char *buf, unsigned long long size); | |
801 | enum event_type pevent_read_token(char **tok); | |
802 | void pevent_free_token(char *token); | |
803 | int pevent_peek_char(void); | |
804 | const char *pevent_get_input_buf(void); | |
805 | unsigned long long pevent_get_input_buf_ptr(void); | |
806 | ||
807 | /* for debugging */ | |
808 | void pevent_print_funcs(struct pevent *pevent); | |
809 | void pevent_print_printk(struct pevent *pevent); | |
810 | ||
811 | /* ----------------------- filtering ----------------------- */ | |
812 | ||
813 | enum filter_boolean_type { | |
814 | FILTER_FALSE, | |
815 | FILTER_TRUE, | |
816 | }; | |
817 | ||
818 | enum filter_op_type { | |
819 | FILTER_OP_AND = 1, | |
820 | FILTER_OP_OR, | |
821 | FILTER_OP_NOT, | |
822 | }; | |
823 | ||
824 | enum filter_cmp_type { | |
825 | FILTER_CMP_NONE, | |
826 | FILTER_CMP_EQ, | |
827 | FILTER_CMP_NE, | |
828 | FILTER_CMP_GT, | |
829 | FILTER_CMP_LT, | |
830 | FILTER_CMP_GE, | |
831 | FILTER_CMP_LE, | |
832 | FILTER_CMP_MATCH, | |
833 | FILTER_CMP_NOT_MATCH, | |
834 | FILTER_CMP_REGEX, | |
835 | FILTER_CMP_NOT_REGEX, | |
836 | }; | |
837 | ||
838 | enum filter_exp_type { | |
839 | FILTER_EXP_NONE, | |
840 | FILTER_EXP_ADD, | |
841 | FILTER_EXP_SUB, | |
842 | FILTER_EXP_MUL, | |
843 | FILTER_EXP_DIV, | |
844 | FILTER_EXP_MOD, | |
845 | FILTER_EXP_RSHIFT, | |
846 | FILTER_EXP_LSHIFT, | |
847 | FILTER_EXP_AND, | |
848 | FILTER_EXP_OR, | |
849 | FILTER_EXP_XOR, | |
850 | FILTER_EXP_NOT, | |
851 | }; | |
852 | ||
853 | enum filter_arg_type { | |
854 | FILTER_ARG_NONE, | |
855 | FILTER_ARG_BOOLEAN, | |
856 | FILTER_ARG_VALUE, | |
857 | FILTER_ARG_FIELD, | |
858 | FILTER_ARG_EXP, | |
859 | FILTER_ARG_OP, | |
860 | FILTER_ARG_NUM, | |
861 | FILTER_ARG_STR, | |
862 | }; | |
863 | ||
864 | enum filter_value_type { | |
865 | FILTER_NUMBER, | |
866 | FILTER_STRING, | |
867 | FILTER_CHAR | |
868 | }; | |
869 | ||
870 | struct fliter_arg; | |
871 | ||
872 | struct filter_arg_boolean { | |
873 | enum filter_boolean_type value; | |
874 | }; | |
875 | ||
876 | struct filter_arg_field { | |
877 | struct format_field *field; | |
878 | }; | |
879 | ||
880 | struct filter_arg_value { | |
881 | enum filter_value_type type; | |
882 | union { | |
883 | char *str; | |
884 | unsigned long long val; | |
885 | }; | |
886 | }; | |
887 | ||
888 | struct filter_arg_op { | |
889 | enum filter_op_type type; | |
890 | struct filter_arg *left; | |
891 | struct filter_arg *right; | |
892 | }; | |
893 | ||
894 | struct filter_arg_exp { | |
895 | enum filter_exp_type type; | |
896 | struct filter_arg *left; | |
897 | struct filter_arg *right; | |
898 | }; | |
899 | ||
900 | struct filter_arg_num { | |
901 | enum filter_cmp_type type; | |
902 | struct filter_arg *left; | |
903 | struct filter_arg *right; | |
904 | }; | |
905 | ||
906 | struct filter_arg_str { | |
907 | enum filter_cmp_type type; | |
908 | struct format_field *field; | |
909 | char *val; | |
910 | char *buffer; | |
911 | regex_t reg; | |
912 | }; | |
913 | ||
914 | struct filter_arg { | |
915 | enum filter_arg_type type; | |
916 | union { | |
668fe01f | 917 | struct filter_arg_boolean boolean; |
f7d82350 SR |
918 | struct filter_arg_field field; |
919 | struct filter_arg_value value; | |
920 | struct filter_arg_op op; | |
921 | struct filter_arg_exp exp; | |
922 | struct filter_arg_num num; | |
923 | struct filter_arg_str str; | |
924 | }; | |
925 | }; | |
926 | ||
927 | struct filter_type { | |
928 | int event_id; | |
929 | struct event_format *event; | |
930 | struct filter_arg *filter; | |
931 | }; | |
932 | ||
bf19b82e NK |
933 | #define PEVENT_FILTER_ERROR_BUFSZ 1024 |
934 | ||
f7d82350 SR |
935 | struct event_filter { |
936 | struct pevent *pevent; | |
937 | int filters; | |
938 | struct filter_type *event_filters; | |
bf19b82e | 939 | char error_buffer[PEVENT_FILTER_ERROR_BUFSZ]; |
f7d82350 SR |
940 | }; |
941 | ||
942 | struct event_filter *pevent_filter_alloc(struct pevent *pevent); | |
943 | ||
41e12e58 | 944 | /* for backward compatibility */ |
45087935 SR |
945 | #define FILTER_NONE PEVENT_ERRNO__NO_FILTER |
946 | #define FILTER_NOEXIST PEVENT_ERRNO__FILTER_NOT_FOUND | |
41e12e58 NK |
947 | #define FILTER_MISS PEVENT_ERRNO__FILTER_MISS |
948 | #define FILTER_MATCH PEVENT_ERRNO__FILTER_MATCH | |
f7d82350 SR |
949 | |
950 | enum filter_trivial_type { | |
951 | FILTER_TRIVIAL_FALSE, | |
952 | FILTER_TRIVIAL_TRUE, | |
953 | FILTER_TRIVIAL_BOTH, | |
954 | }; | |
955 | ||
69c770a6 NK |
956 | enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter, |
957 | const char *filter_str); | |
f7d82350 | 958 | |
41e12e58 NK |
959 | enum pevent_errno pevent_filter_match(struct event_filter *filter, |
960 | struct pevent_record *record); | |
f7d82350 | 961 | |
bf19b82e NK |
962 | int pevent_filter_strerror(struct event_filter *filter, enum pevent_errno err, |
963 | char *buf, size_t buflen); | |
964 | ||
f7d82350 SR |
965 | int pevent_event_filtered(struct event_filter *filter, |
966 | int event_id); | |
967 | ||
968 | void pevent_filter_reset(struct event_filter *filter); | |
969 | ||
7ef2e813 | 970 | int pevent_filter_clear_trivial(struct event_filter *filter, |
f7d82350 SR |
971 | enum filter_trivial_type type); |
972 | ||
973 | void pevent_filter_free(struct event_filter *filter); | |
974 | ||
975 | char *pevent_filter_make_string(struct event_filter *filter, int event_id); | |
976 | ||
977 | int pevent_filter_remove_event(struct event_filter *filter, | |
978 | int event_id); | |
979 | ||
980 | int pevent_filter_event_has_trivial(struct event_filter *filter, | |
981 | int event_id, | |
982 | enum filter_trivial_type type); | |
983 | ||
984 | int pevent_filter_copy(struct event_filter *dest, struct event_filter *source); | |
985 | ||
986 | int pevent_update_trivial(struct event_filter *dest, struct event_filter *source, | |
987 | enum filter_trivial_type type); | |
988 | ||
989 | int pevent_filter_compare(struct event_filter *filter1, struct event_filter *filter2); | |
990 | ||
991 | #endif /* _PARSE_EVENTS_H */ |