aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2015-06-18 03:36:33 -0400
committerIngo Molnar <mingo@kernel.org>2015-06-18 03:40:46 -0400
commit79928928c5a27d58ae48285d2a3f7aa835db7547 (patch)
tree49989d6b2eea50b9c6610d051ed7c1df700755d3
parent61d67d568445413137995e1bea2746783e3a81e9 (diff)
parent5d484f99aed547e235f2229653c95392a1bc3692 (diff)
Merge tag 'perf-core-for-mingo-2' 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: User visible changes: - List perf probes to stdout. (Masami Hiramatsu) - Return error when none of the requested probes were installed. (Masami Hiramatsu) - Cut off the gcc optimization postfixes from function name in 'perf probe'. (Masami Hiramatsu) - Allow disabling/enabling events dynamicly in 'perf top': a 'perf top' session can instantly become a 'perf report' one, i.e. going from dynamic analysis to a static one, returning to a dynamic one is possible, to toogle the modes, just press CTRL+z. (Arnaldo Carvalho de Melo) - Greatly speed up 'perf probe --list' by caching debuginfo. (Masami Hiramatsu) - Fix 'perf trace' race condition at the end of started workloads. (Sukadev Bhattiprolu) - Fix a problem when opening old perf.data with different byte order. (Wang Nan) Infrastructure changes: - Replace map->referenced & maps->removed_maps with map->refcnt. (Arnaldo Carvalho de Melo) - Introduce the xyarray__reset() function. (Jiri Olsa) - Add thread_map__(alloc|realloc)() helpers. (Jiri Olsa) - Move perf_evsel__(alloc|free|reset)_counts into stat object. (Jiri Olsa) - Introduce perf_counts__(new|delete|reset)() functions. (Jiri Olsa) - Ignore .config-detected in .gitignore. (Wang Nan) - Move libtraceevent dynamic list to separated LDFLAGS variable. (Wang Nan) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--tools/perf/.gitignore1
-rw-r--r--tools/perf/Makefile.perf10
-rw-r--r--tools/perf/builtin-stat.c19
-rw-r--r--tools/perf/builtin-top.c52
-rw-r--r--tools/perf/tests/openat-syscall-all-cpus.c1
-rw-r--r--tools/perf/ui/browsers/hists.c2
-rw-r--r--tools/perf/util/evlist.c18
-rw-r--r--tools/perf/util/evlist.h2
-rw-r--r--tools/perf/util/evsel.c19
-rw-r--r--tools/perf/util/evsel.h3
-rw-r--r--tools/perf/util/hist.c37
-rw-r--r--tools/perf/util/map.c58
-rw-r--r--tools/perf/util/map.h10
-rw-r--r--tools/perf/util/probe-event.c240
-rw-r--r--tools/perf/util/python-ext-sources1
-rw-r--r--tools/perf/util/session.c50
-rw-r--r--tools/perf/util/stat.c36
-rw-r--r--tools/perf/util/stat.h6
-rw-r--r--tools/perf/util/thread_map.c24
-rw-r--r--tools/perf/util/unwind-libunwind.c2
-rw-r--r--tools/perf/util/xyarray.c8
-rw-r--r--tools/perf/util/xyarray.h2
22 files changed, 378 insertions, 223 deletions
diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore
index 812f904193e8..09db62ba5786 100644
--- a/tools/perf/.gitignore
+++ b/tools/perf/.gitignore
@@ -28,3 +28,4 @@ config.mak.autogen
28*-flex.* 28*-flex.*
29*.pyc 29*.pyc
30*.pyo 30*.pyo
31.config-detected
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index b1dfcd8e93e3..1af0cfeb7a57 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -174,7 +174,7 @@ LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
174export LIBTRACEEVENT 174export LIBTRACEEVENT
175 175
176LIBTRACEEVENT_DYNAMIC_LIST = $(TE_PATH)libtraceevent-dynamic-list 176LIBTRACEEVENT_DYNAMIC_LIST = $(TE_PATH)libtraceevent-dynamic-list
177LDFLAGS += -Xlinker --dynamic-list=$(LIBTRACEEVENT_DYNAMIC_LIST) 177LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS = -Xlinker --dynamic-list=$(LIBTRACEEVENT_DYNAMIC_LIST)
178 178
179LIBAPI = $(LIB_PATH)libapi.a 179LIBAPI = $(LIB_PATH)libapi.a
180export LIBAPI 180export LIBAPI
@@ -190,8 +190,9 @@ python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT
190PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources) 190PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
191PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPI) 191PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPI)
192 192
193$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) 193$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_DYNAMIC_LIST)
194 $(QUIET_GEN)CFLAGS='$(CFLAGS)' $(PYTHON_WORD) util/setup.py \ 194 $(QUIET_GEN)CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS)' \
195 $(PYTHON_WORD) util/setup.py \
195 --quiet build_ext; \ 196 --quiet build_ext; \
196 mkdir -p $(OUTPUT)python && \ 197 mkdir -p $(OUTPUT)python && \
197 cp $(PYTHON_EXTBUILD_LIB)perf.so $(OUTPUT)python/ 198 cp $(PYTHON_EXTBUILD_LIB)perf.so $(OUTPUT)python/
@@ -282,7 +283,8 @@ $(PERF_IN): $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h FORCE
282 $(Q)$(MAKE) $(build)=perf 283 $(Q)$(MAKE) $(build)=perf
283 284
284$(OUTPUT)perf: $(PERFLIBS) $(PERF_IN) $(LIBTRACEEVENT_DYNAMIC_LIST) 285$(OUTPUT)perf: $(PERFLIBS) $(PERF_IN) $(LIBTRACEEVENT_DYNAMIC_LIST)
285 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(PERF_IN) $(LIBS) -o $@ 286 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS) \
287 $(PERF_IN) $(LIBS) -o $@
286 288
287$(GTK_IN): FORCE 289$(GTK_IN): FORCE
288 $(Q)$(MAKE) $(build)=gtk 290 $(Q)$(MAKE) $(build)=gtk
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index b24ecee95fec..fcf99bdeb19e 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -178,24 +178,19 @@ static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
178 178
179static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel) 179static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel)
180{ 180{
181 void *addr; 181 struct perf_counts *counts;
182 size_t sz;
183 182
184 sz = sizeof(*evsel->counts) + 183 counts = perf_counts__new(perf_evsel__nr_cpus(evsel));
185 (perf_evsel__nr_cpus(evsel) * sizeof(struct perf_counts_values)); 184 if (counts)
185 evsel->prev_raw_counts = counts;
186 186
187 addr = zalloc(sz); 187 return counts ? 0 : -ENOMEM;
188 if (!addr)
189 return -ENOMEM;
190
191 evsel->prev_raw_counts = addr;
192
193 return 0;
194} 188}
195 189
196static void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel) 190static void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel)
197{ 191{
198 zfree(&evsel->prev_raw_counts); 192 perf_counts__delete(evsel->prev_raw_counts);
193 evsel->prev_raw_counts = NULL;
199} 194}
200 195
201static void perf_evlist__free_stats(struct perf_evlist *evlist) 196static void perf_evlist__free_stats(struct perf_evlist *evlist)
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 6b987424d015..72d8a7ae5986 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -235,10 +235,13 @@ static void perf_top__show_details(struct perf_top *top)
235 235
236 more = symbol__annotate_printf(symbol, he->ms.map, top->sym_evsel, 236 more = symbol__annotate_printf(symbol, he->ms.map, top->sym_evsel,
237 0, top->sym_pcnt_filter, top->print_entries, 4); 237 0, top->sym_pcnt_filter, top->print_entries, 4);
238 if (top->zero) 238
239 symbol__annotate_zero_histogram(symbol, top->sym_evsel->idx); 239 if (top->evlist->enabled) {
240 else 240 if (top->zero)
241 symbol__annotate_decay_histogram(symbol, top->sym_evsel->idx); 241 symbol__annotate_zero_histogram(symbol, top->sym_evsel->idx);
242 else
243 symbol__annotate_decay_histogram(symbol, top->sym_evsel->idx);
244 }
242 if (more != 0) 245 if (more != 0)
243 printf("%d lines not displayed, maybe increase display entries [e]\n", more); 246 printf("%d lines not displayed, maybe increase display entries [e]\n", more);
244out_unlock: 247out_unlock:
@@ -276,11 +279,13 @@ static void perf_top__print_sym_table(struct perf_top *top)
276 return; 279 return;
277 } 280 }
278 281
279 if (top->zero) { 282 if (top->evlist->enabled) {
280 hists__delete_entries(hists); 283 if (top->zero) {
281 } else { 284 hists__delete_entries(hists);
282 hists__decay_entries(hists, top->hide_user_symbols, 285 } else {
283 top->hide_kernel_symbols); 286 hists__decay_entries(hists, top->hide_user_symbols,
287 top->hide_kernel_symbols);
288 }
284 } 289 }
285 290
286 hists__collapse_resort(hists, NULL); 291 hists__collapse_resort(hists, NULL);
@@ -545,11 +550,13 @@ static void perf_top__sort_new_samples(void *arg)
545 550
546 hists = evsel__hists(t->sym_evsel); 551 hists = evsel__hists(t->sym_evsel);
547 552
548 if (t->zero) { 553 if (t->evlist->enabled) {
549 hists__delete_entries(hists); 554 if (t->zero) {
550 } else { 555 hists__delete_entries(hists);
551 hists__decay_entries(hists, t->hide_user_symbols, 556 } else {
552 t->hide_kernel_symbols); 557 hists__decay_entries(hists, t->hide_user_symbols,
558 t->hide_kernel_symbols);
559 }
553 } 560 }
554 561
555 hists__collapse_resort(hists, NULL); 562 hists__collapse_resort(hists, NULL);
@@ -579,8 +586,21 @@ static void *display_thread_tui(void *arg)
579 hists->uid_filter_str = top->record_opts.target.uid_str; 586 hists->uid_filter_str = top->record_opts.target.uid_str;
580 } 587 }
581 588
582 perf_evlist__tui_browse_hists(top->evlist, help, &hbt, top->min_percent, 589 while (true) {
583 &top->session->header.env); 590 int key = perf_evlist__tui_browse_hists(top->evlist, help, &hbt,
591 top->min_percent,
592 &top->session->header.env);
593
594 if (key != CTRL('z'))
595 break;
596
597 perf_evlist__toggle_enable(top->evlist);
598 /*
599 * No need to refresh, resort/decay histogram entries
600 * if we are not collecting samples:
601 */
602 hbt.refresh = top->evlist->enabled ? top->delay_secs : 0;
603 }
584 604
585 done = 1; 605 done = 1;
586 return NULL; 606 return NULL;
diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c
index e34dfdf96b5a..9a7a116e09b8 100644
--- a/tools/perf/tests/openat-syscall-all-cpus.c
+++ b/tools/perf/tests/openat-syscall-all-cpus.c
@@ -3,6 +3,7 @@
3#include "thread_map.h" 3#include "thread_map.h"
4#include "cpumap.h" 4#include "cpumap.h"
5#include "debug.h" 5#include "debug.h"
6#include "stat.h"
6 7
7int test__openat_syscall_event_on_all_cpus(void) 8int test__openat_syscall_event_on_all_cpus(void)
8{ 9{
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index e64893f2fd7f..8f7c4d49d327 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1736,6 +1736,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1736 "t Zoom into current Thread\n" 1736 "t Zoom into current Thread\n"
1737 "V Verbose (DSO names in callchains, etc)\n" 1737 "V Verbose (DSO names in callchains, etc)\n"
1738 "z Toggle zeroing of samples\n" 1738 "z Toggle zeroing of samples\n"
1739 "CTRL+z Enable/Disable events\n"
1739 "/ Filter symbol by name"; 1740 "/ Filter symbol by name";
1740 1741
1741 if (browser == NULL) 1742 if (browser == NULL)
@@ -1900,6 +1901,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1900 /* Fall thru */ 1901 /* Fall thru */
1901 case 'q': 1902 case 'q':
1902 case CTRL('c'): 1903 case CTRL('c'):
1904 case CTRL('z'):
1903 goto out_free_stack; 1905 goto out_free_stack;
1904 default: 1906 default:
1905 continue; 1907 continue;
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index dc1dc2c181ef..8366511b45f8 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -297,6 +297,8 @@ void perf_evlist__disable(struct perf_evlist *evlist)
297 PERF_EVENT_IOC_DISABLE, 0); 297 PERF_EVENT_IOC_DISABLE, 0);
298 } 298 }
299 } 299 }
300
301 evlist->enabled = false;
300} 302}
301 303
302void perf_evlist__enable(struct perf_evlist *evlist) 304void perf_evlist__enable(struct perf_evlist *evlist)
@@ -316,6 +318,13 @@ void perf_evlist__enable(struct perf_evlist *evlist)
316 PERF_EVENT_IOC_ENABLE, 0); 318 PERF_EVENT_IOC_ENABLE, 0);
317 } 319 }
318 } 320 }
321
322 evlist->enabled = true;
323}
324
325void perf_evlist__toggle_enable(struct perf_evlist *evlist)
326{
327 (evlist->enabled ? perf_evlist__disable : perf_evlist__enable)(evlist);
319} 328}
320 329
321int perf_evlist__disable_event(struct perf_evlist *evlist, 330int perf_evlist__disable_event(struct perf_evlist *evlist,
@@ -634,11 +643,18 @@ static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist,
634union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) 643union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
635{ 644{
636 struct perf_mmap *md = &evlist->mmap[idx]; 645 struct perf_mmap *md = &evlist->mmap[idx];
637 u64 head = perf_mmap__read_head(md); 646 u64 head;
638 u64 old = md->prev; 647 u64 old = md->prev;
639 unsigned char *data = md->base + page_size; 648 unsigned char *data = md->base + page_size;
640 union perf_event *event = NULL; 649 union perf_event *event = NULL;
641 650
651 /*
652 * Check if event was unmapped due to a POLLHUP/POLLERR.
653 */
654 if (!atomic_read(&md->refcnt))
655 return NULL;
656
657 head = perf_mmap__read_head(md);
642 if (evlist->overwrite) { 658 if (evlist->overwrite) {
643 /* 659 /*
644 * If we're further behind than half the buffer, there's a chance 660 * If we're further behind than half the buffer, there's a chance
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 955bf31b7dd3..a8489b9d2812 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -41,6 +41,7 @@ struct perf_evlist {
41 int nr_groups; 41 int nr_groups;
42 int nr_mmaps; 42 int nr_mmaps;
43 bool overwrite; 43 bool overwrite;
44 bool enabled;
44 size_t mmap_len; 45 size_t mmap_len;
45 int id_pos; 46 int id_pos;
46 int is_pos; 47 int is_pos;
@@ -139,6 +140,7 @@ void perf_evlist__munmap(struct perf_evlist *evlist);
139 140
140void perf_evlist__disable(struct perf_evlist *evlist); 141void perf_evlist__disable(struct perf_evlist *evlist);
141void perf_evlist__enable(struct perf_evlist *evlist); 142void perf_evlist__enable(struct perf_evlist *evlist);
143void perf_evlist__toggle_enable(struct perf_evlist *evlist);
142 144
143int perf_evlist__disable_event(struct perf_evlist *evlist, 145int perf_evlist__disable_event(struct perf_evlist *evlist,
144 struct perf_evsel *evsel); 146 struct perf_evsel *evsel);
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index d4f9994ae47f..33449decf7bd 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -26,6 +26,7 @@
26#include "perf_regs.h" 26#include "perf_regs.h"
27#include "debug.h" 27#include "debug.h"
28#include "trace-event.h" 28#include "trace-event.h"
29#include "stat.h"
29 30
30static struct { 31static struct {
31 bool sample_id_all; 32 bool sample_id_all;
@@ -851,19 +852,6 @@ int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)
851 return 0; 852 return 0;
852} 853}
853 854
854void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus)
855{
856 memset(evsel->counts, 0, (sizeof(*evsel->counts) +
857 (ncpus * sizeof(struct perf_counts_values))));
858}
859
860int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus)
861{
862 evsel->counts = zalloc((sizeof(*evsel->counts) +
863 (ncpus * sizeof(struct perf_counts_values))));
864 return evsel->counts != NULL ? 0 : -ENOMEM;
865}
866
867static void perf_evsel__free_fd(struct perf_evsel *evsel) 855static void perf_evsel__free_fd(struct perf_evsel *evsel)
868{ 856{
869 xyarray__delete(evsel->fd); 857 xyarray__delete(evsel->fd);
@@ -891,11 +879,6 @@ void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
891 } 879 }
892} 880}
893 881
894void perf_evsel__free_counts(struct perf_evsel *evsel)
895{
896 zfree(&evsel->counts);
897}
898
899void perf_evsel__exit(struct perf_evsel *evsel) 882void perf_evsel__exit(struct perf_evsel *evsel)
900{ 883{
901 assert(list_empty(&evsel->node)); 884 assert(list_empty(&evsel->node));
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 21ec08247d47..bb0579e8a10a 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -170,9 +170,6 @@ const char *perf_evsel__group_name(struct perf_evsel *evsel);
170int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size); 170int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size);
171 171
172int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads); 172int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads);
173int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus);
174void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus);
175void perf_evsel__free_counts(struct perf_evsel *evsel);
176void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads); 173void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
177 174
178void __perf_evsel__set_sample_bit(struct perf_evsel *evsel, 175void __perf_evsel__set_sample_bit(struct perf_evsel *evsel,
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index f53d017c7c22..6f28d53d4e46 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -313,8 +313,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template,
313 memset(&he->stat, 0, sizeof(he->stat)); 313 memset(&he->stat, 0, sizeof(he->stat));
314 } 314 }
315 315
316 if (he->ms.map) 316 map__get(he->ms.map);
317 he->ms.map->referenced = true;
318 317
319 if (he->branch_info) { 318 if (he->branch_info) {
320 /* 319 /*
@@ -324,6 +323,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template,
324 */ 323 */
325 he->branch_info = malloc(sizeof(*he->branch_info)); 324 he->branch_info = malloc(sizeof(*he->branch_info));
326 if (he->branch_info == NULL) { 325 if (he->branch_info == NULL) {
326 map__zput(he->ms.map);
327 free(he->stat_acc); 327 free(he->stat_acc);
328 free(he); 328 free(he);
329 return NULL; 329 return NULL;
@@ -332,17 +332,13 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template,
332 memcpy(he->branch_info, template->branch_info, 332 memcpy(he->branch_info, template->branch_info,
333 sizeof(*he->branch_info)); 333 sizeof(*he->branch_info));
334 334
335 if (he->branch_info->from.map) 335 map__get(he->branch_info->from.map);
336 he->branch_info->from.map->referenced = true; 336 map__get(he->branch_info->to.map);
337 if (he->branch_info->to.map)
338 he->branch_info->to.map->referenced = true;
339 } 337 }
340 338
341 if (he->mem_info) { 339 if (he->mem_info) {
342 if (he->mem_info->iaddr.map) 340 map__get(he->mem_info->iaddr.map);
343 he->mem_info->iaddr.map->referenced = true; 341 map__get(he->mem_info->daddr.map);
344 if (he->mem_info->daddr.map)
345 he->mem_info->daddr.map->referenced = true;
346 } 342 }
347 343
348 if (symbol_conf.use_callchain) 344 if (symbol_conf.use_callchain)
@@ -407,9 +403,8 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists,
407 * the history counter to increment. 403 * the history counter to increment.
408 */ 404 */
409 if (he->ms.map != entry->ms.map) { 405 if (he->ms.map != entry->ms.map) {
410 he->ms.map = entry->ms.map; 406 map__put(he->ms.map);
411 if (he->ms.map) 407 he->ms.map = map__get(entry->ms.map);
412 he->ms.map->referenced = true;
413 } 408 }
414 goto out; 409 goto out;
415 } 410 }
@@ -933,8 +928,20 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
933void hist_entry__delete(struct hist_entry *he) 928void hist_entry__delete(struct hist_entry *he)
934{ 929{
935 thread__zput(he->thread); 930 thread__zput(he->thread);
936 zfree(&he->branch_info); 931 map__zput(he->ms.map);
937 zfree(&he->mem_info); 932
933 if (he->branch_info) {
934 map__zput(he->branch_info->from.map);
935 map__zput(he->branch_info->to.map);
936 zfree(&he->branch_info);
937 }
938
939 if (he->mem_info) {
940 map__zput(he->mem_info->iaddr.map);
941 map__zput(he->mem_info->daddr.map);
942 zfree(&he->mem_info);
943 }
944
938 zfree(&he->stat_acc); 945 zfree(&he->stat_acc);
939 free_srcline(he->srcline); 946 free_srcline(he->srcline);
940 free_callchain(he->callchain); 947 free_callchain(he->callchain);
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 1241ab989cf5..b5a5e9c02437 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -137,7 +137,6 @@ void map__init(struct map *map, enum map_type type,
137 map->unmap_ip = map__unmap_ip; 137 map->unmap_ip = map__unmap_ip;
138 RB_CLEAR_NODE(&map->rb_node); 138 RB_CLEAR_NODE(&map->rb_node);
139 map->groups = NULL; 139 map->groups = NULL;
140 map->referenced = false;
141 map->erange_warned = false; 140 map->erange_warned = false;
142 atomic_set(&map->refcnt, 1); 141 atomic_set(&map->refcnt, 1);
143} 142}
@@ -439,7 +438,6 @@ static void maps__init(struct maps *maps)
439{ 438{
440 maps->entries = RB_ROOT; 439 maps->entries = RB_ROOT;
441 pthread_rwlock_init(&maps->lock, NULL); 440 pthread_rwlock_init(&maps->lock, NULL);
442 INIT_LIST_HEAD(&maps->removed_maps);
443} 441}
444 442
445void map_groups__init(struct map_groups *mg, struct machine *machine) 443void map_groups__init(struct map_groups *mg, struct machine *machine)
@@ -466,21 +464,10 @@ static void __maps__purge(struct maps *maps)
466 } 464 }
467} 465}
468 466
469static void __maps__purge_removed_maps(struct maps *maps)
470{
471 struct map *pos, *n;
472
473 list_for_each_entry_safe(pos, n, &maps->removed_maps, node) {
474 list_del_init(&pos->node);
475 map__put(pos);
476 }
477}
478
479static void maps__exit(struct maps *maps) 467static void maps__exit(struct maps *maps)
480{ 468{
481 pthread_rwlock_wrlock(&maps->lock); 469 pthread_rwlock_wrlock(&maps->lock);
482 __maps__purge(maps); 470 __maps__purge(maps);
483 __maps__purge_removed_maps(maps);
484 pthread_rwlock_unlock(&maps->lock); 471 pthread_rwlock_unlock(&maps->lock);
485} 472}
486 473
@@ -499,8 +486,6 @@ bool map_groups__empty(struct map_groups *mg)
499 for (i = 0; i < MAP__NR_TYPES; ++i) { 486 for (i = 0; i < MAP__NR_TYPES; ++i) {
500 if (maps__first(&mg->maps[i])) 487 if (maps__first(&mg->maps[i]))
501 return false; 488 return false;
502 if (!list_empty(&mg->maps[i].removed_maps))
503 return false;
504 } 489 }
505 490
506 return true; 491 return true;
@@ -621,7 +606,7 @@ size_t __map_groups__fprintf_maps(struct map_groups *mg, enum map_type type,
621 return printed += maps__fprintf(&mg->maps[type], fp); 606 return printed += maps__fprintf(&mg->maps[type], fp);
622} 607}
623 608
624static size_t map_groups__fprintf_maps(struct map_groups *mg, FILE *fp) 609size_t map_groups__fprintf(struct map_groups *mg, FILE *fp)
625{ 610{
626 size_t printed = 0, i; 611 size_t printed = 0, i;
627 for (i = 0; i < MAP__NR_TYPES; ++i) 612 for (i = 0; i < MAP__NR_TYPES; ++i)
@@ -629,39 +614,6 @@ static size_t map_groups__fprintf_maps(struct map_groups *mg, FILE *fp)
629 return printed; 614 return printed;
630} 615}
631 616
632static size_t __map_groups__fprintf_removed_maps(struct map_groups *mg,
633 enum map_type type, FILE *fp)
634{
635 struct map *pos;
636 size_t printed = 0;
637
638 list_for_each_entry(pos, &mg->maps[type].removed_maps, node) {
639 printed += fprintf(fp, "Map:");
640 printed += map__fprintf(pos, fp);
641 if (verbose > 1) {
642 printed += dso__fprintf(pos->dso, type, fp);
643 printed += fprintf(fp, "--\n");
644 }
645 }
646 return printed;
647}
648
649static size_t map_groups__fprintf_removed_maps(struct map_groups *mg,
650 FILE *fp)
651{
652 size_t printed = 0, i;
653 for (i = 0; i < MAP__NR_TYPES; ++i)
654 printed += __map_groups__fprintf_removed_maps(mg, i, fp);
655 return printed;
656}
657
658size_t map_groups__fprintf(struct map_groups *mg, FILE *fp)
659{
660 size_t printed = map_groups__fprintf_maps(mg, fp);
661 printed += fprintf(fp, "Removed maps:\n");
662 return printed + map_groups__fprintf_removed_maps(mg, fp);
663}
664
665static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp) 617static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp)
666{ 618{
667 struct rb_root *root; 619 struct rb_root *root;
@@ -719,13 +671,7 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp
719 map__fprintf(after, fp); 671 map__fprintf(after, fp);
720 } 672 }
721put_map: 673put_map:
722 /* 674 map__put(pos);
723 * If we have references, just move them to a separate list.
724 */
725 if (pos->referenced)
726 list_add_tail(&pos->node, &maps->removed_maps);
727 else
728 map__put(pos);
729 675
730 if (err) 676 if (err)
731 goto out; 677 goto out;
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index b8df09d94aca..d73e687b224e 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -34,7 +34,6 @@ struct map {
34 u64 start; 34 u64 start;
35 u64 end; 35 u64 end;
36 u8 /* enum map_type */ type; 36 u8 /* enum map_type */ type;
37 bool referenced;
38 bool erange_warned; 37 bool erange_warned;
39 u32 priv; 38 u32 priv;
40 u32 prot; 39 u32 prot;
@@ -63,7 +62,6 @@ struct kmap {
63struct maps { 62struct maps {
64 struct rb_root entries; 63 struct rb_root entries;
65 pthread_rwlock_t lock; 64 pthread_rwlock_t lock;
66 struct list_head removed_maps;
67}; 65};
68 66
69struct map_groups { 67struct map_groups {
@@ -161,6 +159,14 @@ static inline struct map *map__get(struct map *map)
161 159
162void map__put(struct map *map); 160void map__put(struct map *map);
163 161
162static inline void __map__zput(struct map **map)
163{
164 map__put(*map);
165 *map = NULL;
166}
167
168#define map__zput(map) __map__zput(&map)
169
164int map__overlap(struct map *l, struct map *r); 170int map__overlap(struct map *l, struct map *r);
165size_t map__fprintf(struct map *map, FILE *fp); 171size_t map__fprintf(struct map *map, FILE *fp);
166size_t map__fprintf_dsoname(struct map *map, FILE *fp); 172size_t map__fprintf_dsoname(struct map *map, FILE *fp);
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index d4cf50b91839..076527b639bd 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -246,6 +246,20 @@ static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
246 clear_probe_trace_event(tevs + i); 246 clear_probe_trace_event(tevs + i);
247} 247}
248 248
249static bool kprobe_blacklist__listed(unsigned long address);
250static bool kprobe_warn_out_range(const char *symbol, unsigned long address)
251{
252 /* Get the address of _etext for checking non-probable text symbol */
253 if (kernel_get_symbol_address_by_name("_etext", false) < address)
254 pr_warning("%s is out of .text, skip it.\n", symbol);
255 else if (kprobe_blacklist__listed(address))
256 pr_warning("%s is blacklisted function, skip it.\n", symbol);
257 else
258 return false;
259
260 return true;
261}
262
249#ifdef HAVE_DWARF_SUPPORT 263#ifdef HAVE_DWARF_SUPPORT
250 264
251static int kernel_get_module_dso(const char *module, struct dso **pdso) 265static int kernel_get_module_dso(const char *module, struct dso **pdso)
@@ -415,6 +429,41 @@ static struct debuginfo *open_debuginfo(const char *module, bool silent)
415 return ret; 429 return ret;
416} 430}
417 431
432/* For caching the last debuginfo */
433static struct debuginfo *debuginfo_cache;
434static char *debuginfo_cache_path;
435
436static struct debuginfo *debuginfo_cache__open(const char *module, bool silent)
437{
438 if ((debuginfo_cache_path && !strcmp(debuginfo_cache_path, module)) ||
439 (!debuginfo_cache_path && !module && debuginfo_cache))
440 goto out;
441
442 /* Copy module path */
443 free(debuginfo_cache_path);
444 if (module) {
445 debuginfo_cache_path = strdup(module);
446 if (!debuginfo_cache_path) {
447 debuginfo__delete(debuginfo_cache);
448 debuginfo_cache = NULL;
449 goto out;
450 }
451 }
452
453 debuginfo_cache = open_debuginfo(module, silent);
454 if (!debuginfo_cache)
455 zfree(&debuginfo_cache_path);
456out:
457 return debuginfo_cache;
458}
459
460static void debuginfo_cache__exit(void)
461{
462 debuginfo__delete(debuginfo_cache);
463 debuginfo_cache = NULL;
464 zfree(&debuginfo_cache_path);
465}
466
418 467
419static int get_text_start_address(const char *exec, unsigned long *address) 468static int get_text_start_address(const char *exec, unsigned long *address)
420{ 469{
@@ -476,12 +525,11 @@ static int find_perf_probe_point_from_dwarf(struct probe_trace_point *tp,
476 pr_debug("try to find information at %" PRIx64 " in %s\n", addr, 525 pr_debug("try to find information at %" PRIx64 " in %s\n", addr,
477 tp->module ? : "kernel"); 526 tp->module ? : "kernel");
478 527
479 dinfo = open_debuginfo(tp->module, verbose == 0); 528 dinfo = debuginfo_cache__open(tp->module, verbose == 0);
480 if (dinfo) { 529 if (dinfo)
481 ret = debuginfo__find_probe_point(dinfo, 530 ret = debuginfo__find_probe_point(dinfo,
482 (unsigned long)addr, pp); 531 (unsigned long)addr, pp);
483 debuginfo__delete(dinfo); 532 else
484 } else
485 ret = -ENOENT; 533 ret = -ENOENT;
486 534
487 if (ret > 0) { 535 if (ret > 0) {
@@ -559,7 +607,6 @@ static int post_process_probe_trace_events(struct probe_trace_event *tevs,
559 bool uprobe) 607 bool uprobe)
560{ 608{
561 struct ref_reloc_sym *reloc_sym; 609 struct ref_reloc_sym *reloc_sym;
562 u64 etext_addr;
563 char *tmp; 610 char *tmp;
564 int i, skipped = 0; 611 int i, skipped = 0;
565 612
@@ -575,31 +622,28 @@ static int post_process_probe_trace_events(struct probe_trace_event *tevs,
575 pr_warning("Relocated base symbol is not found!\n"); 622 pr_warning("Relocated base symbol is not found!\n");
576 return -EINVAL; 623 return -EINVAL;
577 } 624 }
578 /* Get the address of _etext for checking non-probable text symbol */
579 etext_addr = kernel_get_symbol_address_by_name("_etext", false);
580 625
581 for (i = 0; i < ntevs; i++) { 626 for (i = 0; i < ntevs; i++) {
582 if (tevs[i].point.address && !tevs[i].point.retprobe) { 627 if (!tevs[i].point.address || tevs[i].point.retprobe)
583 /* If we found a wrong one, mark it by NULL symbol */ 628 continue;
584 if (etext_addr < tevs[i].point.address) { 629 /* If we found a wrong one, mark it by NULL symbol */
585 pr_warning("%s+%lu is out of .text, skip it.\n", 630 if (kprobe_warn_out_range(tevs[i].point.symbol,
586 tevs[i].point.symbol, tevs[i].point.offset); 631 tevs[i].point.address)) {
587 tmp = NULL; 632 tmp = NULL;
588 skipped++; 633 skipped++;
589 } else { 634 } else {
590 tmp = strdup(reloc_sym->name); 635 tmp = strdup(reloc_sym->name);
591 if (!tmp) 636 if (!tmp)
592 return -ENOMEM; 637 return -ENOMEM;
593 }
594 /* If we have no realname, use symbol for it */
595 if (!tevs[i].point.realname)
596 tevs[i].point.realname = tevs[i].point.symbol;
597 else
598 free(tevs[i].point.symbol);
599 tevs[i].point.symbol = tmp;
600 tevs[i].point.offset = tevs[i].point.address -
601 reloc_sym->unrelocated_addr;
602 } 638 }
639 /* If we have no realname, use symbol for it */
640 if (!tevs[i].point.realname)
641 tevs[i].point.realname = tevs[i].point.symbol;
642 else
643 free(tevs[i].point.symbol);
644 tevs[i].point.symbol = tmp;
645 tevs[i].point.offset = tevs[i].point.address -
646 reloc_sym->unrelocated_addr;
603 } 647 }
604 return skipped; 648 return skipped;
605} 649}
@@ -920,6 +964,10 @@ out:
920 964
921#else /* !HAVE_DWARF_SUPPORT */ 965#else /* !HAVE_DWARF_SUPPORT */
922 966
967static void debuginfo_cache__exit(void)
968{
969}
970
923static int 971static int
924find_perf_probe_point_from_dwarf(struct probe_trace_point *tp __maybe_unused, 972find_perf_probe_point_from_dwarf(struct probe_trace_point *tp __maybe_unused,
925 struct perf_probe_point *pp __maybe_unused, 973 struct perf_probe_point *pp __maybe_unused,
@@ -2126,9 +2174,31 @@ kprobe_blacklist__find_by_address(struct list_head *blacklist,
2126 return NULL; 2174 return NULL;
2127} 2175}
2128 2176
2129/* Show an event */ 2177static LIST_HEAD(kprobe_blacklist);
2130static int show_perf_probe_event(struct perf_probe_event *pev, 2178
2131 const char *module) 2179static void kprobe_blacklist__init(void)
2180{
2181 if (!list_empty(&kprobe_blacklist))
2182 return;
2183
2184 if (kprobe_blacklist__load(&kprobe_blacklist) < 0)
2185 pr_debug("No kprobe blacklist support, ignored\n");
2186}
2187
2188static void kprobe_blacklist__release(void)
2189{
2190 kprobe_blacklist__delete(&kprobe_blacklist);
2191}
2192
2193static bool kprobe_blacklist__listed(unsigned long address)
2194{
2195 return !!kprobe_blacklist__find_by_address(&kprobe_blacklist, address);
2196}
2197
2198static int perf_probe_event__sprintf(const char *group, const char *event,
2199 struct perf_probe_event *pev,
2200 const char *module,
2201 struct strbuf *result)
2132{ 2202{
2133 int i, ret; 2203 int i, ret;
2134 char buf[128]; 2204 char buf[128];
@@ -2139,29 +2209,50 @@ static int show_perf_probe_event(struct perf_probe_event *pev,
2139 if (!place) 2209 if (!place)
2140 return -EINVAL; 2210 return -EINVAL;
2141 2211
2142 ret = e_snprintf(buf, 128, "%s:%s", pev->group, pev->event); 2212 ret = e_snprintf(buf, 128, "%s:%s", group, event);
2143 if (ret < 0) 2213 if (ret < 0)
2144 return ret; 2214 goto out;
2145 2215
2146 pr_info(" %-20s (on %s", buf, place); 2216 strbuf_addf(result, " %-20s (on %s", buf, place);
2147 if (module) 2217 if (module)
2148 pr_info(" in %s", module); 2218 strbuf_addf(result, " in %s", module);
2149 2219
2150 if (pev->nargs > 0) { 2220 if (pev->nargs > 0) {
2151 pr_info(" with"); 2221 strbuf_addstr(result, " with");
2152 for (i = 0; i < pev->nargs; i++) { 2222 for (i = 0; i < pev->nargs; i++) {
2153 ret = synthesize_perf_probe_arg(&pev->args[i], 2223 ret = synthesize_perf_probe_arg(&pev->args[i],
2154 buf, 128); 2224 buf, 128);
2155 if (ret < 0) 2225 if (ret < 0)
2156 break; 2226 goto out;
2157 pr_info(" %s", buf); 2227 strbuf_addf(result, " %s", buf);
2158 } 2228 }
2159 } 2229 }
2160 pr_info(")\n"); 2230 strbuf_addch(result, ')');
2231out:
2161 free(place); 2232 free(place);
2162 return ret; 2233 return ret;
2163} 2234}
2164 2235
2236/* Show an event */
2237static int show_perf_probe_event(const char *group, const char *event,
2238 struct perf_probe_event *pev,
2239 const char *module, bool use_stdout)
2240{
2241 struct strbuf buf = STRBUF_INIT;
2242 int ret;
2243
2244 ret = perf_probe_event__sprintf(group, event, pev, module, &buf);
2245 if (ret >= 0) {
2246 if (use_stdout)
2247 printf("%s\n", buf.buf);
2248 else
2249 pr_info("%s\n", buf.buf);
2250 }
2251 strbuf_release(&buf);
2252
2253 return ret;
2254}
2255
2165static bool filter_probe_trace_event(struct probe_trace_event *tev, 2256static bool filter_probe_trace_event(struct probe_trace_event *tev,
2166 struct strfilter *filter) 2257 struct strfilter *filter)
2167{ 2258{
@@ -2200,9 +2291,11 @@ static int __show_perf_probe_events(int fd, bool is_kprobe,
2200 goto next; 2291 goto next;
2201 ret = convert_to_perf_probe_event(&tev, &pev, 2292 ret = convert_to_perf_probe_event(&tev, &pev,
2202 is_kprobe); 2293 is_kprobe);
2203 if (ret >= 0) 2294 if (ret < 0)
2204 ret = show_perf_probe_event(&pev, 2295 goto next;
2205 tev.point.module); 2296 ret = show_perf_probe_event(pev.group, pev.event,
2297 &pev, tev.point.module,
2298 true);
2206 } 2299 }
2207next: 2300next:
2208 clear_perf_probe_event(&pev); 2301 clear_perf_probe_event(&pev);
@@ -2211,6 +2304,8 @@ next:
2211 break; 2304 break;
2212 } 2305 }
2213 strlist__delete(rawlist); 2306 strlist__delete(rawlist);
2307 /* Cleanup cached debuginfo if needed */
2308 debuginfo_cache__exit();
2214 2309
2215 return ret; 2310 return ret;
2216} 2311}
@@ -2316,6 +2411,7 @@ static int get_new_event_name(char *buf, size_t len, const char *base,
2316 struct strlist *namelist, bool allow_suffix) 2411 struct strlist *namelist, bool allow_suffix)
2317{ 2412{
2318 int i, ret; 2413 int i, ret;
2414 char *p;
2319 2415
2320 if (*base == '.') 2416 if (*base == '.')
2321 base++; 2417 base++;
@@ -2326,6 +2422,10 @@ static int get_new_event_name(char *buf, size_t len, const char *base,
2326 pr_debug("snprintf() failed: %d\n", ret); 2422 pr_debug("snprintf() failed: %d\n", ret);
2327 return ret; 2423 return ret;
2328 } 2424 }
2425 /* Cut off the postfixes (e.g. .const, .isra)*/
2426 p = strchr(buf, '.');
2427 if (p && p != buf)
2428 *p = '\0';
2329 if (!strlist__has_entry(namelist, buf)) 2429 if (!strlist__has_entry(namelist, buf))
2330 return 0; 2430 return 0;
2331 2431
@@ -2381,10 +2481,8 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2381 int i, fd, ret; 2481 int i, fd, ret;
2382 struct probe_trace_event *tev = NULL; 2482 struct probe_trace_event *tev = NULL;
2383 char buf[64]; 2483 char buf[64];
2384 const char *event, *group; 2484 const char *event = NULL, *group = NULL;
2385 struct strlist *namelist; 2485 struct strlist *namelist;
2386 LIST_HEAD(blacklist);
2387 struct kprobe_blacklist_node *node;
2388 bool safename; 2486 bool safename;
2389 2487
2390 if (pev->uprobes) 2488 if (pev->uprobes)
@@ -2404,28 +2502,15 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2404 ret = -ENOMEM; 2502 ret = -ENOMEM;
2405 goto close_out; 2503 goto close_out;
2406 } 2504 }
2407 /* Get kprobe blacklist if exists */
2408 if (!pev->uprobes) {
2409 ret = kprobe_blacklist__load(&blacklist);
2410 if (ret < 0)
2411 pr_debug("No kprobe blacklist support, ignored\n");
2412 }
2413 2505
2414 safename = (pev->point.function && !strisglob(pev->point.function)); 2506 safename = (pev->point.function && !strisglob(pev->point.function));
2415 ret = 0; 2507 ret = 0;
2416 pr_info("Added new event%s\n", (ntevs > 1) ? "s:" : ":"); 2508 pr_info("Added new event%s\n", (ntevs > 1) ? "s:" : ":");
2417 for (i = 0; i < ntevs; i++) { 2509 for (i = 0; i < ntevs; i++) {
2418 tev = &tevs[i]; 2510 tev = &tevs[i];
2419 /* Skip if the symbol is out of .text (marked previously) */ 2511 /* Skip if the symbol is out of .text or blacklisted */
2420 if (!tev->point.symbol) 2512 if (!tev->point.symbol)
2421 continue; 2513 continue;
2422 /* Ensure that the address is NOT blacklisted */
2423 node = kprobe_blacklist__find_by_address(&blacklist,
2424 tev->point.address);
2425 if (node) {
2426 pr_warning("Warning: Skipped probing on blacklisted function: %s\n", node->symbol);
2427 continue;
2428 }
2429 2514
2430 if (pev->event) 2515 if (pev->event)
2431 event = pev->event; 2516 event = pev->event;
@@ -2458,15 +2543,12 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2458 /* Add added event name to namelist */ 2543 /* Add added event name to namelist */
2459 strlist__add(namelist, event); 2544 strlist__add(namelist, event);
2460 2545
2461 /* Trick here - save current event/group */ 2546 /* We use tev's name for showing new events */
2462 event = pev->event; 2547 show_perf_probe_event(tev->group, tev->event, pev,
2463 group = pev->group; 2548 tev->point.module, false);
2464 pev->event = tev->event; 2549 /* Save the last valid name */
2465 pev->group = tev->group; 2550 event = tev->event;
2466 show_perf_probe_event(pev, tev->point.module); 2551 group = tev->group;
2467 /* Trick here - restore current event/group */
2468 pev->event = (char *)event;
2469 pev->group = (char *)group;
2470 2552
2471 /* 2553 /*
2472 * Probes after the first probe which comes from same 2554 * Probes after the first probe which comes from same
@@ -2480,14 +2562,12 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2480 warn_uprobe_event_compat(tev); 2562 warn_uprobe_event_compat(tev);
2481 2563
2482 /* Note that it is possible to skip all events because of blacklist */ 2564 /* Note that it is possible to skip all events because of blacklist */
2483 if (ret >= 0 && tev->event) { 2565 if (ret >= 0 && event) {
2484 /* Show how to use the event. */ 2566 /* Show how to use the event. */
2485 pr_info("\nYou can now use it in all perf tools, such as:\n\n"); 2567 pr_info("\nYou can now use it in all perf tools, such as:\n\n");
2486 pr_info("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group, 2568 pr_info("\tperf record -e %s:%s -aR sleep 1\n\n", group, event);
2487 tev->event);
2488 } 2569 }
2489 2570
2490 kprobe_blacklist__delete(&blacklist);
2491 strlist__delete(namelist); 2571 strlist__delete(namelist);
2492close_out: 2572close_out:
2493 close(fd); 2573 close(fd);
@@ -2537,7 +2617,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2537 struct perf_probe_point *pp = &pev->point; 2617 struct perf_probe_point *pp = &pev->point;
2538 struct probe_trace_point *tp; 2618 struct probe_trace_point *tp;
2539 int num_matched_functions; 2619 int num_matched_functions;
2540 int ret, i, j; 2620 int ret, i, j, skipped = 0;
2541 2621
2542 map = get_target_map(pev->target, pev->uprobes); 2622 map = get_target_map(pev->target, pev->uprobes);
2543 if (!map) { 2623 if (!map) {
@@ -2605,7 +2685,12 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2605 } 2685 }
2606 /* Add one probe point */ 2686 /* Add one probe point */
2607 tp->address = map->unmap_ip(map, sym->start) + pp->offset; 2687 tp->address = map->unmap_ip(map, sym->start) + pp->offset;
2608 if (reloc_sym) { 2688 /* If we found a wrong one, mark it by NULL symbol */
2689 if (!pev->uprobes &&
2690 kprobe_warn_out_range(sym->name, tp->address)) {
2691 tp->symbol = NULL; /* Skip it */
2692 skipped++;
2693 } else if (reloc_sym) {
2609 tp->symbol = strdup_or_goto(reloc_sym->name, nomem_out); 2694 tp->symbol = strdup_or_goto(reloc_sym->name, nomem_out);
2610 tp->offset = tp->address - reloc_sym->addr; 2695 tp->offset = tp->address - reloc_sym->addr;
2611 } else { 2696 } else {
@@ -2641,6 +2726,10 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2641 } 2726 }
2642 arch__fix_tev_from_maps(pev, tev, map); 2727 arch__fix_tev_from_maps(pev, tev, map);
2643 } 2728 }
2729 if (ret == skipped) {
2730 ret = -ENOENT;
2731 goto err_out;
2732 }
2644 2733
2645out: 2734out:
2646 put_target_map(map, pev->uprobes); 2735 put_target_map(map, pev->uprobes);
@@ -2711,6 +2800,9 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs)
2711 /* Loop 1: convert all events */ 2800 /* Loop 1: convert all events */
2712 for (i = 0; i < npevs; i++) { 2801 for (i = 0; i < npevs; i++) {
2713 pkgs[i].pev = &pevs[i]; 2802 pkgs[i].pev = &pevs[i];
2803 /* Init kprobe blacklist if needed */
2804 if (!pkgs[i].pev->uprobes)
2805 kprobe_blacklist__init();
2714 /* Convert with or without debuginfo */ 2806 /* Convert with or without debuginfo */
2715 ret = convert_to_probe_trace_events(pkgs[i].pev, 2807 ret = convert_to_probe_trace_events(pkgs[i].pev,
2716 &pkgs[i].tevs); 2808 &pkgs[i].tevs);
@@ -2718,6 +2810,8 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs)
2718 goto end; 2810 goto end;
2719 pkgs[i].ntevs = ret; 2811 pkgs[i].ntevs = ret;
2720 } 2812 }
2813 /* This just release blacklist only if allocated */
2814 kprobe_blacklist__release();
2721 2815
2722 /* Loop 2: add all events */ 2816 /* Loop 2: add all events */
2723 for (i = 0; i < npevs; i++) { 2817 for (i = 0; i < npevs; i++) {
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
index 4d28624a1eca..5925fec90562 100644
--- a/tools/perf/util/python-ext-sources
+++ b/tools/perf/util/python-ext-sources
@@ -16,6 +16,7 @@ util/util.c
16util/xyarray.c 16util/xyarray.c
17util/cgroup.c 17util/cgroup.c
18util/rblist.c 18util/rblist.c
19util/stat.c
19util/strlist.c 20util/strlist.c
20util/trace-event.c 21util/trace-event.c
21../../lib/rbtree.c 22../../lib/rbtree.c
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index f31e024ddf7d..e1cd17c2afab 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -517,20 +517,42 @@ void perf_event__attr_swap(struct perf_event_attr *attr)
517{ 517{
518 attr->type = bswap_32(attr->type); 518 attr->type = bswap_32(attr->type);
519 attr->size = bswap_32(attr->size); 519 attr->size = bswap_32(attr->size);
520 attr->config = bswap_64(attr->config); 520
521 attr->sample_period = bswap_64(attr->sample_period); 521#define bswap_safe(f, n) \
522 attr->sample_type = bswap_64(attr->sample_type); 522 (attr->size > (offsetof(struct perf_event_attr, f) + \
523 attr->read_format = bswap_64(attr->read_format); 523 sizeof(attr->f) * (n)))
524 attr->wakeup_events = bswap_32(attr->wakeup_events); 524#define bswap_field(f, sz) \
525 attr->bp_type = bswap_32(attr->bp_type); 525do { \
526 attr->bp_addr = bswap_64(attr->bp_addr); 526 if (bswap_safe(f, 0)) \
527 attr->bp_len = bswap_64(attr->bp_len); 527 attr->f = bswap_##sz(attr->f); \
528 attr->branch_sample_type = bswap_64(attr->branch_sample_type); 528} while(0)
529 attr->sample_regs_user = bswap_64(attr->sample_regs_user); 529#define bswap_field_32(f) bswap_field(f, 32)
530 attr->sample_stack_user = bswap_32(attr->sample_stack_user); 530#define bswap_field_64(f) bswap_field(f, 64)
531 attr->aux_watermark = bswap_32(attr->aux_watermark); 531
532 532 bswap_field_64(config);
533 swap_bitfield((u8 *) (&attr->read_format + 1), sizeof(u64)); 533 bswap_field_64(sample_period);
534 bswap_field_64(sample_type);
535 bswap_field_64(read_format);
536 bswap_field_32(wakeup_events);
537 bswap_field_32(bp_type);
538 bswap_field_64(bp_addr);
539 bswap_field_64(bp_len);
540 bswap_field_64(branch_sample_type);
541 bswap_field_64(sample_regs_user);
542 bswap_field_32(sample_stack_user);
543 bswap_field_32(aux_watermark);
544
545 /*
546 * After read_format are bitfields. Check read_format because
547 * we are unable to use offsetof on bitfield.
548 */
549 if (bswap_safe(read_format, 1))
550 swap_bitfield((u8 *) (&attr->read_format + 1),
551 sizeof(u64));
552#undef bswap_field_64
553#undef bswap_field_32
554#undef bswap_field
555#undef bswap_safe
534} 556}
535 557
536static void perf_event__hdr_attr_swap(union perf_event *event, 558static void perf_event__hdr_attr_swap(union perf_event *event,
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 60b92822f655..4014b709f956 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -94,3 +94,39 @@ void perf_stat_evsel_id_init(struct perf_evsel *evsel)
94 } 94 }
95 } 95 }
96} 96}
97
98struct perf_counts *perf_counts__new(int ncpus)
99{
100 int size = sizeof(struct perf_counts) +
101 ncpus * sizeof(struct perf_counts_values);
102
103 return zalloc(size);
104}
105
106void perf_counts__delete(struct perf_counts *counts)
107{
108 free(counts);
109}
110
111static void perf_counts__reset(struct perf_counts *counts, int ncpus)
112{
113 memset(counts, 0, (sizeof(*counts) +
114 (ncpus * sizeof(struct perf_counts_values))));
115}
116
117void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus)
118{
119 perf_counts__reset(evsel->counts, ncpus);
120}
121
122int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus)
123{
124 evsel->counts = perf_counts__new(ncpus);
125 return evsel->counts != NULL ? 0 : -ENOMEM;
126}
127
128void perf_evsel__free_counts(struct perf_evsel *evsel)
129{
130 perf_counts__delete(evsel->counts);
131 evsel->counts = NULL;
132}
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 615c779eb42a..093dc3cb28dd 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -62,4 +62,10 @@ void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count,
62void perf_stat__print_shadow_stats(FILE *out, struct perf_evsel *evsel, 62void perf_stat__print_shadow_stats(FILE *out, struct perf_evsel *evsel,
63 double avg, int cpu, enum aggr_mode aggr); 63 double avg, int cpu, enum aggr_mode aggr);
64 64
65struct perf_counts *perf_counts__new(int ncpus);
66void perf_counts__delete(struct perf_counts *counts);
67
68void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus);
69int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus);
70void perf_evsel__free_counts(struct perf_evsel *evsel);
65#endif 71#endif
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index f93b9734735b..f4822bd03709 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -20,6 +20,15 @@ static int filter(const struct dirent *dir)
20 return 1; 20 return 1;
21} 21}
22 22
23static struct thread_map *thread_map__realloc(struct thread_map *map, int nr)
24{
25 size_t size = sizeof(*map) + sizeof(pid_t) * nr;
26
27 return realloc(map, size);
28}
29
30#define thread_map__alloc(__nr) thread_map__realloc(NULL, __nr)
31
23struct thread_map *thread_map__new_by_pid(pid_t pid) 32struct thread_map *thread_map__new_by_pid(pid_t pid)
24{ 33{
25 struct thread_map *threads; 34 struct thread_map *threads;
@@ -33,7 +42,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid)
33 if (items <= 0) 42 if (items <= 0)
34 return NULL; 43 return NULL;
35 44
36 threads = malloc(sizeof(*threads) + sizeof(pid_t) * items); 45 threads = thread_map__alloc(items);
37 if (threads != NULL) { 46 if (threads != NULL) {
38 for (i = 0; i < items; i++) 47 for (i = 0; i < items; i++)
39 threads->map[i] = atoi(namelist[i]->d_name); 48 threads->map[i] = atoi(namelist[i]->d_name);
@@ -49,7 +58,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid)
49 58
50struct thread_map *thread_map__new_by_tid(pid_t tid) 59struct thread_map *thread_map__new_by_tid(pid_t tid)
51{ 60{
52 struct thread_map *threads = malloc(sizeof(*threads) + sizeof(pid_t)); 61 struct thread_map *threads = thread_map__alloc(1);
53 62
54 if (threads != NULL) { 63 if (threads != NULL) {
55 threads->map[0] = tid; 64 threads->map[0] = tid;
@@ -65,8 +74,8 @@ struct thread_map *thread_map__new_by_uid(uid_t uid)
65 int max_threads = 32, items, i; 74 int max_threads = 32, items, i;
66 char path[256]; 75 char path[256];
67 struct dirent dirent, *next, **namelist = NULL; 76 struct dirent dirent, *next, **namelist = NULL;
68 struct thread_map *threads = malloc(sizeof(*threads) + 77 struct thread_map *threads = thread_map__alloc(max_threads);
69 max_threads * sizeof(pid_t)); 78
70 if (threads == NULL) 79 if (threads == NULL)
71 goto out; 80 goto out;
72 81
@@ -185,8 +194,7 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str)
185 goto out_free_threads; 194 goto out_free_threads;
186 195
187 total_tasks += items; 196 total_tasks += items;
188 nt = realloc(threads, (sizeof(*threads) + 197 nt = thread_map__realloc(threads, total_tasks);
189 sizeof(pid_t) * total_tasks));
190 if (nt == NULL) 198 if (nt == NULL)
191 goto out_free_namelist; 199 goto out_free_namelist;
192 200
@@ -216,7 +224,7 @@ out_free_threads:
216 224
217struct thread_map *thread_map__new_dummy(void) 225struct thread_map *thread_map__new_dummy(void)
218{ 226{
219 struct thread_map *threads = malloc(sizeof(*threads) + sizeof(pid_t)); 227 struct thread_map *threads = thread_map__alloc(1);
220 228
221 if (threads != NULL) { 229 if (threads != NULL) {
222 threads->map[0] = -1; 230 threads->map[0] = -1;
@@ -253,7 +261,7 @@ static struct thread_map *thread_map__new_by_tid_str(const char *tid_str)
253 continue; 261 continue;
254 262
255 ntasks++; 263 ntasks++;
256 nt = realloc(threads, sizeof(*threads) + sizeof(pid_t) * ntasks); 264 nt = thread_map__realloc(threads, ntasks);
257 265
258 if (nt == NULL) 266 if (nt == NULL)
259 goto out_free_threads; 267 goto out_free_threads;
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c
index f079b63f0b7f..4c00507ee3fd 100644
--- a/tools/perf/util/unwind-libunwind.c
+++ b/tools/perf/util/unwind-libunwind.c
@@ -360,7 +360,7 @@ find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
360 unw_word_t base = is_exec ? 0 : map->start; 360 unw_word_t base = is_exec ? 0 : map->start;
361 361
362 if (fd >= 0) 362 if (fd >= 0)
363 dso__data_put_fd(dso); 363 dso__data_put_fd(map->dso);
364 364
365 memset(&di, 0, sizeof(di)); 365 memset(&di, 0, sizeof(di));
366 if (dwarf_find_debug_frame(0, &di, ip, base, map->dso->name, 366 if (dwarf_find_debug_frame(0, &di, ip, base, map->dso->name,
diff --git a/tools/perf/util/xyarray.c b/tools/perf/util/xyarray.c
index 22afbf6c536a..c10ba41ef3f6 100644
--- a/tools/perf/util/xyarray.c
+++ b/tools/perf/util/xyarray.c
@@ -9,11 +9,19 @@ struct xyarray *xyarray__new(int xlen, int ylen, size_t entry_size)
9 if (xy != NULL) { 9 if (xy != NULL) {
10 xy->entry_size = entry_size; 10 xy->entry_size = entry_size;
11 xy->row_size = row_size; 11 xy->row_size = row_size;
12 xy->entries = xlen * ylen;
12 } 13 }
13 14
14 return xy; 15 return xy;
15} 16}
16 17
18void xyarray__reset(struct xyarray *xy)
19{
20 size_t n = xy->entries * xy->entry_size;
21
22 memset(xy->contents, 0, n);
23}
24
17void xyarray__delete(struct xyarray *xy) 25void xyarray__delete(struct xyarray *xy)
18{ 26{
19 free(xy); 27 free(xy);
diff --git a/tools/perf/util/xyarray.h b/tools/perf/util/xyarray.h
index c488a07275dd..7f30af371b7e 100644
--- a/tools/perf/util/xyarray.h
+++ b/tools/perf/util/xyarray.h
@@ -6,11 +6,13 @@
6struct xyarray { 6struct xyarray {
7 size_t row_size; 7 size_t row_size;
8 size_t entry_size; 8 size_t entry_size;
9 size_t entries;
9 char contents[]; 10 char contents[];
10}; 11};
11 12
12struct xyarray *xyarray__new(int xlen, int ylen, size_t entry_size); 13struct xyarray *xyarray__new(int xlen, int ylen, size_t entry_size);
13void xyarray__delete(struct xyarray *xy); 14void xyarray__delete(struct xyarray *xy);
15void xyarray__reset(struct xyarray *xy);
14 16
15static inline void *xyarray__entry(struct xyarray *xy, int x, int y) 17static inline void *xyarray__entry(struct xyarray *xy, int x, int y)
16{ 18{