aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2013-12-16 08:52:03 -0500
committerIngo Molnar <mingo@kernel.org>2013-12-16 08:52:03 -0500
commitb283d2f3b74bc98174e8453c0be41dfcda3cae1b (patch)
treee9af6975920c4bf2eb4b8cdb35f88726f3db1e77
parentfe361cfcf40ad4612226347573a8669cd0d44799 (diff)
parent41e12e580a7b0c151199f927193548b84d3e874c (diff)
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: Fixes: * Fix inverted error verification bug in thread__fork, from David Ahern. New features: * Shell completion for 'perf kvm', from Ramkumar Ramachandra. Refactorings: * Get rid of panic() like calls in libtraceevent, from Namyung Kim. * Start carving out symbol parsing routines from perf, just moving routines to topic files in tools/lib/symbol/, tools that want to use it need to integrate it directly, i.e. no tools/lib/symbol/Makefile is provided. * Assorted refactoring patches, moving code around and adding utility evlist methods that will be used in the IPT patchset, from Adrian Hunter. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--tools/lib/symbol/kallsyms.c58
-rw-r--r--tools/lib/symbol/kallsyms.h24
-rw-r--r--tools/lib/traceevent/event-parse.h43
-rw-r--r--tools/lib/traceevent/parse-filter.c507
-rw-r--r--tools/perf/MANIFEST2
-rw-r--r--tools/perf/Makefile.perf5
-rw-r--r--tools/perf/perf-completion.sh4
-rw-r--r--tools/perf/util/event.c1
-rw-r--r--tools/perf/util/evlist.c20
-rw-r--r--tools/perf/util/evlist.h5
-rw-r--r--tools/perf/util/header.c3
-rw-r--r--tools/perf/util/machine.c1
-rw-r--r--tools/perf/util/record.c37
-rw-r--r--tools/perf/util/session.c21
-rw-r--r--tools/perf/util/session.h2
-rw-r--r--tools/perf/util/symbol-elf.c1
-rw-r--r--tools/perf/util/symbol.c69
-rw-r--r--tools/perf/util/symbol.h3
-rw-r--r--tools/perf/util/thread.c2
-rw-r--r--tools/perf/util/util.c41
-rw-r--r--tools/perf/util/util.h4
21 files changed, 550 insertions, 303 deletions
diff --git a/tools/lib/symbol/kallsyms.c b/tools/lib/symbol/kallsyms.c
new file mode 100644
index 000000000000..18bc271a4bbc
--- /dev/null
+++ b/tools/lib/symbol/kallsyms.c
@@ -0,0 +1,58 @@
1#include "symbol/kallsyms.h"
2#include <stdio.h>
3#include <stdlib.h>
4
5int kallsyms__parse(const char *filename, void *arg,
6 int (*process_symbol)(void *arg, const char *name,
7 char type, u64 start))
8{
9 char *line = NULL;
10 size_t n;
11 int err = -1;
12 FILE *file = fopen(filename, "r");
13
14 if (file == NULL)
15 goto out_failure;
16
17 err = 0;
18
19 while (!feof(file)) {
20 u64 start;
21 int line_len, len;
22 char symbol_type;
23 char *symbol_name;
24
25 line_len = getline(&line, &n, file);
26 if (line_len < 0 || !line)
27 break;
28
29 line[--line_len] = '\0'; /* \n */
30
31 len = hex2u64(line, &start);
32
33 len++;
34 if (len + 2 >= line_len)
35 continue;
36
37 symbol_type = line[len];
38 len += 2;
39 symbol_name = line + len;
40 len = line_len - len;
41
42 if (len >= KSYM_NAME_LEN) {
43 err = -1;
44 break;
45 }
46
47 err = process_symbol(arg, symbol_name, symbol_type, start);
48 if (err)
49 break;
50 }
51
52 free(line);
53 fclose(file);
54 return err;
55
56out_failure:
57 return -1;
58}
diff --git a/tools/lib/symbol/kallsyms.h b/tools/lib/symbol/kallsyms.h
new file mode 100644
index 000000000000..6084f5e18b3c
--- /dev/null
+++ b/tools/lib/symbol/kallsyms.h
@@ -0,0 +1,24 @@
1#ifndef __TOOLS_KALLSYMS_H_
2#define __TOOLS_KALLSYMS_H_ 1
3
4#include <elf.h>
5#include <linux/ctype.h>
6#include <linux/types.h>
7
8#ifndef KSYM_NAME_LEN
9#define KSYM_NAME_LEN 256
10#endif
11
12static inline u8 kallsyms2elf_type(char type)
13{
14 if (type == 'W')
15 return STB_WEAK;
16
17 return isupper(type) ? STB_GLOBAL : STB_LOCAL;
18}
19
20int kallsyms__parse(const char *filename, void *arg,
21 int (*process_symbol)(void *arg, const char *name,
22 char type, u64 start));
23
24#endif /* __TOOLS_KALLSYMS_H_ */
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h
index 6e23f197175f..3ad784f5f647 100644
--- a/tools/lib/traceevent/event-parse.h
+++ b/tools/lib/traceevent/event-parse.h
@@ -356,12 +356,35 @@ enum pevent_flag {
356 _PE(READ_FORMAT_FAILED, "failed to read event format"), \ 356 _PE(READ_FORMAT_FAILED, "failed to read event format"), \
357 _PE(READ_PRINT_FAILED, "failed to read event print fmt"), \ 357 _PE(READ_PRINT_FAILED, "failed to read event print fmt"), \
358 _PE(OLD_FTRACE_ARG_FAILED,"failed to allocate field name for ftrace"),\ 358 _PE(OLD_FTRACE_ARG_FAILED,"failed to allocate field name for ftrace"),\
359 _PE(INVALID_ARG_TYPE, "invalid argument type") 359 _PE(INVALID_ARG_TYPE, "invalid argument type"), \
360 _PE(INVALID_EXP_TYPE, "invalid expression type"), \
361 _PE(INVALID_OP_TYPE, "invalid operator type"), \
362 _PE(INVALID_EVENT_NAME, "invalid event name"), \
363 _PE(EVENT_NOT_FOUND, "no event found"), \
364 _PE(SYNTAX_ERROR, "syntax error"), \
365 _PE(ILLEGAL_RVALUE, "illegal rvalue"), \
366 _PE(ILLEGAL_LVALUE, "illegal lvalue for string comparison"), \
367 _PE(INVALID_REGEX, "regex did not compute"), \
368 _PE(ILLEGAL_STRING_CMP, "illegal comparison for string"), \
369 _PE(ILLEGAL_INTEGER_CMP,"illegal comparison for integer"), \
370 _PE(REPARENT_NOT_OP, "cannot reparent other than OP"), \
371 _PE(REPARENT_FAILED, "failed to reparent filter OP"), \
372 _PE(BAD_FILTER_ARG, "bad arg in filter tree"), \
373 _PE(UNEXPECTED_TYPE, "unexpected type (not a value)"), \
374 _PE(ILLEGAL_TOKEN, "illegal token"), \
375 _PE(INVALID_PAREN, "open parenthesis cannot come here"), \
376 _PE(UNBALANCED_PAREN, "unbalanced number of parenthesis"), \
377 _PE(UNKNOWN_TOKEN, "unknown token"), \
378 _PE(FILTER_NOT_FOUND, "no filter found"), \
379 _PE(NOT_A_NUMBER, "must have number field"), \
380 _PE(NO_FILTER, "no filters exists"), \
381 _PE(FILTER_MISS, "record does not match to filter")
360 382
361#undef _PE 383#undef _PE
362#define _PE(__code, __str) PEVENT_ERRNO__ ## __code 384#define _PE(__code, __str) PEVENT_ERRNO__ ## __code
363enum pevent_errno { 385enum pevent_errno {
364 PEVENT_ERRNO__SUCCESS = 0, 386 PEVENT_ERRNO__SUCCESS = 0,
387 PEVENT_ERRNO__FILTER_MATCH = PEVENT_ERRNO__SUCCESS,
365 388
366 /* 389 /*
367 * Choose an arbitrary negative big number not to clash with standard 390 * Choose an arbitrary negative big number not to clash with standard
@@ -836,10 +859,11 @@ struct event_filter {
836 859
837struct event_filter *pevent_filter_alloc(struct pevent *pevent); 860struct event_filter *pevent_filter_alloc(struct pevent *pevent);
838 861
839#define FILTER_NONE -2 862/* for backward compatibility */
840#define FILTER_NOEXIST -1 863#define FILTER_NONE PEVENT_ERRNO__FILTER_NOT_FOUND
841#define FILTER_MISS 0 864#define FILTER_NOEXIST PEVENT_ERRNO__NO_FILTER
842#define FILTER_MATCH 1 865#define FILTER_MISS PEVENT_ERRNO__FILTER_MISS
866#define FILTER_MATCH PEVENT_ERRNO__FILTER_MATCH
843 867
844enum filter_trivial_type { 868enum filter_trivial_type {
845 FILTER_TRIVIAL_FALSE, 869 FILTER_TRIVIAL_FALSE,
@@ -847,13 +871,12 @@ enum filter_trivial_type {
847 FILTER_TRIVIAL_BOTH, 871 FILTER_TRIVIAL_BOTH,
848}; 872};
849 873
850int pevent_filter_add_filter_str(struct event_filter *filter, 874enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter,
851 const char *filter_str, 875 const char *filter_str);
852 char **error_str);
853 876
854 877
855int pevent_filter_match(struct event_filter *filter, 878enum pevent_errno pevent_filter_match(struct event_filter *filter,
856 struct pevent_record *record); 879 struct pevent_record *record);
857 880
858int pevent_event_filtered(struct event_filter *filter, 881int pevent_event_filtered(struct event_filter *filter,
859 int event_id); 882 int event_id);
diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c
index ab402fb2dcf7..9303c55128db 100644
--- a/tools/lib/traceevent/parse-filter.c
+++ b/tools/lib/traceevent/parse-filter.c
@@ -56,7 +56,21 @@ static void show_error(char **error_str, const char *fmt, ...)
56 index = pevent_get_input_buf_ptr(); 56 index = pevent_get_input_buf_ptr();
57 len = input ? strlen(input) : 0; 57 len = input ? strlen(input) : 0;
58 58
59 error = malloc_or_die(MAX_ERR_STR_SIZE + (len*2) + 3); 59 error = malloc(MAX_ERR_STR_SIZE + (len*2) + 3);
60 if (error == NULL) {
61 /*
62 * Maybe it's due to len is too long.
63 * Retry without the input buffer part.
64 */
65 len = 0;
66
67 error = malloc(MAX_ERR_STR_SIZE);
68 if (error == NULL) {
69 /* no memory */
70 *error_str = NULL;
71 return;
72 }
73 }
60 74
61 if (len) { 75 if (len) {
62 strcpy(error, input); 76 strcpy(error, input);
@@ -95,7 +109,11 @@ static enum event_type read_token(char **tok)
95 (strcmp(token, "=") == 0 || strcmp(token, "!") == 0) && 109 (strcmp(token, "=") == 0 || strcmp(token, "!") == 0) &&
96 pevent_peek_char() == '~') { 110 pevent_peek_char() == '~') {
97 /* append it */ 111 /* append it */
98 *tok = malloc_or_die(3); 112 *tok = malloc(3);
113 if (*tok == NULL) {
114 free_token(token);
115 return EVENT_ERROR;
116 }
99 sprintf(*tok, "%c%c", *token, '~'); 117 sprintf(*tok, "%c%c", *token, '~');
100 free_token(token); 118 free_token(token);
101 /* Now remove the '~' from the buffer */ 119 /* Now remove the '~' from the buffer */
@@ -147,11 +165,13 @@ add_filter_type(struct event_filter *filter, int id)
147 if (filter_type) 165 if (filter_type)
148 return filter_type; 166 return filter_type;
149 167
150 filter->event_filters = realloc(filter->event_filters, 168 filter_type = realloc(filter->event_filters,
151 sizeof(*filter->event_filters) * 169 sizeof(*filter->event_filters) *
152 (filter->filters + 1)); 170 (filter->filters + 1));
153 if (!filter->event_filters) 171 if (!filter_type)
154 die("Could not allocate filter"); 172 return NULL;
173
174 filter->event_filters = filter_type;
155 175
156 for (i = 0; i < filter->filters; i++) { 176 for (i = 0; i < filter->filters; i++) {
157 if (filter->event_filters[i].event_id > id) 177 if (filter->event_filters[i].event_id > id)
@@ -195,12 +215,7 @@ struct event_filter *pevent_filter_alloc(struct pevent *pevent)
195 215
196static struct filter_arg *allocate_arg(void) 216static struct filter_arg *allocate_arg(void)
197{ 217{
198 struct filter_arg *arg; 218 return calloc(1, sizeof(struct filter_arg));
199
200 arg = malloc_or_die(sizeof(*arg));
201 memset(arg, 0, sizeof(*arg));
202
203 return arg;
204} 219}
205 220
206static void free_arg(struct filter_arg *arg) 221static void free_arg(struct filter_arg *arg)
@@ -272,7 +287,7 @@ static int event_match(struct event_format *event,
272 !regexec(ereg, event->name, 0, NULL, 0); 287 !regexec(ereg, event->name, 0, NULL, 0);
273} 288}
274 289
275static int 290static enum pevent_errno
276find_event(struct pevent *pevent, struct event_list **events, 291find_event(struct pevent *pevent, struct event_list **events,
277 char *sys_name, char *event_name) 292 char *sys_name, char *event_name)
278{ 293{
@@ -291,23 +306,31 @@ find_event(struct pevent *pevent, struct event_list **events,
291 sys_name = NULL; 306 sys_name = NULL;
292 } 307 }
293 308
294 reg = malloc_or_die(strlen(event_name) + 3); 309 reg = malloc(strlen(event_name) + 3);
310 if (reg == NULL)
311 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
312
295 sprintf(reg, "^%s$", event_name); 313 sprintf(reg, "^%s$", event_name);
296 314
297 ret = regcomp(&ereg, reg, REG_ICASE|REG_NOSUB); 315 ret = regcomp(&ereg, reg, REG_ICASE|REG_NOSUB);
298 free(reg); 316 free(reg);
299 317
300 if (ret) 318 if (ret)
301 return -1; 319 return PEVENT_ERRNO__INVALID_EVENT_NAME;
302 320
303 if (sys_name) { 321 if (sys_name) {
304 reg = malloc_or_die(strlen(sys_name) + 3); 322 reg = malloc(strlen(sys_name) + 3);
323 if (reg == NULL) {
324 regfree(&ereg);
325 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
326 }
327
305 sprintf(reg, "^%s$", sys_name); 328 sprintf(reg, "^%s$", sys_name);
306 ret = regcomp(&sreg, reg, REG_ICASE|REG_NOSUB); 329 ret = regcomp(&sreg, reg, REG_ICASE|REG_NOSUB);
307 free(reg); 330 free(reg);
308 if (ret) { 331 if (ret) {
309 regfree(&ereg); 332 regfree(&ereg);
310 return -1; 333 return PEVENT_ERRNO__INVALID_EVENT_NAME;
311 } 334 }
312 } 335 }
313 336
@@ -327,9 +350,9 @@ find_event(struct pevent *pevent, struct event_list **events,
327 regfree(&sreg); 350 regfree(&sreg);
328 351
329 if (!match) 352 if (!match)
330 return -1; 353 return PEVENT_ERRNO__EVENT_NOT_FOUND;
331 if (fail) 354 if (fail)
332 return -2; 355 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
333 356
334 return 0; 357 return 0;
335} 358}
@@ -345,14 +368,18 @@ static void free_events(struct event_list *events)
345 } 368 }
346} 369}
347 370
348static struct filter_arg * 371static enum pevent_errno
349create_arg_item(struct event_format *event, const char *token, 372create_arg_item(struct event_format *event, const char *token,
350 enum event_type type, char **error_str) 373 enum event_type type, struct filter_arg **parg, char **error_str)
351{ 374{
352 struct format_field *field; 375 struct format_field *field;
353 struct filter_arg *arg; 376 struct filter_arg *arg;
354 377
355 arg = allocate_arg(); 378 arg = allocate_arg();
379 if (arg == NULL) {
380 show_error(error_str, "failed to allocate filter arg");
381 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
382 }
356 383
357 switch (type) { 384 switch (type) {
358 385
@@ -365,7 +392,7 @@ create_arg_item(struct event_format *event, const char *token,
365 if (!arg->value.str) { 392 if (!arg->value.str) {
366 free_arg(arg); 393 free_arg(arg);
367 show_error(error_str, "failed to allocate string filter arg"); 394 show_error(error_str, "failed to allocate string filter arg");
368 return NULL; 395 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
369 } 396 }
370 break; 397 break;
371 case EVENT_ITEM: 398 case EVENT_ITEM:
@@ -393,11 +420,11 @@ create_arg_item(struct event_format *event, const char *token,
393 break; 420 break;
394 default: 421 default:
395 free_arg(arg); 422 free_arg(arg);
396 show_error(error_str, "expected a value but found %s", 423 show_error(error_str, "expected a value but found %s", token);
397 token); 424 return PEVENT_ERRNO__UNEXPECTED_TYPE;
398 return NULL;
399 } 425 }
400 return arg; 426 *parg = arg;
427 return 0;
401} 428}
402 429
403static struct filter_arg * 430static struct filter_arg *
@@ -406,6 +433,9 @@ create_arg_op(enum filter_op_type btype)
406 struct filter_arg *arg; 433 struct filter_arg *arg;
407 434
408 arg = allocate_arg(); 435 arg = allocate_arg();
436 if (!arg)
437 return NULL;
438
409 arg->type = FILTER_ARG_OP; 439 arg->type = FILTER_ARG_OP;
410 arg->op.type = btype; 440 arg->op.type = btype;
411 441
@@ -418,6 +448,9 @@ create_arg_exp(enum filter_exp_type etype)
418 struct filter_arg *arg; 448 struct filter_arg *arg;
419 449
420 arg = allocate_arg(); 450 arg = allocate_arg();
451 if (!arg)
452 return NULL;
453
421 arg->type = FILTER_ARG_EXP; 454 arg->type = FILTER_ARG_EXP;
422 arg->op.type = etype; 455 arg->op.type = etype;
423 456
@@ -430,6 +463,9 @@ create_arg_cmp(enum filter_exp_type etype)
430 struct filter_arg *arg; 463 struct filter_arg *arg;
431 464
432 arg = allocate_arg(); 465 arg = allocate_arg();
466 if (!arg)
467 return NULL;
468
433 /* Use NUM and change if necessary */ 469 /* Use NUM and change if necessary */
434 arg->type = FILTER_ARG_NUM; 470 arg->type = FILTER_ARG_NUM;
435 arg->op.type = etype; 471 arg->op.type = etype;
@@ -437,8 +473,8 @@ create_arg_cmp(enum filter_exp_type etype)
437 return arg; 473 return arg;
438} 474}
439 475
440static int add_right(struct filter_arg *op, struct filter_arg *arg, 476static enum pevent_errno
441 char **error_str) 477add_right(struct filter_arg *op, struct filter_arg *arg, char **error_str)
442{ 478{
443 struct filter_arg *left; 479 struct filter_arg *left;
444 char *str; 480 char *str;
@@ -469,9 +505,8 @@ static int add_right(struct filter_arg *op, struct filter_arg *arg,
469 case FILTER_ARG_FIELD: 505 case FILTER_ARG_FIELD:
470 break; 506 break;
471 default: 507 default:
472 show_error(error_str, 508 show_error(error_str, "Illegal rvalue");
473 "Illegal rvalue"); 509 return PEVENT_ERRNO__ILLEGAL_RVALUE;
474 return -1;
475 } 510 }
476 511
477 /* 512 /*
@@ -518,7 +553,7 @@ static int add_right(struct filter_arg *op, struct filter_arg *arg,
518 if (left->type != FILTER_ARG_FIELD) { 553 if (left->type != FILTER_ARG_FIELD) {
519 show_error(error_str, 554 show_error(error_str,
520 "Illegal lvalue for string comparison"); 555 "Illegal lvalue for string comparison");
521 return -1; 556 return PEVENT_ERRNO__ILLEGAL_LVALUE;
522 } 557 }
523 558
524 /* Make sure this is a valid string compare */ 559 /* Make sure this is a valid string compare */
@@ -537,25 +572,31 @@ static int add_right(struct filter_arg *op, struct filter_arg *arg,
537 show_error(error_str, 572 show_error(error_str,
538 "RegEx '%s' did not compute", 573 "RegEx '%s' did not compute",
539 str); 574 str);
540 return -1; 575 return PEVENT_ERRNO__INVALID_REGEX;
541 } 576 }
542 break; 577 break;
543 default: 578 default:
544 show_error(error_str, 579 show_error(error_str,
545 "Illegal comparison for string"); 580 "Illegal comparison for string");
546 return -1; 581 return PEVENT_ERRNO__ILLEGAL_STRING_CMP;
547 } 582 }
548 583
549 op->type = FILTER_ARG_STR; 584 op->type = FILTER_ARG_STR;
550 op->str.type = op_type; 585 op->str.type = op_type;
551 op->str.field = left->field.field; 586 op->str.field = left->field.field;
552 op->str.val = strdup(str); 587 op->str.val = strdup(str);
553 if (!op->str.val) 588 if (!op->str.val) {
554 die("malloc string"); 589 show_error(error_str, "Failed to allocate string filter");
590 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
591 }
555 /* 592 /*
556 * Need a buffer to copy data for tests 593 * Need a buffer to copy data for tests
557 */ 594 */
558 op->str.buffer = malloc_or_die(op->str.field->size + 1); 595 op->str.buffer = malloc(op->str.field->size + 1);
596 if (!op->str.buffer) {
597 show_error(error_str, "Failed to allocate string filter");
598 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
599 }
559 /* Null terminate this buffer */ 600 /* Null terminate this buffer */
560 op->str.buffer[op->str.field->size] = 0; 601 op->str.buffer[op->str.field->size] = 0;
561 602
@@ -573,7 +614,7 @@ static int add_right(struct filter_arg *op, struct filter_arg *arg,
573 case FILTER_CMP_NOT_REGEX: 614 case FILTER_CMP_NOT_REGEX:
574 show_error(error_str, 615 show_error(error_str,
575 "Op not allowed with integers"); 616 "Op not allowed with integers");
576 return -1; 617 return PEVENT_ERRNO__ILLEGAL_INTEGER_CMP;
577 618
578 default: 619 default:
579 break; 620 break;
@@ -593,9 +634,8 @@ static int add_right(struct filter_arg *op, struct filter_arg *arg,
593 return 0; 634 return 0;
594 635
595 out_fail: 636 out_fail:
596 show_error(error_str, 637 show_error(error_str, "Syntax error");
597 "Syntax error"); 638 return PEVENT_ERRNO__SYNTAX_ERROR;
598 return -1;
599} 639}
600 640
601static struct filter_arg * 641static struct filter_arg *
@@ -608,7 +648,7 @@ rotate_op_right(struct filter_arg *a, struct filter_arg *b)
608 return arg; 648 return arg;
609} 649}
610 650
611static int add_left(struct filter_arg *op, struct filter_arg *arg) 651static enum pevent_errno add_left(struct filter_arg *op, struct filter_arg *arg)
612{ 652{
613 switch (op->type) { 653 switch (op->type) {
614 case FILTER_ARG_EXP: 654 case FILTER_ARG_EXP:
@@ -627,11 +667,11 @@ static int add_left(struct filter_arg *op, struct filter_arg *arg)
627 /* left arg of compares must be a field */ 667 /* left arg of compares must be a field */
628 if (arg->type != FILTER_ARG_FIELD && 668 if (arg->type != FILTER_ARG_FIELD &&
629 arg->type != FILTER_ARG_BOOLEAN) 669 arg->type != FILTER_ARG_BOOLEAN)
630 return -1; 670 return PEVENT_ERRNO__INVALID_ARG_TYPE;
631 op->num.left = arg; 671 op->num.left = arg;
632 break; 672 break;
633 default: 673 default:
634 return -1; 674 return PEVENT_ERRNO__INVALID_ARG_TYPE;
635 } 675 }
636 return 0; 676 return 0;
637} 677}
@@ -744,15 +784,18 @@ enum filter_vals {
744 FILTER_VAL_TRUE, 784 FILTER_VAL_TRUE,
745}; 785};
746 786
747void reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child, 787static enum pevent_errno
748 struct filter_arg *arg) 788reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child,
789 struct filter_arg *arg, char **error_str)
749{ 790{
750 struct filter_arg *other_child; 791 struct filter_arg *other_child;
751 struct filter_arg **ptr; 792 struct filter_arg **ptr;
752 793
753 if (parent->type != FILTER_ARG_OP && 794 if (parent->type != FILTER_ARG_OP &&
754 arg->type != FILTER_ARG_OP) 795 arg->type != FILTER_ARG_OP) {
755 die("can not reparent other than OP"); 796 show_error(error_str, "can not reparent other than OP");
797 return PEVENT_ERRNO__REPARENT_NOT_OP;
798 }
756 799
757 /* Get the sibling */ 800 /* Get the sibling */
758 if (old_child->op.right == arg) { 801 if (old_child->op.right == arg) {
@@ -761,8 +804,10 @@ void reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child,
761 } else if (old_child->op.left == arg) { 804 } else if (old_child->op.left == arg) {
762 ptr = &old_child->op.left; 805 ptr = &old_child->op.left;
763 other_child = old_child->op.right; 806 other_child = old_child->op.right;
764 } else 807 } else {
765 die("Error in reparent op, find other child"); 808 show_error(error_str, "Error in reparent op, find other child");
809 return PEVENT_ERRNO__REPARENT_FAILED;
810 }
766 811
767 /* Detach arg from old_child */ 812 /* Detach arg from old_child */
768 *ptr = NULL; 813 *ptr = NULL;
@@ -773,23 +818,29 @@ void reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child,
773 *parent = *arg; 818 *parent = *arg;
774 /* Free arg without recussion */ 819 /* Free arg without recussion */
775 free(arg); 820 free(arg);
776 return; 821 return 0;
777 } 822 }
778 823
779 if (parent->op.right == old_child) 824 if (parent->op.right == old_child)
780 ptr = &parent->op.right; 825 ptr = &parent->op.right;
781 else if (parent->op.left == old_child) 826 else if (parent->op.left == old_child)
782 ptr = &parent->op.left; 827 ptr = &parent->op.left;
783 else 828 else {
784 die("Error in reparent op"); 829 show_error(error_str, "Error in reparent op");
830 return PEVENT_ERRNO__REPARENT_FAILED;
831 }
832
785 *ptr = arg; 833 *ptr = arg;
786 834
787 free_arg(old_child); 835 free_arg(old_child);
836 return 0;
788} 837}
789 838
790enum filter_vals test_arg(struct filter_arg *parent, struct filter_arg *arg) 839/* Returns either filter_vals (success) or pevent_errno (failfure) */
840static int test_arg(struct filter_arg *parent, struct filter_arg *arg,
841 char **error_str)
791{ 842{
792 enum filter_vals lval, rval; 843 int lval, rval;
793 844
794 switch (arg->type) { 845 switch (arg->type) {
795 846
@@ -804,63 +855,68 @@ enum filter_vals test_arg(struct filter_arg *parent, struct filter_arg *arg)
804 return FILTER_VAL_NORM; 855 return FILTER_VAL_NORM;
805 856
806 case FILTER_ARG_EXP: 857 case FILTER_ARG_EXP:
807 lval = test_arg(arg, arg->exp.left); 858 lval = test_arg(arg, arg->exp.left, error_str);
808 if (lval != FILTER_VAL_NORM) 859 if (lval != FILTER_VAL_NORM)
809 return lval; 860 return lval;
810 rval = test_arg(arg, arg->exp.right); 861 rval = test_arg(arg, arg->exp.right, error_str);
811 if (rval != FILTER_VAL_NORM) 862 if (rval != FILTER_VAL_NORM)
812 return rval; 863 return rval;
813 return FILTER_VAL_NORM; 864 return FILTER_VAL_NORM;
814 865
815 case FILTER_ARG_NUM: 866 case FILTER_ARG_NUM:
816 lval = test_arg(arg, arg->num.left); 867 lval = test_arg(arg, arg->num.left, error_str);
817 if (lval != FILTER_VAL_NORM) 868 if (lval != FILTER_VAL_NORM)
818 return lval; 869 return lval;
819 rval = test_arg(arg, arg->num.right); 870 rval = test_arg(arg, arg->num.right, error_str);
820 if (rval != FILTER_VAL_NORM) 871 if (rval != FILTER_VAL_NORM)
821 return rval; 872 return rval;
822 return FILTER_VAL_NORM; 873 return FILTER_VAL_NORM;
823 874
824 case FILTER_ARG_OP: 875 case FILTER_ARG_OP:
825 if (arg->op.type != FILTER_OP_NOT) { 876 if (arg->op.type != FILTER_OP_NOT) {
826 lval = test_arg(arg, arg->op.left); 877 lval = test_arg(arg, arg->op.left, error_str);
827 switch (lval) { 878 switch (lval) {
828 case FILTER_VAL_NORM: 879 case FILTER_VAL_NORM:
829 break; 880 break;
830 case FILTER_VAL_TRUE: 881 case FILTER_VAL_TRUE:
831 if (arg->op.type == FILTER_OP_OR) 882 if (arg->op.type == FILTER_OP_OR)
832 return FILTER_VAL_TRUE; 883 return FILTER_VAL_TRUE;
833 rval = test_arg(arg, arg->op.right); 884 rval = test_arg(arg, arg->op.right, error_str);
834 if (rval != FILTER_VAL_NORM) 885 if (rval != FILTER_VAL_NORM)
835 return rval; 886 return rval;
836 887
837 reparent_op_arg(parent, arg, arg->op.right); 888 return reparent_op_arg(parent, arg, arg->op.right,
838 return FILTER_VAL_NORM; 889 error_str);
839 890
840 case FILTER_VAL_FALSE: 891 case FILTER_VAL_FALSE:
841 if (arg->op.type == FILTER_OP_AND) 892 if (arg->op.type == FILTER_OP_AND)
842 return FILTER_VAL_FALSE; 893 return FILTER_VAL_FALSE;
843 rval = test_arg(arg, arg->op.right); 894 rval = test_arg(arg, arg->op.right, error_str);
844 if (rval != FILTER_VAL_NORM) 895 if (rval != FILTER_VAL_NORM)
845 return rval; 896 return rval;
846 897
847 reparent_op_arg(parent, arg, arg->op.right); 898 return reparent_op_arg(parent, arg, arg->op.right,
848 return FILTER_VAL_NORM; 899 error_str);
900
901 default:
902 return lval;
849 } 903 }
850 } 904 }
851 905
852 rval = test_arg(arg, arg->op.right); 906 rval = test_arg(arg, arg->op.right, error_str);
853 switch (rval) { 907 switch (rval) {
854 case FILTER_VAL_NORM: 908 case FILTER_VAL_NORM:
909 default:
855 break; 910 break;
911
856 case FILTER_VAL_TRUE: 912 case FILTER_VAL_TRUE:
857 if (arg->op.type == FILTER_OP_OR) 913 if (arg->op.type == FILTER_OP_OR)
858 return FILTER_VAL_TRUE; 914 return FILTER_VAL_TRUE;
859 if (arg->op.type == FILTER_OP_NOT) 915 if (arg->op.type == FILTER_OP_NOT)
860 return FILTER_VAL_FALSE; 916 return FILTER_VAL_FALSE;
861 917
862 reparent_op_arg(parent, arg, arg->op.left); 918 return reparent_op_arg(parent, arg, arg->op.left,
863 return FILTER_VAL_NORM; 919 error_str);
864 920
865 case FILTER_VAL_FALSE: 921 case FILTER_VAL_FALSE:
866 if (arg->op.type == FILTER_OP_AND) 922 if (arg->op.type == FILTER_OP_AND)
@@ -868,39 +924,54 @@ enum filter_vals test_arg(struct filter_arg *parent, struct filter_arg *arg)
868 if (arg->op.type == FILTER_OP_NOT) 924 if (arg->op.type == FILTER_OP_NOT)
869 return FILTER_VAL_TRUE; 925 return FILTER_VAL_TRUE;
870 926
871 reparent_op_arg(parent, arg, arg->op.left); 927 return reparent_op_arg(parent, arg, arg->op.left,
872 return FILTER_VAL_NORM; 928 error_str);
873 } 929 }
874 930
875 return FILTER_VAL_NORM; 931 return rval;
876 default: 932 default:
877 die("bad arg in filter tree"); 933 show_error(error_str, "bad arg in filter tree");
934 return PEVENT_ERRNO__BAD_FILTER_ARG;
878 } 935 }
879 return FILTER_VAL_NORM; 936 return FILTER_VAL_NORM;
880} 937}
881 938
882/* Remove any unknown event fields */ 939/* Remove any unknown event fields */
883static struct filter_arg *collapse_tree(struct filter_arg *arg) 940static int collapse_tree(struct filter_arg *arg,
941 struct filter_arg **arg_collapsed, char **error_str)
884{ 942{
885 enum filter_vals ret; 943 int ret;
886 944
887 ret = test_arg(arg, arg); 945 ret = test_arg(arg, arg, error_str);
888 switch (ret) { 946 switch (ret) {
889 case FILTER_VAL_NORM: 947 case FILTER_VAL_NORM:
890 return arg; 948 break;
891 949
892 case FILTER_VAL_TRUE: 950 case FILTER_VAL_TRUE:
893 case FILTER_VAL_FALSE: 951 case FILTER_VAL_FALSE:
894 free_arg(arg); 952 free_arg(arg);
895 arg = allocate_arg(); 953 arg = allocate_arg();
896 arg->type = FILTER_ARG_BOOLEAN; 954 if (arg) {
897 arg->boolean.value = ret == FILTER_VAL_TRUE; 955 arg->type = FILTER_ARG_BOOLEAN;
956 arg->boolean.value = ret == FILTER_VAL_TRUE;
957 } else {
958 show_error(error_str, "Failed to allocate filter arg");
959 ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
960 }
961 break;
962
963 default:
964 /* test_arg() already set the error_str */
965 free_arg(arg);
966 arg = NULL;
967 break;
898 } 968 }
899 969
900 return arg; 970 *arg_collapsed = arg;
971 return ret;
901} 972}
902 973
903static int 974static enum pevent_errno
904process_filter(struct event_format *event, struct filter_arg **parg, 975process_filter(struct event_format *event, struct filter_arg **parg,
905 char **error_str, int not) 976 char **error_str, int not)
906{ 977{
@@ -914,7 +985,7 @@ process_filter(struct event_format *event, struct filter_arg **parg,
914 enum filter_op_type btype; 985 enum filter_op_type btype;
915 enum filter_exp_type etype; 986 enum filter_exp_type etype;
916 enum filter_cmp_type ctype; 987 enum filter_cmp_type ctype;
917 int ret; 988 enum pevent_errno ret;
918 989
919 *parg = NULL; 990 *parg = NULL;
920 991
@@ -925,8 +996,8 @@ process_filter(struct event_format *event, struct filter_arg **parg,
925 case EVENT_SQUOTE: 996 case EVENT_SQUOTE:
926 case EVENT_DQUOTE: 997 case EVENT_DQUOTE:
927 case EVENT_ITEM: 998 case EVENT_ITEM:
928 arg = create_arg_item(event, token, type, error_str); 999 ret = create_arg_item(event, token, type, &arg, error_str);
929 if (!arg) 1000 if (ret < 0)
930 goto fail; 1001 goto fail;
931 if (!left_item) 1002 if (!left_item)
932 left_item = arg; 1003 left_item = arg;
@@ -939,20 +1010,20 @@ process_filter(struct event_format *event, struct filter_arg **parg,
939 if (not) { 1010 if (not) {
940 arg = NULL; 1011 arg = NULL;
941 if (current_op) 1012 if (current_op)
942 goto fail_print; 1013 goto fail_syntax;
943 free(token); 1014 free(token);
944 *parg = current_exp; 1015 *parg = current_exp;
945 return 0; 1016 return 0;
946 } 1017 }
947 } else 1018 } else
948 goto fail_print; 1019 goto fail_syntax;
949 arg = NULL; 1020 arg = NULL;
950 break; 1021 break;
951 1022
952 case EVENT_DELIM: 1023 case EVENT_DELIM:
953 if (*token == ',') { 1024 if (*token == ',') {
954 show_error(error_str, 1025 show_error(error_str, "Illegal token ','");
955 "Illegal token ','"); 1026 ret = PEVENT_ERRNO__ILLEGAL_TOKEN;
956 goto fail; 1027 goto fail;
957 } 1028 }
958 1029
@@ -960,19 +1031,23 @@ process_filter(struct event_format *event, struct filter_arg **parg,
960 if (left_item) { 1031 if (left_item) {
961 show_error(error_str, 1032 show_error(error_str,
962 "Open paren can not come after item"); 1033 "Open paren can not come after item");
1034 ret = PEVENT_ERRNO__INVALID_PAREN;
963 goto fail; 1035 goto fail;
964 } 1036 }
965 if (current_exp) { 1037 if (current_exp) {
966 show_error(error_str, 1038 show_error(error_str,
967 "Open paren can not come after expression"); 1039 "Open paren can not come after expression");
1040 ret = PEVENT_ERRNO__INVALID_PAREN;
968 goto fail; 1041 goto fail;
969 } 1042 }
970 1043
971 ret = process_filter(event, &arg, error_str, 0); 1044 ret = process_filter(event, &arg, error_str, 0);
972 if (ret != 1) { 1045 if (ret != PEVENT_ERRNO__UNBALANCED_PAREN) {
973 if (ret == 0) 1046 if (ret == 0) {
974 show_error(error_str, 1047 show_error(error_str,
975 "Unbalanced number of '('"); 1048 "Unbalanced number of '('");
1049 ret = PEVENT_ERRNO__UNBALANCED_PAREN;
1050 }
976 goto fail; 1051 goto fail;
977 } 1052 }
978 ret = 0; 1053 ret = 0;
@@ -980,7 +1055,7 @@ process_filter(struct event_format *event, struct filter_arg **parg,
980 /* A not wants just one expression */ 1055 /* A not wants just one expression */
981 if (not) { 1056 if (not) {
982 if (current_op) 1057 if (current_op)
983 goto fail_print; 1058 goto fail_syntax;
984 *parg = arg; 1059 *parg = arg;
985 return 0; 1060 return 0;
986 } 1061 }
@@ -995,19 +1070,19 @@ process_filter(struct event_format *event, struct filter_arg **parg,
995 1070
996 } else { /* ')' */ 1071 } else { /* ')' */
997 if (!current_op && !current_exp) 1072 if (!current_op && !current_exp)
998 goto fail_print; 1073 goto fail_syntax;
999 1074
1000 /* Make sure everything is finished at this level */ 1075 /* Make sure everything is finished at this level */
1001 if (current_exp && !check_op_done(current_exp)) 1076 if (current_exp && !check_op_done(current_exp))
1002 goto fail_print; 1077 goto fail_syntax;
1003 if (current_op && !check_op_done(current_op)) 1078 if (current_op && !check_op_done(current_op))
1004 goto fail_print; 1079 goto fail_syntax;
1005 1080
1006 if (current_op) 1081 if (current_op)
1007 *parg = current_op; 1082 *parg = current_op;
1008 else 1083 else
1009 *parg = current_exp; 1084 *parg = current_exp;
1010 return 1; 1085 return PEVENT_ERRNO__UNBALANCED_PAREN;
1011 } 1086 }
1012 break; 1087 break;
1013 1088
@@ -1019,21 +1094,22 @@ process_filter(struct event_format *event, struct filter_arg **parg,
1019 case OP_BOOL: 1094 case OP_BOOL:
1020 /* Logic ops need a left expression */ 1095 /* Logic ops need a left expression */
1021 if (!current_exp && !current_op) 1096 if (!current_exp && !current_op)
1022 goto fail_print; 1097 goto fail_syntax;
1023 /* fall through */ 1098 /* fall through */
1024 case OP_NOT: 1099 case OP_NOT:
1025 /* logic only processes ops and exp */ 1100 /* logic only processes ops and exp */
1026 if (left_item) 1101 if (left_item)
1027 goto fail_print; 1102 goto fail_syntax;
1028 break; 1103 break;
1029 case OP_EXP: 1104 case OP_EXP:
1030 case OP_CMP: 1105 case OP_CMP:
1031 if (!left_item) 1106 if (!left_item)
1032 goto fail_print; 1107 goto fail_syntax;
1033 break; 1108 break;
1034 case OP_NONE: 1109 case OP_NONE:
1035 show_error(error_str, 1110 show_error(error_str,
1036 "Unknown op token %s", token); 1111 "Unknown op token %s", token);
1112 ret = PEVENT_ERRNO__UNKNOWN_TOKEN;
1037 goto fail; 1113 goto fail;
1038 } 1114 }
1039 1115
@@ -1041,6 +1117,8 @@ process_filter(struct event_format *event, struct filter_arg **parg,
1041 switch (op_type) { 1117 switch (op_type) {
1042 case OP_BOOL: 1118 case OP_BOOL:
1043 arg = create_arg_op(btype); 1119 arg = create_arg_op(btype);
1120 if (arg == NULL)
1121 goto fail_alloc;
1044 if (current_op) 1122 if (current_op)
1045 ret = add_left(arg, current_op); 1123 ret = add_left(arg, current_op);
1046 else 1124 else
@@ -1051,6 +1129,8 @@ process_filter(struct event_format *event, struct filter_arg **parg,
1051 1129
1052 case OP_NOT: 1130 case OP_NOT:
1053 arg = create_arg_op(btype); 1131 arg = create_arg_op(btype);
1132 if (arg == NULL)
1133 goto fail_alloc;
1054 if (current_op) 1134 if (current_op)
1055 ret = add_right(current_op, arg, error_str); 1135 ret = add_right(current_op, arg, error_str);
1056 if (ret < 0) 1136 if (ret < 0)
@@ -1070,6 +1150,8 @@ process_filter(struct event_format *event, struct filter_arg **parg,
1070 arg = create_arg_exp(etype); 1150 arg = create_arg_exp(etype);
1071 else 1151 else
1072 arg = create_arg_cmp(ctype); 1152 arg = create_arg_cmp(ctype);
1153 if (arg == NULL)
1154 goto fail_alloc;
1073 1155
1074 if (current_op) 1156 if (current_op)
1075 ret = add_right(current_op, arg, error_str); 1157 ret = add_right(current_op, arg, error_str);
@@ -1078,7 +1160,7 @@ process_filter(struct event_format *event, struct filter_arg **parg,
1078 ret = add_left(arg, left_item); 1160 ret = add_left(arg, left_item);
1079 if (ret < 0) { 1161 if (ret < 0) {
1080 arg = NULL; 1162 arg = NULL;
1081 goto fail_print; 1163 goto fail_syntax;
1082 } 1164 }
1083 current_exp = arg; 1165 current_exp = arg;
1084 break; 1166 break;
@@ -1087,38 +1169,47 @@ process_filter(struct event_format *event, struct filter_arg **parg,
1087 } 1169 }
1088 arg = NULL; 1170 arg = NULL;
1089 if (ret < 0) 1171 if (ret < 0)
1090 goto fail_print; 1172 goto fail_syntax;
1091 break; 1173 break;
1092 case EVENT_NONE: 1174 case EVENT_NONE:
1093 break; 1175 break;
1176 case EVENT_ERROR:
1177 goto fail_alloc;
1094 default: 1178 default:
1095 goto fail_print; 1179 goto fail_syntax;
1096 } 1180 }
1097 } while (type != EVENT_NONE); 1181 } while (type != EVENT_NONE);
1098 1182
1099 if (!current_op && !current_exp) 1183 if (!current_op && !current_exp)
1100 goto fail_print; 1184 goto fail_syntax;
1101 1185
1102 if (!current_op) 1186 if (!current_op)
1103 current_op = current_exp; 1187 current_op = current_exp;
1104 1188
1105 current_op = collapse_tree(current_op); 1189 ret = collapse_tree(current_op, parg, error_str);
1190 if (ret < 0)
1191 goto fail;
1106 1192
1107 *parg = current_op; 1193 *parg = current_op;
1108 1194
1109 return 0; 1195 return 0;
1110 1196
1111 fail_print: 1197 fail_alloc:
1198 show_error(error_str, "failed to allocate filter arg");
1199 ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
1200 goto fail;
1201 fail_syntax:
1112 show_error(error_str, "Syntax error"); 1202 show_error(error_str, "Syntax error");
1203 ret = PEVENT_ERRNO__SYNTAX_ERROR;
1113 fail: 1204 fail:
1114 free_arg(current_op); 1205 free_arg(current_op);
1115 free_arg(current_exp); 1206 free_arg(current_exp);
1116 free_arg(arg); 1207 free_arg(arg);
1117 free(token); 1208 free(token);
1118 return -1; 1209 return ret;
1119} 1210}
1120 1211
1121static int 1212static enum pevent_errno
1122process_event(struct event_format *event, const char *filter_str, 1213process_event(struct event_format *event, const char *filter_str,
1123 struct filter_arg **parg, char **error_str) 1214 struct filter_arg **parg, char **error_str)
1124{ 1215{
@@ -1127,17 +1218,15 @@ process_event(struct event_format *event, const char *filter_str,
1127 pevent_buffer_init(filter_str, strlen(filter_str)); 1218 pevent_buffer_init(filter_str, strlen(filter_str));
1128 1219
1129 ret = process_filter(event, parg, error_str, 0); 1220 ret = process_filter(event, parg, error_str, 0);
1130 if (ret == 1) {
1131 show_error(error_str,
1132 "Unbalanced number of ')'");
1133 return -1;
1134 }
1135 if (ret < 0) 1221 if (ret < 0)
1136 return ret; 1222 return ret;
1137 1223
1138 /* If parg is NULL, then make it into FALSE */ 1224 /* If parg is NULL, then make it into FALSE */
1139 if (!*parg) { 1225 if (!*parg) {
1140 *parg = allocate_arg(); 1226 *parg = allocate_arg();
1227 if (*parg == NULL)
1228 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
1229
1141 (*parg)->type = FILTER_ARG_BOOLEAN; 1230 (*parg)->type = FILTER_ARG_BOOLEAN;
1142 (*parg)->boolean.value = FILTER_FALSE; 1231 (*parg)->boolean.value = FILTER_FALSE;
1143 } 1232 }
@@ -1145,13 +1234,13 @@ process_event(struct event_format *event, const char *filter_str,
1145 return 0; 1234 return 0;
1146} 1235}
1147 1236
1148static int filter_event(struct event_filter *filter, 1237static enum pevent_errno
1149 struct event_format *event, 1238filter_event(struct event_filter *filter, struct event_format *event,
1150 const char *filter_str, char **error_str) 1239 const char *filter_str, char **error_str)
1151{ 1240{
1152 struct filter_type *filter_type; 1241 struct filter_type *filter_type;
1153 struct filter_arg *arg; 1242 struct filter_arg *arg;
1154 int ret; 1243 enum pevent_errno ret;
1155 1244
1156 if (filter_str) { 1245 if (filter_str) {
1157 ret = process_event(event, filter_str, &arg, error_str); 1246 ret = process_event(event, filter_str, &arg, error_str);
@@ -1161,11 +1250,17 @@ static int filter_event(struct event_filter *filter,
1161 } else { 1250 } else {
1162 /* just add a TRUE arg */ 1251 /* just add a TRUE arg */
1163 arg = allocate_arg(); 1252 arg = allocate_arg();
1253 if (arg == NULL)
1254 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
1255
1164 arg->type = FILTER_ARG_BOOLEAN; 1256 arg->type = FILTER_ARG_BOOLEAN;
1165 arg->boolean.value = FILTER_TRUE; 1257 arg->boolean.value = FILTER_TRUE;
1166 } 1258 }
1167 1259
1168 filter_type = add_filter_type(filter, event->id); 1260 filter_type = add_filter_type(filter, event->id);
1261 if (filter_type == NULL)
1262 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
1263
1169 if (filter_type->filter) 1264 if (filter_type->filter)
1170 free_arg(filter_type->filter); 1265 free_arg(filter_type->filter);
1171 filter_type->filter = arg; 1266 filter_type->filter = arg;
@@ -1177,18 +1272,12 @@ static int filter_event(struct event_filter *filter,
1177 * pevent_filter_add_filter_str - add a new filter 1272 * pevent_filter_add_filter_str - add a new filter
1178 * @filter: the event filter to add to 1273 * @filter: the event filter to add to
1179 * @filter_str: the filter string that contains the filter 1274 * @filter_str: the filter string that contains the filter
1180 * @error_str: string containing reason for failed filter
1181 * 1275 *
1182 * Returns 0 if the filter was successfully added 1276 * Returns 0 if the filter was successfully added or a
1183 * -1 if there was an error. 1277 * negative error code.
1184 *
1185 * On error, if @error_str points to a string pointer,
1186 * it is set to the reason that the filter failed.
1187 * This string must be freed with "free".
1188 */ 1278 */
1189int pevent_filter_add_filter_str(struct event_filter *filter, 1279enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter,
1190 const char *filter_str, 1280 const char *filter_str)
1191 char **error_str)
1192{ 1281{
1193 struct pevent *pevent = filter->pevent; 1282 struct pevent *pevent = filter->pevent;
1194 struct event_list *event; 1283 struct event_list *event;
@@ -1199,23 +1288,20 @@ int pevent_filter_add_filter_str(struct event_filter *filter,
1199 char *event_name = NULL; 1288 char *event_name = NULL;
1200 char *sys_name = NULL; 1289 char *sys_name = NULL;
1201 char *sp; 1290 char *sp;
1202 int rtn = 0; 1291 enum pevent_errno rtn = 0; /* PEVENT_ERRNO__SUCCESS */
1203 int len; 1292 int len;
1204 int ret; 1293 int ret;
1294 char *error_str = NULL;
1205 1295
1206 /* clear buffer to reset show error */ 1296 /* clear buffer to reset show error */
1207 pevent_buffer_init("", 0); 1297 pevent_buffer_init("", 0);
1208 1298
1209 if (error_str)
1210 *error_str = NULL;
1211
1212 filter_start = strchr(filter_str, ':'); 1299 filter_start = strchr(filter_str, ':');
1213 if (filter_start) 1300 if (filter_start)
1214 len = filter_start - filter_str; 1301 len = filter_start - filter_str;
1215 else 1302 else
1216 len = strlen(filter_str); 1303 len = strlen(filter_str);
1217 1304
1218
1219 do { 1305 do {
1220 next_event = strchr(filter_str, ','); 1306 next_event = strchr(filter_str, ',');
1221 if (next_event && 1307 if (next_event &&
@@ -1228,10 +1314,9 @@ int pevent_filter_add_filter_str(struct event_filter *filter,
1228 1314
1229 this_event = malloc(len + 1); 1315 this_event = malloc(len + 1);
1230 if (this_event == NULL) { 1316 if (this_event == NULL) {
1231 show_error(error_str, "Memory allocation failure");
1232 /* This can only happen when events is NULL, but still */ 1317 /* This can only happen when events is NULL, but still */
1233 free_events(events); 1318 free_events(events);
1234 return -1; 1319 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
1235 } 1320 }
1236 memcpy(this_event, filter_str, len); 1321 memcpy(this_event, filter_str, len);
1237 this_event[len] = 0; 1322 this_event[len] = 0;
@@ -1245,27 +1330,18 @@ int pevent_filter_add_filter_str(struct event_filter *filter,
1245 event_name = strtok_r(NULL, "/", &sp); 1330 event_name = strtok_r(NULL, "/", &sp);
1246 1331
1247 if (!sys_name) { 1332 if (!sys_name) {
1248 show_error(error_str, "No filter found");
1249 /* This can only happen when events is NULL, but still */ 1333 /* This can only happen when events is NULL, but still */
1250 free_events(events); 1334 free_events(events);
1251 free(this_event); 1335 free(this_event);
1252 return -1; 1336 return PEVENT_ERRNO__FILTER_NOT_FOUND;
1253 } 1337 }
1254 1338
1255 /* Find this event */ 1339 /* Find this event */
1256 ret = find_event(pevent, &events, strim(sys_name), strim(event_name)); 1340 ret = find_event(pevent, &events, strim(sys_name), strim(event_name));
1257 if (ret < 0) { 1341 if (ret < 0) {
1258 if (event_name)
1259 show_error(error_str,
1260 "No event found under '%s.%s'",
1261 sys_name, event_name);
1262 else
1263 show_error(error_str,
1264 "No event found under '%s'",
1265 sys_name);
1266 free_events(events); 1342 free_events(events);
1267 free(this_event); 1343 free(this_event);
1268 return -1; 1344 return ret;
1269 } 1345 }
1270 free(this_event); 1346 free(this_event);
1271 } while (filter_str); 1347 } while (filter_str);
@@ -1277,7 +1353,7 @@ int pevent_filter_add_filter_str(struct event_filter *filter,
1277 /* filter starts here */ 1353 /* filter starts here */
1278 for (event = events; event; event = event->next) { 1354 for (event = events; event; event = event->next) {
1279 ret = filter_event(filter, event->event, filter_start, 1355 ret = filter_event(filter, event->event, filter_start,
1280 error_str); 1356 &error_str);
1281 /* Failures are returned if a parse error happened */ 1357 /* Failures are returned if a parse error happened */
1282 if (ret < 0) 1358 if (ret < 0)
1283 rtn = ret; 1359 rtn = ret;
@@ -1396,6 +1472,9 @@ static int copy_filter_type(struct event_filter *filter,
1396 if (strcmp(str, "TRUE") == 0 || strcmp(str, "FALSE") == 0) { 1472 if (strcmp(str, "TRUE") == 0 || strcmp(str, "FALSE") == 0) {
1397 /* Add trivial event */ 1473 /* Add trivial event */
1398 arg = allocate_arg(); 1474 arg = allocate_arg();
1475 if (arg == NULL)
1476 return -1;
1477
1399 arg->type = FILTER_ARG_BOOLEAN; 1478 arg->type = FILTER_ARG_BOOLEAN;
1400 if (strcmp(str, "TRUE") == 0) 1479 if (strcmp(str, "TRUE") == 0)
1401 arg->boolean.value = 1; 1480 arg->boolean.value = 1;
@@ -1403,6 +1482,9 @@ static int copy_filter_type(struct event_filter *filter,
1403 arg->boolean.value = 0; 1482 arg->boolean.value = 0;
1404 1483
1405 filter_type = add_filter_type(filter, event->id); 1484 filter_type = add_filter_type(filter, event->id);
1485 if (filter_type == NULL)
1486 return -1;
1487
1406 filter_type->filter = arg; 1488 filter_type->filter = arg;
1407 1489
1408 free(str); 1490 free(str);
@@ -1596,8 +1678,8 @@ int pevent_filter_event_has_trivial(struct event_filter *filter,
1596 } 1678 }
1597} 1679}
1598 1680
1599static int test_filter(struct event_format *event, 1681static int test_filter(struct event_format *event, struct filter_arg *arg,
1600 struct filter_arg *arg, struct pevent_record *record); 1682 struct pevent_record *record, enum pevent_errno *err);
1601 1683
1602static const char * 1684static const char *
1603get_comm(struct event_format *event, struct pevent_record *record) 1685get_comm(struct event_format *event, struct pevent_record *record)
@@ -1643,15 +1725,24 @@ get_value(struct event_format *event,
1643} 1725}
1644 1726
1645static unsigned long long 1727static unsigned long long
1646get_arg_value(struct event_format *event, struct filter_arg *arg, struct pevent_record *record); 1728get_arg_value(struct event_format *event, struct filter_arg *arg,
1729 struct pevent_record *record, enum pevent_errno *err);
1647 1730
1648static unsigned long long 1731static unsigned long long
1649get_exp_value(struct event_format *event, struct filter_arg *arg, struct pevent_record *record) 1732get_exp_value(struct event_format *event, struct filter_arg *arg,
1733 struct pevent_record *record, enum pevent_errno *err)
1650{ 1734{
1651 unsigned long long lval, rval; 1735 unsigned long long lval, rval;
1652 1736
1653 lval = get_arg_value(event, arg->exp.left, record); 1737 lval = get_arg_value(event, arg->exp.left, record, err);
1654 rval = get_arg_value(event, arg->exp.right, record); 1738 rval = get_arg_value(event, arg->exp.right, record, err);
1739
1740 if (*err) {
1741 /*
1742 * There was an error, no need to process anymore.
1743 */
1744 return 0;
1745 }
1655 1746
1656 switch (arg->exp.type) { 1747 switch (arg->exp.type) {
1657 case FILTER_EXP_ADD: 1748 case FILTER_EXP_ADD:
@@ -1686,39 +1777,51 @@ get_exp_value(struct event_format *event, struct filter_arg *arg, struct pevent_
1686 1777
1687 case FILTER_EXP_NOT: 1778 case FILTER_EXP_NOT:
1688 default: 1779 default:
1689 die("error in exp"); 1780 if (!*err)
1781 *err = PEVENT_ERRNO__INVALID_EXP_TYPE;
1690 } 1782 }
1691 return 0; 1783 return 0;
1692} 1784}
1693 1785
1694static unsigned long long 1786static unsigned long long
1695get_arg_value(struct event_format *event, struct filter_arg *arg, struct pevent_record *record) 1787get_arg_value(struct event_format *event, struct filter_arg *arg,
1788 struct pevent_record *record, enum pevent_errno *err)
1696{ 1789{
1697 switch (arg->type) { 1790 switch (arg->type) {
1698 case FILTER_ARG_FIELD: 1791 case FILTER_ARG_FIELD:
1699 return get_value(event, arg->field.field, record); 1792 return get_value(event, arg->field.field, record);
1700 1793
1701 case FILTER_ARG_VALUE: 1794 case FILTER_ARG_VALUE:
1702 if (arg->value.type != FILTER_NUMBER) 1795 if (arg->value.type != FILTER_NUMBER) {
1703 die("must have number field!"); 1796 if (!*err)
1797 *err = PEVENT_ERRNO__NOT_A_NUMBER;
1798 }
1704 return arg->value.val; 1799 return arg->value.val;
1705 1800
1706 case FILTER_ARG_EXP: 1801 case FILTER_ARG_EXP:
1707 return get_exp_value(event, arg, record); 1802 return get_exp_value(event, arg, record, err);
1708 1803
1709 default: 1804 default:
1710 die("oops in filter"); 1805 if (!*err)
1806 *err = PEVENT_ERRNO__INVALID_ARG_TYPE;
1711 } 1807 }
1712 return 0; 1808 return 0;
1713} 1809}
1714 1810
1715static int test_num(struct event_format *event, 1811static int test_num(struct event_format *event, struct filter_arg *arg,
1716 struct filter_arg *arg, struct pevent_record *record) 1812 struct pevent_record *record, enum pevent_errno *err)
1717{ 1813{
1718 unsigned long long lval, rval; 1814 unsigned long long lval, rval;
1719 1815
1720 lval = get_arg_value(event, arg->num.left, record); 1816 lval = get_arg_value(event, arg->num.left, record, err);
1721 rval = get_arg_value(event, arg->num.right, record); 1817 rval = get_arg_value(event, arg->num.right, record, err);
1818
1819 if (*err) {
1820 /*
1821 * There was an error, no need to process anymore.
1822 */
1823 return 0;
1824 }
1722 1825
1723 switch (arg->num.type) { 1826 switch (arg->num.type) {
1724 case FILTER_CMP_EQ: 1827 case FILTER_CMP_EQ:
@@ -1740,7 +1843,8 @@ static int test_num(struct event_format *event,
1740 return lval <= rval; 1843 return lval <= rval;
1741 1844
1742 default: 1845 default:
1743 /* ?? */ 1846 if (!*err)
1847 *err = PEVENT_ERRNO__ILLEGAL_INTEGER_CMP;
1744 return 0; 1848 return 0;
1745 } 1849 }
1746} 1850}
@@ -1787,8 +1891,8 @@ static const char *get_field_str(struct filter_arg *arg, struct pevent_record *r
1787 return val; 1891 return val;
1788} 1892}
1789 1893
1790static int test_str(struct event_format *event, 1894static int test_str(struct event_format *event, struct filter_arg *arg,
1791 struct filter_arg *arg, struct pevent_record *record) 1895 struct pevent_record *record, enum pevent_errno *err)
1792{ 1896{
1793 const char *val; 1897 const char *val;
1794 1898
@@ -1812,48 +1916,57 @@ static int test_str(struct event_format *event,
1812 return regexec(&arg->str.reg, val, 0, NULL, 0); 1916 return regexec(&arg->str.reg, val, 0, NULL, 0);
1813 1917
1814 default: 1918 default:
1815 /* ?? */ 1919 if (!*err)
1920 *err = PEVENT_ERRNO__ILLEGAL_STRING_CMP;
1816 return 0; 1921 return 0;
1817 } 1922 }
1818} 1923}
1819 1924
1820static int test_op(struct event_format *event, 1925static int test_op(struct event_format *event, struct filter_arg *arg,
1821 struct filter_arg *arg, struct pevent_record *record) 1926 struct pevent_record *record, enum pevent_errno *err)
1822{ 1927{
1823 switch (arg->op.type) { 1928 switch (arg->op.type) {
1824 case FILTER_OP_AND: 1929 case FILTER_OP_AND:
1825 return test_filter(event, arg->op.left, record) && 1930 return test_filter(event, arg->op.left, record, err) &&
1826 test_filter(event, arg->op.right, record); 1931 test_filter(event, arg->op.right, record, err);
1827 1932
1828 case FILTER_OP_OR: 1933 case FILTER_OP_OR:
1829 return test_filter(event, arg->op.left, record) || 1934 return test_filter(event, arg->op.left, record, err) ||
1830 test_filter(event, arg->op.right, record); 1935 test_filter(event, arg->op.right, record, err);
1831 1936
1832 case FILTER_OP_NOT: 1937 case FILTER_OP_NOT:
1833 return !test_filter(event, arg->op.right, record); 1938 return !test_filter(event, arg->op.right, record, err);
1834 1939
1835 default: 1940 default:
1836 /* ?? */ 1941 if (!*err)
1942 *err = PEVENT_ERRNO__INVALID_OP_TYPE;
1837 return 0; 1943 return 0;
1838 } 1944 }
1839} 1945}
1840 1946
1841static int test_filter(struct event_format *event, 1947static int test_filter(struct event_format *event, struct filter_arg *arg,
1842 struct filter_arg *arg, struct pevent_record *record) 1948 struct pevent_record *record, enum pevent_errno *err)
1843{ 1949{
1950 if (*err) {
1951 /*
1952 * There was an error, no need to process anymore.
1953 */
1954 return 0;
1955 }
1956
1844 switch (arg->type) { 1957 switch (arg->type) {
1845 case FILTER_ARG_BOOLEAN: 1958 case FILTER_ARG_BOOLEAN:
1846 /* easy case */ 1959 /* easy case */
1847 return arg->boolean.value; 1960 return arg->boolean.value;
1848 1961
1849 case FILTER_ARG_OP: 1962 case FILTER_ARG_OP:
1850 return test_op(event, arg, record); 1963 return test_op(event, arg, record, err);
1851 1964
1852 case FILTER_ARG_NUM: 1965 case FILTER_ARG_NUM:
1853 return test_num(event, arg, record); 1966 return test_num(event, arg, record, err);
1854 1967
1855 case FILTER_ARG_STR: 1968 case FILTER_ARG_STR:
1856 return test_str(event, arg, record); 1969 return test_str(event, arg, record, err);
1857 1970
1858 case FILTER_ARG_EXP: 1971 case FILTER_ARG_EXP:
1859 case FILTER_ARG_VALUE: 1972 case FILTER_ARG_VALUE:
@@ -1862,11 +1975,11 @@ static int test_filter(struct event_format *event,
1862 * Expressions, fields and values evaluate 1975 * Expressions, fields and values evaluate
1863 * to true if they return non zero 1976 * to true if they return non zero
1864 */ 1977 */
1865 return !!get_arg_value(event, arg, record); 1978 return !!get_arg_value(event, arg, record, err);
1866 1979
1867 default: 1980 default:
1868 die("oops!"); 1981 if (!*err)
1869 /* ?? */ 1982 *err = PEVENT_ERRNO__INVALID_ARG_TYPE;
1870 return 0; 1983 return 0;
1871 } 1984 }
1872} 1985}
@@ -1879,8 +1992,7 @@ static int test_filter(struct event_format *event,
1879 * Returns 1 if filter found for @event_id 1992 * Returns 1 if filter found for @event_id
1880 * otherwise 0; 1993 * otherwise 0;
1881 */ 1994 */
1882int pevent_event_filtered(struct event_filter *filter, 1995int pevent_event_filtered(struct event_filter *filter, int event_id)
1883 int event_id)
1884{ 1996{
1885 struct filter_type *filter_type; 1997 struct filter_type *filter_type;
1886 1998
@@ -1897,31 +2009,36 @@ int pevent_event_filtered(struct event_filter *filter,
1897 * @filter: filter struct with filter information 2009 * @filter: filter struct with filter information
1898 * @record: the record to test against the filter 2010 * @record: the record to test against the filter
1899 * 2011 *
1900 * Returns: 2012 * Returns: match result or error code (prefixed with PEVENT_ERRNO__)
1901 * 1 - filter found for event and @record matches 2013 * FILTER_MATCH - filter found for event and @record matches
1902 * 0 - filter found for event and @record does not match 2014 * FILTER_MISS - filter found for event and @record does not match
1903 * -1 - no filter found for @record's event 2015 * FILTER_NOT_FOUND - no filter found for @record's event
1904 * -2 - if no filters exist 2016 * NO_FILTER - if no filters exist
2017 * otherwise - error occurred during test
1905 */ 2018 */
1906int pevent_filter_match(struct event_filter *filter, 2019enum pevent_errno pevent_filter_match(struct event_filter *filter,
1907 struct pevent_record *record) 2020 struct pevent_record *record)
1908{ 2021{
1909 struct pevent *pevent = filter->pevent; 2022 struct pevent *pevent = filter->pevent;
1910 struct filter_type *filter_type; 2023 struct filter_type *filter_type;
1911 int event_id; 2024 int event_id;
2025 int ret;
2026 enum pevent_errno err = 0;
1912 2027
1913 if (!filter->filters) 2028 if (!filter->filters)
1914 return FILTER_NONE; 2029 return PEVENT_ERRNO__NO_FILTER;
1915 2030
1916 event_id = pevent_data_type(pevent, record); 2031 event_id = pevent_data_type(pevent, record);
1917 2032
1918 filter_type = find_filter_type(filter, event_id); 2033 filter_type = find_filter_type(filter, event_id);
1919
1920 if (!filter_type) 2034 if (!filter_type)
1921 return FILTER_NOEXIST; 2035 return PEVENT_ERRNO__FILTER_NOT_FOUND;
2036
2037 ret = test_filter(filter_type->event, filter_type->filter, record, &err);
2038 if (err)
2039 return err;
1922 2040
1923 return test_filter(filter_type->event, filter_type->filter, record) ? 2041 return ret ? PEVENT_ERRNO__FILTER_MATCH : PEVENT_ERRNO__FILTER_MISS;
1924 FILTER_MATCH : FILTER_MISS;
1925} 2042}
1926 2043
1927static char *op_to_str(struct event_filter *filter, struct filter_arg *arg) 2044static char *op_to_str(struct event_filter *filter, struct filter_arg *arg)
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index 025de796067c..3170a7ff5782 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -2,6 +2,8 @@ tools/perf
2tools/scripts 2tools/scripts
3tools/lib/traceevent 3tools/lib/traceevent
4tools/lib/lk 4tools/lib/lk
5tools/lib/symbol/kallsyms.c
6tools/lib/symbol/kallsyms.h
5include/linux/const.h 7include/linux/const.h
6include/linux/perf_event.h 8include/linux/perf_event.h
7include/linux/rbtree.h 9include/linux/rbtree.h
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 9a8cf376f874..fad61079e795 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -202,6 +202,7 @@ $(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c
202 202
203LIB_FILE=$(OUTPUT)libperf.a 203LIB_FILE=$(OUTPUT)libperf.a
204 204
205LIB_H += ../lib/symbol/kallsyms.h
205LIB_H += ../../include/uapi/linux/perf_event.h 206LIB_H += ../../include/uapi/linux/perf_event.h
206LIB_H += ../../include/linux/rbtree.h 207LIB_H += ../../include/linux/rbtree.h
207LIB_H += ../../include/linux/list.h 208LIB_H += ../../include/linux/list.h
@@ -312,6 +313,7 @@ LIB_OBJS += $(OUTPUT)util/evlist.o
312LIB_OBJS += $(OUTPUT)util/evsel.o 313LIB_OBJS += $(OUTPUT)util/evsel.o
313LIB_OBJS += $(OUTPUT)util/exec_cmd.o 314LIB_OBJS += $(OUTPUT)util/exec_cmd.o
314LIB_OBJS += $(OUTPUT)util/help.o 315LIB_OBJS += $(OUTPUT)util/help.o
316LIB_OBJS += $(OUTPUT)util/kallsyms.o
315LIB_OBJS += $(OUTPUT)util/levenshtein.o 317LIB_OBJS += $(OUTPUT)util/levenshtein.o
316LIB_OBJS += $(OUTPUT)util/parse-options.o 318LIB_OBJS += $(OUTPUT)util/parse-options.o
317LIB_OBJS += $(OUTPUT)util/parse-events.o 319LIB_OBJS += $(OUTPUT)util/parse-events.o
@@ -672,6 +674,9 @@ $(OUTPUT)ui/browsers/map.o: ui/browsers/map.c $(OUTPUT)PERF-CFLAGS
672$(OUTPUT)ui/browsers/scripts.o: ui/browsers/scripts.c $(OUTPUT)PERF-CFLAGS 674$(OUTPUT)ui/browsers/scripts.o: ui/browsers/scripts.c $(OUTPUT)PERF-CFLAGS
673 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $< 675 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
674 676
677$(OUTPUT)util/kallsyms.o: ../lib/symbol/kallsyms.c $(OUTPUT)PERF-CFLAGS
678 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $<
679
675$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS 680$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
676 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< 681 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
677 682
diff --git a/tools/perf/perf-completion.sh b/tools/perf/perf-completion.sh
index 49494882d9bb..496e2abb5482 100644
--- a/tools/perf/perf-completion.sh
+++ b/tools/perf/perf-completion.sh
@@ -121,6 +121,10 @@ __perf_main ()
121 elif [[ $prev == "-e" && "${words[1]}" == @(record|stat|top) ]]; then 121 elif [[ $prev == "-e" && "${words[1]}" == @(record|stat|top) ]]; then
122 evts=$($cmd list --raw-dump) 122 evts=$($cmd list --raw-dump)
123 __perfcomp_colon "$evts" "$cur" 123 __perfcomp_colon "$evts" "$cur"
124 # List subcommands for 'perf kvm'
125 elif [[ $prev == "kvm" ]]; then
126 subcmds="top record report diff buildid-list stat"
127 __perfcomp_colon "$subcmds" "$cur"
124 # List long option names 128 # List long option names
125 elif [[ $cur == --* ]]; then 129 elif [[ $cur == --* ]]; then
126 subcmd=${words[1]} 130 subcmd=${words[1]}
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index c77814bf01e1..694876877ae2 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -7,6 +7,7 @@
7#include "strlist.h" 7#include "strlist.h"
8#include "thread.h" 8#include "thread.h"
9#include "thread_map.h" 9#include "thread_map.h"
10#include "symbol/kallsyms.h"
10 11
11static const char *perf_event__names[] = { 12static const char *perf_event__names[] = {
12 [0] = "TOTAL", 13 [0] = "TOTAL",
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index af250556b33f..0b31cee34874 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -1191,8 +1191,7 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused,
1191 "Error:\t%s.\n" 1191 "Error:\t%s.\n"
1192 "Hint:\tCheck /proc/sys/kernel/perf_event_paranoid setting.", emsg); 1192 "Hint:\tCheck /proc/sys/kernel/perf_event_paranoid setting.", emsg);
1193 1193
1194 if (filename__read_int("/proc/sys/kernel/perf_event_paranoid", &value)) 1194 value = perf_event_paranoid();
1195 break;
1196 1195
1197 printed += scnprintf(buf + printed, size - printed, "\nHint:\t"); 1196 printed += scnprintf(buf + printed, size - printed, "\nHint:\t");
1198 1197
@@ -1213,3 +1212,20 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused,
1213 1212
1214 return 0; 1213 return 0;
1215} 1214}
1215
1216void perf_evlist__to_front(struct perf_evlist *evlist,
1217 struct perf_evsel *move_evsel)
1218{
1219 struct perf_evsel *evsel, *n;
1220 LIST_HEAD(move);
1221
1222 if (move_evsel == perf_evlist__first(evlist))
1223 return;
1224
1225 list_for_each_entry_safe(evsel, n, &evlist->entries, node) {
1226 if (evsel->leader == move_evsel->leader)
1227 list_move_tail(&evsel->node, &move);
1228 }
1229
1230 list_splice(&move, &evlist->entries);
1231}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 649d6ea98a84..9f64ede3ecbd 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -193,4 +193,9 @@ static inline void perf_mmap__write_tail(struct perf_mmap *md,
193 pc->data_tail = tail; 193 pc->data_tail = tail;
194} 194}
195 195
196bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str);
197void perf_evlist__to_front(struct perf_evlist *evlist,
198 struct perf_evsel *move_evsel);
199
200
196#endif /* __PERF_EVLIST_H */ 201#endif /* __PERF_EVLIST_H */
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 0bb830f6b49c..61c54213704b 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2327,7 +2327,8 @@ int perf_session__write_header(struct perf_session *session,
2327 } 2327 }
2328 } 2328 }
2329 2329
2330 header->data_offset = lseek(fd, 0, SEEK_CUR); 2330 if (!header->data_offset)
2331 header->data_offset = lseek(fd, 0, SEEK_CUR);
2331 header->feat_offset = header->data_offset + header->data_size; 2332 header->feat_offset = header->data_offset + header->data_size;
2332 2333
2333 if (at_exit) { 2334 if (at_exit) {
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 751454bcde69..c78cc84f433e 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -9,6 +9,7 @@
9#include "strlist.h" 9#include "strlist.h"
10#include "thread.h" 10#include "thread.h"
11#include <stdbool.h> 11#include <stdbool.h>
12#include <symbol/kallsyms.h>
12#include "unwind.h" 13#include "unwind.h"
13 14
14int machine__init(struct machine *machine, const char *root_dir, pid_t pid) 15int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c
index c8845b107f60..e5104538c354 100644
--- a/tools/perf/util/record.c
+++ b/tools/perf/util/record.c
@@ -177,3 +177,40 @@ int perf_record_opts__config(struct perf_record_opts *opts)
177{ 177{
178 return perf_record_opts__config_freq(opts); 178 return perf_record_opts__config_freq(opts);
179} 179}
180
181bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str)
182{
183 struct perf_evlist *temp_evlist;
184 struct perf_evsel *evsel;
185 int err, fd, cpu;
186 bool ret = false;
187
188 temp_evlist = perf_evlist__new();
189 if (!temp_evlist)
190 return false;
191
192 err = parse_events(temp_evlist, str);
193 if (err)
194 goto out_delete;
195
196 evsel = perf_evlist__last(temp_evlist);
197
198 if (!evlist || cpu_map__empty(evlist->cpus)) {
199 struct cpu_map *cpus = cpu_map__new(NULL);
200
201 cpu = cpus ? cpus->map[0] : 0;
202 cpu_map__delete(cpus);
203 } else {
204 cpu = evlist->cpus->map[0];
205 }
206
207 fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, 0);
208 if (fd >= 0) {
209 close(fd);
210 ret = true;
211 }
212
213out_delete:
214 perf_evlist__delete(temp_evlist);
215 return ret;
216}
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index e748f29c53cf..989b2e377626 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -247,27 +247,6 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
247 } 247 }
248} 248}
249 249
250void mem_bswap_32(void *src, int byte_size)
251{
252 u32 *m = src;
253 while (byte_size > 0) {
254 *m = bswap_32(*m);
255 byte_size -= sizeof(u32);
256 ++m;
257 }
258}
259
260void mem_bswap_64(void *src, int byte_size)
261{
262 u64 *m = src;
263
264 while (byte_size > 0) {
265 *m = bswap_64(*m);
266 byte_size -= sizeof(u64);
267 ++m;
268 }
269}
270
271static void swap_sample_id_all(union perf_event *event, void *data) 250static void swap_sample_id_all(union perf_event *event, void *data)
272{ 251{
273 void *end = (void *) event + event->header.size; 252 void *end = (void *) event + event->header.size;
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 2a3955ea4fd8..9c25d49900af 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -74,8 +74,6 @@ int perf_session__resolve_callchain(struct perf_session *session,
74 74
75bool perf_session__has_traces(struct perf_session *session, const char *msg); 75bool perf_session__has_traces(struct perf_session *session, const char *msg);
76 76
77void mem_bswap_64(void *src, int byte_size);
78void mem_bswap_32(void *src, int byte_size);
79void perf_event__attr_swap(struct perf_event_attr *attr); 77void perf_event__attr_swap(struct perf_event_attr *attr);
80 78
81int perf_session__create_kernel_maps(struct perf_session *session); 79int perf_session__create_kernel_maps(struct perf_session *session);
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index eed0b96302af..bf0ce29567b6 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -6,6 +6,7 @@
6#include <inttypes.h> 6#include <inttypes.h>
7 7
8#include "symbol.h" 8#include "symbol.h"
9#include <symbol/kallsyms.h>
9#include "debug.h" 10#include "debug.h"
10 11
11#ifndef HAVE_ELF_GETPHDRNUM_SUPPORT 12#ifndef HAVE_ELF_GETPHDRNUM_SUPPORT
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index e377c2e96191..61eb1cddf01a 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -18,12 +18,9 @@
18 18
19#include <elf.h> 19#include <elf.h>
20#include <limits.h> 20#include <limits.h>
21#include <symbol/kallsyms.h>
21#include <sys/utsname.h> 22#include <sys/utsname.h>
22 23
23#ifndef KSYM_NAME_LEN
24#define KSYM_NAME_LEN 256
25#endif
26
27static int dso__load_kernel_sym(struct dso *dso, struct map *map, 24static int dso__load_kernel_sym(struct dso *dso, struct map *map,
28 symbol_filter_t filter); 25 symbol_filter_t filter);
29static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, 26static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
@@ -446,62 +443,6 @@ size_t dso__fprintf_symbols_by_name(struct dso *dso,
446 return ret; 443 return ret;
447} 444}
448 445
449int kallsyms__parse(const char *filename, void *arg,
450 int (*process_symbol)(void *arg, const char *name,
451 char type, u64 start))
452{
453 char *line = NULL;
454 size_t n;
455 int err = -1;
456 FILE *file = fopen(filename, "r");
457
458 if (file == NULL)
459 goto out_failure;
460
461 err = 0;
462
463 while (!feof(file)) {
464 u64 start;
465 int line_len, len;
466 char symbol_type;
467 char *symbol_name;
468
469 line_len = getline(&line, &n, file);
470 if (line_len < 0 || !line)
471 break;
472
473 line[--line_len] = '\0'; /* \n */
474
475 len = hex2u64(line, &start);
476
477 len++;
478 if (len + 2 >= line_len)
479 continue;
480
481 symbol_type = line[len];
482 len += 2;
483 symbol_name = line + len;
484 len = line_len - len;
485
486 if (len >= KSYM_NAME_LEN) {
487 err = -1;
488 break;
489 }
490
491 err = process_symbol(arg, symbol_name,
492 symbol_type, start);
493 if (err)
494 break;
495 }
496
497 free(line);
498 fclose(file);
499 return err;
500
501out_failure:
502 return -1;
503}
504
505int modules__parse(const char *filename, void *arg, 446int modules__parse(const char *filename, void *arg,
506 int (*process_module)(void *arg, const char *name, 447 int (*process_module)(void *arg, const char *name,
507 u64 start)) 448 u64 start))
@@ -565,14 +506,6 @@ struct process_kallsyms_args {
565 struct dso *dso; 506 struct dso *dso;
566}; 507};
567 508
568static u8 kallsyms2elf_type(char type)
569{
570 if (type == 'W')
571 return STB_WEAK;
572
573 return isupper(type) ? STB_GLOBAL : STB_LOCAL;
574}
575
576bool symbol__is_idle(struct symbol *sym) 509bool symbol__is_idle(struct symbol *sym)
577{ 510{
578 const char * const idle_symbols[] = { 511 const char * const idle_symbols[] = {
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 6de9c2b8a601..8a9d910c5345 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -221,9 +221,6 @@ struct symbol *dso__first_symbol(struct dso *dso, enum map_type type);
221 221
222int filename__read_build_id(const char *filename, void *bf, size_t size); 222int filename__read_build_id(const char *filename, void *bf, size_t size);
223int sysfs__read_build_id(const char *filename, void *bf, size_t size); 223int sysfs__read_build_id(const char *filename, void *bf, size_t size);
224int kallsyms__parse(const char *filename, void *arg,
225 int (*process_symbol)(void *arg, const char *name,
226 char type, u64 start));
227int modules__parse(const char *filename, void *arg, 224int modules__parse(const char *filename, void *arg,
228 int (*process_module)(void *arg, const char *name, 225 int (*process_module)(void *arg, const char *name,
229 u64 start)); 226 u64 start));
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 49eaf1d7d89d..e3948612543e 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -126,7 +126,7 @@ int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp)
126 if (!comm) 126 if (!comm)
127 return -ENOMEM; 127 return -ENOMEM;
128 err = thread__set_comm(thread, comm, timestamp); 128 err = thread__set_comm(thread, comm, timestamp);
129 if (!err) 129 if (err)
130 return err; 130 return err;
131 thread->comm_set = true; 131 thread->comm_set = true;
132 } 132 }
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 4a57609c0b43..42ad667bb317 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -1,5 +1,6 @@
1#include "../perf.h" 1#include "../perf.h"
2#include "util.h" 2#include "util.h"
3#include "fs.h"
3#include <sys/mman.h> 4#include <sys/mman.h>
4#ifdef HAVE_BACKTRACE_SUPPORT 5#ifdef HAVE_BACKTRACE_SUPPORT
5#include <execinfo.h> 6#include <execinfo.h>
@@ -8,6 +9,8 @@
8#include <stdlib.h> 9#include <stdlib.h>
9#include <string.h> 10#include <string.h>
10#include <errno.h> 11#include <errno.h>
12#include <limits.h>
13#include <byteswap.h>
11#include <linux/kernel.h> 14#include <linux/kernel.h>
12 15
13/* 16/*
@@ -496,3 +499,41 @@ const char *get_filename_for_perf_kvm(void)
496 499
497 return filename; 500 return filename;
498} 501}
502
503int perf_event_paranoid(void)
504{
505 char path[PATH_MAX];
506 const char *procfs = procfs__mountpoint();
507 int value;
508
509 if (!procfs)
510 return INT_MAX;
511
512 scnprintf(path, PATH_MAX, "%s/sys/kernel/perf_event_paranoid", procfs);
513
514 if (filename__read_int(path, &value))
515 return INT_MAX;
516
517 return value;
518}
519
520void mem_bswap_32(void *src, int byte_size)
521{
522 u32 *m = src;
523 while (byte_size > 0) {
524 *m = bswap_32(*m);
525 byte_size -= sizeof(u32);
526 ++m;
527 }
528}
529
530void mem_bswap_64(void *src, int byte_size)
531{
532 u64 *m = src;
533
534 while (byte_size > 0) {
535 *m = bswap_64(*m);
536 byte_size -= sizeof(u64);
537 ++m;
538 }
539}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 0171213d1d4d..a1eea3e809a3 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -321,6 +321,10 @@ void free_srcline(char *srcline);
321 321
322int filename__read_int(const char *filename, int *value); 322int filename__read_int(const char *filename, int *value);
323int filename__read_str(const char *filename, char **buf, size_t *sizep); 323int filename__read_str(const char *filename, char **buf, size_t *sizep);
324int perf_event_paranoid(void);
325
326void mem_bswap_64(void *src, int byte_size);
327void mem_bswap_32(void *src, int byte_size);
324 328
325const char *get_filename_for_perf_kvm(void); 329const char *get_filename_for_perf_kvm(void);
326#endif /* GIT_COMPAT_UTIL_H */ 330#endif /* GIT_COMPAT_UTIL_H */