aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2012-05-21 03:17:31 -0400
committerIngo Molnar <mingo@kernel.org>2012-05-21 03:17:50 -0400
commitbb27f55eb9405257a59c82550dbb0d684cc3a665 (patch)
treebdab5866709e6ac7eeef7493d7d73bbd3d6231b6 /tools/perf
parentb732d439cb43336cd6d7e804ecb2c81193ef63b0 (diff)
parent5e1c81d98a5621007824b49dde556fead5ff9c6c (diff)
Merge branch 'perf/core' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Fixes for perf/core: - Rename some perf_target methods to avoid double negation, from Namhyung Kim. - Revert change to use per task events with inheritance, from Namhyung Kim. - Events should start disabled till children starts running, from David Ahern. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Makefile8
-rw-r--r--tools/perf/builtin-record.c3
-rw-r--r--tools/perf/builtin-report.c17
-rw-r--r--tools/perf/builtin-stat.c47
-rw-r--r--tools/perf/builtin-test.c31
-rw-r--r--tools/perf/builtin-top.c5
-rw-r--r--tools/perf/util/evlist.c8
-rw-r--r--tools/perf/util/evsel.c4
-rw-r--r--tools/perf/util/header.c2
-rw-r--r--tools/perf/util/hist.c2
-rw-r--r--tools/perf/util/parse-events.c45
-rw-r--r--tools/perf/util/parse-events.h21
-rw-r--r--tools/perf/util/parse-events.l2
-rw-r--r--tools/perf/util/parse-events.y16
-rw-r--r--tools/perf/util/pmu.c70
-rw-r--r--tools/perf/util/symbol.c13
-rw-r--r--tools/perf/util/target.h11
17 files changed, 208 insertions, 97 deletions
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 4734f41f801d..398094c3d3c9 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -201,8 +201,8 @@ endif
201 201
202export PERL_PATH 202export PERL_PATH
203 203
204FLEX = $(CROSS_COMPILE)flex 204FLEX = flex
205BISON= $(CROSS_COMPILE)bison 205BISON= bison
206 206
207$(OUTPUT)util/parse-events-flex.c: util/parse-events.l 207$(OUTPUT)util/parse-events-flex.c: util/parse-events.l
208 $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/parse-events-flex.h -t util/parse-events.l > $(OUTPUT)util/parse-events-flex.c 208 $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/parse-events-flex.h -t util/parse-events.l > $(OUTPUT)util/parse-events-flex.c
@@ -737,10 +737,10 @@ $(OUTPUT)perf.o perf.spec \
737# over the general rule for .o 737# over the general rule for .o
738 738
739$(OUTPUT)util/%-flex.o: $(OUTPUT)util/%-flex.c $(OUTPUT)PERF-CFLAGS 739$(OUTPUT)util/%-flex.o: $(OUTPUT)util/%-flex.c $(OUTPUT)PERF-CFLAGS
740 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -Iutil/ -Wno-redundant-decls -Wno-switch-default -Wno-unused-function $< 740 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -Iutil/ -w $<
741 741
742$(OUTPUT)util/%-bison.o: $(OUTPUT)util/%-bison.c $(OUTPUT)PERF-CFLAGS 742$(OUTPUT)util/%-bison.o: $(OUTPUT)util/%-bison.c $(OUTPUT)PERF-CFLAGS
743 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -Iutil/ -Wno-redundant-decls -Wno-switch-default -Wno-unused-function $< 743 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -Iutil/ -w $<
744 744
745$(OUTPUT)%.o: %.c $(OUTPUT)PERF-CFLAGS 745$(OUTPUT)%.o: %.c $(OUTPUT)PERF-CFLAGS
746 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $< 746 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $<
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index d19058a7b84c..8a3dfac161e2 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -754,6 +754,9 @@ static struct perf_record record = {
754 .user_freq = UINT_MAX, 754 .user_freq = UINT_MAX,
755 .user_interval = ULLONG_MAX, 755 .user_interval = ULLONG_MAX,
756 .freq = 1000, 756 .freq = 1000,
757 .target = {
758 .uses_mmap = true,
759 },
757 }, 760 },
758 .write_mode = WRITE_FORCE, 761 .write_mode = WRITE_FORCE,
759 .file_new = true, 762 .file_new = true,
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 74776558ddfb..d58e41445d0d 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -377,16 +377,23 @@ static int __cmd_report(struct perf_report *rep)
377 (kernel_map->dso->hit && 377 (kernel_map->dso->hit &&
378 (kernel_kmap->ref_reloc_sym == NULL || 378 (kernel_kmap->ref_reloc_sym == NULL ||
379 kernel_kmap->ref_reloc_sym->addr == 0))) { 379 kernel_kmap->ref_reloc_sym->addr == 0))) {
380 const struct dso *kdso = kernel_map->dso; 380 const char *desc =
381 "As no suitable kallsyms nor vmlinux was found, kernel samples\n"
382 "can't be resolved.";
383
384 if (kernel_map) {
385 const struct dso *kdso = kernel_map->dso;
386 if (!RB_EMPTY_ROOT(&kdso->symbols[MAP__FUNCTION])) {
387 desc = "If some relocation was applied (e.g. "
388 "kexec) symbols may be misresolved.";
389 }
390 }
381 391
382 ui__warning( 392 ui__warning(
383"Kernel address maps (/proc/{kallsyms,modules}) were restricted.\n\n" 393"Kernel address maps (/proc/{kallsyms,modules}) were restricted.\n\n"
384"Check /proc/sys/kernel/kptr_restrict before running 'perf record'.\n\n%s\n\n" 394"Check /proc/sys/kernel/kptr_restrict before running 'perf record'.\n\n%s\n\n"
385"Samples in kernel modules can't be resolved as well.\n\n", 395"Samples in kernel modules can't be resolved as well.\n\n",
386 RB_EMPTY_ROOT(&kdso->symbols[MAP__FUNCTION]) ? 396 desc);
387"As no suitable kallsyms nor vmlinux was found, kernel samples\n"
388"can't be resolved." :
389"If some relocation was applied (e.g. kexec) symbols may be misresolved.");
390 } 397 }
391 398
392 if (dump_trace) { 399 if (dump_trace) {
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index d0605689bad9..62ae30d34fa6 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -282,6 +282,8 @@ static int create_perf_stat_counter(struct perf_evsel *evsel,
282{ 282{
283 struct perf_event_attr *attr = &evsel->attr; 283 struct perf_event_attr *attr = &evsel->attr;
284 struct xyarray *group_fd = NULL; 284 struct xyarray *group_fd = NULL;
285 bool exclude_guest_missing = false;
286 int ret;
285 287
286 if (group && evsel != first) 288 if (group && evsel != first)
287 group_fd = first->fd; 289 group_fd = first->fd;
@@ -292,16 +294,39 @@ static int create_perf_stat_counter(struct perf_evsel *evsel,
292 294
293 attr->inherit = !no_inherit; 295 attr->inherit = !no_inherit;
294 296
295 if (!perf_target__no_cpu(&target)) 297retry:
296 return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, 298 if (exclude_guest_missing)
297 group, group_fd); 299 evsel->attr.exclude_guest = evsel->attr.exclude_host = 0;
298 if (perf_target__no_task(&target) && (!group || evsel == first)) { 300
301 if (perf_target__has_cpu(&target)) {
302 ret = perf_evsel__open_per_cpu(evsel, evsel_list->cpus,
303 group, group_fd);
304 if (ret)
305 goto check_ret;
306 return 0;
307 }
308
309 if (!perf_target__has_task(&target) && (!group || evsel == first)) {
299 attr->disabled = 1; 310 attr->disabled = 1;
300 attr->enable_on_exec = 1; 311 attr->enable_on_exec = 1;
301 } 312 }
302 313
303 return perf_evsel__open_per_thread(evsel, evsel_list->threads, 314 ret = perf_evsel__open_per_thread(evsel, evsel_list->threads,
304 group, group_fd); 315 group, group_fd);
316 if (!ret)
317 return 0;
318 /* fall through */
319check_ret:
320 if (ret && errno == EINVAL) {
321 if (!exclude_guest_missing &&
322 (evsel->attr.exclude_guest || evsel->attr.exclude_host)) {
323 pr_debug("Old kernel, cannot exclude "
324 "guest or host samples.\n");
325 exclude_guest_missing = true;
326 goto retry;
327 }
328 }
329 return ret;
305} 330}
306 331
307/* 332/*
@@ -972,7 +997,7 @@ static void print_stat(int argc, const char **argv)
972 if (!csv_output) { 997 if (!csv_output) {
973 fprintf(output, "\n"); 998 fprintf(output, "\n");
974 fprintf(output, " Performance counter stats for "); 999 fprintf(output, " Performance counter stats for ");
975 if (perf_target__no_task(&target)) { 1000 if (!perf_target__has_task(&target)) {
976 fprintf(output, "\'%s", argv[0]); 1001 fprintf(output, "\'%s", argv[0]);
977 for (i = 1; i < argc; i++) 1002 for (i = 1; i < argc; i++)
978 fprintf(output, " %s", argv[i]); 1003 fprintf(output, " %s", argv[i]);
@@ -1194,13 +1219,13 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
1194 } else if (big_num_opt == 0) /* User passed --no-big-num */ 1219 } else if (big_num_opt == 0) /* User passed --no-big-num */
1195 big_num = false; 1220 big_num = false;
1196 1221
1197 if (!argc && perf_target__no_task(&target)) 1222 if (!argc && !perf_target__has_task(&target))
1198 usage_with_options(stat_usage, options); 1223 usage_with_options(stat_usage, options);
1199 if (run_count <= 0) 1224 if (run_count <= 0)
1200 usage_with_options(stat_usage, options); 1225 usage_with_options(stat_usage, options);
1201 1226
1202 /* no_aggr, cgroup are for system-wide only */ 1227 /* no_aggr, cgroup are for system-wide only */
1203 if ((no_aggr || nr_cgroups) && perf_target__no_cpu(&target)) { 1228 if ((no_aggr || nr_cgroups) && !perf_target__has_cpu(&target)) {
1204 fprintf(stderr, "both cgroup and no-aggregation " 1229 fprintf(stderr, "both cgroup and no-aggregation "
1205 "modes only available in system-wide mode\n"); 1230 "modes only available in system-wide mode\n");
1206 1231
@@ -1213,9 +1238,9 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
1213 perf_target__validate(&target); 1238 perf_target__validate(&target);
1214 1239
1215 if (perf_evlist__create_maps(evsel_list, &target) < 0) { 1240 if (perf_evlist__create_maps(evsel_list, &target) < 0) {
1216 if (!perf_target__no_task(&target)) 1241 if (perf_target__has_task(&target))
1217 pr_err("Problems finding threads of monitor\n"); 1242 pr_err("Problems finding threads of monitor\n");
1218 if (!perf_target__no_cpu(&target)) 1243 if (perf_target__has_cpu(&target))
1219 perror("failed to parse CPUs map"); 1244 perror("failed to parse CPUs map");
1220 1245
1221 usage_with_options(stat_usage, options); 1246 usage_with_options(stat_usage, options);
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 9d9abbbe23be..6c47376e29d8 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -851,6 +851,28 @@ static int test__checkevent_symbolic_name_modifier(struct perf_evlist *evlist)
851 return test__checkevent_symbolic_name(evlist); 851 return test__checkevent_symbolic_name(evlist);
852} 852}
853 853
854static int test__checkevent_exclude_host_modifier(struct perf_evlist *evlist)
855{
856 struct perf_evsel *evsel = list_entry(evlist->entries.next,
857 struct perf_evsel, node);
858
859 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
860 TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
861
862 return test__checkevent_symbolic_name(evlist);
863}
864
865static int test__checkevent_exclude_guest_modifier(struct perf_evlist *evlist)
866{
867 struct perf_evsel *evsel = list_entry(evlist->entries.next,
868 struct perf_evsel, node);
869
870 TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
871 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
872
873 return test__checkevent_symbolic_name(evlist);
874}
875
854static int test__checkevent_symbolic_alias_modifier(struct perf_evlist *evlist) 876static int test__checkevent_symbolic_alias_modifier(struct perf_evlist *evlist)
855{ 877{
856 struct perf_evsel *evsel = list_entry(evlist->entries.next, 878 struct perf_evsel *evsel = list_entry(evlist->entries.next,
@@ -1091,6 +1113,14 @@ static struct test__event_st {
1091 .name = "r1,syscalls:sys_enter_open:k,1:1:hp", 1113 .name = "r1,syscalls:sys_enter_open:k,1:1:hp",
1092 .check = test__checkevent_list, 1114 .check = test__checkevent_list,
1093 }, 1115 },
1116 {
1117 .name = "instructions:G",
1118 .check = test__checkevent_exclude_host_modifier,
1119 },
1120 {
1121 .name = "instructions:H",
1122 .check = test__checkevent_exclude_guest_modifier,
1123 },
1094}; 1124};
1095 1125
1096#define TEST__EVENTS_CNT (sizeof(test__events) / sizeof(struct test__event_st)) 1126#define TEST__EVENTS_CNT (sizeof(test__events) / sizeof(struct test__event_st))
@@ -1167,6 +1197,7 @@ static int test__PERF_RECORD(void)
1167 struct perf_record_opts opts = { 1197 struct perf_record_opts opts = {
1168 .target = { 1198 .target = {
1169 .uid = UINT_MAX, 1199 .uid = UINT_MAX,
1200 .uses_mmap = true,
1170 }, 1201 },
1171 .no_delay = true, 1202 .no_delay = true,
1172 .freq = 10, 1203 .freq = 10,
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 4eb6171e143b..3e981a710c4d 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -1020,7 +1020,7 @@ static int __cmd_top(struct perf_top *top)
1020 if (ret) 1020 if (ret)
1021 goto out_delete; 1021 goto out_delete;
1022 1022
1023 if (!perf_target__no_task(&top->target)) 1023 if (perf_target__has_task(&top->target))
1024 perf_event__synthesize_thread_map(&top->tool, top->evlist->threads, 1024 perf_event__synthesize_thread_map(&top->tool, top->evlist->threads,
1025 perf_event__process, 1025 perf_event__process,
1026 &top->session->host_machine); 1026 &top->session->host_machine);
@@ -1162,6 +1162,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1162 .freq = 1000, /* 1 KHz */ 1162 .freq = 1000, /* 1 KHz */
1163 .mmap_pages = 128, 1163 .mmap_pages = 128,
1164 .sym_pcnt_filter = 5, 1164 .sym_pcnt_filter = 5,
1165 .target = {
1166 .uses_mmap = true,
1167 },
1165 }; 1168 };
1166 char callchain_default_opt[] = "fractal,0.5,callee"; 1169 char callchain_default_opt[] = "fractal,0.5,callee";
1167 const struct option options[] = { 1170 const struct option options[] = {
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 1201daf71719..4ac5f5ae4ce9 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -609,10 +609,12 @@ int perf_evlist__create_maps(struct perf_evlist *evlist,
609 if (evlist->threads == NULL) 609 if (evlist->threads == NULL)
610 return -1; 610 return -1;
611 611
612 if (!perf_target__no_cpu(target)) 612 if (perf_target__has_task(target))
613 evlist->cpus = cpu_map__new(target->cpu_list); 613 evlist->cpus = cpu_map__dummy_new();
614 else 614 else if (!perf_target__has_cpu(target) && !target->uses_mmap)
615 evlist->cpus = cpu_map__dummy_new(); 615 evlist->cpus = cpu_map__dummy_new();
616 else
617 evlist->cpus = cpu_map__new(target->cpu_list);
616 618
617 if (evlist->cpus == NULL) 619 if (evlist->cpus == NULL)
618 goto out_delete_threads; 620 goto out_delete_threads;
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 21eaab240396..f4f427ce4d64 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -70,6 +70,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts,
70 struct perf_event_attr *attr = &evsel->attr; 70 struct perf_event_attr *attr = &evsel->attr;
71 int track = !evsel->idx; /* only the first counter needs these */ 71 int track = !evsel->idx; /* only the first counter needs these */
72 72
73 attr->disabled = 1;
73 attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1; 74 attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1;
74 attr->inherit = !opts->no_inherit; 75 attr->inherit = !opts->no_inherit;
75 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 76 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
@@ -115,7 +116,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts,
115 116
116 if (!opts->sample_id_all_missing && 117 if (!opts->sample_id_all_missing &&
117 (opts->sample_time || !opts->no_inherit || 118 (opts->sample_time || !opts->no_inherit ||
118 !perf_target__no_cpu(&opts->target))) 119 perf_target__has_cpu(&opts->target)))
119 attr->sample_type |= PERF_SAMPLE_TIME; 120 attr->sample_type |= PERF_SAMPLE_TIME;
120 121
121 if (opts->raw_samples) { 122 if (opts->raw_samples) {
@@ -138,7 +139,6 @@ void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts,
138 139
139 if (perf_target__none(&opts->target) && 140 if (perf_target__none(&opts->target) &&
140 (!opts->group || evsel == first)) { 141 (!opts->group || evsel == first)) {
141 attr->disabled = 1;
142 attr->enable_on_exec = 1; 142 attr->enable_on_exec = 1;
143 } 143 }
144} 144}
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 6e618ba21382..538598012139 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -291,7 +291,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
291 if (mkdir_p(filename, 0755)) 291 if (mkdir_p(filename, 0755))
292 goto out_free; 292 goto out_free;
293 293
294 snprintf(filename + len, sizeof(filename) - len, "/%s", sbuild_id); 294 snprintf(filename + len, size - len, "/%s", sbuild_id);
295 295
296 if (access(filename, F_OK)) { 296 if (access(filename, F_OK)) {
297 if (is_kallsyms) { 297 if (is_kallsyms) {
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 9f6d630d5316..1293b5ebea4d 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -599,7 +599,7 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain,
599 if (chain->ms.sym) 599 if (chain->ms.sym)
600 ret += fprintf(fp, "%s\n", chain->ms.sym->name); 600 ret += fprintf(fp, "%s\n", chain->ms.sym->name);
601 else 601 else
602 ret += fprintf(fp, "%p\n", (void *)(long)chain->ip); 602 ret += fprintf(fp, "0x%0" PRIx64 "\n", chain->ip);
603 603
604 return ret; 604 return ret;
605} 605}
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 5b3a0ef4e232..c7fc18a33d54 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -593,17 +593,27 @@ int parse_events_add_breakpoint(struct list_head *list, int *idx,
593static int config_term(struct perf_event_attr *attr, 593static int config_term(struct perf_event_attr *attr,
594 struct parse_events__term *term) 594 struct parse_events__term *term)
595{ 595{
596 switch (term->type) { 596#define CHECK_TYPE_VAL(type) \
597do { \
598 if (PARSE_EVENTS__TERM_TYPE_ ## type != term->type_val) \
599 return -EINVAL; \
600} while (0)
601
602 switch (term->type_term) {
597 case PARSE_EVENTS__TERM_TYPE_CONFIG: 603 case PARSE_EVENTS__TERM_TYPE_CONFIG:
604 CHECK_TYPE_VAL(NUM);
598 attr->config = term->val.num; 605 attr->config = term->val.num;
599 break; 606 break;
600 case PARSE_EVENTS__TERM_TYPE_CONFIG1: 607 case PARSE_EVENTS__TERM_TYPE_CONFIG1:
608 CHECK_TYPE_VAL(NUM);
601 attr->config1 = term->val.num; 609 attr->config1 = term->val.num;
602 break; 610 break;
603 case PARSE_EVENTS__TERM_TYPE_CONFIG2: 611 case PARSE_EVENTS__TERM_TYPE_CONFIG2:
612 CHECK_TYPE_VAL(NUM);
604 attr->config2 = term->val.num; 613 attr->config2 = term->val.num;
605 break; 614 break;
606 case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: 615 case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD:
616 CHECK_TYPE_VAL(NUM);
607 attr->sample_period = term->val.num; 617 attr->sample_period = term->val.num;
608 break; 618 break;
609 case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE: 619 case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE:
@@ -615,7 +625,9 @@ static int config_term(struct perf_event_attr *attr,
615 default: 625 default:
616 return -EINVAL; 626 return -EINVAL;
617 } 627 }
628
618 return 0; 629 return 0;
630#undef CHECK_TYPE_VAL
619} 631}
620 632
621static int config_attr(struct perf_event_attr *attr, 633static int config_attr(struct perf_event_attr *attr,
@@ -1015,11 +1027,12 @@ void print_events(const char *event_glob)
1015 1027
1016int parse_events__is_hardcoded_term(struct parse_events__term *term) 1028int parse_events__is_hardcoded_term(struct parse_events__term *term)
1017{ 1029{
1018 return term->type <= PARSE_EVENTS__TERM_TYPE_HARDCODED_MAX; 1030 return term->type_term != PARSE_EVENTS__TERM_TYPE_USER;
1019} 1031}
1020 1032
1021int parse_events__new_term(struct parse_events__term **_term, int type, 1033static int new_term(struct parse_events__term **_term, int type_val,
1022 char *config, char *str, long num) 1034 int type_term, char *config,
1035 char *str, long num)
1023{ 1036{
1024 struct parse_events__term *term; 1037 struct parse_events__term *term;
1025 1038
@@ -1028,15 +1041,11 @@ int parse_events__new_term(struct parse_events__term **_term, int type,
1028 return -ENOMEM; 1041 return -ENOMEM;
1029 1042
1030 INIT_LIST_HEAD(&term->list); 1043 INIT_LIST_HEAD(&term->list);
1031 term->type = type; 1044 term->type_val = type_val;
1045 term->type_term = type_term;
1032 term->config = config; 1046 term->config = config;
1033 1047
1034 switch (type) { 1048 switch (type_val) {
1035 case PARSE_EVENTS__TERM_TYPE_CONFIG:
1036 case PARSE_EVENTS__TERM_TYPE_CONFIG1:
1037 case PARSE_EVENTS__TERM_TYPE_CONFIG2:
1038 case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD:
1039 case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE:
1040 case PARSE_EVENTS__TERM_TYPE_NUM: 1049 case PARSE_EVENTS__TERM_TYPE_NUM:
1041 term->val.num = num; 1050 term->val.num = num;
1042 break; 1051 break;
@@ -1051,6 +1060,20 @@ int parse_events__new_term(struct parse_events__term **_term, int type,
1051 return 0; 1060 return 0;
1052} 1061}
1053 1062
1063int parse_events__term_num(struct parse_events__term **term,
1064 int type_term, char *config, long num)
1065{
1066 return new_term(term, PARSE_EVENTS__TERM_TYPE_NUM, type_term,
1067 config, NULL, num);
1068}
1069
1070int parse_events__term_str(struct parse_events__term **term,
1071 int type_term, char *config, char *str)
1072{
1073 return new_term(term, PARSE_EVENTS__TERM_TYPE_STR, type_term,
1074 config, str, 0);
1075}
1076
1054void parse_events__free_terms(struct list_head *terms) 1077void parse_events__free_terms(struct list_head *terms)
1055{ 1078{
1056 struct parse_events__term *term, *h; 1079 struct parse_events__term *term, *h;
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 5cb002894a17..3fddd610d350 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -36,16 +36,17 @@ extern int parse_filter(const struct option *opt, const char *str, int unset);
36#define EVENTS_HELP_MAX (128*1024) 36#define EVENTS_HELP_MAX (128*1024)
37 37
38enum { 38enum {
39 PARSE_EVENTS__TERM_TYPE_NUM,
40 PARSE_EVENTS__TERM_TYPE_STR,
41};
42
43enum {
44 PARSE_EVENTS__TERM_TYPE_USER,
39 PARSE_EVENTS__TERM_TYPE_CONFIG, 45 PARSE_EVENTS__TERM_TYPE_CONFIG,
40 PARSE_EVENTS__TERM_TYPE_CONFIG1, 46 PARSE_EVENTS__TERM_TYPE_CONFIG1,
41 PARSE_EVENTS__TERM_TYPE_CONFIG2, 47 PARSE_EVENTS__TERM_TYPE_CONFIG2,
42 PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD, 48 PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD,
43 PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE, 49 PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE,
44 PARSE_EVENTS__TERM_TYPE_NUM,
45 PARSE_EVENTS__TERM_TYPE_STR,
46
47 PARSE_EVENTS__TERM_TYPE_HARDCODED_MAX =
48 PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE,
49}; 50};
50 51
51struct parse_events__term { 52struct parse_events__term {
@@ -54,14 +55,16 @@ struct parse_events__term {
54 char *str; 55 char *str;
55 long num; 56 long num;
56 } val; 57 } val;
57 int type; 58 int type_val;
58 59 int type_term;
59 struct list_head list; 60 struct list_head list;
60}; 61};
61 62
62int parse_events__is_hardcoded_term(struct parse_events__term *term); 63int parse_events__is_hardcoded_term(struct parse_events__term *term);
63int parse_events__new_term(struct parse_events__term **term, int type, 64int parse_events__term_num(struct parse_events__term **_term,
64 char *config, char *str, long num); 65 int type_term, char *config, long num);
66int parse_events__term_str(struct parse_events__term **_term,
67 int type_term, char *config, char *str);
65void parse_events__free_terms(struct list_head *terms); 68void parse_events__free_terms(struct list_head *terms);
66int parse_events_modifier(struct list_head *list __used, char *str __used); 69int parse_events_modifier(struct list_head *list __used, char *str __used);
67int parse_events_add_tracepoint(struct list_head *list, int *idx, 70int parse_events_add_tracepoint(struct list_head *list, int *idx,
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 05d766e3ecb5..1fcf1bbc5458 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -54,7 +54,7 @@ num_dec [0-9]+
54num_hex 0x[a-fA-F0-9]+ 54num_hex 0x[a-fA-F0-9]+
55num_raw_hex [a-fA-F0-9]+ 55num_raw_hex [a-fA-F0-9]+
56name [a-zA-Z_*?][a-zA-Z0-9_*?]* 56name [a-zA-Z_*?][a-zA-Z0-9_*?]*
57modifier_event [ukhp]{1,5} 57modifier_event [ukhpGH]{1,8}
58modifier_bp [rwx] 58modifier_bp [rwx]
59 59
60%% 60%%
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index d9637da7333c..936913ea0ab6 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -176,8 +176,8 @@ PE_NAME '=' PE_NAME
176{ 176{
177 struct parse_events__term *term; 177 struct parse_events__term *term;
178 178
179 ABORT_ON(parse_events__new_term(&term, PARSE_EVENTS__TERM_TYPE_STR, 179 ABORT_ON(parse_events__term_str(&term, PARSE_EVENTS__TERM_TYPE_USER,
180 $1, $3, 0)); 180 $1, $3));
181 $$ = term; 181 $$ = term;
182} 182}
183| 183|
@@ -185,8 +185,8 @@ PE_NAME '=' PE_VALUE
185{ 185{
186 struct parse_events__term *term; 186 struct parse_events__term *term;
187 187
188 ABORT_ON(parse_events__new_term(&term, PARSE_EVENTS__TERM_TYPE_NUM, 188 ABORT_ON(parse_events__term_num(&term, PARSE_EVENTS__TERM_TYPE_USER,
189 $1, NULL, $3)); 189 $1, $3));
190 $$ = term; 190 $$ = term;
191} 191}
192| 192|
@@ -194,8 +194,8 @@ PE_NAME
194{ 194{
195 struct parse_events__term *term; 195 struct parse_events__term *term;
196 196
197 ABORT_ON(parse_events__new_term(&term, PARSE_EVENTS__TERM_TYPE_NUM, 197 ABORT_ON(parse_events__term_num(&term, PARSE_EVENTS__TERM_TYPE_USER,
198 $1, NULL, 1)); 198 $1, 1));
199 $$ = term; 199 $$ = term;
200} 200}
201| 201|
@@ -203,7 +203,7 @@ PE_TERM '=' PE_VALUE
203{ 203{
204 struct parse_events__term *term; 204 struct parse_events__term *term;
205 205
206 ABORT_ON(parse_events__new_term(&term, $1, NULL, NULL, $3)); 206 ABORT_ON(parse_events__term_num(&term, $1, NULL, $3));
207 $$ = term; 207 $$ = term;
208} 208}
209| 209|
@@ -211,7 +211,7 @@ PE_TERM
211{ 211{
212 struct parse_events__term *term; 212 struct parse_events__term *term;
213 213
214 ABORT_ON(parse_events__new_term(&term, $1, NULL, NULL, 1)); 214 ABORT_ON(parse_events__term_num(&term, $1, NULL, 1));
215 $$ = term; 215 $$ = term;
216} 216}
217 217
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index cb08a118e811..8ee219b7285b 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -225,7 +225,7 @@ static int pmu_config_term(struct list_head *formats,
225 if (parse_events__is_hardcoded_term(term)) 225 if (parse_events__is_hardcoded_term(term))
226 return 0; 226 return 0;
227 227
228 if (term->type != PARSE_EVENTS__TERM_TYPE_NUM) 228 if (term->type_val != PARSE_EVENTS__TERM_TYPE_NUM)
229 return -EINVAL; 229 return -EINVAL;
230 230
231 format = pmu_find_format(formats, term->config); 231 format = pmu_find_format(formats, term->config);
@@ -246,6 +246,11 @@ static int pmu_config_term(struct list_head *formats,
246 return -EINVAL; 246 return -EINVAL;
247 } 247 }
248 248
249 /*
250 * XXX If we ever decide to go with string values for
251 * non-hardcoded terms, here's the place to translate
252 * them into value.
253 */
249 *vp |= pmu_format_value(format->bits, term->val.num); 254 *vp |= pmu_format_value(format->bits, term->val.num);
250 return 0; 255 return 0;
251} 256}
@@ -324,49 +329,58 @@ static struct test_format {
324/* Simulated users input. */ 329/* Simulated users input. */
325static struct parse_events__term test_terms[] = { 330static struct parse_events__term test_terms[] = {
326 { 331 {
327 .config = (char *) "krava01", 332 .config = (char *) "krava01",
328 .val.num = 15, 333 .val.num = 15,
329 .type = PARSE_EVENTS__TERM_TYPE_NUM, 334 .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
335 .type_term = PARSE_EVENTS__TERM_TYPE_USER,
330 }, 336 },
331 { 337 {
332 .config = (char *) "krava02", 338 .config = (char *) "krava02",
333 .val.num = 170, 339 .val.num = 170,
334 .type = PARSE_EVENTS__TERM_TYPE_NUM, 340 .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
341 .type_term = PARSE_EVENTS__TERM_TYPE_USER,
335 }, 342 },
336 { 343 {
337 .config = (char *) "krava03", 344 .config = (char *) "krava03",
338 .val.num = 1, 345 .val.num = 1,
339 .type = PARSE_EVENTS__TERM_TYPE_NUM, 346 .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
347 .type_term = PARSE_EVENTS__TERM_TYPE_USER,
340 }, 348 },
341 { 349 {
342 .config = (char *) "krava11", 350 .config = (char *) "krava11",
343 .val.num = 27, 351 .val.num = 27,
344 .type = PARSE_EVENTS__TERM_TYPE_NUM, 352 .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
353 .type_term = PARSE_EVENTS__TERM_TYPE_USER,
345 }, 354 },
346 { 355 {
347 .config = (char *) "krava12", 356 .config = (char *) "krava12",
348 .val.num = 1, 357 .val.num = 1,
349 .type = PARSE_EVENTS__TERM_TYPE_NUM, 358 .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
359 .type_term = PARSE_EVENTS__TERM_TYPE_USER,
350 }, 360 },
351 { 361 {
352 .config = (char *) "krava13", 362 .config = (char *) "krava13",
353 .val.num = 2, 363 .val.num = 2,
354 .type = PARSE_EVENTS__TERM_TYPE_NUM, 364 .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
365 .type_term = PARSE_EVENTS__TERM_TYPE_USER,
355 }, 366 },
356 { 367 {
357 .config = (char *) "krava21", 368 .config = (char *) "krava21",
358 .val.num = 119, 369 .val.num = 119,
359 .type = PARSE_EVENTS__TERM_TYPE_NUM, 370 .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
371 .type_term = PARSE_EVENTS__TERM_TYPE_USER,
360 }, 372 },
361 { 373 {
362 .config = (char *) "krava22", 374 .config = (char *) "krava22",
363 .val.num = 11, 375 .val.num = 11,
364 .type = PARSE_EVENTS__TERM_TYPE_NUM, 376 .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
377 .type_term = PARSE_EVENTS__TERM_TYPE_USER,
365 }, 378 },
366 { 379 {
367 .config = (char *) "krava23", 380 .config = (char *) "krava23",
368 .val.num = 2, 381 .val.num = 2,
369 .type = PARSE_EVENTS__TERM_TYPE_NUM, 382 .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
383 .type_term = PARSE_EVENTS__TERM_TYPE_USER,
370 }, 384 },
371}; 385};
372#define TERMS_CNT (sizeof(test_terms) / sizeof(struct parse_events__term)) 386#define TERMS_CNT (sizeof(test_terms) / sizeof(struct parse_events__term))
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index c0a028c3ebaf..ab9867b2b433 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -977,8 +977,9 @@ static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
977 * And always look at the original dso, not at debuginfo packages, that 977 * And always look at the original dso, not at debuginfo packages, that
978 * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS). 978 * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS).
979 */ 979 */
980static int dso__synthesize_plt_symbols(struct dso *dso, struct map *map, 980static int
981 symbol_filter_t filter) 981dso__synthesize_plt_symbols(struct dso *dso, char *name, struct map *map,
982 symbol_filter_t filter)
982{ 983{
983 uint32_t nr_rel_entries, idx; 984 uint32_t nr_rel_entries, idx;
984 GElf_Sym sym; 985 GElf_Sym sym;
@@ -993,10 +994,7 @@ static int dso__synthesize_plt_symbols(struct dso *dso, struct map *map,
993 char sympltname[1024]; 994 char sympltname[1024];
994 Elf *elf; 995 Elf *elf;
995 int nr = 0, symidx, fd, err = 0; 996 int nr = 0, symidx, fd, err = 0;
996 char name[PATH_MAX];
997 997
998 snprintf(name, sizeof(name), "%s%s",
999 symbol_conf.symfs, dso->long_name);
1000 fd = open(name, O_RDONLY); 998 fd = open(name, O_RDONLY);
1001 if (fd < 0) 999 if (fd < 0)
1002 goto out; 1000 goto out;
@@ -1703,8 +1701,9 @@ restart:
1703 continue; 1701 continue;
1704 1702
1705 if (ret > 0) { 1703 if (ret > 0) {
1706 int nr_plt = dso__synthesize_plt_symbols(dso, map, 1704 int nr_plt;
1707 filter); 1705
1706 nr_plt = dso__synthesize_plt_symbols(dso, name, map, filter);
1708 if (nr_plt > 0) 1707 if (nr_plt > 0)
1709 ret += nr_plt; 1708 ret += nr_plt;
1710 break; 1709 break;
diff --git a/tools/perf/util/target.h b/tools/perf/util/target.h
index 127cff3f8ced..a4be8575fda5 100644
--- a/tools/perf/util/target.h
+++ b/tools/perf/util/target.h
@@ -11,6 +11,7 @@ struct perf_target {
11 const char *uid_str; 11 const char *uid_str;
12 uid_t uid; 12 uid_t uid;
13 bool system_wide; 13 bool system_wide;
14 bool uses_mmap;
14}; 15};
15 16
16enum perf_target_errno { 17enum perf_target_errno {
@@ -46,19 +47,19 @@ enum perf_target_errno perf_target__parse_uid(struct perf_target *target);
46int perf_target__strerror(struct perf_target *target, int errnum, char *buf, 47int perf_target__strerror(struct perf_target *target, int errnum, char *buf,
47 size_t buflen); 48 size_t buflen);
48 49
49static inline bool perf_target__no_task(struct perf_target *target) 50static inline bool perf_target__has_task(struct perf_target *target)
50{ 51{
51 return !target->pid && !target->tid && !target->uid_str; 52 return target->tid || target->pid || target->uid_str;
52} 53}
53 54
54static inline bool perf_target__no_cpu(struct perf_target *target) 55static inline bool perf_target__has_cpu(struct perf_target *target)
55{ 56{
56 return !target->system_wide && !target->cpu_list; 57 return target->system_wide || target->cpu_list;
57} 58}
58 59
59static inline bool perf_target__none(struct perf_target *target) 60static inline bool perf_target__none(struct perf_target *target)
60{ 61{
61 return perf_target__no_task(target) && perf_target__no_cpu(target); 62 return !perf_target__has_task(target) && !perf_target__has_cpu(target);
62} 63}
63 64
64#endif /* _PERF_TARGET_H */ 65#endif /* _PERF_TARGET_H */