aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2011-06-04 06:13:06 -0400
committerIngo Molnar <mingo@elte.hu>2011-06-04 06:13:06 -0400
commit710054ba25c0d1f8f41c22ce13ba336503fb5318 (patch)
treef9b09b722bf511841539173d946f90a20fc2e59a /tools/perf/util
parent74c355fbdfedd3820046dba4f537876cea54c207 (diff)
parentb273fa9716aa1564bee88ceee62f9042981cdc81 (diff)
Merge branch 'perf/urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/event.c31
-rw-r--r--tools/perf/util/event.h2
-rw-r--r--tools/perf/util/evlist.c68
-rw-r--r--tools/perf/util/evlist.h6
-rw-r--r--tools/perf/util/evsel.c26
-rw-r--r--tools/perf/util/evsel.h7
-rw-r--r--tools/perf/util/header.c8
-rw-r--r--tools/perf/util/include/linux/const.h1
-rw-r--r--tools/perf/util/python.c14
-rw-r--r--tools/perf/util/session.c12
-rw-r--r--tools/perf/util/symbol.c48
-rw-r--r--tools/perf/util/symbol.h3
12 files changed, 161 insertions, 65 deletions
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 6635fcd11ca5..3c1b8a632101 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -35,22 +35,6 @@ const char *perf_event__name(unsigned int id)
35 return perf_event__names[id]; 35 return perf_event__names[id];
36} 36}
37 37
38int perf_sample_size(u64 sample_type)
39{
40 u64 mask = sample_type & PERF_SAMPLE_MASK;
41 int size = 0;
42 int i;
43
44 for (i = 0; i < 64; i++) {
45 if (mask & (1ULL << i))
46 size++;
47 }
48
49 size *= sizeof(u64);
50
51 return size;
52}
53
54static struct perf_sample synth_sample = { 38static struct perf_sample synth_sample = {
55 .pid = -1, 39 .pid = -1,
56 .tid = -1, 40 .tid = -1,
@@ -553,9 +537,18 @@ static int perf_event__process_kernel_mmap(union perf_event *event,
553 goto out_problem; 537 goto out_problem;
554 538
555 perf_event__set_kernel_mmap_len(event, machine->vmlinux_maps); 539 perf_event__set_kernel_mmap_len(event, machine->vmlinux_maps);
556 perf_session__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, 540
557 symbol_name, 541 /*
558 event->mmap.pgoff); 542 * Avoid using a zero address (kptr_restrict) for the ref reloc
543 * symbol. Effectively having zero here means that at record
544 * time /proc/sys/kernel/kptr_restrict was non zero.
545 */
546 if (event->mmap.pgoff != 0) {
547 perf_session__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps,
548 symbol_name,
549 event->mmap.pgoff);
550 }
551
559 if (machine__is_default_guest(machine)) { 552 if (machine__is_default_guest(machine)) {
560 /* 553 /*
561 * preload dso of guest kernel and modules 554 * preload dso of guest kernel and modules
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index c08332871408..1d7f66488a88 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -82,8 +82,6 @@ struct perf_sample {
82 struct ip_callchain *callchain; 82 struct ip_callchain *callchain;
83}; 83};
84 84
85int perf_sample_size(u64 sample_type);
86
87#define BUILD_ID_SIZE 20 85#define BUILD_ID_SIZE 20
88 86
89struct build_id_event { 87struct build_id_event {
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 50aa34879c33..b021ea9265c3 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -12,7 +12,6 @@
12#include "evlist.h" 12#include "evlist.h"
13#include "evsel.h" 13#include "evsel.h"
14#include "util.h" 14#include "util.h"
15#include "debug.h"
16 15
17#include <sys/mman.h> 16#include <sys/mman.h>
18 17
@@ -257,19 +256,15 @@ int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
257 return evlist->mmap != NULL ? 0 : -ENOMEM; 256 return evlist->mmap != NULL ? 0 : -ENOMEM;
258} 257}
259 258
260static int __perf_evlist__mmap(struct perf_evlist *evlist, struct perf_evsel *evsel, 259static int __perf_evlist__mmap(struct perf_evlist *evlist,
261 int idx, int prot, int mask, int fd) 260 int idx, int prot, int mask, int fd)
262{ 261{
263 evlist->mmap[idx].prev = 0; 262 evlist->mmap[idx].prev = 0;
264 evlist->mmap[idx].mask = mask; 263 evlist->mmap[idx].mask = mask;
265 evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, prot, 264 evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, prot,
266 MAP_SHARED, fd, 0); 265 MAP_SHARED, fd, 0);
267 if (evlist->mmap[idx].base == MAP_FAILED) { 266 if (evlist->mmap[idx].base == MAP_FAILED)
268 if (evlist->cpus->map[idx] == -1 && evsel->attr.inherit)
269 ui__warning("Inherit is not allowed on per-task "
270 "events using mmap.\n");
271 return -1; 267 return -1;
272 }
273 268
274 perf_evlist__add_pollfd(evlist, fd); 269 perf_evlist__add_pollfd(evlist, fd);
275 return 0; 270 return 0;
@@ -289,7 +284,7 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot, int m
289 284
290 if (output == -1) { 285 if (output == -1) {
291 output = fd; 286 output = fd;
292 if (__perf_evlist__mmap(evlist, evsel, cpu, 287 if (__perf_evlist__mmap(evlist, cpu,
293 prot, mask, output) < 0) 288 prot, mask, output) < 0)
294 goto out_unmap; 289 goto out_unmap;
295 } else { 290 } else {
@@ -329,7 +324,7 @@ static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot, in
329 324
330 if (output == -1) { 325 if (output == -1) {
331 output = fd; 326 output = fd;
332 if (__perf_evlist__mmap(evlist, evsel, thread, 327 if (__perf_evlist__mmap(evlist, thread,
333 prot, mask, output) < 0) 328 prot, mask, output) < 0)
334 goto out_unmap; 329 goto out_unmap;
335 } else { 330 } else {
@@ -460,33 +455,46 @@ int perf_evlist__set_filters(struct perf_evlist *evlist)
460 return 0; 455 return 0;
461} 456}
462 457
463u64 perf_evlist__sample_type(struct perf_evlist *evlist) 458bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist)
464{ 459{
465 struct perf_evsel *pos; 460 struct perf_evsel *pos, *first;
466 u64 type = 0; 461
467 462 pos = first = list_entry(evlist->entries.next, struct perf_evsel, node);
468 list_for_each_entry(pos, &evlist->entries, node) { 463
469 if (!type) 464 list_for_each_entry_continue(pos, &evlist->entries, node) {
470 type = pos->attr.sample_type; 465 if (first->attr.sample_type != pos->attr.sample_type)
471 else if (type != pos->attr.sample_type) 466 return false;
472 die("non matching sample_type");
473 } 467 }
474 468
475 return type; 469 return true;
476} 470}
477 471
478bool perf_evlist__sample_id_all(const struct perf_evlist *evlist) 472u64 perf_evlist__sample_type(const struct perf_evlist *evlist)
473{
474 struct perf_evsel *first;
475
476 first = list_entry(evlist->entries.next, struct perf_evsel, node);
477 return first->attr.sample_type;
478}
479
480bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist)
479{ 481{
480 bool value = false, first = true; 482 struct perf_evsel *pos, *first;
481 struct perf_evsel *pos; 483
482 484 pos = first = list_entry(evlist->entries.next, struct perf_evsel, node);
483 list_for_each_entry(pos, &evlist->entries, node) { 485
484 if (first) { 486 list_for_each_entry_continue(pos, &evlist->entries, node) {
485 value = pos->attr.sample_id_all; 487 if (first->attr.sample_id_all != pos->attr.sample_id_all)
486 first = false; 488 return false;
487 } else if (value != pos->attr.sample_id_all)
488 die("non matching sample_id_all");
489 } 489 }
490 490
491 return value; 491 return true;
492}
493
494bool perf_evlist__sample_id_all(const struct perf_evlist *evlist)
495{
496 struct perf_evsel *first;
497
498 first = list_entry(evlist->entries.next, struct perf_evsel, node);
499 return first->attr.sample_id_all;
492} 500}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 0a1ef1f051f0..b2b862374f37 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -66,7 +66,9 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid,
66void perf_evlist__delete_maps(struct perf_evlist *evlist); 66void perf_evlist__delete_maps(struct perf_evlist *evlist);
67int perf_evlist__set_filters(struct perf_evlist *evlist); 67int perf_evlist__set_filters(struct perf_evlist *evlist);
68 68
69u64 perf_evlist__sample_type(struct perf_evlist *evlist); 69u64 perf_evlist__sample_type(const struct perf_evlist *evlist);
70bool perf_evlist__sample_id_all(const struct perf_evlist *evlist); 70bool perf_evlist__sample_id_all(const const struct perf_evlist *evlist);
71 71
72bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist);
73bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist);
72#endif /* __PERF_EVLIST_H */ 74#endif /* __PERF_EVLIST_H */
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index ee0fe0dffa71..0239eb87b232 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -15,6 +15,22 @@
15 15
16#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 16#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
17 17
18int __perf_evsel__sample_size(u64 sample_type)
19{
20 u64 mask = sample_type & PERF_SAMPLE_MASK;
21 int size = 0;
22 int i;
23
24 for (i = 0; i < 64; i++) {
25 if (mask & (1ULL << i))
26 size++;
27 }
28
29 size *= sizeof(u64);
30
31 return size;
32}
33
18void perf_evsel__init(struct perf_evsel *evsel, 34void perf_evsel__init(struct perf_evsel *evsel,
19 struct perf_event_attr *attr, int idx) 35 struct perf_event_attr *attr, int idx)
20{ 36{
@@ -35,7 +51,17 @@ struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx)
35 51
36int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) 52int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
37{ 53{
54 int cpu, thread;
38 evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int)); 55 evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int));
56
57 if (evsel->fd) {
58 for (cpu = 0; cpu < ncpus; cpu++) {
59 for (thread = 0; thread < nthreads; thread++) {
60 FD(evsel, cpu, thread) = -1;
61 }
62 }
63 }
64
39 return evsel->fd != NULL ? 0 : -ENOMEM; 65 return evsel->fd != NULL ? 0 : -ENOMEM;
40} 66}
41 67
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index f79bb2c09a6c..7e9366e4490b 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -149,4 +149,11 @@ static inline int perf_evsel__read_scaled(struct perf_evsel *evsel,
149 return __perf_evsel__read(evsel, ncpus, nthreads, true); 149 return __perf_evsel__read(evsel, ncpus, nthreads, true);
150} 150}
151 151
152int __perf_evsel__sample_size(u64 sample_type);
153
154static inline int perf_evsel__sample_size(struct perf_evsel *evsel)
155{
156 return __perf_evsel__sample_size(evsel->attr.sample_type);
157}
158
152#endif /* __PERF_EVSEL_H */ 159#endif /* __PERF_EVSEL_H */
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 0717bebc7649..afb0849fe530 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -193,9 +193,13 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
193 *linkname = malloc(size), *targetname; 193 *linkname = malloc(size), *targetname;
194 int len, err = -1; 194 int len, err = -1;
195 195
196 if (is_kallsyms) 196 if (is_kallsyms) {
197 if (symbol_conf.kptr_restrict) {
198 pr_debug("Not caching a kptr_restrict'ed /proc/kallsyms\n");
199 return 0;
200 }
197 realname = (char *)name; 201 realname = (char *)name;
198 else 202 } else
199 realname = realpath(name, NULL); 203 realname = realpath(name, NULL);
200 204
201 if (realname == NULL || filename == NULL || linkname == NULL) 205 if (realname == NULL || filename == NULL || linkname == NULL)
diff --git a/tools/perf/util/include/linux/const.h b/tools/perf/util/include/linux/const.h
new file mode 100644
index 000000000000..1b476c9ae649
--- /dev/null
+++ b/tools/perf/util/include/linux/const.h
@@ -0,0 +1 @@
#include "../../../../include/linux/const.h"
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 69436b3200a4..a9ac0504aabd 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -674,7 +674,7 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
674 struct perf_evlist *evlist = &pevlist->evlist; 674 struct perf_evlist *evlist = &pevlist->evlist;
675 union perf_event *event; 675 union perf_event *event;
676 int sample_id_all = 1, cpu; 676 int sample_id_all = 1, cpu;
677 static char *kwlist[] = {"sample_id_all", NULL, NULL}; 677 static char *kwlist[] = {"cpu", "sample_id_all", NULL, NULL};
678 int err; 678 int err;
679 679
680 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist, 680 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist,
@@ -692,16 +692,14 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
692 692
693 first = list_entry(evlist->entries.next, struct perf_evsel, node); 693 first = list_entry(evlist->entries.next, struct perf_evsel, node);
694 err = perf_event__parse_sample(event, first->attr.sample_type, 694 err = perf_event__parse_sample(event, first->attr.sample_type,
695 perf_sample_size(first->attr.sample_type), 695 perf_evsel__sample_size(first),
696 sample_id_all, &pevent->sample); 696 sample_id_all, &pevent->sample);
697 if (err) { 697 if (err)
698 pr_err("Can't parse sample, err = %d\n", err); 698 return PyErr_Format(PyExc_OSError,
699 goto end; 699 "perf: can't parse sample, err=%d", err);
700 }
701
702 return pyevent; 700 return pyevent;
703 } 701 }
704end: 702
705 Py_INCREF(Py_None); 703 Py_INCREF(Py_None);
706 return Py_None; 704 return Py_None;
707} 705}
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 64500fc78799..f5a8fbdd3f76 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -58,6 +58,16 @@ static int perf_session__open(struct perf_session *self, bool force)
58 goto out_close; 58 goto out_close;
59 } 59 }
60 60
61 if (!perf_evlist__valid_sample_type(self->evlist)) {
62 pr_err("non matching sample_type");
63 goto out_close;
64 }
65
66 if (!perf_evlist__valid_sample_id_all(self->evlist)) {
67 pr_err("non matching sample_id_all");
68 goto out_close;
69 }
70
61 self->size = input_stat.st_size; 71 self->size = input_stat.st_size;
62 return 0; 72 return 0;
63 73
@@ -97,7 +107,7 @@ out:
97void perf_session__update_sample_type(struct perf_session *self) 107void perf_session__update_sample_type(struct perf_session *self)
98{ 108{
99 self->sample_type = perf_evlist__sample_type(self->evlist); 109 self->sample_type = perf_evlist__sample_type(self->evlist);
100 self->sample_size = perf_sample_size(self->sample_type); 110 self->sample_size = __perf_evsel__sample_size(self->sample_type);
101 self->sample_id_all = perf_evlist__sample_id_all(self->evlist); 111 self->sample_id_all = perf_evlist__sample_id_all(self->evlist);
102 perf_session__id_header_size(self); 112 perf_session__id_header_size(self);
103} 113}
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 516876dfbe52..eec196329fd9 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -676,9 +676,30 @@ discard_symbol: rb_erase(&pos->rb_node, root);
676 return count + moved; 676 return count + moved;
677} 677}
678 678
679static bool symbol__restricted_filename(const char *filename,
680 const char *restricted_filename)
681{
682 bool restricted = false;
683
684 if (symbol_conf.kptr_restrict) {
685 char *r = realpath(filename, NULL);
686
687 if (r != NULL) {
688 restricted = strcmp(r, restricted_filename) == 0;
689 free(r);
690 return restricted;
691 }
692 }
693
694 return restricted;
695}
696
679int dso__load_kallsyms(struct dso *dso, const char *filename, 697int dso__load_kallsyms(struct dso *dso, const char *filename,
680 struct map *map, symbol_filter_t filter) 698 struct map *map, symbol_filter_t filter)
681{ 699{
700 if (symbol__restricted_filename(filename, "/proc/kallsyms"))
701 return -1;
702
682 if (dso__load_all_kallsyms(dso, filename, map) < 0) 703 if (dso__load_all_kallsyms(dso, filename, map) < 0)
683 return -1; 704 return -1;
684 705
@@ -1790,6 +1811,9 @@ static int machine__create_modules(struct machine *machine)
1790 modules = path; 1811 modules = path;
1791 } 1812 }
1792 1813
1814 if (symbol__restricted_filename(path, "/proc/modules"))
1815 return -1;
1816
1793 file = fopen(modules, "r"); 1817 file = fopen(modules, "r");
1794 if (file == NULL) 1818 if (file == NULL)
1795 return -1; 1819 return -1;
@@ -2239,6 +2263,9 @@ static u64 machine__get_kernel_start_addr(struct machine *machine)
2239 } 2263 }
2240 } 2264 }
2241 2265
2266 if (symbol__restricted_filename(filename, "/proc/kallsyms"))
2267 return 0;
2268
2242 if (kallsyms__parse(filename, &args, symbol__in_kernel) <= 0) 2269 if (kallsyms__parse(filename, &args, symbol__in_kernel) <= 0)
2243 return 0; 2270 return 0;
2244 2271
@@ -2410,6 +2437,25 @@ static int setup_list(struct strlist **list, const char *list_str,
2410 return 0; 2437 return 0;
2411} 2438}
2412 2439
2440static bool symbol__read_kptr_restrict(void)
2441{
2442 bool value = false;
2443
2444 if (geteuid() != 0) {
2445 FILE *fp = fopen("/proc/sys/kernel/kptr_restrict", "r");
2446 if (fp != NULL) {
2447 char line[8];
2448
2449 if (fgets(line, sizeof(line), fp) != NULL)
2450 value = atoi(line) != 0;
2451
2452 fclose(fp);
2453 }
2454 }
2455
2456 return value;
2457}
2458
2413int symbol__init(void) 2459int symbol__init(void)
2414{ 2460{
2415 const char *symfs; 2461 const char *symfs;
@@ -2456,6 +2502,8 @@ int symbol__init(void)
2456 if (symfs != symbol_conf.symfs) 2502 if (symfs != symbol_conf.symfs)
2457 free((void *)symfs); 2503 free((void *)symfs);
2458 2504
2505 symbol_conf.kptr_restrict = symbol__read_kptr_restrict();
2506
2459 symbol_conf.initialized = true; 2507 symbol_conf.initialized = true;
2460 return 0; 2508 return 0;
2461 2509
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 242de0101a86..325ee36a9d29 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -75,7 +75,8 @@ struct symbol_conf {
75 use_callchain, 75 use_callchain,
76 exclude_other, 76 exclude_other,
77 show_cpu_utilization, 77 show_cpu_utilization,
78 initialized; 78 initialized,
79 kptr_restrict;
79 const char *vmlinux_name, 80 const char *vmlinux_name,
80 *kallsyms_name, 81 *kallsyms_name,
81 *source_prefix, 82 *source_prefix,