Commit 2a20b02c055a14eb60ac8da737d79dc940bb9ee0
Exists in
master
and in
39 other branches
Merge branch 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
…/git/tip/linux-2.6-tip * 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: perf, x86: Complain louder about BIOSen corrupting CPU/PMU state and continue perf, x86: P4 PMU - Read proper MSR register to catch unflagged overflows perf symbols: Look at .dynsym again if .symtab not found perf build-id: Add quirk to deal with perf.data file format breakage perf session: Pass evsel in event_ops->sample() perf: Better fit max unprivileged mlock pages for tools needs perf_events: Fix stale ->cgrp pointer in update_cgrp_time_from_cpuctx() perf top: Fix uninitialized 'counter' variable tracing: Fix set_ftrace_filter probe function display perf, x86: Fix Intel fixed counters base initialization
Showing 25 changed files Side-by-side Diff
- arch/x86/kernel/cpu/perf_event.c
- arch/x86/kernel/cpu/perf_event_p4.c
- include/linux/perf_event.h
- kernel/perf_event.c
- kernel/trace/ftrace.c
- tools/perf/builtin-annotate.c
- tools/perf/builtin-diff.c
- tools/perf/builtin-inject.c
- tools/perf/builtin-kmem.c
- tools/perf/builtin-lock.c
- tools/perf/builtin-report.c
- tools/perf/builtin-sched.c
- tools/perf/builtin-script.c
- tools/perf/builtin-timechart.c
- tools/perf/builtin-top.c
- tools/perf/util/build-id.c
- tools/perf/util/header.c
- tools/perf/util/hist.h
- tools/perf/util/scripting-engines/trace-event-perl.c
- tools/perf/util/scripting-engines/trace-event-python.c
- tools/perf/util/session.c
- tools/perf/util/session.h
- tools/perf/util/symbol.c
- tools/perf/util/trace-event-scripting.c
- tools/perf/util/trace-event.h
arch/x86/kernel/cpu/perf_event.c
... | ... | @@ -500,12 +500,17 @@ |
500 | 500 | return true; |
501 | 501 | |
502 | 502 | bios_fail: |
503 | - printk(KERN_CONT "Broken BIOS detected, using software events only.\n"); | |
503 | + /* | |
504 | + * We still allow the PMU driver to operate: | |
505 | + */ | |
506 | + printk(KERN_CONT "Broken BIOS detected, complain to your hardware vendor.\n"); | |
504 | 507 | printk(KERN_ERR FW_BUG "the BIOS has corrupted hw-PMU resources (MSR %x is %Lx)\n", reg, val); |
505 | - return false; | |
506 | 508 | |
509 | + return true; | |
510 | + | |
507 | 511 | msr_fail: |
508 | 512 | printk(KERN_CONT "Broken PMU hardware detected, using software events only.\n"); |
513 | + | |
509 | 514 | return false; |
510 | 515 | } |
511 | 516 | |
... | ... | @@ -912,7 +917,7 @@ |
912 | 917 | hwc->event_base = 0; |
913 | 918 | } else if (hwc->idx >= X86_PMC_IDX_FIXED) { |
914 | 919 | hwc->config_base = MSR_ARCH_PERFMON_FIXED_CTR_CTRL; |
915 | - hwc->event_base = MSR_ARCH_PERFMON_FIXED_CTR0; | |
920 | + hwc->event_base = MSR_ARCH_PERFMON_FIXED_CTR0 + (hwc->idx - X86_PMC_IDX_FIXED); | |
916 | 921 | } else { |
917 | 922 | hwc->config_base = x86_pmu_config_addr(hwc->idx); |
918 | 923 | hwc->event_base = x86_pmu_event_addr(hwc->idx); |
arch/x86/kernel/cpu/perf_event_p4.c
include/linux/perf_event.h
kernel/perf_event.c
... | ... | @@ -145,7 +145,8 @@ |
145 | 145 | */ |
146 | 146 | int sysctl_perf_event_paranoid __read_mostly = 1; |
147 | 147 | |
148 | -int sysctl_perf_event_mlock __read_mostly = 512; /* 'free' kb per user */ | |
148 | +/* Minimum for 128 pages + 1 for the user control page */ | |
149 | +int sysctl_perf_event_mlock __read_mostly = 516; /* 'free' kb per user */ | |
149 | 150 | |
150 | 151 | /* |
151 | 152 | * max perf event sample rate |
... | ... | @@ -941,6 +942,7 @@ |
941 | 942 | static void |
942 | 943 | list_del_event(struct perf_event *event, struct perf_event_context *ctx) |
943 | 944 | { |
945 | + struct perf_cpu_context *cpuctx; | |
944 | 946 | /* |
945 | 947 | * We can have double detach due to exit/hot-unplug + close. |
946 | 948 | */ |
947 | 949 | |
... | ... | @@ -949,8 +951,17 @@ |
949 | 951 | |
950 | 952 | event->attach_state &= ~PERF_ATTACH_CONTEXT; |
951 | 953 | |
952 | - if (is_cgroup_event(event)) | |
954 | + if (is_cgroup_event(event)) { | |
953 | 955 | ctx->nr_cgroups--; |
956 | + cpuctx = __get_cpu_context(ctx); | |
957 | + /* | |
958 | + * if there are no more cgroup events | |
959 | + * then cler cgrp to avoid stale pointer | |
960 | + * in update_cgrp_time_from_cpuctx() | |
961 | + */ | |
962 | + if (!ctx->nr_cgroups) | |
963 | + cpuctx->cgrp = NULL; | |
964 | + } | |
954 | 965 | |
955 | 966 | ctx->nr_events--; |
956 | 967 | if (event->attr.inherit_stat) |
kernel/trace/ftrace.c
... | ... | @@ -1467,7 +1467,7 @@ |
1467 | 1467 | return t_hash_next(m, pos); |
1468 | 1468 | |
1469 | 1469 | (*pos)++; |
1470 | - iter->pos = *pos; | |
1470 | + iter->pos = iter->func_pos = *pos; | |
1471 | 1471 | |
1472 | 1472 | if (iter->flags & FTRACE_ITER_PRINTALL) |
1473 | 1473 | return t_hash_start(m, pos); |
... | ... | @@ -1502,7 +1502,6 @@ |
1502 | 1502 | if (!rec) |
1503 | 1503 | return t_hash_start(m, pos); |
1504 | 1504 | |
1505 | - iter->func_pos = *pos; | |
1506 | 1505 | iter->func = rec; |
1507 | 1506 | |
1508 | 1507 | return iter; |
tools/perf/builtin-annotate.c
... | ... | @@ -42,9 +42,9 @@ |
42 | 42 | |
43 | 43 | static int perf_evlist__add_sample(struct perf_evlist *evlist, |
44 | 44 | struct perf_sample *sample, |
45 | + struct perf_evsel *evsel, | |
45 | 46 | struct addr_location *al) |
46 | 47 | { |
47 | - struct perf_evsel *evsel; | |
48 | 48 | struct hist_entry *he; |
49 | 49 | int ret; |
50 | 50 | |
... | ... | @@ -59,18 +59,6 @@ |
59 | 59 | return 0; |
60 | 60 | } |
61 | 61 | |
62 | - evsel = perf_evlist__id2evsel(evlist, sample->id); | |
63 | - if (evsel == NULL) { | |
64 | - /* | |
65 | - * FIXME: Propagate this back, but at least we're in a builtin, | |
66 | - * where exit() is allowed. ;-) | |
67 | - */ | |
68 | - ui__warning("Invalid %s file, contains samples with id not in " | |
69 | - "its header!\n", input_name); | |
70 | - exit_browser(0); | |
71 | - exit(1); | |
72 | - } | |
73 | - | |
74 | 62 | he = __hists__add_entry(&evsel->hists, al, NULL, 1); |
75 | 63 | if (he == NULL) |
76 | 64 | return -ENOMEM; |
... | ... | @@ -92,6 +80,7 @@ |
92 | 80 | |
93 | 81 | static int process_sample_event(union perf_event *event, |
94 | 82 | struct perf_sample *sample, |
83 | + struct perf_evsel *evsel, | |
95 | 84 | struct perf_session *session) |
96 | 85 | { |
97 | 86 | struct addr_location al; |
... | ... | @@ -103,7 +92,8 @@ |
103 | 92 | return -1; |
104 | 93 | } |
105 | 94 | |
106 | - if (!al.filtered && perf_evlist__add_sample(session->evlist, sample, &al)) { | |
95 | + if (!al.filtered && | |
96 | + perf_evlist__add_sample(session->evlist, sample, evsel, &al)) { | |
107 | 97 | pr_warning("problem incrementing symbol count, " |
108 | 98 | "skipping event\n"); |
109 | 99 | return -1; |
tools/perf/builtin-diff.c
tools/perf/builtin-inject.c
... | ... | @@ -43,6 +43,14 @@ |
43 | 43 | return perf_event__repipe_synth(event, session); |
44 | 44 | } |
45 | 45 | |
46 | +static int perf_event__repipe_sample(union perf_event *event, | |
47 | + struct perf_sample *sample __used, | |
48 | + struct perf_evsel *evsel __used, | |
49 | + struct perf_session *session) | |
50 | +{ | |
51 | + return perf_event__repipe_synth(event, session); | |
52 | +} | |
53 | + | |
46 | 54 | static int perf_event__repipe_mmap(union perf_event *event, |
47 | 55 | struct perf_sample *sample, |
48 | 56 | struct perf_session *session) |
... | ... | @@ -124,6 +132,7 @@ |
124 | 132 | |
125 | 133 | static int perf_event__inject_buildid(union perf_event *event, |
126 | 134 | struct perf_sample *sample, |
135 | + struct perf_evsel *evsel __used, | |
127 | 136 | struct perf_session *session) |
128 | 137 | { |
129 | 138 | struct addr_location al; |
... | ... | @@ -164,7 +173,7 @@ |
164 | 173 | } |
165 | 174 | |
166 | 175 | struct perf_event_ops inject_ops = { |
167 | - .sample = perf_event__repipe, | |
176 | + .sample = perf_event__repipe_sample, | |
168 | 177 | .mmap = perf_event__repipe, |
169 | 178 | .comm = perf_event__repipe, |
170 | 179 | .fork = perf_event__repipe, |
tools/perf/builtin-kmem.c
... | ... | @@ -305,6 +305,7 @@ |
305 | 305 | |
306 | 306 | static int process_sample_event(union perf_event *event, |
307 | 307 | struct perf_sample *sample, |
308 | + struct perf_evsel *evsel __used, | |
308 | 309 | struct perf_session *session) |
309 | 310 | { |
310 | 311 | struct thread *thread = perf_session__findnew(session, event->ip.pid); |
tools/perf/builtin-lock.c
... | ... | @@ -845,7 +845,9 @@ |
845 | 845 | die("Unknown type of information\n"); |
846 | 846 | } |
847 | 847 | |
848 | -static int process_sample_event(union perf_event *event, struct perf_sample *sample, | |
848 | +static int process_sample_event(union perf_event *event, | |
849 | + struct perf_sample *sample, | |
850 | + struct perf_evsel *evsel __used, | |
849 | 851 | struct perf_session *s) |
850 | 852 | { |
851 | 853 | struct thread *thread = perf_session__findnew(s, sample->tid); |
tools/perf/builtin-report.c
... | ... | @@ -50,12 +50,12 @@ |
50 | 50 | |
51 | 51 | static int perf_session__add_hist_entry(struct perf_session *session, |
52 | 52 | struct addr_location *al, |
53 | - struct perf_sample *sample) | |
53 | + struct perf_sample *sample, | |
54 | + struct perf_evsel *evsel) | |
54 | 55 | { |
55 | 56 | struct symbol *parent = NULL; |
56 | 57 | int err = 0; |
57 | 58 | struct hist_entry *he; |
58 | - struct perf_evsel *evsel; | |
59 | 59 | |
60 | 60 | if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) { |
61 | 61 | err = perf_session__resolve_callchain(session, al->thread, |
... | ... | @@ -64,18 +64,6 @@ |
64 | 64 | return err; |
65 | 65 | } |
66 | 66 | |
67 | - evsel = perf_evlist__id2evsel(session->evlist, sample->id); | |
68 | - if (evsel == NULL) { | |
69 | - /* | |
70 | - * FIXME: Propagate this back, but at least we're in a builtin, | |
71 | - * where exit() is allowed. ;-) | |
72 | - */ | |
73 | - ui__warning("Invalid %s file, contains samples with id %" PRIu64 " not in " | |
74 | - "its header!\n", input_name, sample->id); | |
75 | - exit_browser(0); | |
76 | - exit(1); | |
77 | - } | |
78 | - | |
79 | 67 | he = __hists__add_entry(&evsel->hists, al, parent, sample->period); |
80 | 68 | if (he == NULL) |
81 | 69 | return -ENOMEM; |
... | ... | @@ -113,6 +101,7 @@ |
113 | 101 | |
114 | 102 | static int process_sample_event(union perf_event *event, |
115 | 103 | struct perf_sample *sample, |
104 | + struct perf_evsel *evsel, | |
116 | 105 | struct perf_session *session) |
117 | 106 | { |
118 | 107 | struct addr_location al; |
... | ... | @@ -127,7 +116,7 @@ |
127 | 116 | if (al.filtered || (hide_unresolved && al.sym == NULL)) |
128 | 117 | return 0; |
129 | 118 | |
130 | - if (perf_session__add_hist_entry(session, &al, sample)) { | |
119 | + if (perf_session__add_hist_entry(session, &al, sample, evsel)) { | |
131 | 120 | pr_debug("problem incrementing symbol period, skipping event\n"); |
132 | 121 | return -1; |
133 | 122 | } |
tools/perf/builtin-sched.c
tools/perf/builtin-script.c
... | ... | @@ -162,20 +162,12 @@ |
162 | 162 | |
163 | 163 | static void process_event(union perf_event *event __unused, |
164 | 164 | struct perf_sample *sample, |
165 | + struct perf_evsel *evsel, | |
165 | 166 | struct perf_session *session, |
166 | 167 | struct thread *thread) |
167 | 168 | { |
168 | - struct perf_event_attr *attr; | |
169 | - struct perf_evsel *evsel; | |
169 | + struct perf_event_attr *attr = &evsel->attr; | |
170 | 170 | |
171 | - evsel = perf_evlist__id2evsel(session->evlist, sample->id); | |
172 | - if (evsel == NULL) { | |
173 | - pr_err("Invalid data. Contains samples with id not in " | |
174 | - "its header!\n"); | |
175 | - return; | |
176 | - } | |
177 | - attr = &evsel->attr; | |
178 | - | |
179 | 171 | if (output_fields[attr->type] == 0) |
180 | 172 | return; |
181 | 173 | |
... | ... | @@ -244,6 +236,7 @@ |
244 | 236 | |
245 | 237 | static int process_sample_event(union perf_event *event, |
246 | 238 | struct perf_sample *sample, |
239 | + struct perf_evsel *evsel, | |
247 | 240 | struct perf_session *session) |
248 | 241 | { |
249 | 242 | struct thread *thread = perf_session__findnew(session, event->ip.pid); |
... | ... | @@ -264,7 +257,7 @@ |
264 | 257 | last_timestamp = sample->time; |
265 | 258 | return 0; |
266 | 259 | } |
267 | - scripting_ops->process_event(event, sample, session, thread); | |
260 | + scripting_ops->process_event(event, sample, evsel, session, thread); | |
268 | 261 | |
269 | 262 | session->hists.stats.total_period += sample->period; |
270 | 263 | return 0; |
tools/perf/builtin-timechart.c
... | ... | @@ -488,6 +488,7 @@ |
488 | 488 | |
489 | 489 | static int process_sample_event(union perf_event *event __used, |
490 | 490 | struct perf_sample *sample, |
491 | + struct perf_evsel *evsel __used, | |
491 | 492 | struct perf_session *session) |
492 | 493 | { |
493 | 494 | struct trace_entry *te; |
... | ... | @@ -506,6 +507,16 @@ |
506 | 507 | struct power_entry_old *peo; |
507 | 508 | peo = (void *)te; |
508 | 509 | #endif |
510 | + /* | |
511 | + * FIXME: use evsel, its already mapped from id to perf_evsel, | |
512 | + * remove perf_header__find_event infrastructure bits. | |
513 | + * Mapping all these "power:cpu_idle" strings to the tracepoint | |
514 | + * ID and then just comparing against evsel->attr.config. | |
515 | + * | |
516 | + * e.g.: | |
517 | + * | |
518 | + * if (evsel->attr.config == power_cpu_idle_id) | |
519 | + */ | |
509 | 520 | event_str = perf_header__find_event(te->type); |
510 | 521 | |
511 | 522 | if (!event_str) |
tools/perf/builtin-top.c
... | ... | @@ -515,7 +515,9 @@ |
515 | 515 | break; |
516 | 516 | case 'E': |
517 | 517 | if (top.evlist->nr_entries > 1) { |
518 | - int counter; | |
518 | + /* Select 0 as the default event: */ | |
519 | + int counter = 0; | |
520 | + | |
519 | 521 | fprintf(stderr, "\nAvailable events:"); |
520 | 522 | |
521 | 523 | list_for_each_entry(top.sym_evsel, &top.evlist->entries, node) |
tools/perf/util/build-id.c
tools/perf/util/header.c
... | ... | @@ -695,13 +695,50 @@ |
695 | 695 | return err; |
696 | 696 | } |
697 | 697 | |
698 | +static int perf_header__read_build_ids_abi_quirk(struct perf_header *header, | |
699 | + int input, u64 offset, u64 size) | |
700 | +{ | |
701 | + struct perf_session *session = container_of(header, struct perf_session, header); | |
702 | + struct { | |
703 | + struct perf_event_header header; | |
704 | + u8 build_id[ALIGN(BUILD_ID_SIZE, sizeof(u64))]; | |
705 | + char filename[0]; | |
706 | + } old_bev; | |
707 | + struct build_id_event bev; | |
708 | + char filename[PATH_MAX]; | |
709 | + u64 limit = offset + size; | |
710 | + | |
711 | + while (offset < limit) { | |
712 | + ssize_t len; | |
713 | + | |
714 | + if (read(input, &old_bev, sizeof(old_bev)) != sizeof(old_bev)) | |
715 | + return -1; | |
716 | + | |
717 | + if (header->needs_swap) | |
718 | + perf_event_header__bswap(&old_bev.header); | |
719 | + | |
720 | + len = old_bev.header.size - sizeof(old_bev); | |
721 | + if (read(input, filename, len) != len) | |
722 | + return -1; | |
723 | + | |
724 | + bev.header = old_bev.header; | |
725 | + bev.pid = 0; | |
726 | + memcpy(bev.build_id, old_bev.build_id, sizeof(bev.build_id)); | |
727 | + __event_process_build_id(&bev, filename, session); | |
728 | + | |
729 | + offset += bev.header.size; | |
730 | + } | |
731 | + | |
732 | + return 0; | |
733 | +} | |
734 | + | |
698 | 735 | static int perf_header__read_build_ids(struct perf_header *header, |
699 | 736 | int input, u64 offset, u64 size) |
700 | 737 | { |
701 | 738 | struct perf_session *session = container_of(header, struct perf_session, header); |
702 | 739 | struct build_id_event bev; |
703 | 740 | char filename[PATH_MAX]; |
704 | - u64 limit = offset + size; | |
741 | + u64 limit = offset + size, orig_offset = offset; | |
705 | 742 | int err = -1; |
706 | 743 | |
707 | 744 | while (offset < limit) { |
... | ... | @@ -716,6 +753,24 @@ |
716 | 753 | len = bev.header.size - sizeof(bev); |
717 | 754 | if (read(input, filename, len) != len) |
718 | 755 | goto out; |
756 | + /* | |
757 | + * The a1645ce1 changeset: | |
758 | + * | |
759 | + * "perf: 'perf kvm' tool for monitoring guest performance from host" | |
760 | + * | |
761 | + * Added a field to struct build_id_event that broke the file | |
762 | + * format. | |
763 | + * | |
764 | + * Since the kernel build-id is the first entry, process the | |
765 | + * table using the old format if the well known | |
766 | + * '[kernel.kallsyms]' string for the kernel build-id has the | |
767 | + * first 4 characters chopped off (where the pid_t sits). | |
768 | + */ | |
769 | + if (memcmp(filename, "nel.kallsyms]", 13) == 0) { | |
770 | + if (lseek(input, orig_offset, SEEK_SET) == (off_t)-1) | |
771 | + return -1; | |
772 | + return perf_header__read_build_ids_abi_quirk(header, input, offset, size); | |
773 | + } | |
719 | 774 | |
720 | 775 | __event_process_build_id(&bev, filename, session); |
721 | 776 |
tools/perf/util/hist.h
tools/perf/util/scripting-engines/trace-event-perl.c
tools/perf/util/scripting-engines/trace-event-python.c
tools/perf/util/session.c
... | ... | @@ -280,6 +280,15 @@ |
280 | 280 | return 0; |
281 | 281 | } |
282 | 282 | |
283 | +static int process_event_sample_stub(union perf_event *event __used, | |
284 | + struct perf_sample *sample __used, | |
285 | + struct perf_evsel *evsel __used, | |
286 | + struct perf_session *session __used) | |
287 | +{ | |
288 | + dump_printf(": unhandled!\n"); | |
289 | + return 0; | |
290 | +} | |
291 | + | |
283 | 292 | static int process_event_stub(union perf_event *event __used, |
284 | 293 | struct perf_sample *sample __used, |
285 | 294 | struct perf_session *session __used) |
... | ... | @@ -303,7 +312,7 @@ |
303 | 312 | static void perf_event_ops__fill_defaults(struct perf_event_ops *handler) |
304 | 313 | { |
305 | 314 | if (handler->sample == NULL) |
306 | - handler->sample = process_event_stub; | |
315 | + handler->sample = process_event_sample_stub; | |
307 | 316 | if (handler->mmap == NULL) |
308 | 317 | handler->mmap = process_event_stub; |
309 | 318 | if (handler->comm == NULL) |
310 | 319 | |
... | ... | @@ -698,12 +707,19 @@ |
698 | 707 | struct perf_event_ops *ops, |
699 | 708 | u64 file_offset) |
700 | 709 | { |
710 | + struct perf_evsel *evsel; | |
711 | + | |
701 | 712 | dump_event(session, event, file_offset, sample); |
702 | 713 | |
703 | 714 | switch (event->header.type) { |
704 | 715 | case PERF_RECORD_SAMPLE: |
705 | 716 | dump_sample(session, event, sample); |
706 | - return ops->sample(event, sample, session); | |
717 | + evsel = perf_evlist__id2evsel(session->evlist, sample->id); | |
718 | + if (evsel == NULL) { | |
719 | + ++session->hists.stats.nr_unknown_id; | |
720 | + return -1; | |
721 | + } | |
722 | + return ops->sample(event, sample, evsel, session); | |
707 | 723 | case PERF_RECORD_MMAP: |
708 | 724 | return ops->mmap(event, sample, session); |
709 | 725 | case PERF_RECORD_COMM: |
... | ... | @@ -843,6 +859,11 @@ |
843 | 859 | "If that is not the case, consider " |
844 | 860 | "reporting to linux-kernel@vger.kernel.org.\n\n", |
845 | 861 | session->hists.stats.nr_unknown_events); |
862 | + } | |
863 | + | |
864 | + if (session->hists.stats.nr_unknown_id != 0) { | |
865 | + ui__warning("%u samples with id not present in the header\n", | |
866 | + session->hists.stats.nr_unknown_id); | |
846 | 867 | } |
847 | 868 | |
848 | 869 | if (session->hists.stats.nr_invalid_chains != 0) { |
tools/perf/util/session.h
... | ... | @@ -55,8 +55,11 @@ |
55 | 55 | char filename[0]; |
56 | 56 | }; |
57 | 57 | |
58 | +struct perf_evsel; | |
58 | 59 | struct perf_event_ops; |
59 | 60 | |
61 | +typedef int (*event_sample)(union perf_event *event, struct perf_sample *sample, | |
62 | + struct perf_evsel *evsel, struct perf_session *session); | |
60 | 63 | typedef int (*event_op)(union perf_event *self, struct perf_sample *sample, |
61 | 64 | struct perf_session *session); |
62 | 65 | typedef int (*event_synth_op)(union perf_event *self, |
... | ... | @@ -65,8 +68,8 @@ |
65 | 68 | struct perf_event_ops *ops); |
66 | 69 | |
67 | 70 | struct perf_event_ops { |
68 | - event_op sample, | |
69 | - mmap, | |
71 | + event_sample sample; | |
72 | + event_op mmap, | |
70 | 73 | comm, |
71 | 74 | fork, |
72 | 75 | exit, |
tools/perf/util/symbol.c
... | ... | @@ -1486,7 +1486,9 @@ |
1486 | 1486 | * On the first pass, only load images if they have a full symtab. |
1487 | 1487 | * Failing that, do a second pass where we accept .dynsym also |
1488 | 1488 | */ |
1489 | - for (self->symtab_type = SYMTAB__BUILD_ID_CACHE, want_symtab = 1; | |
1489 | + want_symtab = 1; | |
1490 | +restart: | |
1491 | + for (self->symtab_type = SYMTAB__BUILD_ID_CACHE; | |
1490 | 1492 | self->symtab_type != SYMTAB__NOT_FOUND; |
1491 | 1493 | self->symtab_type++) { |
1492 | 1494 | switch (self->symtab_type) { |
... | ... | @@ -1536,17 +1538,7 @@ |
1536 | 1538 | snprintf(name, size, "%s%s", symbol_conf.symfs, |
1537 | 1539 | self->long_name); |
1538 | 1540 | break; |
1539 | - | |
1540 | - default: | |
1541 | - /* | |
1542 | - * If we wanted a full symtab but no image had one, | |
1543 | - * relax our requirements and repeat the search. | |
1544 | - */ | |
1545 | - if (want_symtab) { | |
1546 | - want_symtab = 0; | |
1547 | - self->symtab_type = SYMTAB__BUILD_ID_CACHE; | |
1548 | - } else | |
1549 | - continue; | |
1541 | + default:; | |
1550 | 1542 | } |
1551 | 1543 | |
1552 | 1544 | /* Name is now the name of the next image to try */ |
... | ... | @@ -1571,6 +1563,15 @@ |
1571 | 1563 | ret += nr_plt; |
1572 | 1564 | break; |
1573 | 1565 | } |
1566 | + } | |
1567 | + | |
1568 | + /* | |
1569 | + * If we wanted a full symtab but no image had one, | |
1570 | + * relax our requirements and repeat the search. | |
1571 | + */ | |
1572 | + if (ret <= 0 && want_symtab) { | |
1573 | + want_symtab = 0; | |
1574 | + goto restart; | |
1574 | 1575 | } |
1575 | 1576 | |
1576 | 1577 | free(name); |
tools/perf/util/trace-event-scripting.c
tools/perf/util/trace-event.h
... | ... | @@ -280,6 +280,7 @@ |
280 | 280 | int (*stop_script) (void); |
281 | 281 | void (*process_event) (union perf_event *event, |
282 | 282 | struct perf_sample *sample, |
283 | + struct perf_evsel *evsel, | |
283 | 284 | struct perf_session *session, |
284 | 285 | struct thread *thread); |
285 | 286 | int (*generate_script) (const char *outfile); |