aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-08-09 06:46:45 -0400
committerIngo Molnar <mingo@elte.hu>2009-08-09 06:46:49 -0400
commite3560336be655c6791316482fe288b119f34c427 (patch)
tree43ca9a6b489aaa3918b773f78a7eda37458ef0a8 /tools/perf
parent26528e773ecc74fb1b61b7275f86f761cbb340ec (diff)
parent7b2aa037e878c939676675969983284a02958ae3 (diff)
Merge branch 'linus' into tracing/urgent
Merge reason: Merge up to almost-rc6 to pick up latest perfcounters (on which we'll queue up a dependent fix) Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Documentation/perf-record.txt60
-rw-r--r--tools/perf/Makefile29
-rw-r--r--tools/perf/builtin-report.c28
-rw-r--r--tools/perf/builtin-top.c1
-rw-r--r--tools/perf/util/quote.c2
-rw-r--r--tools/perf/util/symbol.c87
6 files changed, 189 insertions, 18 deletions
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 1dbc1eeb4c01..6be696b0a2bb 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -29,13 +29,67 @@ OPTIONS
29 Select the PMU event. Selection can be a symbolic event name 29 Select the PMU event. Selection can be a symbolic event name
30 (use 'perf list' to list all events) or a raw PMU 30 (use 'perf list' to list all events) or a raw PMU
31 event (eventsel+umask) in the form of rNNN where NNN is a 31 event (eventsel+umask) in the form of rNNN where NNN is a
32 hexadecimal event descriptor. 32 hexadecimal event descriptor.
33 33
34-a:: 34-a::
35 system-wide collection 35 System-wide collection.
36 36
37-l:: 37-l::
38 scale counter values 38 Scale counter values.
39
40-p::
41--pid=::
42 Record events on existing pid.
43
44-r::
45--realtime=::
46 Collect data with this RT SCHED_FIFO priority.
47-A::
48--append::
49 Append to the output file to do incremental profiling.
50
51-f::
52--force::
53 Overwrite existing data file.
54
55-c::
56--count=::
57 Event period to sample.
58
59-o::
60--output=::
61 Output file name.
62
63-i::
64--inherit::
65 Child tasks inherit counters.
66-F::
67--freq=::
68 Profile at this frequency.
69
70-m::
71--mmap-pages=::
72 Number of mmap data pages.
73
74-g::
75--call-graph::
76 Do call-graph (stack chain/backtrace) recording.
77
78-v::
79--verbose::
80 Be more verbose (show counter open errors, etc).
81
82-s::
83--stat::
84 Per thread counts.
85
86-d::
87--data::
88 Sample addresses.
89
90-n::
91--no-samples::
92 Don't sample.
39 93
40SEE ALSO 94SEE ALSO
41-------- 95--------
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index a5e9b876ca09..1916e44b9bb0 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -158,8 +158,10 @@ uname_P := $(shell sh -c 'uname -p 2>/dev/null || echo not')
158uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not') 158uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not')
159 159
160# If we're on a 64-bit kernel, use -m64 160# If we're on a 64-bit kernel, use -m64
161ifneq ($(patsubst %64,%,$(uname_M)),$(uname_M)) 161ifndef NO_64BIT
162 M64 := -m64 162 ifneq ($(patsubst %64,%,$(uname_M)),$(uname_M))
163 M64 := -m64
164 endif
163endif 165endif
164 166
165# CFLAGS and LDFLAGS are for the users to override from the command line. 167# CFLAGS and LDFLAGS are for the users to override from the command line.
@@ -345,7 +347,6 @@ BUILTIN_OBJS += builtin-stat.o
345BUILTIN_OBJS += builtin-top.o 347BUILTIN_OBJS += builtin-top.o
346 348
347PERFLIBS = $(LIB_FILE) 349PERFLIBS = $(LIB_FILE)
348EXTLIBS = -lbfd
349 350
350# 351#
351# Platform specific tweaks 352# Platform specific tweaks
@@ -374,6 +375,28 @@ ifeq ($(uname_S),Darwin)
374 PTHREAD_LIBS = 375 PTHREAD_LIBS =
375endif 376endif
376 377
378ifneq ($(shell sh -c "(echo '\#include <libelf.h>'; echo 'int main(void) { Elf * elf = elf_begin(0, ELF_C_READ_MMAP, 0); return (long)elf; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -o /dev/null $(ALL_LDFLAGS) > /dev/null 2>&1 && echo y"), y)
379 msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel);
380endif
381
382ifdef NO_DEMANGLE
383 BASIC_CFLAGS += -DNO_DEMANGLE
384else
385
386 has_bfd := $(shell sh -c "(echo '\#include <bfd.h>'; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o /dev/null $(ALL_LDFLAGS) -lbfd > /dev/null 2>&1 && echo y")
387
388 has_bfd_iberty := $(shell sh -c "(echo '\#include <bfd.h>'; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o /dev/null $(ALL_LDFLAGS) -lbfd -liberty > /dev/null 2>&1 && echo y")
389
390 ifeq ($(has_bfd),y)
391 EXTLIBS += -lbfd
392 else ifeq ($(has_bfd_iberty),y)
393 EXTLIBS += -lbfd -liberty
394 else
395 msg := $(warning No bfd.h/libbfd found, install binutils-dev[el] to gain symbol demangling)
396 BASIC_CFLAGS += -DNO_DEMANGLE
397 endif
398endif
399
377ifndef CC_LD_DYNPATH 400ifndef CC_LD_DYNPATH
378 ifdef NO_R_TO_GCC_LINKER 401 ifdef NO_R_TO_GCC_LINKER
379 # Some gcc does not accept and pass -R to the linker to specify 402 # Some gcc does not accept and pass -R to the linker to specify
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index b20a4b6e31b7..8cb58d68a006 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -31,7 +31,7 @@
31static char const *input_name = "perf.data"; 31static char const *input_name = "perf.data";
32static char *vmlinux = NULL; 32static char *vmlinux = NULL;
33 33
34static char default_sort_order[] = "comm,dso"; 34static char default_sort_order[] = "comm,dso,symbol";
35static char *sort_order = default_sort_order; 35static char *sort_order = default_sort_order;
36static char *dso_list_str, *comm_list_str, *sym_list_str, 36static char *dso_list_str, *comm_list_str, *sym_list_str,
37 *col_width_list_str; 37 *col_width_list_str;
@@ -99,6 +99,7 @@ struct comm_event {
99struct fork_event { 99struct fork_event {
100 struct perf_event_header header; 100 struct perf_event_header header;
101 u32 pid, ppid; 101 u32 pid, ppid;
102 u32 tid, ptid;
102}; 103};
103 104
104struct lost_event { 105struct lost_event {
@@ -252,7 +253,7 @@ static int strcommon(const char *pathname)
252{ 253{
253 int n = 0; 254 int n = 0;
254 255
255 while (pathname[n] == cwd[n] && n < cwdlen) 256 while (n < cwdlen && pathname[n] == cwd[n])
256 ++n; 257 ++n;
257 258
258 return n; 259 return n;
@@ -1423,7 +1424,7 @@ print_entries:
1423 if (sort_order == default_sort_order && 1424 if (sort_order == default_sort_order &&
1424 parent_pattern == default_parent_pattern) { 1425 parent_pattern == default_parent_pattern) {
1425 fprintf(fp, "#\n"); 1426 fprintf(fp, "#\n");
1426 fprintf(fp, "# (For more details, try: perf report --sort comm,dso,symbol)\n"); 1427 fprintf(fp, "# (For a higher level overview, try: perf report --sort comm,dso)\n");
1427 fprintf(fp, "#\n"); 1428 fprintf(fp, "#\n");
1428 } 1429 }
1429 fprintf(fp, "\n"); 1430 fprintf(fp, "\n");
@@ -1608,15 +1609,27 @@ process_comm_event(event_t *event, unsigned long offset, unsigned long head)
1608} 1609}
1609 1610
1610static int 1611static int
1611process_fork_event(event_t *event, unsigned long offset, unsigned long head) 1612process_task_event(event_t *event, unsigned long offset, unsigned long head)
1612{ 1613{
1613 struct thread *thread = threads__findnew(event->fork.pid); 1614 struct thread *thread = threads__findnew(event->fork.pid);
1614 struct thread *parent = threads__findnew(event->fork.ppid); 1615 struct thread *parent = threads__findnew(event->fork.ppid);
1615 1616
1616 dprintf("%p [%p]: PERF_EVENT_FORK: %d:%d\n", 1617 dprintf("%p [%p]: PERF_EVENT_%s: (%d:%d):(%d:%d)\n",
1617 (void *)(offset + head), 1618 (void *)(offset + head),
1618 (void *)(long)(event->header.size), 1619 (void *)(long)(event->header.size),
1619 event->fork.pid, event->fork.ppid); 1620 event->header.type == PERF_EVENT_FORK ? "FORK" : "EXIT",
1621 event->fork.pid, event->fork.tid,
1622 event->fork.ppid, event->fork.ptid);
1623
1624 /*
1625 * A thread clone will have the same PID for both
1626 * parent and child.
1627 */
1628 if (thread == parent)
1629 return 0;
1630
1631 if (event->header.type == PERF_EVENT_EXIT)
1632 return 0;
1620 1633
1621 if (!thread || !parent || thread__fork(thread, parent)) { 1634 if (!thread || !parent || thread__fork(thread, parent)) {
1622 dprintf("problem processing PERF_EVENT_FORK, skipping event.\n"); 1635 dprintf("problem processing PERF_EVENT_FORK, skipping event.\n");
@@ -1706,7 +1719,8 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
1706 return process_comm_event(event, offset, head); 1719 return process_comm_event(event, offset, head);
1707 1720
1708 case PERF_EVENT_FORK: 1721 case PERF_EVENT_FORK:
1709 return process_fork_event(event, offset, head); 1722 case PERF_EVENT_EXIT:
1723 return process_task_event(event, offset, head);
1710 1724
1711 case PERF_EVENT_LOST: 1725 case PERF_EVENT_LOST:
1712 return process_lost_event(event, offset, head); 1726 return process_lost_event(event, offset, head);
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index c0a423004e15..f139f1ab9333 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -285,6 +285,7 @@ static const char *skip_symbols[] = {
285 "enter_idle", 285 "enter_idle",
286 "exit_idle", 286 "exit_idle",
287 "mwait_idle", 287 "mwait_idle",
288 "mwait_idle_with_hints",
288 "ppc64_runlatch_off", 289 "ppc64_runlatch_off",
289 "pseries_dedicated_idle_sleep", 290 "pseries_dedicated_idle_sleep",
290 NULL 291 NULL
diff --git a/tools/perf/util/quote.c b/tools/perf/util/quote.c
index c6e5dc0dc82f..2726fe40eb5d 100644
--- a/tools/perf/util/quote.c
+++ b/tools/perf/util/quote.c
@@ -318,7 +318,7 @@ char *quote_path_relative(const char *in, int len,
318 strbuf_addch(out, '"'); 318 strbuf_addch(out, '"');
319 if (prefix) { 319 if (prefix) {
320 int off = 0; 320 int off = 0;
321 while (prefix[off] && off < len && prefix[off] == in[off]) 321 while (off < len && prefix[off] && prefix[off] == in[off])
322 if (prefix[off] == '/') { 322 if (prefix[off] == '/') {
323 prefix += off + 1; 323 prefix += off + 1;
324 in += off + 1; 324 in += off + 1;
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 28106059bf12..16ddca202948 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -6,7 +6,16 @@
6#include <libelf.h> 6#include <libelf.h>
7#include <gelf.h> 7#include <gelf.h>
8#include <elf.h> 8#include <elf.h>
9
10#ifndef NO_DEMANGLE
9#include <bfd.h> 11#include <bfd.h>
12#else
13static inline
14char *bfd_demangle(void __used *v, const char __used *c, int __used i)
15{
16 return NULL;
17}
18#endif
10 19
11const char *sym_hist_filter; 20const char *sym_hist_filter;
12 21
@@ -565,7 +574,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
565 goto out_elf_end; 574 goto out_elf_end;
566 575
567 secstrs = elf_getdata(sec_strndx, NULL); 576 secstrs = elf_getdata(sec_strndx, NULL);
568 if (symstrs == NULL) 577 if (secstrs == NULL)
569 goto out_elf_end; 578 goto out_elf_end;
570 579
571 nr_syms = shdr.sh_size / shdr.sh_entsize; 580 nr_syms = shdr.sh_size / shdr.sh_entsize;
@@ -652,10 +661,69 @@ out_close:
652 return err; 661 return err;
653} 662}
654 663
664#define BUILD_ID_SIZE 128
665
666static char *dso__read_build_id(struct dso *self, int verbose)
667{
668 int i;
669 GElf_Ehdr ehdr;
670 GElf_Shdr shdr;
671 Elf_Data *build_id_data;
672 Elf_Scn *sec;
673 char *build_id = NULL, *bid;
674 unsigned char *raw;
675 Elf *elf;
676 int fd = open(self->name, O_RDONLY);
677
678 if (fd < 0)
679 goto out;
680
681 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
682 if (elf == NULL) {
683 if (verbose)
684 fprintf(stderr, "%s: cannot read %s ELF file.\n",
685 __func__, self->name);
686 goto out_close;
687 }
688
689 if (gelf_getehdr(elf, &ehdr) == NULL) {
690 if (verbose)
691 fprintf(stderr, "%s: cannot get elf header.\n", __func__);
692 goto out_elf_end;
693 }
694
695 sec = elf_section_by_name(elf, &ehdr, &shdr, ".note.gnu.build-id", NULL);
696 if (sec == NULL)
697 goto out_elf_end;
698
699 build_id_data = elf_getdata(sec, NULL);
700 if (build_id_data == NULL)
701 goto out_elf_end;
702 build_id = malloc(BUILD_ID_SIZE);
703 if (build_id == NULL)
704 goto out_elf_end;
705 raw = build_id_data->d_buf + 16;
706 bid = build_id;
707
708 for (i = 0; i < 20; ++i) {
709 sprintf(bid, "%02x", *raw);
710 ++raw;
711 bid += 2;
712 }
713 if (verbose)
714 printf("%s(%s): %s\n", __func__, self->name, build_id);
715out_elf_end:
716 elf_end(elf);
717out_close:
718 close(fd);
719out:
720 return build_id;
721}
722
655int dso__load(struct dso *self, symbol_filter_t filter, int verbose) 723int dso__load(struct dso *self, symbol_filter_t filter, int verbose)
656{ 724{
657 int size = strlen(self->name) + sizeof("/usr/lib/debug%s.debug"); 725 int size = PATH_MAX;
658 char *name = malloc(size); 726 char *name = malloc(size), *build_id = NULL;
659 int variant = 0; 727 int variant = 0;
660 int ret = -1; 728 int ret = -1;
661 int fd; 729 int fd;
@@ -677,7 +745,18 @@ more:
677 case 1: /* Ubuntu */ 745 case 1: /* Ubuntu */
678 snprintf(name, size, "/usr/lib/debug%s", self->name); 746 snprintf(name, size, "/usr/lib/debug%s", self->name);
679 break; 747 break;
680 case 2: /* Sane people */ 748 case 2:
749 build_id = dso__read_build_id(self, verbose);
750 if (build_id != NULL) {
751 snprintf(name, size,
752 "/usr/lib/debug/.build-id/%.2s/%s.debug",
753 build_id, build_id + 2);
754 free(build_id);
755 break;
756 }
757 variant++;
758 /* Fall thru */
759 case 3: /* Sane people */
681 snprintf(name, size, "%s", self->name); 760 snprintf(name, size, "%s", self->name);
682 break; 761 break;
683 762