aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2017-07-26 13:07:30 -0400
committerIngo Molnar <mingo@kernel.org>2017-07-26 13:07:30 -0400
commitee438ec8f33c5af0d4a4ffb935c5b9272e8c2680 (patch)
treed95fe900307968a2874b5cd64e09bbb378c77e23
parent510457ec9dc259b002879bcfe475f89d4514a0fc (diff)
parent62e6039f02888efdd824e8c596c4927616a97ce3 (diff)
Merge tag 'perf-core-for-mingo-4.14-20170725' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvemends and fixes for v4.14: New features: - Filter out 'sshd' in the tracer ancestry in 'perf trace' syswide tracing, to elliminate tracing loops (Arnaldo Carvalho de Melo) - Support lookup of symbols in other mount namespaces in 'perf top' (Krister Johansen) - Initial 'clone' syscall args beautifier in 'perf trace' (Arnaldo Carvalho de Melo) User visible changes: - Ignore 'fd' and 'offset' args for MAP_ANONYMOUS in 'perf trace' (Arnaldo Carvalho de Melo) - Process tracing data in 'perf annotate' pipe mode (David Carrillo-Cisneros) - Make 'perf report --branch-history' work without callgraphs(-g) option in perf record (Jin Yao) - Tag branch type/flag on "to" and tag cycles on "from" in 'perf report' (Jin Yao) Fixes: - Fix jvmti linker error when libelf config is disabled (Sudeep Holla) - Fix cgroups refcount usage (Arnaldo Carvalho de Melo) - Fix kernel symbol adjustment for s390x (Thomas Richter) - Fix 'perf report --stdio --show-total-period', it was showing the number of samples, not the total period (Taeung Song) Infrastructure changes: - Add perf_sample dictionary to tracepoint handlers in 'perf script' python, which were already present for other types of events (hardware, etc) (Arun Kalyanasundaram) - Make build fail on vendor events JSON parse error (Andi Kleen) - Adopt strstarts() from the kernel (Arnaldo Carvalho de Melo) Arch specific changes: - Set no_aux_samples for the tracking event in Intel PT (Kan Liang) - Always set no branch for Intel PT dummy event (Kan Liang) Trivial changes: - Simplify some error handlers in 'perf script' (Dan Carpenter) - Add EXCLUDE_EXTLIBS and EXTRA_PERFLIBS to makefile (David Carrillo-Cisneros) Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--tools/include/linux/string.h12
-rw-r--r--tools/include/uapi/linux/sched.h52
-rw-r--r--tools/lib/string.c41
-rw-r--r--tools/lib/subcmd/help.c2
-rw-r--r--tools/lib/subcmd/parse-options.c18
-rw-r--r--tools/perf/Documentation/perf-top.txt4
-rw-r--r--tools/perf/MANIFEST2
-rw-r--r--tools/perf/Makefile.perf10
-rw-r--r--tools/perf/arch/s390/util/Build1
-rw-r--r--tools/perf/arch/s390/util/sym-handling.c22
-rw-r--r--tools/perf/arch/x86/util/intel-pt.c3
-rw-r--r--tools/perf/builtin-annotate.c4
-rw-r--r--tools/perf/builtin-config.c3
-rw-r--r--tools/perf/builtin-ftrace.c2
-rw-r--r--tools/perf/builtin-help.c6
-rw-r--r--tools/perf/builtin-report.c27
-rw-r--r--tools/perf/builtin-script.c7
-rw-r--r--tools/perf/builtin-top.c20
-rw-r--r--tools/perf/builtin-trace.c140
-rwxr-xr-xtools/perf/check-headers.sh1
-rw-r--r--tools/perf/perf.c16
-rw-r--r--tools/perf/pmu-events/README4
-rw-r--r--tools/perf/pmu-events/jevents.c21
-rw-r--r--tools/perf/trace/beauty/Build1
-rw-r--r--tools/perf/trace/beauty/beauty.h3
-rw-r--r--tools/perf/trace/beauty/clone.c75
-rw-r--r--tools/perf/trace/beauty/mmap.c3
-rw-r--r--tools/perf/ui/browser.c3
-rw-r--r--tools/perf/ui/browsers/annotate.c9
-rw-r--r--tools/perf/ui/gtk/annotate.c4
-rw-r--r--tools/perf/ui/stdio/hist.c3
-rw-r--r--tools/perf/util/annotate.c99
-rw-r--r--tools/perf/util/annotate.h18
-rw-r--r--tools/perf/util/bpf-loader.c2
-rw-r--r--tools/perf/util/branch.h11
-rw-r--r--tools/perf/util/callchain.c157
-rw-r--r--tools/perf/util/cgroup.c8
-rw-r--r--tools/perf/util/config.c13
-rw-r--r--tools/perf/util/evsel.c8
-rw-r--r--tools/perf/util/hist.c2
-rw-r--r--tools/perf/util/llvm-utils.c2
-rw-r--r--tools/perf/util/machine.c13
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c246
43 files changed, 798 insertions, 300 deletions
diff --git a/tools/include/linux/string.h b/tools/include/linux/string.h
index d62b56cf8c12..a30fad536f52 100644
--- a/tools/include/linux/string.h
+++ b/tools/include/linux/string.h
@@ -1,8 +1,8 @@
1#ifndef _TOOLS_LINUX_STRING_H_ 1#ifndef _TOOLS_LINUX_STRING_H_
2#define _TOOLS_LINUX_STRING_H_ 2#define _TOOLS_LINUX_STRING_H_
3 3
4
5#include <linux/types.h> /* for size_t */ 4#include <linux/types.h> /* for size_t */
5#include <string.h>
6 6
7void *memdup(const void *src, size_t len); 7void *memdup(const void *src, size_t len);
8 8
@@ -18,6 +18,14 @@ extern size_t strlcpy(char *dest, const char *src, size_t size);
18 18
19char *str_error_r(int errnum, char *buf, size_t buflen); 19char *str_error_r(int errnum, char *buf, size_t buflen);
20 20
21int prefixcmp(const char *str, const char *prefix); 21/**
22 * strstarts - does @str start with @prefix?
23 * @str: string to examine
24 * @prefix: prefix to look for.
25 */
26static inline bool strstarts(const char *str, const char *prefix)
27{
28 return strncmp(str, prefix, strlen(prefix)) == 0;
29}
22 30
23#endif /* _LINUX_STRING_H_ */ 31#endif /* _LINUX_STRING_H_ */
diff --git a/tools/include/uapi/linux/sched.h b/tools/include/uapi/linux/sched.h
new file mode 100644
index 000000000000..e2a6c7b3510b
--- /dev/null
+++ b/tools/include/uapi/linux/sched.h
@@ -0,0 +1,52 @@
1#ifndef _UAPI_LINUX_SCHED_H
2#define _UAPI_LINUX_SCHED_H
3
4/*
5 * cloning flags:
6 */
7#define CSIGNAL 0x000000ff /* signal mask to be sent at exit */
8#define CLONE_VM 0x00000100 /* set if VM shared between processes */
9#define CLONE_FS 0x00000200 /* set if fs info shared between processes */
10#define CLONE_FILES 0x00000400 /* set if open files shared between processes */
11#define CLONE_SIGHAND 0x00000800 /* set if signal handlers and blocked signals shared */
12#define CLONE_PTRACE 0x00002000 /* set if we want to let tracing continue on the child too */
13#define CLONE_VFORK 0x00004000 /* set if the parent wants the child to wake it up on mm_release */
14#define CLONE_PARENT 0x00008000 /* set if we want to have the same parent as the cloner */
15#define CLONE_THREAD 0x00010000 /* Same thread group? */
16#define CLONE_NEWNS 0x00020000 /* New mount namespace group */
17#define CLONE_SYSVSEM 0x00040000 /* share system V SEM_UNDO semantics */
18#define CLONE_SETTLS 0x00080000 /* create a new TLS for the child */
19#define CLONE_PARENT_SETTID 0x00100000 /* set the TID in the parent */
20#define CLONE_CHILD_CLEARTID 0x00200000 /* clear the TID in the child */
21#define CLONE_DETACHED 0x00400000 /* Unused, ignored */
22#define CLONE_UNTRACED 0x00800000 /* set if the tracing process can't force CLONE_PTRACE on this clone */
23#define CLONE_CHILD_SETTID 0x01000000 /* set the TID in the child */
24#define CLONE_NEWCGROUP 0x02000000 /* New cgroup namespace */
25#define CLONE_NEWUTS 0x04000000 /* New utsname namespace */
26#define CLONE_NEWIPC 0x08000000 /* New ipc namespace */
27#define CLONE_NEWUSER 0x10000000 /* New user namespace */
28#define CLONE_NEWPID 0x20000000 /* New pid namespace */
29#define CLONE_NEWNET 0x40000000 /* New network namespace */
30#define CLONE_IO 0x80000000 /* Clone io context */
31
32/*
33 * Scheduling policies
34 */
35#define SCHED_NORMAL 0
36#define SCHED_FIFO 1
37#define SCHED_RR 2
38#define SCHED_BATCH 3
39/* SCHED_ISO: reserved but not implemented yet */
40#define SCHED_IDLE 5
41#define SCHED_DEADLINE 6
42
43/* Can be ORed in to make sure the process is reverted back to SCHED_NORMAL on fork */
44#define SCHED_RESET_ON_FORK 0x40000000
45
46/*
47 * For the sched_{set,get}attr() calls
48 */
49#define SCHED_FLAG_RESET_ON_FORK 0x01
50#define SCHED_FLAG_RECLAIM 0x02
51
52#endif /* _UAPI_LINUX_SCHED_H */
diff --git a/tools/lib/string.c b/tools/lib/string.c
index 8e678af1c6ee..a4246f14ded1 100644
--- a/tools/lib/string.c
+++ b/tools/lib/string.c
@@ -39,27 +39,45 @@ void *memdup(const void *src, size_t len)
39 * @s: input string 39 * @s: input string
40 * @res: result 40 * @res: result
41 * 41 *
42 * This routine returns 0 iff the first character is one of 'Yy1Nn0'. 42 * This routine returns 0 iff the first character is one of 'Yy1Nn0', or
43 * Otherwise it will return -EINVAL. Value pointed to by res is 43 * [oO][NnFf] for "on" and "off". Otherwise it will return -EINVAL. Value
44 * updated upon finding a match. 44 * pointed to by res is updated upon finding a match.
45 */ 45 */
46int strtobool(const char *s, bool *res) 46int strtobool(const char *s, bool *res)
47{ 47{
48 if (!s)
49 return -EINVAL;
50
48 switch (s[0]) { 51 switch (s[0]) {
49 case 'y': 52 case 'y':
50 case 'Y': 53 case 'Y':
51 case '1': 54 case '1':
52 *res = true; 55 *res = true;
53 break; 56 return 0;
54 case 'n': 57 case 'n':
55 case 'N': 58 case 'N':
56 case '0': 59 case '0':
57 *res = false; 60 *res = false;
58 break; 61 return 0;
62 case 'o':
63 case 'O':
64 switch (s[1]) {
65 case 'n':
66 case 'N':
67 *res = true;
68 return 0;
69 case 'f':
70 case 'F':
71 *res = false;
72 return 0;
73 default:
74 break;
75 }
59 default: 76 default:
60 return -EINVAL; 77 break;
61 } 78 }
62 return 0; 79
80 return -EINVAL;
63} 81}
64 82
65/** 83/**
@@ -87,12 +105,3 @@ size_t __weak strlcpy(char *dest, const char *src, size_t size)
87 } 105 }
88 return ret; 106 return ret;
89} 107}
90
91int prefixcmp(const char *str, const char *prefix)
92{
93 for (; ; str++, prefix++)
94 if (!*prefix)
95 return 0;
96 else if (*str != *prefix)
97 return (unsigned char)*prefix - (unsigned char)*str;
98}
diff --git a/tools/lib/subcmd/help.c b/tools/lib/subcmd/help.c
index ba970a73d053..0310520f918e 100644
--- a/tools/lib/subcmd/help.c
+++ b/tools/lib/subcmd/help.c
@@ -171,7 +171,7 @@ static void list_commands_in_dir(struct cmdnames *cmds,
171 while ((de = readdir(dir)) != NULL) { 171 while ((de = readdir(dir)) != NULL) {
172 int entlen; 172 int entlen;
173 173
174 if (prefixcmp(de->d_name, prefix)) 174 if (!strstarts(de->d_name, prefix))
175 continue; 175 continue;
176 176
177 astrcat(&buf, de->d_name); 177 astrcat(&buf, de->d_name);
diff --git a/tools/lib/subcmd/parse-options.c b/tools/lib/subcmd/parse-options.c
index 359bfa77f39c..2bd6fd0c1d40 100644
--- a/tools/lib/subcmd/parse-options.c
+++ b/tools/lib/subcmd/parse-options.c
@@ -368,7 +368,7 @@ retry:
368 return 0; 368 return 0;
369 } 369 }
370 if (!rest) { 370 if (!rest) {
371 if (!prefixcmp(options->long_name, "no-")) { 371 if (strstarts(options->long_name, "no-")) {
372 /* 372 /*
373 * The long name itself starts with "no-", so 373 * The long name itself starts with "no-", so
374 * accept the option without "no-" so that users 374 * accept the option without "no-" so that users
@@ -381,7 +381,7 @@ retry:
381 goto match; 381 goto match;
382 } 382 }
383 /* Abbreviated case */ 383 /* Abbreviated case */
384 if (!prefixcmp(options->long_name + 3, arg)) { 384 if (strstarts(options->long_name + 3, arg)) {
385 flags |= OPT_UNSET; 385 flags |= OPT_UNSET;
386 goto is_abbreviated; 386 goto is_abbreviated;
387 } 387 }
@@ -406,7 +406,7 @@ is_abbreviated:
406 continue; 406 continue;
407 } 407 }
408 /* negated and abbreviated very much? */ 408 /* negated and abbreviated very much? */
409 if (!prefixcmp("no-", arg)) { 409 if (strstarts("no-", arg)) {
410 flags |= OPT_UNSET; 410 flags |= OPT_UNSET;
411 goto is_abbreviated; 411 goto is_abbreviated;
412 } 412 }
@@ -416,7 +416,7 @@ is_abbreviated:
416 flags |= OPT_UNSET; 416 flags |= OPT_UNSET;
417 rest = skip_prefix(arg + 3, options->long_name); 417 rest = skip_prefix(arg + 3, options->long_name);
418 /* abbreviated and negated? */ 418 /* abbreviated and negated? */
419 if (!rest && !prefixcmp(options->long_name, arg + 3)) 419 if (!rest && strstarts(options->long_name, arg + 3))
420 goto is_abbreviated; 420 goto is_abbreviated;
421 if (!rest) 421 if (!rest)
422 continue; 422 continue;
@@ -456,7 +456,7 @@ static void check_typos(const char *arg, const struct option *options)
456 if (strlen(arg) < 3) 456 if (strlen(arg) < 3)
457 return; 457 return;
458 458
459 if (!prefixcmp(arg, "no-")) { 459 if (strstarts(arg, "no-")) {
460 fprintf(stderr, " Error: did you mean `--%s` (with two dashes ?)", arg); 460 fprintf(stderr, " Error: did you mean `--%s` (with two dashes ?)", arg);
461 exit(129); 461 exit(129);
462 } 462 }
@@ -464,7 +464,7 @@ static void check_typos(const char *arg, const struct option *options)
464 for (; options->type != OPTION_END; options++) { 464 for (; options->type != OPTION_END; options++) {
465 if (!options->long_name) 465 if (!options->long_name)
466 continue; 466 continue;
467 if (!prefixcmp(options->long_name, arg)) { 467 if (strstarts(options->long_name, arg)) {
468 fprintf(stderr, " Error: did you mean `--%s` (with two dashes ?)", arg); 468 fprintf(stderr, " Error: did you mean `--%s` (with two dashes ?)", arg);
469 exit(129); 469 exit(129);
470 } 470 }
@@ -933,10 +933,10 @@ opt:
933 if (opts->long_name == NULL) 933 if (opts->long_name == NULL)
934 continue; 934 continue;
935 935
936 if (!prefixcmp(opts->long_name, optstr)) 936 if (strstarts(opts->long_name, optstr))
937 print_option_help(opts, 0); 937 print_option_help(opts, 0);
938 if (!prefixcmp("no-", optstr) && 938 if (strstarts("no-", optstr) &&
939 !prefixcmp(opts->long_name, optstr + 3)) 939 strstarts(opts->long_name, optstr + 3))
940 print_option_help(opts, 0); 940 print_option_help(opts, 0);
941 } 941 }
942 942
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index e71d63843f45..d864ea6fd367 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -237,6 +237,10 @@ Default is to monitor all CPUS.
237--hierarchy:: 237--hierarchy::
238 Enable hierarchy output. 238 Enable hierarchy output.
239 239
240--force::
241 Don't do ownership validation.
242
243
240INTERACTIVE PROMPTING KEYS 244INTERACTIVE PROMPTING KEYS
241-------------------------- 245--------------------------
242 246
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index a29da46d180f..705bdb147e73 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -70,6 +70,7 @@ tools/include/linux/hash.h
70tools/include/linux/kernel.h 70tools/include/linux/kernel.h
71tools/include/linux/list.h 71tools/include/linux/list.h
72tools/include/linux/log2.h 72tools/include/linux/log2.h
73tools/include/uapi/asm-generic/fcntl.h
73tools/include/uapi/asm-generic/mman-common.h 74tools/include/uapi/asm-generic/mman-common.h
74tools/include/uapi/asm-generic/mman.h 75tools/include/uapi/asm-generic/mman.h
75tools/include/uapi/linux/bpf.h 76tools/include/uapi/linux/bpf.h
@@ -78,6 +79,7 @@ tools/include/uapi/linux/fcntl.h
78tools/include/uapi/linux/hw_breakpoint.h 79tools/include/uapi/linux/hw_breakpoint.h
79tools/include/uapi/linux/mman.h 80tools/include/uapi/linux/mman.h
80tools/include/uapi/linux/perf_event.h 81tools/include/uapi/linux/perf_event.h
82tools/include/uapi/linux/sched.h
81tools/include/uapi/linux/stat.h 83tools/include/uapi/linux/stat.h
82tools/include/linux/poison.h 84tools/include/linux/poison.h
83tools/include/linux/rbtree.h 85tools/include/linux/rbtree.h
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 5008f51a08a2..d66f90e6be5c 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -33,6 +33,11 @@ include ../scripts/utilities.mak
33# 33#
34# Define EXTRA_CFLAGS=-m64 or EXTRA_CFLAGS=-m32 as appropriate for cross-builds. 34# Define EXTRA_CFLAGS=-m64 or EXTRA_CFLAGS=-m32 as appropriate for cross-builds.
35# 35#
36# Define EXCLUDE_EXTLIBS=-lmylib to exclude libmylib from the auto-generated
37# EXTLIBS.
38#
39# Define EXTRA_PERFLIBS to pass extra libraries to PERFLIBS.
40#
36# Define NO_DWARF if you do not want debug-info analysis feature at all. 41# Define NO_DWARF if you do not want debug-info analysis feature at all.
37# 42#
38# Define WERROR=0 to disable treating any warnings as errors. 43# Define WERROR=0 to disable treating any warnings as errors.
@@ -352,7 +357,8 @@ ifdef ASCIIDOC8
352 export ASCIIDOC8 357 export ASCIIDOC8
353endif 358endif
354 359
355LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive -Wl,--start-group $(EXTLIBS) -Wl,--end-group 360EXTLIBS := $(call filter-out,$(EXCLUDE_EXTLIBS),$(EXTLIBS))
361LIBS = -Wl,--whole-archive $(PERFLIBS) $(EXTRA_PERFLIBS) -Wl,--no-whole-archive -Wl,--start-group $(EXTLIBS) -Wl,--end-group
356 362
357ifeq ($(USE_CLANG), 1) 363ifeq ($(USE_CLANG), 1)
358 CLANGLIBS_LIST = AST Basic CodeGen Driver Frontend Lex Tooling Edit Sema Analysis Parse Serialization 364 CLANGLIBS_LIST = AST Basic CodeGen Driver Frontend Lex Tooling Edit Sema Analysis Parse Serialization
@@ -512,7 +518,7 @@ $(LIBJVMTI_IN): FORCE
512 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=jvmti obj=jvmti 518 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=jvmti obj=jvmti
513 519
514$(OUTPUT)$(LIBJVMTI): $(LIBJVMTI_IN) 520$(OUTPUT)$(LIBJVMTI): $(LIBJVMTI_IN)
515 $(QUIET_LINK)$(CC) -shared -Wl,-soname -Wl,$(LIBJVMTI) -o $@ $< -lelf -lrt 521 $(QUIET_LINK)$(CC) -shared -Wl,-soname -Wl,$(LIBJVMTI) -o $@ $<
516endif 522endif
517 523
518$(patsubst perf-%,%.o,$(PROGRAMS)): $(wildcard */*.h) 524$(patsubst perf-%,%.o,$(PROGRAMS)): $(wildcard */*.h)
diff --git a/tools/perf/arch/s390/util/Build b/tools/perf/arch/s390/util/Build
index 5bd7b9260cc0..bd518b623d7a 100644
--- a/tools/perf/arch/s390/util/Build
+++ b/tools/perf/arch/s390/util/Build
@@ -1,4 +1,5 @@
1libperf-y += header.o 1libperf-y += header.o
2libperf-y += sym-handling.o
2libperf-y += kvm-stat.o 3libperf-y += kvm-stat.o
3 4
4libperf-$(CONFIG_DWARF) += dwarf-regs.o 5libperf-$(CONFIG_DWARF) += dwarf-regs.o
diff --git a/tools/perf/arch/s390/util/sym-handling.c b/tools/perf/arch/s390/util/sym-handling.c
new file mode 100644
index 000000000000..b6cd056ccf71
--- /dev/null
+++ b/tools/perf/arch/s390/util/sym-handling.c
@@ -0,0 +1,22 @@
1/*
2 * Architecture specific ELF symbol handling and relocation mapping.
3 *
4 * Copyright 2017 IBM Corp.
5 * Author(s): Thomas Richter <tmricht@linux.vnet.ibm.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License (version 2 only)
9 * as published by the Free Software Foundation.
10 */
11
12#include "symbol.h"
13
14#ifdef HAVE_LIBELF_SUPPORT
15bool elf__needs_adjust_symbols(GElf_Ehdr ehdr)
16{
17 if (ehdr.e_type == ET_EXEC)
18 return false;
19 return ehdr.e_type == ET_REL || ehdr.e_type == ET_DYN;
20}
21
22#endif
diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c
index 9535be57033f..db0ba8caf5a2 100644
--- a/tools/perf/arch/x86/util/intel-pt.c
+++ b/tools/perf/arch/x86/util/intel-pt.c
@@ -701,6 +701,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
701 perf_evsel__set_sample_bit(switch_evsel, TID); 701 perf_evsel__set_sample_bit(switch_evsel, TID);
702 perf_evsel__set_sample_bit(switch_evsel, TIME); 702 perf_evsel__set_sample_bit(switch_evsel, TIME);
703 perf_evsel__set_sample_bit(switch_evsel, CPU); 703 perf_evsel__set_sample_bit(switch_evsel, CPU);
704 perf_evsel__reset_sample_bit(switch_evsel, BRANCH_STACK);
704 705
705 opts->record_switch_events = false; 706 opts->record_switch_events = false;
706 ptr->have_sched_switch = 3; 707 ptr->have_sched_switch = 3;
@@ -752,6 +753,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
752 tracking_evsel->attr.freq = 0; 753 tracking_evsel->attr.freq = 0;
753 tracking_evsel->attr.sample_period = 1; 754 tracking_evsel->attr.sample_period = 1;
754 755
756 tracking_evsel->no_aux_samples = true;
755 if (need_immediate) 757 if (need_immediate)
756 tracking_evsel->immediate = true; 758 tracking_evsel->immediate = true;
757 759
@@ -761,6 +763,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
761 /* And the CPU for switch events */ 763 /* And the CPU for switch events */
762 perf_evsel__set_sample_bit(tracking_evsel, CPU); 764 perf_evsel__set_sample_bit(tracking_evsel, CPU);
763 } 765 }
766 perf_evsel__reset_sample_bit(tracking_evsel, BRANCH_STACK);
764 } 767 }
765 768
766 /* 769 /*
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 5205408e795b..6db782dfce96 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -177,14 +177,13 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
177 */ 177 */
178 process_branch_stack(sample->branch_stack, al, sample); 178 process_branch_stack(sample->branch_stack, al, sample);
179 179
180 sample->period = 1;
181 sample->weight = 1; 180 sample->weight = 1;
182 181
183 he = hists__add_entry(hists, al, NULL, NULL, NULL, sample, true); 182 he = hists__add_entry(hists, al, NULL, NULL, NULL, sample, true);
184 if (he == NULL) 183 if (he == NULL)
185 return -ENOMEM; 184 return -ENOMEM;
186 185
187 ret = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); 186 ret = hist_entry__inc_addr_samples(he, sample, evsel->idx, al->addr);
188 hists__inc_nr_samples(hists, true); 187 hists__inc_nr_samples(hists, true);
189 return ret; 188 return ret;
190} 189}
@@ -397,6 +396,7 @@ int cmd_annotate(int argc, const char **argv)
397 .namespaces = perf_event__process_namespaces, 396 .namespaces = perf_event__process_namespaces,
398 .attr = perf_event__process_attr, 397 .attr = perf_event__process_attr,
399 .build_id = perf_event__process_build_id, 398 .build_id = perf_event__process_build_id,
399 .tracing_data = perf_event__process_tracing_data,
400 .feature = perf_event__process_feature, 400 .feature = perf_event__process_feature,
401 .ordered_events = true, 401 .ordered_events = true,
402 .ordering_requires_timestamps = true, 402 .ordering_requires_timestamps = true,
diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
index ece45582a48d..3ddcc6e2abeb 100644
--- a/tools/perf/builtin-config.c
+++ b/tools/perf/builtin-config.c
@@ -13,6 +13,7 @@
13#include "util/util.h" 13#include "util/util.h"
14#include "util/debug.h" 14#include "util/debug.h"
15#include "util/config.h" 15#include "util/config.h"
16#include <linux/string.h>
16 17
17static bool use_system_config, use_user_config; 18static bool use_system_config, use_user_config;
18 19
@@ -79,7 +80,7 @@ static int show_spec_config(struct perf_config_set *set, const char *var)
79 return -1; 80 return -1;
80 81
81 perf_config_items__for_each_entry(&set->sections, section) { 82 perf_config_items__for_each_entry(&set->sections, section) {
82 if (prefixcmp(var, section->name) != 0) 83 if (!strstarts(var, section->name))
83 continue; 84 continue;
84 85
85 perf_config_items__for_each_entry(&section->items, item) { 86 perf_config_items__for_each_entry(&section->items, item) {
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index dd26c62c9893..25a42acabee1 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -381,7 +381,7 @@ static int perf_ftrace_config(const char *var, const char *value, void *cb)
381{ 381{
382 struct perf_ftrace *ftrace = cb; 382 struct perf_ftrace *ftrace = cb;
383 383
384 if (prefixcmp(var, "ftrace.")) 384 if (!strstarts(var, "ftrace."))
385 return 0; 385 return 0;
386 386
387 if (strcmp(var, "ftrace.tracer")) 387 if (strcmp(var, "ftrace.tracer"))
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c
index 530a7f2fa0f3..dbe4e4153bcf 100644
--- a/tools/perf/builtin-help.c
+++ b/tools/perf/builtin-help.c
@@ -90,7 +90,7 @@ static int check_emacsclient_version(void)
90 */ 90 */
91 finish_command(&ec_process); 91 finish_command(&ec_process);
92 92
93 if (prefixcmp(buffer.buf, "emacsclient")) { 93 if (!strstarts(buffer.buf, "emacsclient")) {
94 fprintf(stderr, "Failed to parse emacsclient version.\n"); 94 fprintf(stderr, "Failed to parse emacsclient version.\n");
95 goto out; 95 goto out;
96 } 96 }
@@ -283,7 +283,7 @@ static int perf_help_config(const char *var, const char *value, void *cb)
283 add_man_viewer(value); 283 add_man_viewer(value);
284 return 0; 284 return 0;
285 } 285 }
286 if (!prefixcmp(var, "man.")) 286 if (!strstarts(var, "man."))
287 return add_man_viewer_info(var, value); 287 return add_man_viewer_info(var, value);
288 288
289 return 0; 289 return 0;
@@ -313,7 +313,7 @@ static const char *cmd_to_page(const char *perf_cmd)
313 313
314 if (!perf_cmd) 314 if (!perf_cmd)
315 return "perf"; 315 return "perf";
316 else if (!prefixcmp(perf_cmd, "perf")) 316 else if (!strstarts(perf_cmd, "perf"))
317 return perf_cmd; 317 return perf_cmd;
318 318
319 return asprintf(&s, "perf-%s", perf_cmd) < 0 ? NULL : s; 319 return asprintf(&s, "perf-%s", perf_cmd) < 0 ? NULL : s;
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index cea25d03f4dd..bace3429c030 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -115,37 +115,38 @@ static int hist_iter__report_callback(struct hist_entry_iter *iter,
115 struct report *rep = arg; 115 struct report *rep = arg;
116 struct hist_entry *he = iter->he; 116 struct hist_entry *he = iter->he;
117 struct perf_evsel *evsel = iter->evsel; 117 struct perf_evsel *evsel = iter->evsel;
118 struct perf_sample *sample = iter->sample;
118 struct mem_info *mi; 119 struct mem_info *mi;
119 struct branch_info *bi; 120 struct branch_info *bi;
120 121
121 if (!ui__has_annotation()) 122 if (!ui__has_annotation())
122 return 0; 123 return 0;
123 124
124 hist__account_cycles(iter->sample->branch_stack, al, iter->sample, 125 hist__account_cycles(sample->branch_stack, al, sample,
125 rep->nonany_branch_mode); 126 rep->nonany_branch_mode);
126 127
127 if (sort__mode == SORT_MODE__BRANCH) { 128 if (sort__mode == SORT_MODE__BRANCH) {
128 bi = he->branch_info; 129 bi = he->branch_info;
129 err = addr_map_symbol__inc_samples(&bi->from, evsel->idx); 130 err = addr_map_symbol__inc_samples(&bi->from, sample, evsel->idx);
130 if (err) 131 if (err)
131 goto out; 132 goto out;
132 133
133 err = addr_map_symbol__inc_samples(&bi->to, evsel->idx); 134 err = addr_map_symbol__inc_samples(&bi->to, sample, evsel->idx);
134 135
135 } else if (rep->mem_mode) { 136 } else if (rep->mem_mode) {
136 mi = he->mem_info; 137 mi = he->mem_info;
137 err = addr_map_symbol__inc_samples(&mi->daddr, evsel->idx); 138 err = addr_map_symbol__inc_samples(&mi->daddr, sample, evsel->idx);
138 if (err) 139 if (err)
139 goto out; 140 goto out;
140 141
141 err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); 142 err = hist_entry__inc_addr_samples(he, sample, evsel->idx, al->addr);
142 143
143 } else if (symbol_conf.cumulate_callchain) { 144 } else if (symbol_conf.cumulate_callchain) {
144 if (single) 145 if (single)
145 err = hist_entry__inc_addr_samples(he, evsel->idx, 146 err = hist_entry__inc_addr_samples(he, sample, evsel->idx,
146 al->addr); 147 al->addr);
147 } else { 148 } else {
148 err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); 149 err = hist_entry__inc_addr_samples(he, sample, evsel->idx, al->addr);
149 } 150 }
150 151
151out: 152out:
@@ -278,10 +279,11 @@ static int report__setup_sample_type(struct report *rep)
278 "'perf record' without -g?\n"); 279 "'perf record' without -g?\n");
279 return -EINVAL; 280 return -EINVAL;
280 } 281 }
281 if (symbol_conf.use_callchain) { 282 if (symbol_conf.use_callchain &&
282 ui__error("Selected -g or --branch-history but no " 283 !symbol_conf.show_branchflag_count) {
283 "callchain data. Did\n" 284 ui__error("Selected -g or --branch-history.\n"
284 "you call 'perf record' without -g?\n"); 285 "But no callchain or branch data.\n"
286 "Did you call 'perf record' without -g or -b?\n");
285 return -1; 287 return -1;
286 } 288 }
287 } else if (!callchain_param.enabled && 289 } else if (!callchain_param.enabled &&
@@ -416,7 +418,8 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
416 418
417 hists__fprintf_nr_sample_events(hists, rep, evname, stdout); 419 hists__fprintf_nr_sample_events(hists, rep, evname, stdout);
418 hists__fprintf(hists, !quiet, 0, 0, rep->min_percent, stdout, 420 hists__fprintf(hists, !quiet, 0, 0, rep->min_percent, stdout,
419 symbol_conf.use_callchain); 421 symbol_conf.use_callchain ||
422 symbol_conf.show_branchflag_count);
420 fprintf(stdout, "\n\n"); 423 fprintf(stdout, "\n\n");
421 } 424 }
422 425
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index d430ff42208a..378f76cdf923 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -2199,16 +2199,11 @@ static struct script_desc *script_desc__findnew(const char *name)
2199 2199
2200 s = script_desc__new(name); 2200 s = script_desc__new(name);
2201 if (!s) 2201 if (!s)
2202 goto out_delete_desc; 2202 return NULL;
2203 2203
2204 script_desc__add(s); 2204 script_desc__add(s);
2205 2205
2206 return s; 2206 return s;
2207
2208out_delete_desc:
2209 script_desc__delete(s);
2210
2211 return NULL;
2212} 2207}
2213 2208
2214static const char *ends_with(const char *str, const char *suffix) 2209static const char *ends_with(const char *str, const char *suffix)
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 022486dc67f5..ee954bde7e3e 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -183,6 +183,7 @@ static void ui__warn_map_erange(struct map *map, struct symbol *sym, u64 ip)
183 183
184static void perf_top__record_precise_ip(struct perf_top *top, 184static void perf_top__record_precise_ip(struct perf_top *top,
185 struct hist_entry *he, 185 struct hist_entry *he,
186 struct perf_sample *sample,
186 int counter, u64 ip) 187 int counter, u64 ip)
187{ 188{
188 struct annotation *notes; 189 struct annotation *notes;
@@ -199,7 +200,7 @@ static void perf_top__record_precise_ip(struct perf_top *top,
199 if (pthread_mutex_trylock(&notes->lock)) 200 if (pthread_mutex_trylock(&notes->lock))
200 return; 201 return;
201 202
202 err = hist_entry__inc_addr_samples(he, counter, ip); 203 err = hist_entry__inc_addr_samples(he, sample, counter, ip);
203 204
204 pthread_mutex_unlock(&notes->lock); 205 pthread_mutex_unlock(&notes->lock);
205 206
@@ -586,6 +587,13 @@ static void *display_thread_tui(void *arg)
586 .refresh = top->delay_secs, 587 .refresh = top->delay_secs,
587 }; 588 };
588 589
590 /* In order to read symbols from other namespaces perf to needs to call
591 * setns(2). This isn't permitted if the struct_fs has multiple users.
592 * unshare(2) the fs so that we may continue to setns into namespaces
593 * that we're observing.
594 */
595 unshare(CLONE_FS);
596
589 perf_top__sort_new_samples(top); 597 perf_top__sort_new_samples(top);
590 598
591 /* 599 /*
@@ -627,6 +635,13 @@ static void *display_thread(void *arg)
627 struct perf_top *top = arg; 635 struct perf_top *top = arg;
628 int delay_msecs, c; 636 int delay_msecs, c;
629 637
638 /* In order to read symbols from other namespaces perf to needs to call
639 * setns(2). This isn't permitted if the struct_fs has multiple users.
640 * unshare(2) the fs so that we may continue to setns into namespaces
641 * that we're observing.
642 */
643 unshare(CLONE_FS);
644
630 display_setup_sig(); 645 display_setup_sig();
631 pthread__unblock_sigwinch(); 646 pthread__unblock_sigwinch();
632repeat: 647repeat:
@@ -671,7 +686,7 @@ static int hist_iter__top_callback(struct hist_entry_iter *iter,
671 struct perf_evsel *evsel = iter->evsel; 686 struct perf_evsel *evsel = iter->evsel;
672 687
673 if (perf_hpp_list.sym && single) 688 if (perf_hpp_list.sym && single)
674 perf_top__record_precise_ip(top, he, evsel->idx, al->addr); 689 perf_top__record_precise_ip(top, he, iter->sample, evsel->idx, al->addr);
675 690
676 hist__account_cycles(iter->sample->branch_stack, al, iter->sample, 691 hist__account_cycles(iter->sample->branch_stack, al, iter->sample,
677 !(top->record_opts.branch_stack & PERF_SAMPLE_BRANCH_ANY)); 692 !(top->record_opts.branch_stack & PERF_SAMPLE_BRANCH_ANY));
@@ -1205,6 +1220,7 @@ int cmd_top(int argc, const char **argv)
1205 "Show raw trace event output (do not use print fmt or plugins)"), 1220 "Show raw trace event output (do not use print fmt or plugins)"),
1206 OPT_BOOLEAN(0, "hierarchy", &symbol_conf.report_hierarchy, 1221 OPT_BOOLEAN(0, "hierarchy", &symbol_conf.report_hierarchy,
1207 "Show entries in a hierarchy"), 1222 "Show entries in a hierarchy"),
1223 OPT_BOOLEAN(0, "force", &symbol_conf.force, "don't complain, do it"),
1208 OPT_END() 1224 OPT_END()
1209 }; 1225 };
1210 const char * const top_usage[] = { 1226 const char * const top_usage[] = {
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 1e4c0657b712..05d24b6570ee 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -604,6 +604,7 @@ static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size,
604struct syscall_arg_fmt { 604struct syscall_arg_fmt {
605 size_t (*scnprintf)(char *bf, size_t size, struct syscall_arg *arg); 605 size_t (*scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
606 void *parm; 606 void *parm;
607 const char *name;
607 bool show_zero; 608 bool show_zero;
608}; 609};
609 610
@@ -611,6 +612,7 @@ static struct syscall_fmt {
611 const char *name; 612 const char *name;
612 const char *alias; 613 const char *alias;
613 struct syscall_arg_fmt arg[6]; 614 struct syscall_arg_fmt arg[6];
615 u8 nr_args;
614 bool errpid; 616 bool errpid;
615 bool timeout; 617 bool timeout;
616 bool hexret; 618 bool hexret;
@@ -624,7 +626,12 @@ static struct syscall_fmt {
624 .arg = { [0] = { .scnprintf = SCA_HEX, /* brk */ }, }, }, 626 .arg = { [0] = { .scnprintf = SCA_HEX, /* brk */ }, }, },
625 { .name = "clock_gettime", 627 { .name = "clock_gettime",
626 .arg = { [0] = STRARRAY(clk_id, clockid), }, }, 628 .arg = { [0] = STRARRAY(clk_id, clockid), }, },
627 { .name = "clone", .errpid = true, }, 629 { .name = "clone", .errpid = true, .nr_args = 5,
630 .arg = { [0] = { .name = "flags", .scnprintf = SCA_CLONE_FLAGS, },
631 [1] = { .name = "child_stack", .scnprintf = SCA_HEX, },
632 [2] = { .name = "parent_tidptr", .scnprintf = SCA_HEX, },
633 [3] = { .name = "child_tidptr", .scnprintf = SCA_HEX, },
634 [4] = { .name = "tls", .scnprintf = SCA_HEX, }, }, },
628 { .name = "close", 635 { .name = "close",
629 .arg = { [0] = { .scnprintf = SCA_CLOSE_FD, /* fd */ }, }, }, 636 .arg = { [0] = { .scnprintf = SCA_CLOSE_FD, /* fd */ }, }, },
630 { .name = "epoll_ctl", 637 { .name = "epoll_ctl",
@@ -1165,22 +1172,34 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
1165 return err; 1172 return err;
1166} 1173}
1167 1174
1168static int syscall__set_arg_fmts(struct syscall *sc) 1175static int syscall__alloc_arg_fmts(struct syscall *sc, int nr_args)
1169{ 1176{
1170 struct format_field *field; 1177 int idx;
1171 int idx = 0, len; 1178
1179 if (nr_args == 6 && sc->fmt && sc->fmt->nr_args != 0)
1180 nr_args = sc->fmt->nr_args;
1172 1181
1173 sc->arg_fmt = calloc(sc->nr_args, sizeof(*sc->arg_fmt)); 1182 sc->arg_fmt = calloc(nr_args, sizeof(*sc->arg_fmt));
1174 if (sc->arg_fmt == NULL) 1183 if (sc->arg_fmt == NULL)
1175 return -1; 1184 return -1;
1176 1185
1177 for (field = sc->args; field; field = field->next, ++idx) { 1186 for (idx = 0; idx < nr_args; ++idx) {
1178 if (sc->fmt) { 1187 if (sc->fmt)
1179 sc->arg_fmt[idx] = sc->fmt->arg[idx]; 1188 sc->arg_fmt[idx] = sc->fmt->arg[idx];
1189 }
1180 1190
1181 if (sc->fmt->arg[idx].scnprintf) 1191 sc->nr_args = nr_args;
1182 continue; 1192 return 0;
1183 } 1193}
1194
1195static int syscall__set_arg_fmts(struct syscall *sc)
1196{
1197 struct format_field *field;
1198 int idx = 0, len;
1199
1200 for (field = sc->args; field; field = field->next, ++idx) {
1201 if (sc->fmt && sc->fmt->arg[idx].scnprintf)
1202 continue;
1184 1203
1185 if (strcmp(field->type, "const char *") == 0 && 1204 if (strcmp(field->type, "const char *") == 0 &&
1186 (strcmp(field->name, "filename") == 0 || 1205 (strcmp(field->name, "filename") == 0 ||
@@ -1251,11 +1270,13 @@ static int trace__read_syscall_info(struct trace *trace, int id)
1251 sc->tp_format = trace_event__tp_format("syscalls", tp_name); 1270 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
1252 } 1271 }
1253 1272
1273 if (syscall__alloc_arg_fmts(sc, IS_ERR(sc->tp_format) ? 6 : sc->tp_format->format.nr_fields))
1274 return -1;
1275
1254 if (IS_ERR(sc->tp_format)) 1276 if (IS_ERR(sc->tp_format))
1255 return -1; 1277 return -1;
1256 1278
1257 sc->args = sc->tp_format->format.fields; 1279 sc->args = sc->tp_format->format.fields;
1258 sc->nr_args = sc->tp_format->format.nr_fields;
1259 /* 1280 /*
1260 * We need to check and discard the first variable '__syscall_nr' 1281 * We need to check and discard the first variable '__syscall_nr'
1261 * or 'nr' that mean the syscall number. It is needless here. 1282 * or 'nr' that mean the syscall number. It is needless here.
@@ -1325,18 +1346,34 @@ out:
1325 * variable to read it. Most notably this avoids extended load instructions 1346 * variable to read it. Most notably this avoids extended load instructions
1326 * on unaligned addresses 1347 * on unaligned addresses
1327 */ 1348 */
1328static unsigned long __syscall_arg__val(unsigned char *args, u8 idx) 1349unsigned long syscall_arg__val(struct syscall_arg *arg, u8 idx)
1329{ 1350{
1330 unsigned long val; 1351 unsigned long val;
1331 unsigned char *p = args + sizeof(unsigned long) * idx; 1352 unsigned char *p = arg->args + sizeof(unsigned long) * idx;
1332 1353
1333 memcpy(&val, p, sizeof(val)); 1354 memcpy(&val, p, sizeof(val));
1334 return val; 1355 return val;
1335} 1356}
1336 1357
1337unsigned long syscall_arg__val(struct syscall_arg *arg, u8 idx) 1358static size_t syscall__scnprintf_name(struct syscall *sc, char *bf, size_t size,
1359 struct syscall_arg *arg)
1360{
1361 if (sc->arg_fmt && sc->arg_fmt[arg->idx].name)
1362 return scnprintf(bf, size, "%s: ", sc->arg_fmt[arg->idx].name);
1363
1364 return scnprintf(bf, size, "arg%d: ", arg->idx);
1365}
1366
1367static size_t syscall__scnprintf_val(struct syscall *sc, char *bf, size_t size,
1368 struct syscall_arg *arg, unsigned long val)
1338{ 1369{
1339 return __syscall_arg__val(arg->args, idx); 1370 if (sc->arg_fmt && sc->arg_fmt[arg->idx].scnprintf) {
1371 arg->val = val;
1372 if (sc->arg_fmt[arg->idx].parm)
1373 arg->parm = sc->arg_fmt[arg->idx].parm;
1374 return sc->arg_fmt[arg->idx].scnprintf(bf, size, arg);
1375 }
1376 return scnprintf(bf, size, "%ld", val);
1340} 1377}
1341 1378
1342static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size, 1379static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
@@ -1345,6 +1382,14 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
1345{ 1382{
1346 size_t printed = 0; 1383 size_t printed = 0;
1347 unsigned long val; 1384 unsigned long val;
1385 u8 bit = 1;
1386 struct syscall_arg arg = {
1387 .args = args,
1388 .idx = 0,
1389 .mask = 0,
1390 .trace = trace,
1391 .thread = thread,
1392 };
1348 struct thread_trace *ttrace = thread__priv(thread); 1393 struct thread_trace *ttrace = thread__priv(thread);
1349 1394
1350 /* 1395 /*
@@ -1356,14 +1401,6 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
1356 1401
1357 if (sc->args != NULL) { 1402 if (sc->args != NULL) {
1358 struct format_field *field; 1403 struct format_field *field;
1359 u8 bit = 1;
1360 struct syscall_arg arg = {
1361 .args = args,
1362 .idx = 0,
1363 .mask = 0,
1364 .trace = trace,
1365 .thread = thread,
1366 };
1367 1404
1368 for (field = sc->args; field; 1405 for (field = sc->args; field;
1369 field = field->next, ++arg.idx, bit <<= 1) { 1406 field = field->next, ++arg.idx, bit <<= 1) {
@@ -1387,15 +1424,7 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
1387 1424
1388 printed += scnprintf(bf + printed, size - printed, 1425 printed += scnprintf(bf + printed, size - printed,
1389 "%s%s: ", printed ? ", " : "", field->name); 1426 "%s%s: ", printed ? ", " : "", field->name);
1390 if (sc->arg_fmt && sc->arg_fmt[arg.idx].scnprintf) { 1427 printed += syscall__scnprintf_val(sc, bf + printed, size - printed, &arg, val);
1391 arg.val = val;
1392 if (sc->arg_fmt[arg.idx].parm)
1393 arg.parm = sc->arg_fmt[arg.idx].parm;
1394 printed += sc->arg_fmt[arg.idx].scnprintf(bf + printed, size - printed, &arg);
1395 } else {
1396 printed += scnprintf(bf + printed, size - printed,
1397 "%ld", val);
1398 }
1399 } 1428 }
1400 } else if (IS_ERR(sc->tp_format)) { 1429 } else if (IS_ERR(sc->tp_format)) {
1401 /* 1430 /*
@@ -1403,14 +1432,17 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
1403 * may end up not having any args, like with gettid(), so only 1432 * may end up not having any args, like with gettid(), so only
1404 * print the raw args when we didn't manage to read it. 1433 * print the raw args when we didn't manage to read it.
1405 */ 1434 */
1406 int i = 0; 1435 while (arg.idx < sc->nr_args) {
1407 1436 if (arg.mask & bit)
1408 while (i < 6) { 1437 goto next_arg;
1409 val = __syscall_arg__val(args, i); 1438 val = syscall_arg__val(&arg, arg.idx);
1410 printed += scnprintf(bf + printed, size - printed, 1439 if (printed)
1411 "%sarg%d: %ld", 1440 printed += scnprintf(bf + printed, size - printed, ", ");
1412 printed ? ", " : "", i, val); 1441 printed += syscall__scnprintf_name(sc, bf + printed, size - printed, &arg);
1413 ++i; 1442 printed += syscall__scnprintf_val(sc, bf + printed, size - printed, &arg, val);
1443next_arg:
1444 ++arg.idx;
1445 bit <<= 1;
1414 } 1446 }
1415 } 1447 }
1416 1448
@@ -1660,7 +1692,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
1660 if (ret < 0) 1692 if (ret < 0)
1661 goto errno_print; 1693 goto errno_print;
1662signed_print: 1694signed_print:
1663 fprintf(trace->output, ") %ld", ret); 1695 fprintf(trace->output, ") = %ld", ret);
1664 } else if (ret < 0) { 1696 } else if (ret < 0) {
1665errno_print: { 1697errno_print: {
1666 char bf[STRERR_BUFSIZE]; 1698 char bf[STRERR_BUFSIZE];
@@ -2207,6 +2239,30 @@ out_enomem:
2207 goto out; 2239 goto out;
2208} 2240}
2209 2241
2242static int trace__set_filter_loop_pids(struct trace *trace)
2243{
2244 unsigned int nr = 1;
2245 pid_t pids[32] = {
2246 getpid(),
2247 };
2248 struct thread *thread = machine__find_thread(trace->host, pids[0], pids[0]);
2249
2250 while (thread && nr < ARRAY_SIZE(pids)) {
2251 struct thread *parent = machine__find_thread(trace->host, thread->ppid, thread->ppid);
2252
2253 if (parent == NULL)
2254 break;
2255
2256 if (!strcmp(thread__comm_str(parent), "sshd")) {
2257 pids[nr++] = parent->tid;
2258 break;
2259 }
2260 thread = parent;
2261 }
2262
2263 return perf_evlist__set_filter_pids(trace->evlist, nr, pids);
2264}
2265
2210static int trace__run(struct trace *trace, int argc, const char **argv) 2266static int trace__run(struct trace *trace, int argc, const char **argv)
2211{ 2267{
2212 struct perf_evlist *evlist = trace->evlist; 2268 struct perf_evlist *evlist = trace->evlist;
@@ -2330,7 +2386,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2330 if (trace->filter_pids.nr > 0) 2386 if (trace->filter_pids.nr > 0)
2331 err = perf_evlist__set_filter_pids(evlist, trace->filter_pids.nr, trace->filter_pids.entries); 2387 err = perf_evlist__set_filter_pids(evlist, trace->filter_pids.nr, trace->filter_pids.entries);
2332 else if (thread_map__pid(evlist->threads, 0) == -1) 2388 else if (thread_map__pid(evlist->threads, 0) == -1)
2333 err = perf_evlist__set_filter_pid(evlist, getpid()); 2389 err = trace__set_filter_loop_pids(trace);
2334 2390
2335 if (err < 0) 2391 if (err < 0)
2336 goto out_error_mem; 2392 goto out_error_mem;
diff --git a/tools/perf/check-headers.sh b/tools/perf/check-headers.sh
index 47abd3325190..9b6295809a3b 100755
--- a/tools/perf/check-headers.sh
+++ b/tools/perf/check-headers.sh
@@ -3,6 +3,7 @@
3HEADERS=' 3HEADERS='
4include/uapi/linux/fcntl.h 4include/uapi/linux/fcntl.h
5include/uapi/linux/perf_event.h 5include/uapi/linux/perf_event.h
6include/uapi/linux/sched.h
6include/uapi/linux/stat.h 7include/uapi/linux/stat.h
7include/linux/hash.h 8include/linux/hash.h
8include/uapi/linux/hw_breakpoint.h 9include/uapi/linux/hw_breakpoint.h
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 628a5e412cb1..e0279babe0c0 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -89,7 +89,7 @@ struct pager_config {
89static int pager_command_config(const char *var, const char *value, void *data) 89static int pager_command_config(const char *var, const char *value, void *data)
90{ 90{
91 struct pager_config *c = data; 91 struct pager_config *c = data;
92 if (!prefixcmp(var, "pager.") && !strcmp(var + 6, c->cmd)) 92 if (strstarts(var, "pager.") && !strcmp(var + 6, c->cmd))
93 c->val = perf_config_bool(var, value); 93 c->val = perf_config_bool(var, value);
94 return 0; 94 return 0;
95} 95}
@@ -108,9 +108,9 @@ static int check_pager_config(const char *cmd)
108static int browser_command_config(const char *var, const char *value, void *data) 108static int browser_command_config(const char *var, const char *value, void *data)
109{ 109{
110 struct pager_config *c = data; 110 struct pager_config *c = data;
111 if (!prefixcmp(var, "tui.") && !strcmp(var + 4, c->cmd)) 111 if (strstarts(var, "tui.") && !strcmp(var + 4, c->cmd))
112 c->val = perf_config_bool(var, value); 112 c->val = perf_config_bool(var, value);
113 if (!prefixcmp(var, "gtk.") && !strcmp(var + 4, c->cmd)) 113 if (strstarts(var, "gtk.") && !strcmp(var + 4, c->cmd))
114 c->val = perf_config_bool(var, value) ? 2 : 0; 114 c->val = perf_config_bool(var, value) ? 2 : 0;
115 return 0; 115 return 0;
116} 116}
@@ -192,7 +192,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
192 /* 192 /*
193 * Check remaining flags. 193 * Check remaining flags.
194 */ 194 */
195 if (!prefixcmp(cmd, CMD_EXEC_PATH)) { 195 if (strstarts(cmd, CMD_EXEC_PATH)) {
196 cmd += strlen(CMD_EXEC_PATH); 196 cmd += strlen(CMD_EXEC_PATH);
197 if (*cmd == '=') 197 if (*cmd == '=')
198 set_argv_exec_path(cmd + 1); 198 set_argv_exec_path(cmd + 1);
@@ -229,7 +229,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
229 *envchanged = 1; 229 *envchanged = 1;
230 (*argv)++; 230 (*argv)++;
231 (*argc)--; 231 (*argc)--;
232 } else if (!prefixcmp(cmd, CMD_DEBUGFS_DIR)) { 232 } else if (strstarts(cmd, CMD_DEBUGFS_DIR)) {
233 tracing_path_set(cmd + strlen(CMD_DEBUGFS_DIR)); 233 tracing_path_set(cmd + strlen(CMD_DEBUGFS_DIR));
234 fprintf(stderr, "dir: %s\n", tracing_path); 234 fprintf(stderr, "dir: %s\n", tracing_path);
235 if (envchanged) 235 if (envchanged)
@@ -470,14 +470,14 @@ int main(int argc, const char **argv)
470 * So we just directly call the internal command handler, and 470 * So we just directly call the internal command handler, and
471 * die if that one cannot handle it. 471 * die if that one cannot handle it.
472 */ 472 */
473 if (!prefixcmp(cmd, "perf-")) { 473 if (strstarts(cmd, "perf-")) {
474 cmd += 5; 474 cmd += 5;
475 argv[0] = cmd; 475 argv[0] = cmd;
476 handle_internal_command(argc, argv); 476 handle_internal_command(argc, argv);
477 fprintf(stderr, "cannot handle %s internally", cmd); 477 fprintf(stderr, "cannot handle %s internally", cmd);
478 goto out; 478 goto out;
479 } 479 }
480 if (!prefixcmp(cmd, "trace")) { 480 if (strstarts(cmd, "trace")) {
481#ifdef HAVE_LIBAUDIT_SUPPORT 481#ifdef HAVE_LIBAUDIT_SUPPORT
482 setup_path(); 482 setup_path();
483 argv[0] = "trace"; 483 argv[0] = "trace";
@@ -495,7 +495,7 @@ int main(int argc, const char **argv)
495 commit_pager_choice(); 495 commit_pager_choice();
496 496
497 if (argc > 0) { 497 if (argc > 0) {
498 if (!prefixcmp(argv[0], "--")) 498 if (strstarts(argv[0], "--"))
499 argv[0] += 2; 499 argv[0] += 2;
500 } else { 500 } else {
501 /* The user didn't specify a command; give them help */ 501 /* The user didn't specify a command; give them help */
diff --git a/tools/perf/pmu-events/README b/tools/perf/pmu-events/README
index 1408ade0d773..c2ee3e4417fe 100644
--- a/tools/perf/pmu-events/README
+++ b/tools/perf/pmu-events/README
@@ -85,10 +85,6 @@ users to specify events by their name:
85 85
86where 'pm_1plus_ppc_cmpl' is a Power8 PMU event. 86where 'pm_1plus_ppc_cmpl' is a Power8 PMU event.
87 87
88In case of errors when processing files in the tools/perf/pmu-events/arch
89directory, 'jevents' tries to create an empty mapping file to allow the perf
90build to succeed even if the PMU event aliases cannot be used.
91
92However some errors in processing may cause the perf build to fail. 88However some errors in processing may cause the perf build to fail.
93 89
94Mapfile format 90Mapfile format
diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c
index bd0aabb2bd0f..2350f6099a46 100644
--- a/tools/perf/pmu-events/jevents.c
+++ b/tools/perf/pmu-events/jevents.c
@@ -822,10 +822,6 @@ static int process_one_file(const char *fpath, const struct stat *sb,
822 * PMU event tables (see struct pmu_events_map). 822 * PMU event tables (see struct pmu_events_map).
823 * 823 *
824 * Write out the PMU events tables and the mapping table to pmu-event.c. 824 * Write out the PMU events tables and the mapping table to pmu-event.c.
825 *
826 * If unable to process the JSON or arch files, create an empty mapping
827 * table so we can continue to build/use perf even if we cannot use the
828 * PMU event aliases.
829 */ 825 */
830int main(int argc, char *argv[]) 826int main(int argc, char *argv[])
831{ 827{
@@ -836,6 +832,7 @@ int main(int argc, char *argv[])
836 const char *arch; 832 const char *arch;
837 const char *output_file; 833 const char *output_file;
838 const char *start_dirname; 834 const char *start_dirname;
835 struct stat stbuf;
839 836
840 prog = basename(argv[0]); 837 prog = basename(argv[0]);
841 if (argc < 4) { 838 if (argc < 4) {
@@ -857,11 +854,17 @@ int main(int argc, char *argv[])
857 return 2; 854 return 2;
858 } 855 }
859 856
857 sprintf(ldirname, "%s/%s", start_dirname, arch);
858
859 /* If architecture does not have any event lists, bail out */
860 if (stat(ldirname, &stbuf) < 0) {
861 pr_info("%s: Arch %s has no PMU event lists\n", prog, arch);
862 goto empty_map;
863 }
864
860 /* Include pmu-events.h first */ 865 /* Include pmu-events.h first */
861 fprintf(eventsfp, "#include \"../../pmu-events/pmu-events.h\"\n"); 866 fprintf(eventsfp, "#include \"../../pmu-events/pmu-events.h\"\n");
862 867
863 sprintf(ldirname, "%s/%s", start_dirname, arch);
864
865 /* 868 /*
866 * The mapfile allows multiple CPUids to point to the same JSON file, 869 * The mapfile allows multiple CPUids to point to the same JSON file,
867 * so, not sure if there is a need for symlinks within the pmu-events 870 * so, not sure if there is a need for symlinks within the pmu-events
@@ -878,6 +881,9 @@ int main(int argc, char *argv[])
878 if (rc && verbose) { 881 if (rc && verbose) {
879 pr_info("%s: Error walking file tree %s\n", prog, ldirname); 882 pr_info("%s: Error walking file tree %s\n", prog, ldirname);
880 goto empty_map; 883 goto empty_map;
884 } else if (rc < 0) {
885 /* Make build fail */
886 return 1;
881 } else if (rc) { 887 } else if (rc) {
882 goto empty_map; 888 goto empty_map;
883 } 889 }
@@ -892,7 +898,8 @@ int main(int argc, char *argv[])
892 898
893 if (process_mapfile(eventsfp, mapfile)) { 899 if (process_mapfile(eventsfp, mapfile)) {
894 pr_info("%s: Error processing mapfile %s\n", prog, mapfile); 900 pr_info("%s: Error processing mapfile %s\n", prog, mapfile);
895 goto empty_map; 901 /* Make build fail */
902 return 1;
896 } 903 }
897 904
898 return 0; 905 return 0;
diff --git a/tools/perf/trace/beauty/Build b/tools/perf/trace/beauty/Build
index c9e215b806f1..eaa1e8e8e100 100644
--- a/tools/perf/trace/beauty/Build
+++ b/tools/perf/trace/beauty/Build
@@ -1,2 +1,3 @@
1libperf-y += clone.o
1libperf-y += fcntl.o 2libperf-y += fcntl.o
2libperf-y += statx.o 3libperf-y += statx.o
diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h
index f75ef7d0b303..69a5c8a2d420 100644
--- a/tools/perf/trace/beauty/beauty.h
+++ b/tools/perf/trace/beauty/beauty.h
@@ -66,6 +66,9 @@ size_t syscall_arg__scnprintf_long(char *bf, size_t size, struct syscall_arg *ar
66size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_arg *arg); 66size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_arg *arg);
67#define SCA_PID syscall_arg__scnprintf_pid 67#define SCA_PID syscall_arg__scnprintf_pid
68 68
69size_t syscall_arg__scnprintf_clone_flags(char *bf, size_t size, struct syscall_arg *arg);
70#define SCA_CLONE_FLAGS syscall_arg__scnprintf_clone_flags
71
69size_t syscall_arg__scnprintf_fcntl_cmd(char *bf, size_t size, struct syscall_arg *arg); 72size_t syscall_arg__scnprintf_fcntl_cmd(char *bf, size_t size, struct syscall_arg *arg);
70#define SCA_FCNTL_CMD syscall_arg__scnprintf_fcntl_cmd 73#define SCA_FCNTL_CMD syscall_arg__scnprintf_fcntl_cmd
71 74
diff --git a/tools/perf/trace/beauty/clone.c b/tools/perf/trace/beauty/clone.c
new file mode 100644
index 000000000000..d64d049ab991
--- /dev/null
+++ b/tools/perf/trace/beauty/clone.c
@@ -0,0 +1,75 @@
1/*
2 * trace/beauty/cone.c
3 *
4 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
5 *
6 * Released under the GPL v2. (and only v2, not any later version)
7 */
8
9#include "trace/beauty/beauty.h"
10#include <linux/kernel.h>
11#include <sys/types.h>
12#include <uapi/linux/sched.h>
13
14static size_t clone__scnprintf_flags(unsigned long flags, char *bf, size_t size)
15{
16 int printed = 0;
17
18#define P_FLAG(n) \
19 if (flags & CLONE_##n) { \
20 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
21 flags &= ~CLONE_##n; \
22 }
23
24 P_FLAG(VM);
25 P_FLAG(FS);
26 P_FLAG(FILES);
27 P_FLAG(SIGHAND);
28 P_FLAG(PTRACE);
29 P_FLAG(VFORK);
30 P_FLAG(PARENT);
31 P_FLAG(THREAD);
32 P_FLAG(NEWNS);
33 P_FLAG(SYSVSEM);
34 P_FLAG(SETTLS);
35 P_FLAG(PARENT_SETTID);
36 P_FLAG(CHILD_CLEARTID);
37 P_FLAG(DETACHED);
38 P_FLAG(UNTRACED);
39 P_FLAG(CHILD_SETTID);
40 P_FLAG(NEWCGROUP);
41 P_FLAG(NEWUTS);
42 P_FLAG(NEWIPC);
43 P_FLAG(NEWUSER);
44 P_FLAG(NEWPID);
45 P_FLAG(NEWNET);
46 P_FLAG(IO);
47#undef P_FLAG
48
49 if (flags)
50 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
51
52 return printed;
53}
54
55size_t syscall_arg__scnprintf_clone_flags(char *bf, size_t size, struct syscall_arg *arg)
56{
57 unsigned long flags = arg->val;
58 enum syscall_clone_args {
59 SCC_FLAGS = (1 << 0),
60 SCC_CHILD_STACK = (1 << 1),
61 SCC_PARENT_TIDPTR = (1 << 2),
62 SCC_CHILD_TIDPTR = (1 << 3),
63 SCC_TLS = (1 << 4),
64 };
65 if (!(flags & CLONE_PARENT_SETTID))
66 arg->mask |= SCC_PARENT_TIDPTR;
67
68 if (!(flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)))
69 arg->mask |= SCC_CHILD_TIDPTR;
70
71 if (!(flags & CLONE_SETTLS))
72 arg->mask |= SCC_TLS;
73
74 return clone__scnprintf_flags(flags, bf, size);
75}
diff --git a/tools/perf/trace/beauty/mmap.c b/tools/perf/trace/beauty/mmap.c
index af1cfde6b97b..754558f9009d 100644
--- a/tools/perf/trace/beauty/mmap.c
+++ b/tools/perf/trace/beauty/mmap.c
@@ -34,6 +34,9 @@ static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
34{ 34{
35 int printed = 0, flags = arg->val; 35 int printed = 0, flags = arg->val;
36 36
37 if (flags & MAP_ANONYMOUS)
38 arg->mask |= (1 << 4) | (1 << 5); /* Mask 4th ('fd') and 5th ('offset') args, ignored */
39
37#define P_MMAP_FLAG(n) \ 40#define P_MMAP_FLAG(n) \
38 if (flags & MAP_##n) { \ 41 if (flags & MAP_##n) { \
39 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \ 42 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c
index f73f3f13e01d..d0c2007c307b 100644
--- a/tools/perf/ui/browser.c
+++ b/tools/perf/ui/browser.c
@@ -8,6 +8,7 @@
8#include <linux/compiler.h> 8#include <linux/compiler.h>
9#include <linux/list.h> 9#include <linux/list.h>
10#include <linux/rbtree.h> 10#include <linux/rbtree.h>
11#include <linux/string.h>
11#include <stdlib.h> 12#include <stdlib.h>
12#include <sys/ttydefaults.h> 13#include <sys/ttydefaults.h>
13#include "browser.h" 14#include "browser.h"
@@ -563,7 +564,7 @@ static int ui_browser__color_config(const char *var, const char *value,
563 int i; 564 int i;
564 565
565 /* same dir for all commands */ 566 /* same dir for all commands */
566 if (prefixcmp(var, "colors.") != 0) 567 if (!strstarts(var, "colors.") != 0)
567 return 0; 568 return 0;
568 569
569 for (i = 0; ui_browser__colorsets[i].name != NULL; ++i) { 570 for (i = 0; ui_browser__colorsets[i].name != NULL; ++i) {
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 8d3f6f53c122..dbe4e630b90f 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -13,6 +13,7 @@
13#include <inttypes.h> 13#include <inttypes.h>
14#include <pthread.h> 14#include <pthread.h>
15#include <linux/kernel.h> 15#include <linux/kernel.h>
16#include <linux/string.h>
16#include <sys/ttydefaults.h> 17#include <sys/ttydefaults.h>
17 18
18struct disasm_line_samples { 19struct disasm_line_samples {
@@ -449,14 +450,14 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,
449 next = disasm__get_next_ip_line(&notes->src->source, pos); 450 next = disasm__get_next_ip_line(&notes->src->source, pos);
450 451
451 for (i = 0; i < browser->nr_events; i++) { 452 for (i = 0; i < browser->nr_events; i++) {
452 u64 nr_samples; 453 struct sym_hist_entry sample;
453 454
454 bpos->samples[i].percent = disasm__calc_percent(notes, 455 bpos->samples[i].percent = disasm__calc_percent(notes,
455 evsel->idx + i, 456 evsel->idx + i,
456 pos->offset, 457 pos->offset,
457 next ? next->offset : len, 458 next ? next->offset : len,
458 &path, &nr_samples); 459 &path, &sample);
459 bpos->samples[i].nr = nr_samples; 460 bpos->samples[i].nr = sample.nr_samples;
460 461
461 if (max_percent < bpos->samples[i].percent) 462 if (max_percent < bpos->samples[i].percent)
462 max_percent = bpos->samples[i].percent; 463 max_percent = bpos->samples[i].percent;
@@ -1198,7 +1199,7 @@ static int annotate__config(const char *var, const char *value,
1198 struct annotate_config *cfg; 1199 struct annotate_config *cfg;
1199 const char *name; 1200 const char *name;
1200 1201
1201 if (prefixcmp(var, "annotate.") != 0) 1202 if (!strstarts(var, "annotate."))
1202 return 0; 1203 return 0;
1203 1204
1204 name = var + 9; 1205 name = var + 9;
diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c
index 87e3760624f2..02176193f427 100644
--- a/tools/perf/ui/gtk/annotate.c
+++ b/tools/perf/ui/gtk/annotate.c
@@ -34,10 +34,10 @@ static int perf_gtk__get_percent(char *buf, size_t size, struct symbol *sym,
34 return 0; 34 return 0;
35 35
36 symhist = annotation__histogram(symbol__annotation(sym), evidx); 36 symhist = annotation__histogram(symbol__annotation(sym), evidx);
37 if (!symbol_conf.event_group && !symhist->addr[dl->offset]) 37 if (!symbol_conf.event_group && !symhist->addr[dl->offset].nr_samples)
38 return 0; 38 return 0;
39 39
40 percent = 100.0 * symhist->addr[dl->offset] / symhist->sum; 40 percent = 100.0 * symhist->addr[dl->offset].nr_samples / symhist->nr_samples;
41 41
42 markup = perf_gtk__get_percent_color(percent); 42 markup = perf_gtk__get_percent_color(percent);
43 if (markup) 43 if (markup)
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 2df8eb1ed3c0..5c95b8301c67 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -1,4 +1,5 @@
1#include <stdio.h> 1#include <stdio.h>
2#include <linux/string.h>
2 3
3#include "../../util/util.h" 4#include "../../util/util.h"
4#include "../../util/hist.h" 5#include "../../util/hist.h"
@@ -292,7 +293,7 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
292 * displayed twice. 293 * displayed twice.
293 */ 294 */
294 if (!i++ && field_order == NULL && 295 if (!i++ && field_order == NULL &&
295 sort_order && !prefixcmp(sort_order, "sym")) 296 sort_order && strstarts(sort_order, "sym"))
296 continue; 297 continue;
297 298
298 if (!printed) { 299 if (!printed) {
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 1742510f0120..c2b4b00166ed 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -610,10 +610,10 @@ int symbol__alloc_hist(struct symbol *sym)
610 size_t sizeof_sym_hist; 610 size_t sizeof_sym_hist;
611 611
612 /* Check for overflow when calculating sizeof_sym_hist */ 612 /* Check for overflow when calculating sizeof_sym_hist */
613 if (size > (SIZE_MAX - sizeof(struct sym_hist)) / sizeof(u64)) 613 if (size > (SIZE_MAX - sizeof(struct sym_hist)) / sizeof(struct sym_hist_entry))
614 return -1; 614 return -1;
615 615
616 sizeof_sym_hist = (sizeof(struct sym_hist) + size * sizeof(u64)); 616 sizeof_sym_hist = (sizeof(struct sym_hist) + size * sizeof(struct sym_hist_entry));
617 617
618 /* Check for overflow in zalloc argument */ 618 /* Check for overflow in zalloc argument */
619 if (sizeof_sym_hist > (SIZE_MAX - sizeof(*notes->src)) 619 if (sizeof_sym_hist > (SIZE_MAX - sizeof(*notes->src))
@@ -697,7 +697,8 @@ static int __symbol__account_cycles(struct annotation *notes,
697} 697}
698 698
699static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map, 699static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map,
700 struct annotation *notes, int evidx, u64 addr) 700 struct annotation *notes, int evidx, u64 addr,
701 struct perf_sample *sample)
701{ 702{
702 unsigned offset; 703 unsigned offset;
703 struct sym_hist *h; 704 struct sym_hist *h;
@@ -713,12 +714,15 @@ static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map,
713 714
714 offset = addr - sym->start; 715 offset = addr - sym->start;
715 h = annotation__histogram(notes, evidx); 716 h = annotation__histogram(notes, evidx);
716 h->sum++; 717 h->nr_samples++;
717 h->addr[offset]++; 718 h->addr[offset].nr_samples++;
719 h->period += sample->period;
720 h->addr[offset].period += sample->period;
718 721
719 pr_debug3("%#" PRIx64 " %s: period++ [addr: %#" PRIx64 ", %#" PRIx64 722 pr_debug3("%#" PRIx64 " %s: period++ [addr: %#" PRIx64 ", %#" PRIx64
720 ", evidx=%d] => %" PRIu64 "\n", sym->start, sym->name, 723 ", evidx=%d] => nr_samples: %" PRIu64 ", period: %" PRIu64 "\n",
721 addr, addr - sym->start, evidx, h->addr[offset]); 724 sym->start, sym->name, addr, addr - sym->start, evidx,
725 h->addr[offset].nr_samples, h->addr[offset].period);
722 return 0; 726 return 0;
723} 727}
724 728
@@ -738,7 +742,8 @@ static struct annotation *symbol__get_annotation(struct symbol *sym, bool cycles
738} 742}
739 743
740static int symbol__inc_addr_samples(struct symbol *sym, struct map *map, 744static int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
741 int evidx, u64 addr) 745 int evidx, u64 addr,
746 struct perf_sample *sample)
742{ 747{
743 struct annotation *notes; 748 struct annotation *notes;
744 749
@@ -747,7 +752,7 @@ static int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
747 notes = symbol__get_annotation(sym, false); 752 notes = symbol__get_annotation(sym, false);
748 if (notes == NULL) 753 if (notes == NULL)
749 return -ENOMEM; 754 return -ENOMEM;
750 return __symbol__inc_addr_samples(sym, map, notes, evidx, addr); 755 return __symbol__inc_addr_samples(sym, map, notes, evidx, addr, sample);
751} 756}
752 757
753static int symbol__account_cycles(u64 addr, u64 start, 758static int symbol__account_cycles(u64 addr, u64 start,
@@ -811,14 +816,16 @@ int addr_map_symbol__account_cycles(struct addr_map_symbol *ams,
811 return err; 816 return err;
812} 817}
813 818
814int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, int evidx) 819int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample,
820 int evidx)
815{ 821{
816 return symbol__inc_addr_samples(ams->sym, ams->map, evidx, ams->al_addr); 822 return symbol__inc_addr_samples(ams->sym, ams->map, evidx, ams->al_addr, sample);
817} 823}
818 824
819int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 ip) 825int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *sample,
826 int evidx, u64 ip)
820{ 827{
821 return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip); 828 return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip, sample);
822} 829}
823 830
824static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, struct map *map) 831static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, struct map *map)
@@ -928,11 +935,12 @@ struct disasm_line *disasm__get_next_ip_line(struct list_head *head, struct disa
928} 935}
929 936
930double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset, 937double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset,
931 s64 end, const char **path, u64 *nr_samples) 938 s64 end, const char **path, struct sym_hist_entry *sample)
932{ 939{
933 struct source_line *src_line = notes->src->lines; 940 struct source_line *src_line = notes->src->lines;
934 double percent = 0.0; 941 double percent = 0.0;
935 *nr_samples = 0; 942
943 sample->nr_samples = sample->period = 0;
936 944
937 if (src_line) { 945 if (src_line) {
938 size_t sizeof_src_line = sizeof(*src_line) + 946 size_t sizeof_src_line = sizeof(*src_line) +
@@ -946,19 +954,23 @@ double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset,
946 *path = src_line->path; 954 *path = src_line->path;
947 955
948 percent += src_line->samples[evidx].percent; 956 percent += src_line->samples[evidx].percent;
949 *nr_samples += src_line->samples[evidx].nr; 957 sample->nr_samples += src_line->samples[evidx].nr;
950 offset++; 958 offset++;
951 } 959 }
952 } else { 960 } else {
953 struct sym_hist *h = annotation__histogram(notes, evidx); 961 struct sym_hist *h = annotation__histogram(notes, evidx);
954 unsigned int hits = 0; 962 unsigned int hits = 0;
963 u64 period = 0;
955 964
956 while (offset < end) 965 while (offset < end) {
957 hits += h->addr[offset++]; 966 hits += h->addr[offset++].nr_samples;
967 period += h->addr[offset++].period;
968 }
958 969
959 if (h->sum) { 970 if (h->nr_samples) {
960 *nr_samples = hits; 971 sample->period = period;
961 percent = 100.0 * hits / h->sum; 972 sample->nr_samples = hits;
973 percent = 100.0 * hits / h->nr_samples;
962 } 974 }
963 } 975 }
964 976
@@ -1057,10 +1069,10 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
1057 1069
1058 if (dl->offset != -1) { 1070 if (dl->offset != -1) {
1059 const char *path = NULL; 1071 const char *path = NULL;
1060 u64 nr_samples;
1061 double percent, max_percent = 0.0; 1072 double percent, max_percent = 0.0;
1062 double *ppercents = &percent; 1073 double *ppercents = &percent;
1063 u64 *psamples = &nr_samples; 1074 struct sym_hist_entry sample;
1075 struct sym_hist_entry *psamples = &sample;
1064 int i, nr_percent = 1; 1076 int i, nr_percent = 1;
1065 const char *color; 1077 const char *color;
1066 struct annotation *notes = symbol__annotation(sym); 1078 struct annotation *notes = symbol__annotation(sym);
@@ -1074,7 +1086,7 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
1074 if (perf_evsel__is_group_event(evsel)) { 1086 if (perf_evsel__is_group_event(evsel)) {
1075 nr_percent = evsel->nr_members; 1087 nr_percent = evsel->nr_members;
1076 ppercents = calloc(nr_percent, sizeof(double)); 1088 ppercents = calloc(nr_percent, sizeof(double));
1077 psamples = calloc(nr_percent, sizeof(u64)); 1089 psamples = calloc(nr_percent, sizeof(struct sym_hist_entry));
1078 if (ppercents == NULL || psamples == NULL) { 1090 if (ppercents == NULL || psamples == NULL) {
1079 return -1; 1091 return -1;
1080 } 1092 }
@@ -1085,10 +1097,10 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
1085 notes->src->lines ? i : evsel->idx + i, 1097 notes->src->lines ? i : evsel->idx + i,
1086 offset, 1098 offset,
1087 next ? next->offset : (s64) len, 1099 next ? next->offset : (s64) len,
1088 &path, &nr_samples); 1100 &path, &sample);
1089 1101
1090 ppercents[i] = percent; 1102 ppercents[i] = percent;
1091 psamples[i] = nr_samples; 1103 psamples[i] = sample;
1092 if (percent > max_percent) 1104 if (percent > max_percent)
1093 max_percent = percent; 1105 max_percent = percent;
1094 } 1106 }
@@ -1126,12 +1138,12 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
1126 1138
1127 for (i = 0; i < nr_percent; i++) { 1139 for (i = 0; i < nr_percent; i++) {
1128 percent = ppercents[i]; 1140 percent = ppercents[i];
1129 nr_samples = psamples[i]; 1141 sample = psamples[i];
1130 color = get_percent_color(percent); 1142 color = get_percent_color(percent);
1131 1143
1132 if (symbol_conf.show_total_period) 1144 if (symbol_conf.show_total_period)
1133 color_fprintf(stdout, color, " %7" PRIu64, 1145 color_fprintf(stdout, color, " %7" PRIu64,
1134 nr_samples); 1146 sample.period);
1135 else 1147 else
1136 color_fprintf(stdout, color, " %7.2f", percent); 1148 color_fprintf(stdout, color, " %7.2f", percent);
1137 } 1149 }
@@ -1147,7 +1159,7 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
1147 if (ppercents != &percent) 1159 if (ppercents != &percent)
1148 free(ppercents); 1160 free(ppercents);
1149 1161
1150 if (psamples != &nr_samples) 1162 if (psamples != &sample)
1151 free(psamples); 1163 free(psamples);
1152 1164
1153 } else if (max_lines && printed >= max_lines) 1165 } else if (max_lines && printed >= max_lines)
@@ -1671,19 +1683,19 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
1671 struct sym_hist *h = annotation__histogram(notes, evidx); 1683 struct sym_hist *h = annotation__histogram(notes, evidx);
1672 struct rb_root tmp_root = RB_ROOT; 1684 struct rb_root tmp_root = RB_ROOT;
1673 int nr_pcnt = 1; 1685 int nr_pcnt = 1;
1674 u64 h_sum = h->sum; 1686 u64 nr_samples = h->nr_samples;
1675 size_t sizeof_src_line = sizeof(struct source_line); 1687 size_t sizeof_src_line = sizeof(struct source_line);
1676 1688
1677 if (perf_evsel__is_group_event(evsel)) { 1689 if (perf_evsel__is_group_event(evsel)) {
1678 for (i = 1; i < evsel->nr_members; i++) { 1690 for (i = 1; i < evsel->nr_members; i++) {
1679 h = annotation__histogram(notes, evidx + i); 1691 h = annotation__histogram(notes, evidx + i);
1680 h_sum += h->sum; 1692 nr_samples += h->nr_samples;
1681 } 1693 }
1682 nr_pcnt = evsel->nr_members; 1694 nr_pcnt = evsel->nr_members;
1683 sizeof_src_line += (nr_pcnt - 1) * sizeof(src_line->samples); 1695 sizeof_src_line += (nr_pcnt - 1) * sizeof(src_line->samples);
1684 } 1696 }
1685 1697
1686 if (!h_sum) 1698 if (!nr_samples)
1687 return 0; 1699 return 0;
1688 1700
1689 src_line = notes->src->lines = calloc(len, sizeof_src_line); 1701 src_line = notes->src->lines = calloc(len, sizeof_src_line);
@@ -1693,7 +1705,7 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
1693 start = map__rip_2objdump(map, sym->start); 1705 start = map__rip_2objdump(map, sym->start);
1694 1706
1695 for (i = 0; i < len; i++) { 1707 for (i = 0; i < len; i++) {
1696 u64 offset, nr_samples; 1708 u64 offset;
1697 double percent_max = 0.0; 1709 double percent_max = 0.0;
1698 1710
1699 src_line->nr_pcnt = nr_pcnt; 1711 src_line->nr_pcnt = nr_pcnt;
@@ -1702,9 +1714,9 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
1702 double percent = 0.0; 1714 double percent = 0.0;
1703 1715
1704 h = annotation__histogram(notes, evidx + k); 1716 h = annotation__histogram(notes, evidx + k);
1705 nr_samples = h->addr[i]; 1717 nr_samples = h->addr[i].nr_samples;
1706 if (h->sum) 1718 if (h->nr_samples)
1707 percent = 100.0 * nr_samples / h->sum; 1719 percent = 100.0 * nr_samples / h->nr_samples;
1708 1720
1709 if (percent > percent_max) 1721 if (percent > percent_max)
1710 percent_max = percent; 1722 percent_max = percent;
@@ -1773,10 +1785,10 @@ static void symbol__annotate_hits(struct symbol *sym, struct perf_evsel *evsel)
1773 u64 len = symbol__size(sym), offset; 1785 u64 len = symbol__size(sym), offset;
1774 1786
1775 for (offset = 0; offset < len; ++offset) 1787 for (offset = 0; offset < len; ++offset)
1776 if (h->addr[offset] != 0) 1788 if (h->addr[offset].nr_samples != 0)
1777 printf("%*" PRIx64 ": %" PRIu64 "\n", BITS_PER_LONG / 2, 1789 printf("%*" PRIx64 ": %" PRIu64 "\n", BITS_PER_LONG / 2,
1778 sym->start + offset, h->addr[offset]); 1790 sym->start + offset, h->addr[offset].nr_samples);
1779 printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->sum", h->sum); 1791 printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->nr_samples", h->nr_samples);
1780} 1792}
1781 1793
1782int symbol__annotate_printf(struct symbol *sym, struct map *map, 1794int symbol__annotate_printf(struct symbol *sym, struct map *map,
@@ -1812,7 +1824,8 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
1812 width *= evsel->nr_members; 1824 width *= evsel->nr_members;
1813 1825
1814 graph_dotted_len = printf(" %-*.*s| Source code & Disassembly of %s for %s (%" PRIu64 " samples)\n", 1826 graph_dotted_len = printf(" %-*.*s| Source code & Disassembly of %s for %s (%" PRIu64 " samples)\n",
1815 width, width, "Percent", d_filename, evsel_name, h->sum); 1827 width, width, symbol_conf.show_total_period ? "Event count" : "Percent",
1828 d_filename, evsel_name, h->nr_samples);
1816 1829
1817 printf("%-*.*s----\n", 1830 printf("%-*.*s----\n",
1818 graph_dotted_len, graph_dotted_len, graph_dotted_line); 1831 graph_dotted_len, graph_dotted_len, graph_dotted_line);
@@ -1876,10 +1889,10 @@ void symbol__annotate_decay_histogram(struct symbol *sym, int evidx)
1876 struct sym_hist *h = annotation__histogram(notes, evidx); 1889 struct sym_hist *h = annotation__histogram(notes, evidx);
1877 int len = symbol__size(sym), offset; 1890 int len = symbol__size(sym), offset;
1878 1891
1879 h->sum = 0; 1892 h->nr_samples = 0;
1880 for (offset = 0; offset < len; ++offset) { 1893 for (offset = 0; offset < len; ++offset) {
1881 h->addr[offset] = h->addr[offset] * 7 / 8; 1894 h->addr[offset].nr_samples = h->addr[offset].nr_samples * 7 / 8;
1882 h->sum += h->addr[offset]; 1895 h->nr_samples += h->addr[offset].nr_samples;
1883 } 1896 }
1884} 1897}
1885 1898
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index bac698d7cc6a..9ce575c25fd9 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -74,16 +74,22 @@ static inline bool disasm_line__has_offset(const struct disasm_line *dl)
74 return dl->ops.target.offset_avail; 74 return dl->ops.target.offset_avail;
75} 75}
76 76
77struct sym_hist_entry {
78 u64 nr_samples;
79 u64 period;
80};
81
77void disasm_line__free(struct disasm_line *dl); 82void disasm_line__free(struct disasm_line *dl);
78struct disasm_line *disasm__get_next_ip_line(struct list_head *head, struct disasm_line *pos); 83struct disasm_line *disasm__get_next_ip_line(struct list_head *head, struct disasm_line *pos);
79int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw); 84int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw);
80size_t disasm__fprintf(struct list_head *head, FILE *fp); 85size_t disasm__fprintf(struct list_head *head, FILE *fp);
81double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset, 86double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset,
82 s64 end, const char **path, u64 *nr_samples); 87 s64 end, const char **path, struct sym_hist_entry *sample);
83 88
84struct sym_hist { 89struct sym_hist {
85 u64 sum; 90 u64 nr_samples;
86 u64 addr[0]; 91 u64 period;
92 struct sym_hist_entry addr[0];
87}; 93};
88 94
89struct cyc_hist { 95struct cyc_hist {
@@ -149,13 +155,15 @@ static inline struct annotation *symbol__annotation(struct symbol *sym)
149 return (void *)sym - symbol_conf.priv_size; 155 return (void *)sym - symbol_conf.priv_size;
150} 156}
151 157
152int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, int evidx); 158int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample,
159 int evidx);
153 160
154int addr_map_symbol__account_cycles(struct addr_map_symbol *ams, 161int addr_map_symbol__account_cycles(struct addr_map_symbol *ams,
155 struct addr_map_symbol *start, 162 struct addr_map_symbol *start,
156 unsigned cycles); 163 unsigned cycles);
157 164
158int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 addr); 165int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *sample,
166 int evidx, u64 addr);
159 167
160int symbol__alloc_hist(struct symbol *sym); 168int symbol__alloc_hist(struct symbol *sym);
161void symbol__annotate_zero_histograms(struct symbol *sym); 169void symbol__annotate_zero_histograms(struct symbol *sym);
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 4bd2d1d882af..4a1264c66101 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -1246,7 +1246,7 @@ int bpf__config_obj(struct bpf_object *obj,
1246 if (!obj || !term || !term->config) 1246 if (!obj || !term || !term->config)
1247 return -EINVAL; 1247 return -EINVAL;
1248 1248
1249 if (!prefixcmp(term->config, "map:")) { 1249 if (strstarts(term->config, "map:")) {
1250 key_scan_pos = sizeof("map:") - 1; 1250 key_scan_pos = sizeof("map:") - 1;
1251 err = bpf__obj_config_map(obj, term, evlist, &key_scan_pos); 1251 err = bpf__obj_config_map(obj, term, evlist, &key_scan_pos);
1252 goto out; 1252 goto out;
diff --git a/tools/perf/util/branch.h b/tools/perf/util/branch.h
index 686f2b65ba84..1e3c7c5cdc63 100644
--- a/tools/perf/util/branch.h
+++ b/tools/perf/util/branch.h
@@ -5,11 +5,12 @@
5#include "../perf.h" 5#include "../perf.h"
6 6
7struct branch_type_stat { 7struct branch_type_stat {
8 u64 counts[PERF_BR_MAX]; 8 bool branch_to;
9 u64 cond_fwd; 9 u64 counts[PERF_BR_MAX];
10 u64 cond_bwd; 10 u64 cond_fwd;
11 u64 cross_4k; 11 u64 cond_bwd;
12 u64 cross_2m; 12 u64 cross_4k;
13 u64 cross_2m;
13}; 14};
14 15
15struct branch_flags; 16struct branch_flags;
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 22d413ae6025..f320b0777e0d 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -304,7 +304,7 @@ int perf_callchain_config(const char *var, const char *value)
304{ 304{
305 char *endptr; 305 char *endptr;
306 306
307 if (prefixcmp(var, "call-graph.")) 307 if (!strstarts(var, "call-graph."))
308 return 0; 308 return 0;
309 var += sizeof("call-graph.") - 1; 309 var += sizeof("call-graph.") - 1;
310 310
@@ -563,20 +563,33 @@ fill_node(struct callchain_node *node, struct callchain_cursor *cursor)
563 if (cursor_node->branch) { 563 if (cursor_node->branch) {
564 call->branch_count = 1; 564 call->branch_count = 1;
565 565
566 if (cursor_node->branch_flags.predicted) 566 if (cursor_node->branch_from) {
567 call->predicted_count = 1; 567 /*
568 568 * branch_from is set with value somewhere else
569 if (cursor_node->branch_flags.abort) 569 * to imply it's "to" of a branch.
570 call->abort_count = 1; 570 */
571 571 call->brtype_stat.branch_to = true;
572 call->cycles_count = cursor_node->branch_flags.cycles; 572
573 call->iter_count = cursor_node->nr_loop_iter; 573 if (cursor_node->branch_flags.predicted)
574 call->samples_count = cursor_node->samples; 574 call->predicted_count = 1;
575 575
576 branch_type_count(&call->brtype_stat, 576 if (cursor_node->branch_flags.abort)
577 &cursor_node->branch_flags, 577 call->abort_count = 1;
578 cursor_node->branch_from, 578
579 cursor_node->ip); 579 branch_type_count(&call->brtype_stat,
580 &cursor_node->branch_flags,
581 cursor_node->branch_from,
582 cursor_node->ip);
583 } else {
584 /*
585 * It's "from" of a branch
586 */
587 call->brtype_stat.branch_to = false;
588 call->cycles_count =
589 cursor_node->branch_flags.cycles;
590 call->iter_count = cursor_node->nr_loop_iter;
591 call->samples_count = cursor_node->samples;
592 }
580 } 593 }
581 594
582 list_add_tail(&call->list, &node->val); 595 list_add_tail(&call->list, &node->val);
@@ -685,20 +698,32 @@ static enum match_result match_chain(struct callchain_cursor_node *node,
685 if (node->branch) { 698 if (node->branch) {
686 cnode->branch_count++; 699 cnode->branch_count++;
687 700
688 if (node->branch_flags.predicted) 701 if (node->branch_from) {
689 cnode->predicted_count++; 702 /*
690 703 * It's "to" of a branch
691 if (node->branch_flags.abort) 704 */
692 cnode->abort_count++; 705 cnode->brtype_stat.branch_to = true;
693 706
694 cnode->cycles_count += node->branch_flags.cycles; 707 if (node->branch_flags.predicted)
695 cnode->iter_count += node->nr_loop_iter; 708 cnode->predicted_count++;
696 cnode->samples_count += node->samples; 709
697 710 if (node->branch_flags.abort)
698 branch_type_count(&cnode->brtype_stat, 711 cnode->abort_count++;
699 &node->branch_flags, 712
700 node->branch_from, 713 branch_type_count(&cnode->brtype_stat,
701 node->ip); 714 &node->branch_flags,
715 node->branch_from,
716 node->ip);
717 } else {
718 /*
719 * It's "from" of a branch
720 */
721 cnode->brtype_stat.branch_to = false;
722 cnode->cycles_count +=
723 node->branch_flags.cycles;
724 cnode->iter_count += node->nr_loop_iter;
725 cnode->samples_count += node->samples;
726 }
702 } 727 }
703 728
704 return MATCH_EQ; 729 return MATCH_EQ;
@@ -1010,11 +1035,11 @@ int sample__resolve_callchain(struct perf_sample *sample,
1010 struct perf_evsel *evsel, struct addr_location *al, 1035 struct perf_evsel *evsel, struct addr_location *al,
1011 int max_stack) 1036 int max_stack)
1012{ 1037{
1013 if (sample->callchain == NULL) 1038 if (sample->callchain == NULL && !symbol_conf.show_branchflag_count)
1014 return 0; 1039 return 0;
1015 1040
1016 if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain || 1041 if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain ||
1017 perf_hpp_list.parent) { 1042 perf_hpp_list.parent || symbol_conf.show_branchflag_count) {
1018 return thread__resolve_callchain(al->thread, cursor, evsel, sample, 1043 return thread__resolve_callchain(al->thread, cursor, evsel, sample,
1019 parent, al, max_stack); 1044 parent, al, max_stack);
1020 } 1045 }
@@ -1023,7 +1048,8 @@ int sample__resolve_callchain(struct perf_sample *sample,
1023 1048
1024int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample) 1049int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample)
1025{ 1050{
1026 if (!symbol_conf.use_callchain || sample->callchain == NULL) 1051 if ((!symbol_conf.use_callchain || sample->callchain == NULL) &&
1052 !symbol_conf.show_branchflag_count)
1027 return 0; 1053 return 0;
1028 return callchain_append(he->callchain, &callchain_cursor, sample->period); 1054 return callchain_append(he->callchain, &callchain_cursor, sample->period);
1029} 1055}
@@ -1235,27 +1261,26 @@ static int count_pri64_printf(int idx, const char *str, u64 value, char *bf, int
1235 return printed; 1261 return printed;
1236} 1262}
1237 1263
1238static int count_float_printf(int idx, const char *str, float value, char *bf, int bfsize) 1264static int count_float_printf(int idx, const char *str, float value,
1265 char *bf, int bfsize, float threshold)
1239{ 1266{
1240 int printed; 1267 int printed;
1241 1268
1269 if (threshold != 0.0 && value < threshold)
1270 return 0;
1271
1242 printed = scnprintf(bf, bfsize, "%s%s:%.1f%%", (idx) ? " " : " (", str, value); 1272 printed = scnprintf(bf, bfsize, "%s%s:%.1f%%", (idx) ? " " : " (", str, value);
1243 1273
1244 return printed; 1274 return printed;
1245} 1275}
1246 1276
1247static int counts_str_build(char *bf, int bfsize, 1277static int branch_to_str(char *bf, int bfsize,
1248 u64 branch_count, u64 predicted_count, 1278 u64 branch_count, u64 predicted_count,
1249 u64 abort_count, u64 cycles_count, 1279 u64 abort_count,
1250 u64 iter_count, u64 samples_count, 1280 struct branch_type_stat *brtype_stat)
1251 struct branch_type_stat *brtype_stat)
1252{ 1281{
1253 u64 cycles;
1254 int printed, i = 0; 1282 int printed, i = 0;
1255 1283
1256 if (branch_count == 0)
1257 return scnprintf(bf, bfsize, " (calltrace)");
1258
1259 printed = branch_type_str(brtype_stat, bf, bfsize); 1284 printed = branch_type_str(brtype_stat, bf, bfsize);
1260 if (printed) 1285 if (printed)
1261 i++; 1286 i++;
@@ -1263,15 +1288,29 @@ static int counts_str_build(char *bf, int bfsize,
1263 if (predicted_count < branch_count) { 1288 if (predicted_count < branch_count) {
1264 printed += count_float_printf(i++, "predicted", 1289 printed += count_float_printf(i++, "predicted",
1265 predicted_count * 100.0 / branch_count, 1290 predicted_count * 100.0 / branch_count,
1266 bf + printed, bfsize - printed); 1291 bf + printed, bfsize - printed, 0.0);
1267 } 1292 }
1268 1293
1269 if (abort_count) { 1294 if (abort_count) {
1270 printed += count_float_printf(i++, "abort", 1295 printed += count_float_printf(i++, "abort",
1271 abort_count * 100.0 / branch_count, 1296 abort_count * 100.0 / branch_count,
1272 bf + printed, bfsize - printed); 1297 bf + printed, bfsize - printed, 0.1);
1273 } 1298 }
1274 1299
1300 if (i)
1301 printed += scnprintf(bf + printed, bfsize - printed, ")");
1302
1303 return printed;
1304}
1305
1306static int branch_from_str(char *bf, int bfsize,
1307 u64 branch_count,
1308 u64 cycles_count, u64 iter_count,
1309 u64 samples_count)
1310{
1311 int printed = 0, i = 0;
1312 u64 cycles;
1313
1275 cycles = cycles_count / branch_count; 1314 cycles = cycles_count / branch_count;
1276 if (cycles) { 1315 if (cycles) {
1277 printed += count_pri64_printf(i++, "cycles", 1316 printed += count_pri64_printf(i++, "cycles",
@@ -1286,10 +1325,34 @@ static int counts_str_build(char *bf, int bfsize,
1286 } 1325 }
1287 1326
1288 if (i) 1327 if (i)
1289 return scnprintf(bf + printed, bfsize - printed, ")"); 1328 printed += scnprintf(bf + printed, bfsize - printed, ")");
1290 1329
1291 bf[0] = 0; 1330 return printed;
1292 return 0; 1331}
1332
1333static int counts_str_build(char *bf, int bfsize,
1334 u64 branch_count, u64 predicted_count,
1335 u64 abort_count, u64 cycles_count,
1336 u64 iter_count, u64 samples_count,
1337 struct branch_type_stat *brtype_stat)
1338{
1339 int printed;
1340
1341 if (branch_count == 0)
1342 return scnprintf(bf, bfsize, " (calltrace)");
1343
1344 if (brtype_stat->branch_to) {
1345 printed = branch_to_str(bf, bfsize, branch_count,
1346 predicted_count, abort_count, brtype_stat);
1347 } else {
1348 printed = branch_from_str(bf, bfsize, branch_count,
1349 cycles_count, iter_count, samples_count);
1350 }
1351
1352 if (!printed)
1353 bf[0] = 0;
1354
1355 return printed;
1293} 1356}
1294 1357
1295static int callchain_counts_printf(FILE *fp, char *bf, int bfsize, 1358static int callchain_counts_printf(FILE *fp, char *bf, int bfsize,
diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c
index 03347748f3fa..0e77bc9e5f3c 100644
--- a/tools/perf/util/cgroup.c
+++ b/tools/perf/util/cgroup.c
@@ -98,8 +98,10 @@ static int add_cgroup(struct perf_evlist *evlist, char *str)
98 cgrp = counter->cgrp; 98 cgrp = counter->cgrp;
99 if (!cgrp) 99 if (!cgrp)
100 continue; 100 continue;
101 if (!strcmp(cgrp->name, str)) 101 if (!strcmp(cgrp->name, str)) {
102 refcount_inc(&cgrp->refcnt);
102 break; 103 break;
104 }
103 105
104 cgrp = NULL; 106 cgrp = NULL;
105 } 107 }
@@ -110,6 +112,7 @@ static int add_cgroup(struct perf_evlist *evlist, char *str)
110 return -1; 112 return -1;
111 113
112 cgrp->name = str; 114 cgrp->name = str;
115 refcount_set(&cgrp->refcnt, 1);
113 116
114 cgrp->fd = open_cgroup(str); 117 cgrp->fd = open_cgroup(str);
115 if (cgrp->fd == -1) { 118 if (cgrp->fd == -1) {
@@ -128,12 +131,11 @@ static int add_cgroup(struct perf_evlist *evlist, char *str)
128 goto found; 131 goto found;
129 n++; 132 n++;
130 } 133 }
131 if (refcount_read(&cgrp->refcnt) == 0) 134 if (refcount_dec_and_test(&cgrp->refcnt))
132 free(cgrp); 135 free(cgrp);
133 136
134 return -1; 137 return -1;
135found: 138found:
136 refcount_inc(&cgrp->refcnt);
137 counter->cgrp = cgrp; 139 counter->cgrp = cgrp;
138 return 0; 140 return 0;
139} 141}
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 31a7dea248d0..bc75596f9e79 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -19,6 +19,7 @@
19#include <sys/types.h> 19#include <sys/types.h>
20#include <sys/stat.h> 20#include <sys/stat.h>
21#include <unistd.h> 21#include <unistd.h>
22#include <linux/string.h>
22 23
23#include "sane_ctype.h" 24#include "sane_ctype.h"
24 25
@@ -433,22 +434,22 @@ static int perf_ui_config(const char *var, const char *value)
433int perf_default_config(const char *var, const char *value, 434int perf_default_config(const char *var, const char *value,
434 void *dummy __maybe_unused) 435 void *dummy __maybe_unused)
435{ 436{
436 if (!prefixcmp(var, "core.")) 437 if (strstarts(var, "core."))
437 return perf_default_core_config(var, value); 438 return perf_default_core_config(var, value);
438 439
439 if (!prefixcmp(var, "hist.")) 440 if (strstarts(var, "hist."))
440 return perf_hist_config(var, value); 441 return perf_hist_config(var, value);
441 442
442 if (!prefixcmp(var, "ui.")) 443 if (strstarts(var, "ui."))
443 return perf_ui_config(var, value); 444 return perf_ui_config(var, value);
444 445
445 if (!prefixcmp(var, "call-graph.")) 446 if (strstarts(var, "call-graph."))
446 return perf_callchain_config(var, value); 447 return perf_callchain_config(var, value);
447 448
448 if (!prefixcmp(var, "llvm.")) 449 if (strstarts(var, "llvm."))
449 return perf_llvm_config(var, value); 450 return perf_llvm_config(var, value);
450 451
451 if (!prefixcmp(var, "buildid.")) 452 if (strstarts(var, "buildid."))
452 return perf_buildid_config(var, value); 453 return perf_buildid_config(var, value);
453 454
454 /* Add other config variables here. */ 455 /* Add other config variables here. */
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 6dd069a41ac3..450b5fadf8cb 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -1671,31 +1671,39 @@ try_fallback:
1671 */ 1671 */
1672 if (!perf_missing_features.write_backward && evsel->attr.write_backward) { 1672 if (!perf_missing_features.write_backward && evsel->attr.write_backward) {
1673 perf_missing_features.write_backward = true; 1673 perf_missing_features.write_backward = true;
1674 pr_debug2("switching off write_backward\n");
1674 goto out_close; 1675 goto out_close;
1675 } else if (!perf_missing_features.clockid_wrong && evsel->attr.use_clockid) { 1676 } else if (!perf_missing_features.clockid_wrong && evsel->attr.use_clockid) {
1676 perf_missing_features.clockid_wrong = true; 1677 perf_missing_features.clockid_wrong = true;
1678 pr_debug2("switching off clockid\n");
1677 goto fallback_missing_features; 1679 goto fallback_missing_features;
1678 } else if (!perf_missing_features.clockid && evsel->attr.use_clockid) { 1680 } else if (!perf_missing_features.clockid && evsel->attr.use_clockid) {
1679 perf_missing_features.clockid = true; 1681 perf_missing_features.clockid = true;
1682 pr_debug2("switching off use_clockid\n");
1680 goto fallback_missing_features; 1683 goto fallback_missing_features;
1681 } else if (!perf_missing_features.cloexec && (flags & PERF_FLAG_FD_CLOEXEC)) { 1684 } else if (!perf_missing_features.cloexec && (flags & PERF_FLAG_FD_CLOEXEC)) {
1682 perf_missing_features.cloexec = true; 1685 perf_missing_features.cloexec = true;
1686 pr_debug2("switching off cloexec flag\n");
1683 goto fallback_missing_features; 1687 goto fallback_missing_features;
1684 } else if (!perf_missing_features.mmap2 && evsel->attr.mmap2) { 1688 } else if (!perf_missing_features.mmap2 && evsel->attr.mmap2) {
1685 perf_missing_features.mmap2 = true; 1689 perf_missing_features.mmap2 = true;
1690 pr_debug2("switching off mmap2\n");
1686 goto fallback_missing_features; 1691 goto fallback_missing_features;
1687 } else if (!perf_missing_features.exclude_guest && 1692 } else if (!perf_missing_features.exclude_guest &&
1688 (evsel->attr.exclude_guest || evsel->attr.exclude_host)) { 1693 (evsel->attr.exclude_guest || evsel->attr.exclude_host)) {
1689 perf_missing_features.exclude_guest = true; 1694 perf_missing_features.exclude_guest = true;
1695 pr_debug2("switching off exclude_guest, exclude_host\n");
1690 goto fallback_missing_features; 1696 goto fallback_missing_features;
1691 } else if (!perf_missing_features.sample_id_all) { 1697 } else if (!perf_missing_features.sample_id_all) {
1692 perf_missing_features.sample_id_all = true; 1698 perf_missing_features.sample_id_all = true;
1699 pr_debug2("switching off sample_id_all\n");
1693 goto retry_sample_id; 1700 goto retry_sample_id;
1694 } else if (!perf_missing_features.lbr_flags && 1701 } else if (!perf_missing_features.lbr_flags &&
1695 (evsel->attr.branch_sample_type & 1702 (evsel->attr.branch_sample_type &
1696 (PERF_SAMPLE_BRANCH_NO_CYCLES | 1703 (PERF_SAMPLE_BRANCH_NO_CYCLES |
1697 PERF_SAMPLE_BRANCH_NO_FLAGS))) { 1704 PERF_SAMPLE_BRANCH_NO_FLAGS))) {
1698 perf_missing_features.lbr_flags = true; 1705 perf_missing_features.lbr_flags = true;
1706 pr_debug2("switching off branch sample type no (cycles/flags)\n");
1699 goto fallback_missing_features; 1707 goto fallback_missing_features;
1700 } 1708 }
1701out_close: 1709out_close:
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 2f6c5e6c16f9..9453b2e27015 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -1759,6 +1759,8 @@ void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *pro
1759 else 1759 else
1760 use_callchain = symbol_conf.use_callchain; 1760 use_callchain = symbol_conf.use_callchain;
1761 1761
1762 use_callchain |= symbol_conf.show_branchflag_count;
1763
1762 output_resort(evsel__hists(evsel), prog, use_callchain, NULL); 1764 output_resort(evsel__hists(evsel), prog, use_callchain, NULL);
1763} 1765}
1764 1766
diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c
index c6a15f204c03..209b0c82eff4 100644
--- a/tools/perf/util/llvm-utils.c
+++ b/tools/perf/util/llvm-utils.c
@@ -33,7 +33,7 @@ struct llvm_param llvm_param = {
33 33
34int perf_llvm_config(const char *var, const char *value) 34int perf_llvm_config(const char *var, const char *value)
35{ 35{
36 if (prefixcmp(var, "llvm.")) 36 if (!strstarts(var, "llvm."))
37 return 0; 37 return 0;
38 var += sizeof("llvm.") - 1; 38 var += sizeof("llvm.") - 1;
39 39
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 79d08ea694da..d4df353051af 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -1902,13 +1902,16 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1902{ 1902{
1903 struct branch_stack *branch = sample->branch_stack; 1903 struct branch_stack *branch = sample->branch_stack;
1904 struct ip_callchain *chain = sample->callchain; 1904 struct ip_callchain *chain = sample->callchain;
1905 int chain_nr = chain->nr; 1905 int chain_nr = 0;
1906 u8 cpumode = PERF_RECORD_MISC_USER; 1906 u8 cpumode = PERF_RECORD_MISC_USER;
1907 int i, j, err, nr_entries; 1907 int i, j, err, nr_entries;
1908 int skip_idx = -1; 1908 int skip_idx = -1;
1909 int first_call = 0; 1909 int first_call = 0;
1910 int nr_loop_iter; 1910 int nr_loop_iter;
1911 1911
1912 if (chain)
1913 chain_nr = chain->nr;
1914
1912 if (perf_evsel__has_branch_callstack(evsel)) { 1915 if (perf_evsel__has_branch_callstack(evsel)) {
1913 err = resolve_lbr_callchain_sample(thread, cursor, sample, parent, 1916 err = resolve_lbr_callchain_sample(thread, cursor, sample, parent,
1914 root_al, max_stack); 1917 root_al, max_stack);
@@ -1946,6 +1949,10 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1946 for (i = 0; i < nr; i++) { 1949 for (i = 0; i < nr; i++) {
1947 if (callchain_param.order == ORDER_CALLEE) { 1950 if (callchain_param.order == ORDER_CALLEE) {
1948 be[i] = branch->entries[i]; 1951 be[i] = branch->entries[i];
1952
1953 if (chain == NULL)
1954 continue;
1955
1949 /* 1956 /*
1950 * Check for overlap into the callchain. 1957 * Check for overlap into the callchain.
1951 * The return address is one off compared to 1958 * The return address is one off compared to
@@ -2000,6 +2007,10 @@ static int thread__resolve_callchain_sample(struct thread *thread,
2000 if (err) 2007 if (err)
2001 return err; 2008 return err;
2002 } 2009 }
2010
2011 if (chain_nr == 0)
2012 return 0;
2013
2003 chain_nr -= nr; 2014 chain_nr -= nr;
2004 } 2015 }
2005 2016
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 57b7a00e6f16..c7187f067d31 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -116,6 +116,34 @@ static PyObject *get_handler(const char *handler_name)
116 return handler; 116 return handler;
117} 117}
118 118
119static int get_argument_count(PyObject *handler)
120{
121 int arg_count = 0;
122
123 /*
124 * The attribute for the code object is func_code in Python 2,
125 * whereas it is __code__ in Python 3.0+.
126 */
127 PyObject *code_obj = PyObject_GetAttrString(handler,
128 "func_code");
129 if (PyErr_Occurred()) {
130 PyErr_Clear();
131 code_obj = PyObject_GetAttrString(handler,
132 "__code__");
133 }
134 PyErr_Clear();
135 if (code_obj) {
136 PyObject *arg_count_obj = PyObject_GetAttrString(code_obj,
137 "co_argcount");
138 if (arg_count_obj) {
139 arg_count = (int) PyInt_AsLong(arg_count_obj);
140 Py_DECREF(arg_count_obj);
141 }
142 Py_DECREF(code_obj);
143 }
144 return arg_count;
145}
146
119static void call_object(PyObject *handler, PyObject *args, const char *die_msg) 147static void call_object(PyObject *handler, PyObject *args, const char *die_msg)
120{ 148{
121 PyObject *retval; 149 PyObject *retval;
@@ -391,13 +419,115 @@ exit:
391 return pylist; 419 return pylist;
392} 420}
393 421
422static PyObject *get_sample_value_as_tuple(struct sample_read_value *value)
423{
424 PyObject *t;
425
426 t = PyTuple_New(2);
427 if (!t)
428 Py_FatalError("couldn't create Python tuple");
429 PyTuple_SetItem(t, 0, PyLong_FromUnsignedLongLong(value->id));
430 PyTuple_SetItem(t, 1, PyLong_FromUnsignedLongLong(value->value));
431 return t;
432}
433
434static void set_sample_read_in_dict(PyObject *dict_sample,
435 struct perf_sample *sample,
436 struct perf_evsel *evsel)
437{
438 u64 read_format = evsel->attr.read_format;
439 PyObject *values;
440 unsigned int i;
441
442 if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
443 pydict_set_item_string_decref(dict_sample, "time_enabled",
444 PyLong_FromUnsignedLongLong(sample->read.time_enabled));
445 }
446
447 if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
448 pydict_set_item_string_decref(dict_sample, "time_running",
449 PyLong_FromUnsignedLongLong(sample->read.time_running));
450 }
451
452 if (read_format & PERF_FORMAT_GROUP)
453 values = PyList_New(sample->read.group.nr);
454 else
455 values = PyList_New(1);
456
457 if (!values)
458 Py_FatalError("couldn't create Python list");
459
460 if (read_format & PERF_FORMAT_GROUP) {
461 for (i = 0; i < sample->read.group.nr; i++) {
462 PyObject *t = get_sample_value_as_tuple(&sample->read.group.values[i]);
463 PyList_SET_ITEM(values, i, t);
464 }
465 } else {
466 PyObject *t = get_sample_value_as_tuple(&sample->read.one);
467 PyList_SET_ITEM(values, 0, t);
468 }
469 pydict_set_item_string_decref(dict_sample, "values", values);
470}
471
472static PyObject *get_perf_sample_dict(struct perf_sample *sample,
473 struct perf_evsel *evsel,
474 struct addr_location *al,
475 PyObject *callchain)
476{
477 PyObject *dict, *dict_sample;
478
479 dict = PyDict_New();
480 if (!dict)
481 Py_FatalError("couldn't create Python dictionary");
482
483 dict_sample = PyDict_New();
484 if (!dict_sample)
485 Py_FatalError("couldn't create Python dictionary");
486
487 pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel)));
488 pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
489 (const char *)&evsel->attr, sizeof(evsel->attr)));
490
491 pydict_set_item_string_decref(dict_sample, "pid",
492 PyInt_FromLong(sample->pid));
493 pydict_set_item_string_decref(dict_sample, "tid",
494 PyInt_FromLong(sample->tid));
495 pydict_set_item_string_decref(dict_sample, "cpu",
496 PyInt_FromLong(sample->cpu));
497 pydict_set_item_string_decref(dict_sample, "ip",
498 PyLong_FromUnsignedLongLong(sample->ip));
499 pydict_set_item_string_decref(dict_sample, "time",
500 PyLong_FromUnsignedLongLong(sample->time));
501 pydict_set_item_string_decref(dict_sample, "period",
502 PyLong_FromUnsignedLongLong(sample->period));
503 set_sample_read_in_dict(dict_sample, sample, evsel);
504 pydict_set_item_string_decref(dict, "sample", dict_sample);
505
506 pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize(
507 (const char *)sample->raw_data, sample->raw_size));
508 pydict_set_item_string_decref(dict, "comm",
509 PyString_FromString(thread__comm_str(al->thread)));
510 if (al->map) {
511 pydict_set_item_string_decref(dict, "dso",
512 PyString_FromString(al->map->dso->name));
513 }
514 if (al->sym) {
515 pydict_set_item_string_decref(dict, "symbol",
516 PyString_FromString(al->sym->name));
517 }
518
519 pydict_set_item_string_decref(dict, "callchain", callchain);
520
521 return dict;
522}
523
394static void python_process_tracepoint(struct perf_sample *sample, 524static void python_process_tracepoint(struct perf_sample *sample,
395 struct perf_evsel *evsel, 525 struct perf_evsel *evsel,
396 struct addr_location *al) 526 struct addr_location *al)
397{ 527{
398 struct event_format *event = evsel->tp_format; 528 struct event_format *event = evsel->tp_format;
399 PyObject *handler, *context, *t, *obj = NULL, *callchain; 529 PyObject *handler, *context, *t, *obj = NULL, *callchain;
400 PyObject *dict = NULL; 530 PyObject *dict = NULL, *all_entries_dict = NULL;
401 static char handler_name[256]; 531 static char handler_name[256];
402 struct format_field *field; 532 struct format_field *field;
403 unsigned long s, ns; 533 unsigned long s, ns;
@@ -407,10 +537,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
407 void *data = sample->raw_data; 537 void *data = sample->raw_data;
408 unsigned long long nsecs = sample->time; 538 unsigned long long nsecs = sample->time;
409 const char *comm = thread__comm_str(al->thread); 539 const char *comm = thread__comm_str(al->thread);
410 540 const char *default_handler_name = "trace_unhandled";
411 t = PyTuple_New(MAX_FIELDS);
412 if (!t)
413 Py_FatalError("couldn't create Python tuple");
414 541
415 if (!event) { 542 if (!event) {
416 snprintf(handler_name, sizeof(handler_name), 543 snprintf(handler_name, sizeof(handler_name),
@@ -427,10 +554,19 @@ static void python_process_tracepoint(struct perf_sample *sample,
427 554
428 handler = get_handler(handler_name); 555 handler = get_handler(handler_name);
429 if (!handler) { 556 if (!handler) {
557 handler = get_handler(default_handler_name);
558 if (!handler)
559 return;
430 dict = PyDict_New(); 560 dict = PyDict_New();
431 if (!dict) 561 if (!dict)
432 Py_FatalError("couldn't create Python dict"); 562 Py_FatalError("couldn't create Python dict");
433 } 563 }
564
565 t = PyTuple_New(MAX_FIELDS);
566 if (!t)
567 Py_FatalError("couldn't create Python tuple");
568
569
434 s = nsecs / NSEC_PER_SEC; 570 s = nsecs / NSEC_PER_SEC;
435 ns = nsecs - s * NSEC_PER_SEC; 571 ns = nsecs - s * NSEC_PER_SEC;
436 572
@@ -444,8 +580,10 @@ static void python_process_tracepoint(struct perf_sample *sample,
444 580
445 /* ip unwinding */ 581 /* ip unwinding */
446 callchain = python_process_callchain(sample, evsel, al); 582 callchain = python_process_callchain(sample, evsel, al);
583 /* Need an additional reference for the perf_sample dict */
584 Py_INCREF(callchain);
447 585
448 if (handler) { 586 if (!dict) {
449 PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); 587 PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
450 PyTuple_SetItem(t, n++, PyInt_FromLong(s)); 588 PyTuple_SetItem(t, n++, PyInt_FromLong(s));
451 PyTuple_SetItem(t, n++, PyInt_FromLong(ns)); 589 PyTuple_SetItem(t, n++, PyInt_FromLong(ns));
@@ -484,26 +622,35 @@ static void python_process_tracepoint(struct perf_sample *sample,
484 } else { /* FIELD_IS_NUMERIC */ 622 } else { /* FIELD_IS_NUMERIC */
485 obj = get_field_numeric_entry(event, field, data); 623 obj = get_field_numeric_entry(event, field, data);
486 } 624 }
487 if (handler) 625 if (!dict)
488 PyTuple_SetItem(t, n++, obj); 626 PyTuple_SetItem(t, n++, obj);
489 else 627 else
490 pydict_set_item_string_decref(dict, field->name, obj); 628 pydict_set_item_string_decref(dict, field->name, obj);
491 629
492 } 630 }
493 631
494 if (!handler) 632 if (dict)
495 PyTuple_SetItem(t, n++, dict); 633 PyTuple_SetItem(t, n++, dict);
496 634
635 if (get_argument_count(handler) == (int) n + 1) {
636 all_entries_dict = get_perf_sample_dict(sample, evsel, al,
637 callchain);
638 PyTuple_SetItem(t, n++, all_entries_dict);
639 } else {
640 Py_DECREF(callchain);
641 }
642
497 if (_PyTuple_Resize(&t, n) == -1) 643 if (_PyTuple_Resize(&t, n) == -1)
498 Py_FatalError("error resizing Python tuple"); 644 Py_FatalError("error resizing Python tuple");
499 645
500 if (handler) { 646 if (!dict) {
501 call_object(handler, t, handler_name); 647 call_object(handler, t, handler_name);
502 } else { 648 } else {
503 try_call_object("trace_unhandled", t); 649 call_object(handler, t, default_handler_name);
504 Py_DECREF(dict); 650 Py_DECREF(dict);
505 } 651 }
506 652
653 Py_XDECREF(all_entries_dict);
507 Py_DECREF(t); 654 Py_DECREF(t);
508} 655}
509 656
@@ -795,10 +942,16 @@ static void python_process_general_event(struct perf_sample *sample,
795 struct perf_evsel *evsel, 942 struct perf_evsel *evsel,
796 struct addr_location *al) 943 struct addr_location *al)
797{ 944{
798 PyObject *handler, *t, *dict, *callchain, *dict_sample; 945 PyObject *handler, *t, *dict, *callchain;
799 static char handler_name[64]; 946 static char handler_name[64];
800 unsigned n = 0; 947 unsigned n = 0;
801 948
949 snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
950
951 handler = get_handler(handler_name);
952 if (!handler)
953 return;
954
802 /* 955 /*
803 * Use the MAX_FIELDS to make the function expandable, though 956 * Use the MAX_FIELDS to make the function expandable, though
804 * currently there is only one item for the tuple. 957 * currently there is only one item for the tuple.
@@ -807,61 +960,16 @@ static void python_process_general_event(struct perf_sample *sample,
807 if (!t) 960 if (!t)
808 Py_FatalError("couldn't create Python tuple"); 961 Py_FatalError("couldn't create Python tuple");
809 962
810 dict = PyDict_New();
811 if (!dict)
812 Py_FatalError("couldn't create Python dictionary");
813
814 dict_sample = PyDict_New();
815 if (!dict_sample)
816 Py_FatalError("couldn't create Python dictionary");
817
818 snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
819
820 handler = get_handler(handler_name);
821 if (!handler)
822 goto exit;
823
824 pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel)));
825 pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
826 (const char *)&evsel->attr, sizeof(evsel->attr)));
827
828 pydict_set_item_string_decref(dict_sample, "pid",
829 PyInt_FromLong(sample->pid));
830 pydict_set_item_string_decref(dict_sample, "tid",
831 PyInt_FromLong(sample->tid));
832 pydict_set_item_string_decref(dict_sample, "cpu",
833 PyInt_FromLong(sample->cpu));
834 pydict_set_item_string_decref(dict_sample, "ip",
835 PyLong_FromUnsignedLongLong(sample->ip));
836 pydict_set_item_string_decref(dict_sample, "time",
837 PyLong_FromUnsignedLongLong(sample->time));
838 pydict_set_item_string_decref(dict_sample, "period",
839 PyLong_FromUnsignedLongLong(sample->period));
840 pydict_set_item_string_decref(dict, "sample", dict_sample);
841
842 pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize(
843 (const char *)sample->raw_data, sample->raw_size));
844 pydict_set_item_string_decref(dict, "comm",
845 PyString_FromString(thread__comm_str(al->thread)));
846 if (al->map) {
847 pydict_set_item_string_decref(dict, "dso",
848 PyString_FromString(al->map->dso->name));
849 }
850 if (al->sym) {
851 pydict_set_item_string_decref(dict, "symbol",
852 PyString_FromString(al->sym->name));
853 }
854
855 /* ip unwinding */ 963 /* ip unwinding */
856 callchain = python_process_callchain(sample, evsel, al); 964 callchain = python_process_callchain(sample, evsel, al);
857 pydict_set_item_string_decref(dict, "callchain", callchain); 965 dict = get_perf_sample_dict(sample, evsel, al, callchain);
858 966
859 PyTuple_SetItem(t, n++, dict); 967 PyTuple_SetItem(t, n++, dict);
860 if (_PyTuple_Resize(&t, n) == -1) 968 if (_PyTuple_Resize(&t, n) == -1)
861 Py_FatalError("error resizing Python tuple"); 969 Py_FatalError("error resizing Python tuple");
862 970
863 call_object(handler, t, handler_name); 971 call_object(handler, t, handler_name);
864exit: 972
865 Py_DECREF(dict); 973 Py_DECREF(dict);
866 Py_DECREF(t); 974 Py_DECREF(t);
867} 975}
@@ -1259,6 +1367,12 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
1259 1367
1260 fprintf(ofp, "%s", f->name); 1368 fprintf(ofp, "%s", f->name);
1261 } 1369 }
1370 if (not_first++)
1371 fprintf(ofp, ", ");
1372 if (++count % 5 == 0)
1373 fprintf(ofp, "\n\t\t");
1374 fprintf(ofp, "perf_sample_dict");
1375
1262 fprintf(ofp, "):\n"); 1376 fprintf(ofp, "):\n");
1263 1377
1264 fprintf(ofp, "\t\tprint_header(event_name, common_cpu, " 1378 fprintf(ofp, "\t\tprint_header(event_name, common_cpu, "
@@ -1328,6 +1442,9 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
1328 1442
1329 fprintf(ofp, ")\n\n"); 1443 fprintf(ofp, ")\n\n");
1330 1444
1445 fprintf(ofp, "\t\tprint 'Sample: {'+"
1446 "get_dict_as_string(perf_sample_dict['sample'], ', ')+'}'\n\n");
1447
1331 fprintf(ofp, "\t\tfor node in common_callchain:"); 1448 fprintf(ofp, "\t\tfor node in common_callchain:");
1332 fprintf(ofp, "\n\t\t\tif 'sym' in node:"); 1449 fprintf(ofp, "\n\t\t\tif 'sym' in node:");
1333 fprintf(ofp, "\n\t\t\t\tprint \"\\t[%%x] %%s\" %% (node['ip'], node['sym']['name'])"); 1450 fprintf(ofp, "\n\t\t\t\tprint \"\\t[%%x] %%s\" %% (node['ip'], node['sym']['name'])");
@@ -1338,15 +1455,20 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
1338 } 1455 }
1339 1456
1340 fprintf(ofp, "def trace_unhandled(event_name, context, " 1457 fprintf(ofp, "def trace_unhandled(event_name, context, "
1341 "event_fields_dict):\n"); 1458 "event_fields_dict, perf_sample_dict):\n");
1342 1459
1343 fprintf(ofp, "\t\tprint ' '.join(['%%s=%%s'%%(k,str(v))" 1460 fprintf(ofp, "\t\tprint get_dict_as_string(event_fields_dict)\n");
1344 "for k,v in sorted(event_fields_dict.items())])\n\n"); 1461 fprintf(ofp, "\t\tprint 'Sample: {'+"
1462 "get_dict_as_string(perf_sample_dict['sample'], ', ')+'}'\n\n");
1345 1463
1346 fprintf(ofp, "def print_header(" 1464 fprintf(ofp, "def print_header("
1347 "event_name, cpu, secs, nsecs, pid, comm):\n" 1465 "event_name, cpu, secs, nsecs, pid, comm):\n"
1348 "\tprint \"%%-20s %%5u %%05u.%%09u %%8u %%-20s \" %% \\\n\t" 1466 "\tprint \"%%-20s %%5u %%05u.%%09u %%8u %%-20s \" %% \\\n\t"
1349 "(event_name, cpu, secs, nsecs, pid, comm),\n"); 1467 "(event_name, cpu, secs, nsecs, pid, comm),\n\n");
1468
1469 fprintf(ofp, "def get_dict_as_string(a_dict, delimiter=' '):\n"
1470 "\treturn delimiter.join"
1471 "(['%%s=%%s'%%(k,str(v))for k,v in sorted(a_dict.items())])\n");
1350 1472
1351 fclose(ofp); 1473 fclose(ofp);
1352 1474