From 58c3439083f8fde61de842c93d1407f0f881cd92 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Fri, 16 Jul 2010 04:02:14 +0200 Subject: perf: Fix various display bugs with parent filtering Hists that have been filtered, because they don't have callchains matching the parent filter, won't be printed. As such, hist_entry__snprintf() returns 0 for them, but we don't control this value and we always print the buffer, which might be untouched and then only made of random stack garbage. Not only does it paint the screen with barf, it also prints the callchains for these hists, even though they have been filtered, since the hist has been filtered as well. We need to check the return value of hist_entry__snprintf() and ignore the hist if it is 0, which means it didn't get any callchain matching the parent filter. This fixes the barf and the undesired callchains. Reported-by: Ingo Molnar Signed-off-by: Frederic Weisbecker Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras --- tools/perf/util/hist.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 07f89b66..699cf81 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -631,9 +631,14 @@ int hist_entry__fprintf(struct hist_entry *self, struct hists *pair_hists, u64 session_total) { char bf[512]; - hist_entry__snprintf(self, bf, sizeof(bf), pair_hists, - show_displacement, displacement, - true, session_total); + int ret; + + ret = hist_entry__snprintf(self, bf, sizeof(bf), pair_hists, + show_displacement, displacement, + true, session_total); + if (!ret) + return 0; + return fprintf(fp, "%s\n", bf); } @@ -762,6 +767,7 @@ size_t hists__fprintf(struct hists *self, struct hists *pair, print_entries: for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) { struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); + int cnt; if (show_displacement) { if (h->pair != NULL) @@ -771,8 +777,13 @@ print_entries: displacement = 0; ++position; } - ret += hist_entry__fprintf(h, pair, show_displacement, - displacement, fp, self->stats.total_period); + cnt = hist_entry__fprintf(h, pair, show_displacement, + displacement, fp, self->stats.total_period); + /* Ignore those that didn't match the parent filter */ + if (!cnt) + continue; + + ret += cnt; if (symbol_conf.use_callchain) ret += hist_entry__fprintf_callchain(h, fp, self->stats.total_period); -- cgit v1.1 From 74534341c1214ac5993904680616afe698dde3b6 Mon Sep 17 00:00:00 2001 From: Gui Jianfeng Date: Thu, 24 Jun 2010 15:04:02 +0800 Subject: perf symbols: Fix directory descriptor leaking When I ran "perf kvm ... top", I encountered the following error output. Error: perfcounter syscall returned with -1 (Too many open files) Fatal: No CONFIG_PERF_EVENTS=y kernel support configured? Looking into perf, I found perf opens too many directories at initialization time, but forgets to close them. Here is the fix. LKML-Reference: <4C230362.5080704@cn.fujitsu.com> Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Signed-off-by: Gui Jianfeng Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/symbol.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index b63e571..5b27683 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1443,6 +1443,7 @@ static int map_groups__set_modules_path_dir(struct map_groups *self, { struct dirent *dent; DIR *dir = opendir(dir_name); + int ret = 0; if (!dir) { pr_debug("%s: cannot open %s dir\n", __func__, dir_name); @@ -1465,8 +1466,9 @@ static int map_groups__set_modules_path_dir(struct map_groups *self, snprintf(path, sizeof(path), "%s/%s", dir_name, dent->d_name); - if (map_groups__set_modules_path_dir(self, path) < 0) - goto failure; + ret = map_groups__set_modules_path_dir(self, path); + if (ret < 0) + goto out; } else { char *dot = strrchr(dent->d_name, '.'), dso_name[PATH_MAX]; @@ -1487,17 +1489,18 @@ static int map_groups__set_modules_path_dir(struct map_groups *self, dir_name, dent->d_name); long_name = strdup(path); - if (long_name == NULL) - goto failure; + if (long_name == NULL) { + ret = -1; + goto out; + } dso__set_long_name(map->dso, long_name); dso__kernel_module_get_build_id(map->dso, ""); } } - return 0; -failure: +out: closedir(dir); - return -1; + return ret; } static char *get_kernel_version(const char *root_dir) -- cgit v1.1 From 07fca0e57fca925032526349f4370f97ed580cc9 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sat, 10 Jul 2010 08:35:00 +0200 Subject: tracing: Properly align linker defined symbols We define a number of symbols in the linker scipt like this: __start_syscalls_metadata = .; *(__syscalls_metadata) But we do not know the alignment of "." when we assign the __start_syscalls_metadata symbol. gcc started to uses bigger alignment for structs (32 bytes), so we saw situations where the linker due to alignment constraints increased the value of "." after the symbol assignment. This resulted in boot fails. Fix this by forcing a 32 byte alignment of "." before the assignment. This patch introduces the forced alignment for ftrace_events and syscalls_metadata. It may be required in more places. Reported-by: Zeev Tarantov Signed-off-by: Sam Ravnborg LKML-Reference: <20100710063459.GA14596@merkur.ravnborg.org> Cc: Frederic Weisbecker Signed-off-by: Steven Rostedt --- include/asm-generic/vmlinux.lds.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 48c5299..4b5902a 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -63,6 +63,12 @@ /* Align . to a 8 byte boundary equals to maximum function alignment. */ #define ALIGN_FUNCTION() . = ALIGN(8) +/* + * Align to a 32 byte boundary equal to the + * alignment gcc 4.5 uses for a struct + */ +#define STRUCT_ALIGN() . = ALIGN(32) + /* The actual configuration determine if the init/exit sections * are handled as text/data or they can be discarded (which * often happens at runtime) @@ -166,7 +172,11 @@ LIKELY_PROFILE() \ BRANCH_PROFILE() \ TRACE_PRINTKS() \ + \ + STRUCT_ALIGN(); \ FTRACE_EVENTS() \ + \ + STRUCT_ALIGN(); \ TRACE_SYSCALLS() /* -- cgit v1.1 From 70a7cb3b39994ff366ff100b46f9dc97b1510c0f Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 22 Jul 2010 14:04:13 -0300 Subject: perf annotate: Fix handling of goto labels that are valid hex numbers When parsing the objdump disassembly output we can have goto labels that are valid hex numbers and thus get confused with lines with machine code. Handle the common case of a label that has nothing after it and other cases where there is just source code by validating the resulting "ip". It is still possible that we find goto labels that are in the function address range, but only if they are located before the real address we should be OK. A change in the objdump output to have a clear marker separating addresses from the disassembly would come handy, but we would still have to deal with older versions. Reported-by: Gleb Natapov Cc: Frederic Weisbecker Cc: Gleb Natapov Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Stephane Eranian LKML-Reference: <20100722170541.GF17631@ghostprotocols.net> Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/hist.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 699cf81..784ee0b 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -976,13 +976,17 @@ static int hist_entry__parse_objdump_line(struct hist_entry *self, FILE *file, * Parse hexa addresses followed by ':' */ line_ip = strtoull(tmp, &tmp2, 16); - if (*tmp2 != ':' || tmp == tmp2) + if (*tmp2 != ':' || tmp == tmp2 || tmp2[1] == '\0') line_ip = -1; } if (line_ip != -1) { - u64 start = map__rip_2objdump(self->ms.map, sym->start); + u64 start = map__rip_2objdump(self->ms.map, sym->start), + end = map__rip_2objdump(self->ms.map, sym->end); + offset = line_ip - start; + if (offset < 0 || (u64)line_ip > end) + offset = -1; } objdump_line = objdump_line__new(offset, line); -- cgit v1.1 From 8a4fd31e0e8dc33f00b8949a12ac56310bac57bc Mon Sep 17 00:00:00 2001 From: Conny Seidel Date: Tue, 6 Jul 2010 17:39:43 +0200 Subject: perf tools: Fix fallback to cplus_demangle() when bfd_demangle() is not available make version 3.80 doesn't support "else ifdef" on the same line, also it doesn't support unindented nested constructs. Build fails with: Makefile:608: Extraneous text after `else' directive Makefile:611: *** only one `else' per conditional. Stop. This patch fixes the build for make 3.80. Cc: Ingo Molnar , Cc: Borislav Petkov LKML-Reference: <1278430783-17259-1-git-send-email-conny.seidel@amd.com> Signed-off-by: Conny Seidel Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 3d8f31e..d75c28a 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -600,30 +600,32 @@ endif ifdef NO_DEMANGLE BASIC_CFLAGS += -DNO_DEMANGLE -else ifdef HAVE_CPLUS_DEMANGLE - EXTLIBS += -liberty - BASIC_CFLAGS += -DHAVE_CPLUS_DEMANGLE else - has_bfd := $(shell sh -c "(echo '\#include '; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) -lbfd "$(QUIET_STDERR)" && echo y") - - ifeq ($(has_bfd),y) - EXTLIBS += -lbfd + ifdef HAVE_CPLUS_DEMANGLE + EXTLIBS += -liberty + BASIC_CFLAGS += -DHAVE_CPLUS_DEMANGLE else - has_bfd_iberty := $(shell sh -c "(echo '\#include '; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) -lbfd -liberty "$(QUIET_STDERR)" && echo y") - ifeq ($(has_bfd_iberty),y) - EXTLIBS += -lbfd -liberty + has_bfd := $(shell sh -c "(echo '\#include '; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) -lbfd "$(QUIET_STDERR)" && echo y") + + ifeq ($(has_bfd),y) + EXTLIBS += -lbfd else - has_bfd_iberty_z := $(shell sh -c "(echo '\#include '; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) -lbfd -liberty -lz "$(QUIET_STDERR)" && echo y") - ifeq ($(has_bfd_iberty_z),y) - EXTLIBS += -lbfd -liberty -lz + has_bfd_iberty := $(shell sh -c "(echo '\#include '; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) -lbfd -liberty "$(QUIET_STDERR)" && echo y") + ifeq ($(has_bfd_iberty),y) + EXTLIBS += -lbfd -liberty else - has_cplus_demangle := $(shell sh -c "(echo 'extern char *cplus_demangle(const char *, int);'; echo 'int main(void) { cplus_demangle(0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) -liberty "$(QUIET_STDERR)" && echo y") - ifeq ($(has_cplus_demangle),y) - EXTLIBS += -liberty - BASIC_CFLAGS += -DHAVE_CPLUS_DEMANGLE + has_bfd_iberty_z := $(shell sh -c "(echo '\#include '; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) -lbfd -liberty -lz "$(QUIET_STDERR)" && echo y") + ifeq ($(has_bfd_iberty_z),y) + EXTLIBS += -lbfd -liberty -lz else - msg := $(warning No bfd.h/libbfd found, install binutils-dev[el]/zlib-static to gain symbol demangling) - BASIC_CFLAGS += -DNO_DEMANGLE + has_cplus_demangle := $(shell sh -c "(echo 'extern char *cplus_demangle(const char *, int);'; echo 'int main(void) { cplus_demangle(0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) -liberty "$(QUIET_STDERR)" && echo y") + ifeq ($(has_cplus_demangle),y) + EXTLIBS += -liberty + BASIC_CFLAGS += -DHAVE_CPLUS_DEMANGLE + else + msg := $(warning No bfd.h/libbfd found, install binutils-dev[el]/zlib-static to gain symbol demangling) + BASIC_CFLAGS += -DNO_DEMANGLE + endif endif endif endif -- cgit v1.1