aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/annotate.c21
-rw-r--r--tools/perf/util/cache.h1
-rw-r--r--tools/perf/util/callchain.c240
-rw-r--r--tools/perf/util/callchain.h6
-rw-r--r--tools/perf/util/cloexec.c35
-rw-r--r--tools/perf/util/color.c16
-rw-r--r--tools/perf/util/color.h1
-rw-r--r--tools/perf/util/comm.c7
-rw-r--r--tools/perf/util/comm.h6
-rw-r--r--tools/perf/util/config.c40
-rw-r--r--tools/perf/util/data.c8
-rw-r--r--tools/perf/util/debug.c36
-rw-r--r--tools/perf/util/debug.h11
-rw-r--r--tools/perf/util/dso.c121
-rw-r--r--tools/perf/util/dso.h16
-rw-r--r--tools/perf/util/event.c14
-rw-r--r--tools/perf/util/event.h2
-rw-r--r--tools/perf/util/evlist.c236
-rw-r--r--tools/perf/util/evlist.h21
-rw-r--r--tools/perf/util/evsel.c67
-rw-r--r--tools/perf/util/evsel.h2
-rw-r--r--tools/perf/util/header.c32
-rw-r--r--tools/perf/util/hist.c22
-rw-r--r--tools/perf/util/hist.h18
-rw-r--r--tools/perf/util/kvm-stat.h1
-rw-r--r--tools/perf/util/machine.c96
-rw-r--r--tools/perf/util/machine.h26
-rw-r--r--tools/perf/util/map.c1
-rw-r--r--tools/perf/util/ordered-events.c245
-rw-r--r--tools/perf/util/ordered-events.h51
-rw-r--r--tools/perf/util/parse-events.c29
-rw-r--r--tools/perf/util/parse-events.y10
-rw-r--r--tools/perf/util/pmu.c121
-rw-r--r--tools/perf/util/pmu.h25
-rw-r--r--tools/perf/util/probe-event.c181
-rw-r--r--tools/perf/util/probe-event.h3
-rw-r--r--tools/perf/util/probe-finder.c23
-rw-r--r--tools/perf/util/python.c6
-rw-r--r--tools/perf/util/record.c40
-rw-r--r--tools/perf/util/run-command.c9
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c6
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c120
-rw-r--r--tools/perf/util/session.c300
-rw-r--r--tools/perf/util/session.h32
-rw-r--r--tools/perf/util/sort.c119
-rw-r--r--tools/perf/util/sort.h1
-rw-r--r--tools/perf/util/string.c90
-rw-r--r--tools/perf/util/symbol-elf.c31
-rw-r--r--tools/perf/util/symbol.c43
-rw-r--r--tools/perf/util/symbol.h14
-rw-r--r--tools/perf/util/thread.c24
-rw-r--r--tools/perf/util/thread.h10
-rw-r--r--tools/perf/util/tool.h2
-rw-r--r--tools/perf/util/trace-event-scripting.c7
-rw-r--r--tools/perf/util/trace-event.h1
-rw-r--r--tools/perf/util/util.c54
-rw-r--r--tools/perf/util/util.h23
57 files changed, 2002 insertions, 721 deletions
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 809b4c50beae..36437527dbb3 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -232,9 +232,16 @@ static int mov__parse(struct ins_operands *ops)
232 return -1; 232 return -1;
233 233
234 target = ++s; 234 target = ++s;
235 comment = strchr(s, '#');
235 236
236 while (s[0] != '\0' && !isspace(s[0])) 237 if (comment != NULL)
237 ++s; 238 s = comment - 1;
239 else
240 s = strchr(s, '\0') - 1;
241
242 while (s > target && isspace(s[0]))
243 --s;
244 s++;
238 prev = *s; 245 prev = *s;
239 *s = '\0'; 246 *s = '\0';
240 247
@@ -244,7 +251,6 @@ static int mov__parse(struct ins_operands *ops)
244 if (ops->target.raw == NULL) 251 if (ops->target.raw == NULL)
245 goto out_free_source; 252 goto out_free_source;
246 253
247 comment = strchr(s, '#');
248 if (comment == NULL) 254 if (comment == NULL)
249 return 0; 255 return 0;
250 256
@@ -899,10 +905,8 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
899 struct kcore_extract kce; 905 struct kcore_extract kce;
900 bool delete_extract = false; 906 bool delete_extract = false;
901 907
902 if (filename) { 908 if (filename)
903 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s", 909 symbol__join_symfs(symfs_filename, filename);
904 symbol_conf.symfs, filename);
905 }
906 910
907 if (filename == NULL) { 911 if (filename == NULL) {
908 if (dso->has_build_id) { 912 if (dso->has_build_id) {
@@ -922,8 +926,7 @@ fallback:
922 * DSO is the same as when 'perf record' ran. 926 * DSO is the same as when 'perf record' ran.
923 */ 927 */
924 filename = (char *)dso->long_name; 928 filename = (char *)dso->long_name;
925 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s", 929 symbol__join_symfs(symfs_filename, filename);
926 symbol_conf.symfs, filename);
927 free_filename = false; 930 free_filename = false;
928 } 931 }
929 932
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 7b176dd02e1a..5cf9e1b5989d 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -22,6 +22,7 @@ typedef int (*config_fn_t)(const char *, const char *, void *);
22extern int perf_default_config(const char *, const char *, void *); 22extern int perf_default_config(const char *, const char *, void *);
23extern int perf_config(config_fn_t fn, void *); 23extern int perf_config(config_fn_t fn, void *);
24extern int perf_config_int(const char *, const char *); 24extern int perf_config_int(const char *, const char *);
25extern u64 perf_config_u64(const char *, const char *);
25extern int perf_config_bool(const char *, const char *); 26extern int perf_config_bool(const char *, const char *);
26extern int config_error_nonbool(const char *); 27extern int config_error_nonbool(const char *);
27extern const char *perf_config_dirname(const char *, const char *); 28extern const char *perf_config_dirname(const char *, const char *);
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 437ee09727e6..c84d3f8dcb75 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -25,77 +25,172 @@
25 25
26__thread struct callchain_cursor callchain_cursor; 26__thread struct callchain_cursor callchain_cursor;
27 27
28int 28#ifdef HAVE_DWARF_UNWIND_SUPPORT
29parse_callchain_report_opt(const char *arg) 29static int get_stack_size(const char *str, unsigned long *_size)
30{ 30{
31 char *tok, *tok2;
32 char *endptr; 31 char *endptr;
32 unsigned long size;
33 unsigned long max_size = round_down(USHRT_MAX, sizeof(u64));
33 34
34 symbol_conf.use_callchain = true; 35 size = strtoul(str, &endptr, 0);
35 36
36 if (!arg) 37 do {
38 if (*endptr)
39 break;
40
41 size = round_up(size, sizeof(u64));
42 if (!size || size > max_size)
43 break;
44
45 *_size = size;
37 return 0; 46 return 0;
38 47
39 tok = strtok((char *)arg, ","); 48 } while (0);
40 if (!tok)
41 return -1;
42 49
43 /* get the output mode */ 50 pr_err("callchain: Incorrect stack dump size (max %ld): %s\n",
44 if (!strncmp(tok, "graph", strlen(arg))) { 51 max_size, str);
45 callchain_param.mode = CHAIN_GRAPH_ABS; 52 return -1;
53}
54#endif /* HAVE_DWARF_UNWIND_SUPPORT */
46 55
47 } else if (!strncmp(tok, "flat", strlen(arg))) { 56int parse_callchain_record_opt(const char *arg)
48 callchain_param.mode = CHAIN_FLAT; 57{
49 } else if (!strncmp(tok, "fractal", strlen(arg))) { 58 char *tok, *name, *saveptr = NULL;
50 callchain_param.mode = CHAIN_GRAPH_REL; 59 char *buf;
51 } else if (!strncmp(tok, "none", strlen(arg))) { 60 int ret = -1;
52 callchain_param.mode = CHAIN_NONE; 61
53 symbol_conf.use_callchain = false; 62 /* We need buffer that we know we can write to. */
54 return 0; 63 buf = malloc(strlen(arg) + 1);
55 } else { 64 if (!buf)
56 return -1; 65 return -ENOMEM;
57 } 66
67 strcpy(buf, arg);
68
69 tok = strtok_r((char *)buf, ",", &saveptr);
70 name = tok ? : (char *)buf;
71
72 do {
73 /* Framepointer style */
74 if (!strncmp(name, "fp", sizeof("fp"))) {
75 if (!strtok_r(NULL, ",", &saveptr)) {
76 callchain_param.record_mode = CALLCHAIN_FP;
77 ret = 0;
78 } else
79 pr_err("callchain: No more arguments "
80 "needed for -g fp\n");
81 break;
58 82
59 /* get the min percentage */ 83#ifdef HAVE_DWARF_UNWIND_SUPPORT
60 tok = strtok(NULL, ","); 84 /* Dwarf style */
61 if (!tok) 85 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
62 goto setup; 86 const unsigned long default_stack_dump_size = 8192;
63 87
64 callchain_param.min_percent = strtod(tok, &endptr); 88 ret = 0;
65 if (tok == endptr) 89 callchain_param.record_mode = CALLCHAIN_DWARF;
66 return -1; 90 callchain_param.dump_size = default_stack_dump_size;
67 91
68 /* get the print limit */ 92 tok = strtok_r(NULL, ",", &saveptr);
69 tok2 = strtok(NULL, ","); 93 if (tok) {
70 if (!tok2) 94 unsigned long size = 0;
71 goto setup;
72 95
73 if (tok2[0] != 'c') { 96 ret = get_stack_size(tok, &size);
74 callchain_param.print_limit = strtoul(tok2, &endptr, 0); 97 callchain_param.dump_size = size;
75 tok2 = strtok(NULL, ","); 98 }
76 if (!tok2) 99#endif /* HAVE_DWARF_UNWIND_SUPPORT */
77 goto setup; 100 } else {
101 pr_err("callchain: Unknown --call-graph option "
102 "value: %s\n", arg);
103 break;
104 }
105
106 } while (0);
107
108 free(buf);
109 return ret;
110}
111
112static int parse_callchain_mode(const char *value)
113{
114 if (!strncmp(value, "graph", strlen(value))) {
115 callchain_param.mode = CHAIN_GRAPH_ABS;
116 return 0;
117 }
118 if (!strncmp(value, "flat", strlen(value))) {
119 callchain_param.mode = CHAIN_FLAT;
120 return 0;
78 } 121 }
122 if (!strncmp(value, "fractal", strlen(value))) {
123 callchain_param.mode = CHAIN_GRAPH_REL;
124 return 0;
125 }
126 return -1;
127}
79 128
80 /* get the call chain order */ 129static int parse_callchain_order(const char *value)
81 if (!strncmp(tok2, "caller", strlen("caller"))) 130{
131 if (!strncmp(value, "caller", strlen(value))) {
82 callchain_param.order = ORDER_CALLER; 132 callchain_param.order = ORDER_CALLER;
83 else if (!strncmp(tok2, "callee", strlen("callee"))) 133 return 0;
134 }
135 if (!strncmp(value, "callee", strlen(value))) {
84 callchain_param.order = ORDER_CALLEE; 136 callchain_param.order = ORDER_CALLEE;
85 else 137 return 0;
86 return -1; 138 }
139 return -1;
140}
87 141
88 /* Get the sort key */ 142static int parse_callchain_sort_key(const char *value)
89 tok2 = strtok(NULL, ","); 143{
90 if (!tok2) 144 if (!strncmp(value, "function", strlen(value))) {
91 goto setup;
92 if (!strncmp(tok2, "function", strlen("function")))
93 callchain_param.key = CCKEY_FUNCTION; 145 callchain_param.key = CCKEY_FUNCTION;
94 else if (!strncmp(tok2, "address", strlen("address"))) 146 return 0;
147 }
148 if (!strncmp(value, "address", strlen(value))) {
95 callchain_param.key = CCKEY_ADDRESS; 149 callchain_param.key = CCKEY_ADDRESS;
96 else 150 return 0;
97 return -1; 151 }
98setup: 152 return -1;
153}
154
155int
156parse_callchain_report_opt(const char *arg)
157{
158 char *tok;
159 char *endptr;
160 bool minpcnt_set = false;
161
162 symbol_conf.use_callchain = true;
163
164 if (!arg)
165 return 0;
166
167 while ((tok = strtok((char *)arg, ",")) != NULL) {
168 if (!strncmp(tok, "none", strlen(tok))) {
169 callchain_param.mode = CHAIN_NONE;
170 symbol_conf.use_callchain = false;
171 return 0;
172 }
173
174 if (!parse_callchain_mode(tok) ||
175 !parse_callchain_order(tok) ||
176 !parse_callchain_sort_key(tok)) {
177 /* parsing ok - move on to the next */
178 } else if (!minpcnt_set) {
179 /* try to get the min percent */
180 callchain_param.min_percent = strtod(tok, &endptr);
181 if (tok == endptr)
182 return -1;
183 minpcnt_set = true;
184 } else {
185 /* try print limit at last */
186 callchain_param.print_limit = strtoul(tok, &endptr, 0);
187 if (tok == endptr)
188 return -1;
189 }
190
191 arg = NULL;
192 }
193
99 if (callchain_register_param(&callchain_param) < 0) { 194 if (callchain_register_param(&callchain_param) < 0) {
100 pr_err("Can't register callchain params\n"); 195 pr_err("Can't register callchain params\n");
101 return -1; 196 return -1;
@@ -103,6 +198,47 @@ setup:
103 return 0; 198 return 0;
104} 199}
105 200
201int perf_callchain_config(const char *var, const char *value)
202{
203 char *endptr;
204
205 if (prefixcmp(var, "call-graph."))
206 return 0;
207 var += sizeof("call-graph.") - 1;
208
209 if (!strcmp(var, "record-mode"))
210 return parse_callchain_record_opt(value);
211#ifdef HAVE_DWARF_UNWIND_SUPPORT
212 if (!strcmp(var, "dump-size")) {
213 unsigned long size = 0;
214 int ret;
215
216 ret = get_stack_size(value, &size);
217 callchain_param.dump_size = size;
218
219 return ret;
220 }
221#endif
222 if (!strcmp(var, "print-type"))
223 return parse_callchain_mode(value);
224 if (!strcmp(var, "order"))
225 return parse_callchain_order(value);
226 if (!strcmp(var, "sort-key"))
227 return parse_callchain_sort_key(value);
228 if (!strcmp(var, "threshold")) {
229 callchain_param.min_percent = strtod(value, &endptr);
230 if (value == endptr)
231 return -1;
232 }
233 if (!strcmp(var, "print-limit")) {
234 callchain_param.print_limit = strtod(value, &endptr);
235 if (value == endptr)
236 return -1;
237 }
238
239 return 0;
240}
241
106static void 242static void
107rb_insert_callchain(struct rb_root *root, struct callchain_node *chain, 243rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
108 enum chain_mode mode) 244 enum chain_mode mode)
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index da43619d6173..2a1f5a46543a 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -54,6 +54,9 @@ enum chain_key {
54}; 54};
55 55
56struct callchain_param { 56struct callchain_param {
57 bool enabled;
58 enum perf_call_graph_mode record_mode;
59 u32 dump_size;
57 enum chain_mode mode; 60 enum chain_mode mode;
58 u32 print_limit; 61 u32 print_limit;
59 double min_percent; 62 double min_percent;
@@ -154,7 +157,6 @@ static inline void callchain_cursor_advance(struct callchain_cursor *cursor)
154struct option; 157struct option;
155struct hist_entry; 158struct hist_entry;
156 159
157int record_parse_callchain(const char *arg, struct record_opts *opts);
158int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset); 160int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset);
159int record_callchain_opt(const struct option *opt, const char *arg, int unset); 161int record_callchain_opt(const struct option *opt, const char *arg, int unset);
160 162
@@ -166,7 +168,9 @@ int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *
166 bool hide_unresolved); 168 bool hide_unresolved);
167 169
168extern const char record_callchain_help[]; 170extern const char record_callchain_help[];
171int parse_callchain_record_opt(const char *arg);
169int parse_callchain_report_opt(const char *arg); 172int parse_callchain_report_opt(const char *arg);
173int perf_callchain_config(const char *var, const char *value);
170 174
171static inline void callchain_cursor_snapshot(struct callchain_cursor *dest, 175static inline void callchain_cursor_snapshot(struct callchain_cursor *dest,
172 struct callchain_cursor *src) 176 struct callchain_cursor *src)
diff --git a/tools/perf/util/cloexec.c b/tools/perf/util/cloexec.c
index c5d05ec17220..47b78b3f0325 100644
--- a/tools/perf/util/cloexec.c
+++ b/tools/perf/util/cloexec.c
@@ -1,7 +1,9 @@
1#include <sched.h>
1#include "util.h" 2#include "util.h"
2#include "../perf.h" 3#include "../perf.h"
3#include "cloexec.h" 4#include "cloexec.h"
4#include "asm/bug.h" 5#include "asm/bug.h"
6#include "debug.h"
5 7
6static unsigned long flag = PERF_FLAG_FD_CLOEXEC; 8static unsigned long flag = PERF_FLAG_FD_CLOEXEC;
7 9
@@ -9,15 +11,30 @@ static int perf_flag_probe(void)
9{ 11{
10 /* use 'safest' configuration as used in perf_evsel__fallback() */ 12 /* use 'safest' configuration as used in perf_evsel__fallback() */
11 struct perf_event_attr attr = { 13 struct perf_event_attr attr = {
12 .type = PERF_COUNT_SW_CPU_CLOCK, 14 .type = PERF_TYPE_SOFTWARE,
13 .config = PERF_COUNT_SW_CPU_CLOCK, 15 .config = PERF_COUNT_SW_CPU_CLOCK,
16 .exclude_kernel = 1,
14 }; 17 };
15 int fd; 18 int fd;
16 int err; 19 int err;
20 int cpu;
21 pid_t pid = -1;
22 char sbuf[STRERR_BUFSIZE];
17 23
18 /* check cloexec flag */ 24 cpu = sched_getcpu();
19 fd = sys_perf_event_open(&attr, 0, -1, -1, 25 if (cpu < 0)
20 PERF_FLAG_FD_CLOEXEC); 26 cpu = 0;
27
28 while (1) {
29 /* check cloexec flag */
30 fd = sys_perf_event_open(&attr, pid, cpu, -1,
31 PERF_FLAG_FD_CLOEXEC);
32 if (fd < 0 && pid == -1 && errno == EACCES) {
33 pid = 0;
34 continue;
35 }
36 break;
37 }
21 err = errno; 38 err = errno;
22 39
23 if (fd >= 0) { 40 if (fd >= 0) {
@@ -25,17 +42,17 @@ static int perf_flag_probe(void)
25 return 1; 42 return 1;
26 } 43 }
27 44
28 WARN_ONCE(err != EINVAL, 45 WARN_ONCE(err != EINVAL && err != EBUSY,
29 "perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error %d (%s)\n", 46 "perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error %d (%s)\n",
30 err, strerror(err)); 47 err, strerror_r(err, sbuf, sizeof(sbuf)));
31 48
32 /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */ 49 /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */
33 fd = sys_perf_event_open(&attr, 0, -1, -1, 0); 50 fd = sys_perf_event_open(&attr, pid, cpu, -1, 0);
34 err = errno; 51 err = errno;
35 52
36 if (WARN_ONCE(fd < 0, 53 if (WARN_ONCE(fd < 0 && err != EBUSY,
37 "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n", 54 "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n",
38 err, strerror(err))) 55 err, strerror_r(err, sbuf, sizeof(sbuf))))
39 return -1; 56 return -1;
40 57
41 close(fd); 58 close(fd);
diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c
index 87b8672eb413..f4654183d391 100644
--- a/tools/perf/util/color.c
+++ b/tools/perf/util/color.c
@@ -335,3 +335,19 @@ int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...)
335 va_end(args); 335 va_end(args);
336 return value_color_snprintf(bf, size, fmt, percent); 336 return value_color_snprintf(bf, size, fmt, percent);
337} 337}
338
339int percent_color_len_snprintf(char *bf, size_t size, const char *fmt, ...)
340{
341 va_list args;
342 int len;
343 double percent;
344 const char *color;
345
346 va_start(args, fmt);
347 len = va_arg(args, int);
348 percent = va_arg(args, double);
349 va_end(args);
350
351 color = get_percent_color(percent);
352 return color_snprintf(bf, size, color, fmt, len, percent);
353}
diff --git a/tools/perf/util/color.h b/tools/perf/util/color.h
index 7ff30a62a132..0a594b8a0c26 100644
--- a/tools/perf/util/color.h
+++ b/tools/perf/util/color.h
@@ -41,6 +41,7 @@ int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...);
41int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf); 41int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf);
42int value_color_snprintf(char *bf, size_t size, const char *fmt, double value); 42int value_color_snprintf(char *bf, size_t size, const char *fmt, double value);
43int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...); 43int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...);
44int percent_color_len_snprintf(char *bf, size_t size, const char *fmt, ...);
44int percent_color_fprintf(FILE *fp, const char *fmt, double percent); 45int percent_color_fprintf(FILE *fp, const char *fmt, double percent);
45const char *get_percent_color(double percent); 46const char *get_percent_color(double percent);
46 47
diff --git a/tools/perf/util/comm.c b/tools/perf/util/comm.c
index f9e777629e21..b2bb59df65e1 100644
--- a/tools/perf/util/comm.c
+++ b/tools/perf/util/comm.c
@@ -74,7 +74,7 @@ static struct comm_str *comm_str__findnew(const char *str, struct rb_root *root)
74 return new; 74 return new;
75} 75}
76 76
77struct comm *comm__new(const char *str, u64 timestamp) 77struct comm *comm__new(const char *str, u64 timestamp, bool exec)
78{ 78{
79 struct comm *comm = zalloc(sizeof(*comm)); 79 struct comm *comm = zalloc(sizeof(*comm));
80 80
@@ -82,6 +82,7 @@ struct comm *comm__new(const char *str, u64 timestamp)
82 return NULL; 82 return NULL;
83 83
84 comm->start = timestamp; 84 comm->start = timestamp;
85 comm->exec = exec;
85 86
86 comm->comm_str = comm_str__findnew(str, &comm_str_root); 87 comm->comm_str = comm_str__findnew(str, &comm_str_root);
87 if (!comm->comm_str) { 88 if (!comm->comm_str) {
@@ -94,7 +95,7 @@ struct comm *comm__new(const char *str, u64 timestamp)
94 return comm; 95 return comm;
95} 96}
96 97
97int comm__override(struct comm *comm, const char *str, u64 timestamp) 98int comm__override(struct comm *comm, const char *str, u64 timestamp, bool exec)
98{ 99{
99 struct comm_str *new, *old = comm->comm_str; 100 struct comm_str *new, *old = comm->comm_str;
100 101
@@ -106,6 +107,8 @@ int comm__override(struct comm *comm, const char *str, u64 timestamp)
106 comm_str__put(old); 107 comm_str__put(old);
107 comm->comm_str = new; 108 comm->comm_str = new;
108 comm->start = timestamp; 109 comm->start = timestamp;
110 if (exec)
111 comm->exec = true;
109 112
110 return 0; 113 return 0;
111} 114}
diff --git a/tools/perf/util/comm.h b/tools/perf/util/comm.h
index fac5bd51befc..51c10ab257f8 100644
--- a/tools/perf/util/comm.h
+++ b/tools/perf/util/comm.h
@@ -11,11 +11,13 @@ struct comm {
11 struct comm_str *comm_str; 11 struct comm_str *comm_str;
12 u64 start; 12 u64 start;
13 struct list_head list; 13 struct list_head list;
14 bool exec;
14}; 15};
15 16
16void comm__free(struct comm *comm); 17void comm__free(struct comm *comm);
17struct comm *comm__new(const char *str, u64 timestamp); 18struct comm *comm__new(const char *str, u64 timestamp, bool exec);
18const char *comm__str(const struct comm *comm); 19const char *comm__str(const struct comm *comm);
19int comm__override(struct comm *comm, const char *str, u64 timestamp); 20int comm__override(struct comm *comm, const char *str, u64 timestamp,
21 bool exec);
20 22
21#endif /* __PERF_COMM_H */ 23#endif /* __PERF_COMM_H */
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 1e5e2e5af6b1..57ff826f150b 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -222,7 +222,8 @@ static int perf_parse_file(config_fn_t fn, void *data)
222 const unsigned char *bomptr = utf8_bom; 222 const unsigned char *bomptr = utf8_bom;
223 223
224 for (;;) { 224 for (;;) {
225 int c = get_next_char(); 225 int line, c = get_next_char();
226
226 if (bomptr && *bomptr) { 227 if (bomptr && *bomptr) {
227 /* We are at the file beginning; skip UTF8-encoded BOM 228 /* We are at the file beginning; skip UTF8-encoded BOM
228 * if present. Sane editors won't put this in on their 229 * if present. Sane editors won't put this in on their
@@ -261,8 +262,16 @@ static int perf_parse_file(config_fn_t fn, void *data)
261 if (!isalpha(c)) 262 if (!isalpha(c))
262 break; 263 break;
263 var[baselen] = tolower(c); 264 var[baselen] = tolower(c);
264 if (get_value(fn, data, var, baselen+1) < 0) 265
266 /*
267 * The get_value function might or might not reach the '\n',
268 * so saving the current line number for error reporting.
269 */
270 line = config_linenr;
271 if (get_value(fn, data, var, baselen+1) < 0) {
272 config_linenr = line;
265 break; 273 break;
274 }
266 } 275 }
267 die("bad config file line %d in %s", config_linenr, config_file_name); 276 die("bad config file line %d in %s", config_linenr, config_file_name);
268} 277}
@@ -286,6 +295,21 @@ static int parse_unit_factor(const char *end, unsigned long *val)
286 return 0; 295 return 0;
287} 296}
288 297
298static int perf_parse_llong(const char *value, long long *ret)
299{
300 if (value && *value) {
301 char *end;
302 long long val = strtoll(value, &end, 0);
303 unsigned long factor = 1;
304
305 if (!parse_unit_factor(end, &factor))
306 return 0;
307 *ret = val * factor;
308 return 1;
309 }
310 return 0;
311}
312
289static int perf_parse_long(const char *value, long *ret) 313static int perf_parse_long(const char *value, long *ret)
290{ 314{
291 if (value && *value) { 315 if (value && *value) {
@@ -307,6 +331,15 @@ static void die_bad_config(const char *name)
307 die("bad config value for '%s'", name); 331 die("bad config value for '%s'", name);
308} 332}
309 333
334u64 perf_config_u64(const char *name, const char *value)
335{
336 long long ret = 0;
337
338 if (!perf_parse_llong(value, &ret))
339 die_bad_config(name);
340 return (u64) ret;
341}
342
310int perf_config_int(const char *name, const char *value) 343int perf_config_int(const char *name, const char *value)
311{ 344{
312 long ret = 0; 345 long ret = 0;
@@ -372,6 +405,9 @@ int perf_default_config(const char *var, const char *value,
372 if (!prefixcmp(var, "ui.")) 405 if (!prefixcmp(var, "ui."))
373 return perf_ui_config(var, value); 406 return perf_ui_config(var, value);
374 407
408 if (!prefixcmp(var, "call-graph."))
409 return perf_callchain_config(var, value);
410
375 /* Add other config variables here. */ 411 /* Add other config variables here. */
376 return 0; 412 return 0;
377} 413}
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index 29d720cf5844..1921942fc2e0 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -50,12 +50,14 @@ static int open_file_read(struct perf_data_file *file)
50{ 50{
51 struct stat st; 51 struct stat st;
52 int fd; 52 int fd;
53 char sbuf[STRERR_BUFSIZE];
53 54
54 fd = open(file->path, O_RDONLY); 55 fd = open(file->path, O_RDONLY);
55 if (fd < 0) { 56 if (fd < 0) {
56 int err = errno; 57 int err = errno;
57 58
58 pr_err("failed to open %s: %s", file->path, strerror(err)); 59 pr_err("failed to open %s: %s", file->path,
60 strerror_r(err, sbuf, sizeof(sbuf)));
59 if (err == ENOENT && !strcmp(file->path, "perf.data")) 61 if (err == ENOENT && !strcmp(file->path, "perf.data"))
60 pr_err(" (try 'perf record' first)"); 62 pr_err(" (try 'perf record' first)");
61 pr_err("\n"); 63 pr_err("\n");
@@ -88,6 +90,7 @@ static int open_file_read(struct perf_data_file *file)
88static int open_file_write(struct perf_data_file *file) 90static int open_file_write(struct perf_data_file *file)
89{ 91{
90 int fd; 92 int fd;
93 char sbuf[STRERR_BUFSIZE];
91 94
92 if (check_backup(file)) 95 if (check_backup(file))
93 return -1; 96 return -1;
@@ -95,7 +98,8 @@ static int open_file_write(struct perf_data_file *file)
95 fd = open(file->path, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR); 98 fd = open(file->path, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR);
96 99
97 if (fd < 0) 100 if (fd < 0)
98 pr_err("failed to open %s : %s\n", file->path, strerror(errno)); 101 pr_err("failed to open %s : %s\n", file->path,
102 strerror_r(errno, sbuf, sizeof(sbuf)));
99 103
100 return fd; 104 return fd;
101} 105}
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index 71d419362634..ba357f3226c6 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -13,8 +13,12 @@
13#include "util.h" 13#include "util.h"
14#include "target.h" 14#include "target.h"
15 15
16#define NSECS_PER_SEC 1000000000ULL
17#define NSECS_PER_USEC 1000ULL
18
16int verbose; 19int verbose;
17bool dump_trace = false, quiet = false; 20bool dump_trace = false, quiet = false;
21int debug_ordered_events;
18 22
19static int _eprintf(int level, int var, const char *fmt, va_list args) 23static int _eprintf(int level, int var, const char *fmt, va_list args)
20{ 24{
@@ -42,6 +46,35 @@ int eprintf(int level, int var, const char *fmt, ...)
42 return ret; 46 return ret;
43} 47}
44 48
49static int __eprintf_time(u64 t, const char *fmt, va_list args)
50{
51 int ret = 0;
52 u64 secs, usecs, nsecs = t;
53
54 secs = nsecs / NSECS_PER_SEC;
55 nsecs -= secs * NSECS_PER_SEC;
56 usecs = nsecs / NSECS_PER_USEC;
57
58 ret = fprintf(stderr, "[%13" PRIu64 ".%06" PRIu64 "] ",
59 secs, usecs);
60 ret += vfprintf(stderr, fmt, args);
61 return ret;
62}
63
64int eprintf_time(int level, int var, u64 t, const char *fmt, ...)
65{
66 int ret = 0;
67 va_list args;
68
69 if (var >= level) {
70 va_start(args, fmt);
71 ret = __eprintf_time(t, fmt, args);
72 va_end(args);
73 }
74
75 return ret;
76}
77
45/* 78/*
46 * Overloading libtraceevent standard info print 79 * Overloading libtraceevent standard info print
47 * function, display with -v in perf. 80 * function, display with -v in perf.
@@ -110,7 +143,8 @@ static struct debug_variable {
110 const char *name; 143 const char *name;
111 int *ptr; 144 int *ptr;
112} debug_variables[] = { 145} debug_variables[] = {
113 { .name = "verbose", .ptr = &verbose }, 146 { .name = "verbose", .ptr = &verbose },
147 { .name = "ordered-events", .ptr = &debug_ordered_events},
114 { .name = NULL, } 148 { .name = NULL, }
115}; 149};
116 150
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index 89fb6b0f7ab2..be264d6f3b30 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -3,6 +3,7 @@
3#define __PERF_DEBUG_H 3#define __PERF_DEBUG_H
4 4
5#include <stdbool.h> 5#include <stdbool.h>
6#include <string.h>
6#include "event.h" 7#include "event.h"
7#include "../ui/helpline.h" 8#include "../ui/helpline.h"
8#include "../ui/progress.h" 9#include "../ui/progress.h"
@@ -10,6 +11,7 @@
10 11
11extern int verbose; 12extern int verbose;
12extern bool quiet, dump_trace; 13extern bool quiet, dump_trace;
14extern int debug_ordered_events;
13 15
14#ifndef pr_fmt 16#ifndef pr_fmt
15#define pr_fmt(fmt) fmt 17#define pr_fmt(fmt) fmt
@@ -29,6 +31,14 @@ extern bool quiet, dump_trace;
29#define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__) 31#define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__)
30#define pr_debug4(fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__) 32#define pr_debug4(fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__)
31 33
34#define pr_time_N(n, var, t, fmt, ...) \
35 eprintf_time(n, var, t, fmt, ##__VA_ARGS__)
36
37#define pr_oe_time(t, fmt, ...) pr_time_N(1, debug_ordered_events, t, pr_fmt(fmt), ##__VA_ARGS__)
38#define pr_oe_time2(t, fmt, ...) pr_time_N(2, debug_ordered_events, t, pr_fmt(fmt), ##__VA_ARGS__)
39
40#define STRERR_BUFSIZE 128 /* For the buffer size of strerror_r */
41
32int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); 42int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
33void trace_event(union perf_event *event); 43void trace_event(union perf_event *event);
34 44
@@ -38,6 +48,7 @@ int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
38void pr_stat(const char *fmt, ...); 48void pr_stat(const char *fmt, ...);
39 49
40int eprintf(int level, int var, const char *fmt, ...) __attribute__((format(printf, 3, 4))); 50int eprintf(int level, int var, const char *fmt, ...) __attribute__((format(printf, 3, 4)));
51int eprintf_time(int level, int var, u64 t, const char *fmt, ...) __attribute__((format(printf, 4, 5)));
41 52
42int perf_debug_option(const char *str); 53int perf_debug_option(const char *str);
43 54
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 90d02c661dd4..0247acfdfaca 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -37,6 +37,7 @@ int dso__read_binary_type_filename(const struct dso *dso,
37{ 37{
38 char build_id_hex[BUILD_ID_SIZE * 2 + 1]; 38 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
39 int ret = 0; 39 int ret = 0;
40 size_t len;
40 41
41 switch (type) { 42 switch (type) {
42 case DSO_BINARY_TYPE__DEBUGLINK: { 43 case DSO_BINARY_TYPE__DEBUGLINK: {
@@ -60,26 +61,25 @@ int dso__read_binary_type_filename(const struct dso *dso,
60 break; 61 break;
61 62
62 case DSO_BINARY_TYPE__FEDORA_DEBUGINFO: 63 case DSO_BINARY_TYPE__FEDORA_DEBUGINFO:
63 snprintf(filename, size, "%s/usr/lib/debug%s.debug", 64 len = __symbol__join_symfs(filename, size, "/usr/lib/debug");
64 symbol_conf.symfs, dso->long_name); 65 snprintf(filename + len, size - len, "%s.debug", dso->long_name);
65 break; 66 break;
66 67
67 case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO: 68 case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO:
68 snprintf(filename, size, "%s/usr/lib/debug%s", 69 len = __symbol__join_symfs(filename, size, "/usr/lib/debug");
69 symbol_conf.symfs, dso->long_name); 70 snprintf(filename + len, size - len, "%s", dso->long_name);
70 break; 71 break;
71 72
72 case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO: 73 case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO:
73 { 74 {
74 const char *last_slash; 75 const char *last_slash;
75 size_t len;
76 size_t dir_size; 76 size_t dir_size;
77 77
78 last_slash = dso->long_name + dso->long_name_len; 78 last_slash = dso->long_name + dso->long_name_len;
79 while (last_slash != dso->long_name && *last_slash != '/') 79 while (last_slash != dso->long_name && *last_slash != '/')
80 last_slash--; 80 last_slash--;
81 81
82 len = scnprintf(filename, size, "%s", symbol_conf.symfs); 82 len = __symbol__join_symfs(filename, size, "");
83 dir_size = last_slash - dso->long_name + 2; 83 dir_size = last_slash - dso->long_name + 2;
84 if (dir_size > (size - len)) { 84 if (dir_size > (size - len)) {
85 ret = -1; 85 ret = -1;
@@ -100,26 +100,24 @@ int dso__read_binary_type_filename(const struct dso *dso,
100 build_id__sprintf(dso->build_id, 100 build_id__sprintf(dso->build_id,
101 sizeof(dso->build_id), 101 sizeof(dso->build_id),
102 build_id_hex); 102 build_id_hex);
103 snprintf(filename, size, 103 len = __symbol__join_symfs(filename, size, "/usr/lib/debug/.build-id/");
104 "%s/usr/lib/debug/.build-id/%.2s/%s.debug", 104 snprintf(filename + len, size - len, "%.2s/%s.debug",
105 symbol_conf.symfs, build_id_hex, build_id_hex + 2); 105 build_id_hex, build_id_hex + 2);
106 break; 106 break;
107 107
108 case DSO_BINARY_TYPE__VMLINUX: 108 case DSO_BINARY_TYPE__VMLINUX:
109 case DSO_BINARY_TYPE__GUEST_VMLINUX: 109 case DSO_BINARY_TYPE__GUEST_VMLINUX:
110 case DSO_BINARY_TYPE__SYSTEM_PATH_DSO: 110 case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
111 snprintf(filename, size, "%s%s", 111 __symbol__join_symfs(filename, size, dso->long_name);
112 symbol_conf.symfs, dso->long_name);
113 break; 112 break;
114 113
115 case DSO_BINARY_TYPE__GUEST_KMODULE: 114 case DSO_BINARY_TYPE__GUEST_KMODULE:
116 snprintf(filename, size, "%s%s%s", symbol_conf.symfs, 115 path__join3(filename, size, symbol_conf.symfs,
117 root_dir, dso->long_name); 116 root_dir, dso->long_name);
118 break; 117 break;
119 118
120 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE: 119 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
121 snprintf(filename, size, "%s%s", symbol_conf.symfs, 120 __symbol__join_symfs(filename, size, dso->long_name);
122 dso->long_name);
123 break; 121 break;
124 122
125 case DSO_BINARY_TYPE__KCORE: 123 case DSO_BINARY_TYPE__KCORE:
@@ -164,13 +162,15 @@ static void close_first_dso(void);
164static int do_open(char *name) 162static int do_open(char *name)
165{ 163{
166 int fd; 164 int fd;
165 char sbuf[STRERR_BUFSIZE];
167 166
168 do { 167 do {
169 fd = open(name, O_RDONLY); 168 fd = open(name, O_RDONLY);
170 if (fd >= 0) 169 if (fd >= 0)
171 return fd; 170 return fd;
172 171
173 pr_debug("dso open failed, mmap: %s\n", strerror(errno)); 172 pr_debug("dso open failed, mmap: %s\n",
173 strerror_r(errno, sbuf, sizeof(sbuf)));
174 if (!dso__data_open_cnt || errno != EMFILE) 174 if (!dso__data_open_cnt || errno != EMFILE)
175 break; 175 break;
176 176
@@ -532,10 +532,12 @@ static ssize_t cached_read(struct dso *dso, u64 offset, u8 *data, ssize_t size)
532static int data_file_size(struct dso *dso) 532static int data_file_size(struct dso *dso)
533{ 533{
534 struct stat st; 534 struct stat st;
535 char sbuf[STRERR_BUFSIZE];
535 536
536 if (!dso->data.file_size) { 537 if (!dso->data.file_size) {
537 if (fstat(dso->data.fd, &st)) { 538 if (fstat(dso->data.fd, &st)) {
538 pr_err("dso mmap failed, fstat: %s\n", strerror(errno)); 539 pr_err("dso mmap failed, fstat: %s\n",
540 strerror_r(errno, sbuf, sizeof(sbuf)));
539 return -1; 541 return -1;
540 } 542 }
541 dso->data.file_size = st.st_size; 543 dso->data.file_size = st.st_size;
@@ -651,6 +653,65 @@ struct dso *dso__kernel_findnew(struct machine *machine, const char *name,
651 return dso; 653 return dso;
652} 654}
653 655
656/*
657 * Find a matching entry and/or link current entry to RB tree.
658 * Either one of the dso or name parameter must be non-NULL or the
659 * function will not work.
660 */
661static struct dso *dso__findlink_by_longname(struct rb_root *root,
662 struct dso *dso, const char *name)
663{
664 struct rb_node **p = &root->rb_node;
665 struct rb_node *parent = NULL;
666
667 if (!name)
668 name = dso->long_name;
669 /*
670 * Find node with the matching name
671 */
672 while (*p) {
673 struct dso *this = rb_entry(*p, struct dso, rb_node);
674 int rc = strcmp(name, this->long_name);
675
676 parent = *p;
677 if (rc == 0) {
678 /*
679 * In case the new DSO is a duplicate of an existing
680 * one, print an one-time warning & put the new entry
681 * at the end of the list of duplicates.
682 */
683 if (!dso || (dso == this))
684 return this; /* Find matching dso */
685 /*
686 * The core kernel DSOs may have duplicated long name.
687 * In this case, the short name should be different.
688 * Comparing the short names to differentiate the DSOs.
689 */
690 rc = strcmp(dso->short_name, this->short_name);
691 if (rc == 0) {
692 pr_err("Duplicated dso name: %s\n", name);
693 return NULL;
694 }
695 }
696 if (rc < 0)
697 p = &parent->rb_left;
698 else
699 p = &parent->rb_right;
700 }
701 if (dso) {
702 /* Add new node and rebalance tree */
703 rb_link_node(&dso->rb_node, parent, p);
704 rb_insert_color(&dso->rb_node, root);
705 }
706 return NULL;
707}
708
709static inline struct dso *
710dso__find_by_longname(const struct rb_root *root, const char *name)
711{
712 return dso__findlink_by_longname((struct rb_root *)root, NULL, name);
713}
714
654void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated) 715void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated)
655{ 716{
656 if (name == NULL) 717 if (name == NULL)
@@ -753,6 +814,7 @@ struct dso *dso__new(const char *name)
753 dso->a2l_fails = 1; 814 dso->a2l_fails = 1;
754 dso->kernel = DSO_TYPE_USER; 815 dso->kernel = DSO_TYPE_USER;
755 dso->needs_swap = DSO_SWAP__UNSET; 816 dso->needs_swap = DSO_SWAP__UNSET;
817 RB_CLEAR_NODE(&dso->rb_node);
756 INIT_LIST_HEAD(&dso->node); 818 INIT_LIST_HEAD(&dso->node);
757 INIT_LIST_HEAD(&dso->data.open_entry); 819 INIT_LIST_HEAD(&dso->data.open_entry);
758 } 820 }
@@ -763,6 +825,10 @@ struct dso *dso__new(const char *name)
763void dso__delete(struct dso *dso) 825void dso__delete(struct dso *dso)
764{ 826{
765 int i; 827 int i;
828
829 if (!RB_EMPTY_NODE(&dso->rb_node))
830 pr_err("DSO %s is still in rbtree when being deleted!\n",
831 dso->long_name);
766 for (i = 0; i < MAP__NR_TYPES; ++i) 832 for (i = 0; i < MAP__NR_TYPES; ++i)
767 symbols__delete(&dso->symbols[i]); 833 symbols__delete(&dso->symbols[i]);
768 834
@@ -849,35 +915,34 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
849 return have_build_id; 915 return have_build_id;
850} 916}
851 917
852void dsos__add(struct list_head *head, struct dso *dso) 918void dsos__add(struct dsos *dsos, struct dso *dso)
853{ 919{
854 list_add_tail(&dso->node, head); 920 list_add_tail(&dso->node, &dsos->head);
921 dso__findlink_by_longname(&dsos->root, dso, NULL);
855} 922}
856 923
857struct dso *dsos__find(const struct list_head *head, const char *name, bool cmp_short) 924struct dso *dsos__find(const struct dsos *dsos, const char *name,
925 bool cmp_short)
858{ 926{
859 struct dso *pos; 927 struct dso *pos;
860 928
861 if (cmp_short) { 929 if (cmp_short) {
862 list_for_each_entry(pos, head, node) 930 list_for_each_entry(pos, &dsos->head, node)
863 if (strcmp(pos->short_name, name) == 0) 931 if (strcmp(pos->short_name, name) == 0)
864 return pos; 932 return pos;
865 return NULL; 933 return NULL;
866 } 934 }
867 list_for_each_entry(pos, head, node) 935 return dso__find_by_longname(&dsos->root, name);
868 if (strcmp(pos->long_name, name) == 0)
869 return pos;
870 return NULL;
871} 936}
872 937
873struct dso *__dsos__findnew(struct list_head *head, const char *name) 938struct dso *__dsos__findnew(struct dsos *dsos, const char *name)
874{ 939{
875 struct dso *dso = dsos__find(head, name, false); 940 struct dso *dso = dsos__find(dsos, name, false);
876 941
877 if (!dso) { 942 if (!dso) {
878 dso = dso__new(name); 943 dso = dso__new(name);
879 if (dso != NULL) { 944 if (dso != NULL) {
880 dsos__add(head, dso); 945 dsos__add(dsos, dso);
881 dso__set_basename(dso); 946 dso__set_basename(dso);
882 } 947 }
883 } 948 }
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 5e463c0964d4..acb651acc7fd 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -90,8 +90,18 @@ struct dso_cache {
90 char data[0]; 90 char data[0];
91}; 91};
92 92
93/*
94 * DSOs are put into both a list for fast iteration and rbtree for fast
95 * long name lookup.
96 */
97struct dsos {
98 struct list_head head;
99 struct rb_root root; /* rbtree root sorted by long name */
100};
101
93struct dso { 102struct dso {
94 struct list_head node; 103 struct list_head node;
104 struct rb_node rb_node; /* rbtree node sorted by long name */
95 struct rb_root symbols[MAP__NR_TYPES]; 105 struct rb_root symbols[MAP__NR_TYPES];
96 struct rb_root symbol_names[MAP__NR_TYPES]; 106 struct rb_root symbol_names[MAP__NR_TYPES];
97 void *a2l; 107 void *a2l;
@@ -224,10 +234,10 @@ struct map *dso__new_map(const char *name);
224struct dso *dso__kernel_findnew(struct machine *machine, const char *name, 234struct dso *dso__kernel_findnew(struct machine *machine, const char *name,
225 const char *short_name, int dso_type); 235 const char *short_name, int dso_type);
226 236
227void dsos__add(struct list_head *head, struct dso *dso); 237void dsos__add(struct dsos *dsos, struct dso *dso);
228struct dso *dsos__find(const struct list_head *head, const char *name, 238struct dso *dsos__find(const struct dsos *dsos, const char *name,
229 bool cmp_short); 239 bool cmp_short);
230struct dso *__dsos__findnew(struct list_head *head, const char *name); 240struct dso *__dsos__findnew(struct dsos *dsos, const char *name);
231bool __dsos__read_build_ids(struct list_head *head, bool with_hits); 241bool __dsos__read_build_ids(struct list_head *head, bool with_hits);
232 242
233size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, 243size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 1398c83d896d..4af6b279e34a 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -558,13 +558,17 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
558 struct map *map; 558 struct map *map;
559 struct kmap *kmap; 559 struct kmap *kmap;
560 int err; 560 int err;
561 union perf_event *event;
562
563 if (machine->vmlinux_maps[0] == NULL)
564 return -1;
565
561 /* 566 /*
562 * We should get this from /sys/kernel/sections/.text, but till that is 567 * We should get this from /sys/kernel/sections/.text, but till that is
563 * available use this, and after it is use this as a fallback for older 568 * available use this, and after it is use this as a fallback for older
564 * kernels. 569 * kernels.
565 */ 570 */
566 union perf_event *event = zalloc((sizeof(event->mmap) + 571 event = zalloc((sizeof(event->mmap) + machine->id_hdr_size));
567 machine->id_hdr_size));
568 if (event == NULL) { 572 if (event == NULL) {
569 pr_debug("Not enough memory synthesizing mmap event " 573 pr_debug("Not enough memory synthesizing mmap event "
570 "for kernel modules\n"); 574 "for kernel modules\n");
@@ -784,9 +788,9 @@ try_again:
784 * "[vdso]" dso, but for now lets use the old trick of looking 788 * "[vdso]" dso, but for now lets use the old trick of looking
785 * in the whole kernel symbol list. 789 * in the whole kernel symbol list.
786 */ 790 */
787 if ((long long)al->addr < 0 && 791 if (cpumode == PERF_RECORD_MISC_USER && machine &&
788 cpumode == PERF_RECORD_MISC_USER && 792 mg != &machine->kmaps &&
789 machine && mg != &machine->kmaps) { 793 machine__kernel_ip(machine, al->addr)) {
790 mg = &machine->kmaps; 794 mg = &machine->kmaps;
791 load_map = true; 795 load_map = true;
792 goto try_again; 796 goto try_again;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 94d6976180da..7eb7107731ec 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -156,6 +156,8 @@ struct perf_sample {
156 u32 cpu; 156 u32 cpu;
157 u32 raw_size; 157 u32 raw_size;
158 u64 data_src; 158 u64 data_src;
159 u32 flags;
160 u16 insn_len;
159 void *raw_data; 161 void *raw_data;
160 struct ip_callchain *callchain; 162 struct ip_callchain *callchain;
161 struct branch_stack *branch_stack; 163 struct branch_stack *branch_stack;
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 814e954c1318..3cebc9a8d52e 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -25,6 +25,9 @@
25#include <linux/bitops.h> 25#include <linux/bitops.h>
26#include <linux/hash.h> 26#include <linux/hash.h>
27 27
28static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx);
29static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx);
30
28#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 31#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
29#define SID(e, x, y) xyarray__entry(e->sample_id, x, y) 32#define SID(e, x, y) xyarray__entry(e->sample_id, x, y)
30 33
@@ -37,6 +40,7 @@ void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
37 INIT_HLIST_HEAD(&evlist->heads[i]); 40 INIT_HLIST_HEAD(&evlist->heads[i]);
38 INIT_LIST_HEAD(&evlist->entries); 41 INIT_LIST_HEAD(&evlist->entries);
39 perf_evlist__set_maps(evlist, cpus, threads); 42 perf_evlist__set_maps(evlist, cpus, threads);
43 fdarray__init(&evlist->pollfd, 64);
40 evlist->workload.pid = -1; 44 evlist->workload.pid = -1;
41} 45}
42 46
@@ -102,7 +106,7 @@ static void perf_evlist__purge(struct perf_evlist *evlist)
102void perf_evlist__exit(struct perf_evlist *evlist) 106void perf_evlist__exit(struct perf_evlist *evlist)
103{ 107{
104 zfree(&evlist->mmap); 108 zfree(&evlist->mmap);
105 zfree(&evlist->pollfd); 109 fdarray__exit(&evlist->pollfd);
106} 110}
107 111
108void perf_evlist__delete(struct perf_evlist *evlist) 112void perf_evlist__delete(struct perf_evlist *evlist)
@@ -122,6 +126,7 @@ void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
122{ 126{
123 list_add_tail(&entry->node, &evlist->entries); 127 list_add_tail(&entry->node, &evlist->entries);
124 entry->idx = evlist->nr_entries; 128 entry->idx = evlist->nr_entries;
129 entry->tracking = !entry->idx;
125 130
126 if (!evlist->nr_entries++) 131 if (!evlist->nr_entries++)
127 perf_evlist__set_id_pos(evlist); 132 perf_evlist__set_id_pos(evlist);
@@ -265,17 +270,27 @@ int perf_evlist__add_newtp(struct perf_evlist *evlist,
265 return 0; 270 return 0;
266} 271}
267 272
273static int perf_evlist__nr_threads(struct perf_evlist *evlist,
274 struct perf_evsel *evsel)
275{
276 if (evsel->system_wide)
277 return 1;
278 else
279 return thread_map__nr(evlist->threads);
280}
281
268void perf_evlist__disable(struct perf_evlist *evlist) 282void perf_evlist__disable(struct perf_evlist *evlist)
269{ 283{
270 int cpu, thread; 284 int cpu, thread;
271 struct perf_evsel *pos; 285 struct perf_evsel *pos;
272 int nr_cpus = cpu_map__nr(evlist->cpus); 286 int nr_cpus = cpu_map__nr(evlist->cpus);
273 int nr_threads = thread_map__nr(evlist->threads); 287 int nr_threads;
274 288
275 for (cpu = 0; cpu < nr_cpus; cpu++) { 289 for (cpu = 0; cpu < nr_cpus; cpu++) {
276 evlist__for_each(evlist, pos) { 290 evlist__for_each(evlist, pos) {
277 if (!perf_evsel__is_group_leader(pos) || !pos->fd) 291 if (!perf_evsel__is_group_leader(pos) || !pos->fd)
278 continue; 292 continue;
293 nr_threads = perf_evlist__nr_threads(evlist, pos);
279 for (thread = 0; thread < nr_threads; thread++) 294 for (thread = 0; thread < nr_threads; thread++)
280 ioctl(FD(pos, cpu, thread), 295 ioctl(FD(pos, cpu, thread),
281 PERF_EVENT_IOC_DISABLE, 0); 296 PERF_EVENT_IOC_DISABLE, 0);
@@ -288,12 +303,13 @@ void perf_evlist__enable(struct perf_evlist *evlist)
288 int cpu, thread; 303 int cpu, thread;
289 struct perf_evsel *pos; 304 struct perf_evsel *pos;
290 int nr_cpus = cpu_map__nr(evlist->cpus); 305 int nr_cpus = cpu_map__nr(evlist->cpus);
291 int nr_threads = thread_map__nr(evlist->threads); 306 int nr_threads;
292 307
293 for (cpu = 0; cpu < nr_cpus; cpu++) { 308 for (cpu = 0; cpu < nr_cpus; cpu++) {
294 evlist__for_each(evlist, pos) { 309 evlist__for_each(evlist, pos) {
295 if (!perf_evsel__is_group_leader(pos) || !pos->fd) 310 if (!perf_evsel__is_group_leader(pos) || !pos->fd)
296 continue; 311 continue;
312 nr_threads = perf_evlist__nr_threads(evlist, pos);
297 for (thread = 0; thread < nr_threads; thread++) 313 for (thread = 0; thread < nr_threads; thread++)
298 ioctl(FD(pos, cpu, thread), 314 ioctl(FD(pos, cpu, thread),
299 PERF_EVENT_IOC_ENABLE, 0); 315 PERF_EVENT_IOC_ENABLE, 0);
@@ -305,12 +321,14 @@ int perf_evlist__disable_event(struct perf_evlist *evlist,
305 struct perf_evsel *evsel) 321 struct perf_evsel *evsel)
306{ 322{
307 int cpu, thread, err; 323 int cpu, thread, err;
324 int nr_cpus = cpu_map__nr(evlist->cpus);
325 int nr_threads = perf_evlist__nr_threads(evlist, evsel);
308 326
309 if (!evsel->fd) 327 if (!evsel->fd)
310 return 0; 328 return 0;
311 329
312 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { 330 for (cpu = 0; cpu < nr_cpus; cpu++) {
313 for (thread = 0; thread < evlist->threads->nr; thread++) { 331 for (thread = 0; thread < nr_threads; thread++) {
314 err = ioctl(FD(evsel, cpu, thread), 332 err = ioctl(FD(evsel, cpu, thread),
315 PERF_EVENT_IOC_DISABLE, 0); 333 PERF_EVENT_IOC_DISABLE, 0);
316 if (err) 334 if (err)
@@ -324,12 +342,14 @@ int perf_evlist__enable_event(struct perf_evlist *evlist,
324 struct perf_evsel *evsel) 342 struct perf_evsel *evsel)
325{ 343{
326 int cpu, thread, err; 344 int cpu, thread, err;
345 int nr_cpus = cpu_map__nr(evlist->cpus);
346 int nr_threads = perf_evlist__nr_threads(evlist, evsel);
327 347
328 if (!evsel->fd) 348 if (!evsel->fd)
329 return -EINVAL; 349 return -EINVAL;
330 350
331 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { 351 for (cpu = 0; cpu < nr_cpus; cpu++) {
332 for (thread = 0; thread < evlist->threads->nr; thread++) { 352 for (thread = 0; thread < nr_threads; thread++) {
333 err = ioctl(FD(evsel, cpu, thread), 353 err = ioctl(FD(evsel, cpu, thread),
334 PERF_EVENT_IOC_ENABLE, 0); 354 PERF_EVENT_IOC_ENABLE, 0);
335 if (err) 355 if (err)
@@ -339,21 +359,111 @@ int perf_evlist__enable_event(struct perf_evlist *evlist,
339 return 0; 359 return 0;
340} 360}
341 361
342static int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) 362static int perf_evlist__enable_event_cpu(struct perf_evlist *evlist,
363 struct perf_evsel *evsel, int cpu)
364{
365 int thread, err;
366 int nr_threads = perf_evlist__nr_threads(evlist, evsel);
367
368 if (!evsel->fd)
369 return -EINVAL;
370
371 for (thread = 0; thread < nr_threads; thread++) {
372 err = ioctl(FD(evsel, cpu, thread),
373 PERF_EVENT_IOC_ENABLE, 0);
374 if (err)
375 return err;
376 }
377 return 0;
378}
379
380static int perf_evlist__enable_event_thread(struct perf_evlist *evlist,
381 struct perf_evsel *evsel,
382 int thread)
383{
384 int cpu, err;
385 int nr_cpus = cpu_map__nr(evlist->cpus);
386
387 if (!evsel->fd)
388 return -EINVAL;
389
390 for (cpu = 0; cpu < nr_cpus; cpu++) {
391 err = ioctl(FD(evsel, cpu, thread), PERF_EVENT_IOC_ENABLE, 0);
392 if (err)
393 return err;
394 }
395 return 0;
396}
397
398int perf_evlist__enable_event_idx(struct perf_evlist *evlist,
399 struct perf_evsel *evsel, int idx)
400{
401 bool per_cpu_mmaps = !cpu_map__empty(evlist->cpus);
402
403 if (per_cpu_mmaps)
404 return perf_evlist__enable_event_cpu(evlist, evsel, idx);
405 else
406 return perf_evlist__enable_event_thread(evlist, evsel, idx);
407}
408
409int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
343{ 410{
344 int nr_cpus = cpu_map__nr(evlist->cpus); 411 int nr_cpus = cpu_map__nr(evlist->cpus);
345 int nr_threads = thread_map__nr(evlist->threads); 412 int nr_threads = thread_map__nr(evlist->threads);
346 int nfds = nr_cpus * nr_threads * evlist->nr_entries; 413 int nfds = 0;
347 evlist->pollfd = malloc(sizeof(struct pollfd) * nfds); 414 struct perf_evsel *evsel;
348 return evlist->pollfd != NULL ? 0 : -ENOMEM; 415
416 list_for_each_entry(evsel, &evlist->entries, node) {
417 if (evsel->system_wide)
418 nfds += nr_cpus;
419 else
420 nfds += nr_cpus * nr_threads;
421 }
422
423 if (fdarray__available_entries(&evlist->pollfd) < nfds &&
424 fdarray__grow(&evlist->pollfd, nfds) < 0)
425 return -ENOMEM;
426
427 return 0;
428}
429
430static int __perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd, int idx)
431{
432 int pos = fdarray__add(&evlist->pollfd, fd, POLLIN | POLLERR | POLLHUP);
433 /*
434 * Save the idx so that when we filter out fds POLLHUP'ed we can
435 * close the associated evlist->mmap[] entry.
436 */
437 if (pos >= 0) {
438 evlist->pollfd.priv[pos].idx = idx;
439
440 fcntl(fd, F_SETFL, O_NONBLOCK);
441 }
442
443 return pos;
444}
445
446int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd)
447{
448 return __perf_evlist__add_pollfd(evlist, fd, -1);
449}
450
451static void perf_evlist__munmap_filtered(struct fdarray *fda, int fd)
452{
453 struct perf_evlist *evlist = container_of(fda, struct perf_evlist, pollfd);
454
455 perf_evlist__mmap_put(evlist, fda->priv[fd].idx);
456}
457
458int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask)
459{
460 return fdarray__filter(&evlist->pollfd, revents_and_mask,
461 perf_evlist__munmap_filtered);
349} 462}
350 463
351void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd) 464int perf_evlist__poll(struct perf_evlist *evlist, int timeout)
352{ 465{
353 fcntl(fd, F_SETFL, O_NONBLOCK); 466 return fdarray__poll(&evlist->pollfd, timeout);
354 evlist->pollfd[evlist->nr_fds].fd = fd;
355 evlist->pollfd[evlist->nr_fds].events = POLLIN;
356 evlist->nr_fds++;
357} 467}
358 468
359static void perf_evlist__id_hash(struct perf_evlist *evlist, 469static void perf_evlist__id_hash(struct perf_evlist *evlist,
@@ -566,14 +676,36 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
566 return event; 676 return event;
567} 677}
568 678
679static bool perf_mmap__empty(struct perf_mmap *md)
680{
681 return perf_mmap__read_head(md) != md->prev;
682}
683
684static void perf_evlist__mmap_get(struct perf_evlist *evlist, int idx)
685{
686 ++evlist->mmap[idx].refcnt;
687}
688
689static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx)
690{
691 BUG_ON(evlist->mmap[idx].refcnt == 0);
692
693 if (--evlist->mmap[idx].refcnt == 0)
694 __perf_evlist__munmap(evlist, idx);
695}
696
569void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx) 697void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
570{ 698{
699 struct perf_mmap *md = &evlist->mmap[idx];
700
571 if (!evlist->overwrite) { 701 if (!evlist->overwrite) {
572 struct perf_mmap *md = &evlist->mmap[idx];
573 unsigned int old = md->prev; 702 unsigned int old = md->prev;
574 703
575 perf_mmap__write_tail(md, old); 704 perf_mmap__write_tail(md, old);
576 } 705 }
706
707 if (md->refcnt == 1 && perf_mmap__empty(md))
708 perf_evlist__mmap_put(evlist, idx);
577} 709}
578 710
579static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx) 711static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx)
@@ -581,6 +713,7 @@ static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx)
581 if (evlist->mmap[idx].base != NULL) { 713 if (evlist->mmap[idx].base != NULL) {
582 munmap(evlist->mmap[idx].base, evlist->mmap_len); 714 munmap(evlist->mmap[idx].base, evlist->mmap_len);
583 evlist->mmap[idx].base = NULL; 715 evlist->mmap[idx].base = NULL;
716 evlist->mmap[idx].refcnt = 0;
584 } 717 }
585} 718}
586 719
@@ -614,6 +747,20 @@ struct mmap_params {
614static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx, 747static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx,
615 struct mmap_params *mp, int fd) 748 struct mmap_params *mp, int fd)
616{ 749{
750 /*
751 * The last one will be done at perf_evlist__mmap_consume(), so that we
752 * make sure we don't prevent tools from consuming every last event in
753 * the ring buffer.
754 *
755 * I.e. we can get the POLLHUP meaning that the fd doesn't exist
756 * anymore, but the last events for it are still in the ring buffer,
757 * waiting to be consumed.
758 *
759 * Tools can chose to ignore this at their own discretion, but the
760 * evlist layer can't just drop it when filtering events in
761 * perf_evlist__filter_pollfd().
762 */
763 evlist->mmap[idx].refcnt = 2;
617 evlist->mmap[idx].prev = 0; 764 evlist->mmap[idx].prev = 0;
618 evlist->mmap[idx].mask = mp->mask; 765 evlist->mmap[idx].mask = mp->mask;
619 evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, mp->prot, 766 evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, mp->prot,
@@ -625,7 +772,6 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx,
625 return -1; 772 return -1;
626 } 773 }
627 774
628 perf_evlist__add_pollfd(evlist, fd);
629 return 0; 775 return 0;
630} 776}
631 777
@@ -636,7 +782,12 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
636 struct perf_evsel *evsel; 782 struct perf_evsel *evsel;
637 783
638 evlist__for_each(evlist, evsel) { 784 evlist__for_each(evlist, evsel) {
639 int fd = FD(evsel, cpu, thread); 785 int fd;
786
787 if (evsel->system_wide && thread)
788 continue;
789
790 fd = FD(evsel, cpu, thread);
640 791
641 if (*output == -1) { 792 if (*output == -1) {
642 *output = fd; 793 *output = fd;
@@ -645,6 +796,13 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
645 } else { 796 } else {
646 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0) 797 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0)
647 return -1; 798 return -1;
799
800 perf_evlist__mmap_get(evlist, idx);
801 }
802
803 if (__perf_evlist__add_pollfd(evlist, fd, idx) < 0) {
804 perf_evlist__mmap_put(evlist, idx);
805 return -1;
648 } 806 }
649 807
650 if ((evsel->attr.read_format & PERF_FORMAT_ID) && 808 if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
@@ -804,7 +962,7 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
804 if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0) 962 if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0)
805 return -ENOMEM; 963 return -ENOMEM;
806 964
807 if (evlist->pollfd == NULL && perf_evlist__alloc_pollfd(evlist) < 0) 965 if (evlist->pollfd.entries == NULL && perf_evlist__alloc_pollfd(evlist) < 0)
808 return -ENOMEM; 966 return -ENOMEM;
809 967
810 evlist->overwrite = overwrite; 968 evlist->overwrite = overwrite;
@@ -1061,6 +1219,8 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar
1061 } 1219 }
1062 1220
1063 if (!evlist->workload.pid) { 1221 if (!evlist->workload.pid) {
1222 int ret;
1223
1064 if (pipe_output) 1224 if (pipe_output)
1065 dup2(2, 1); 1225 dup2(2, 1);
1066 1226
@@ -1078,8 +1238,22 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar
1078 /* 1238 /*
1079 * Wait until the parent tells us to go. 1239 * Wait until the parent tells us to go.
1080 */ 1240 */
1081 if (read(go_pipe[0], &bf, 1) == -1) 1241 ret = read(go_pipe[0], &bf, 1);
1082 perror("unable to read pipe"); 1242 /*
1243 * The parent will ask for the execvp() to be performed by
1244 * writing exactly one byte, in workload.cork_fd, usually via
1245 * perf_evlist__start_workload().
1246 *
1247 * For cancelling the workload without actuallin running it,
1248 * the parent will just close workload.cork_fd, without writing
1249 * anything, i.e. read will return zero and we just exit()
1250 * here.
1251 */
1252 if (ret != 1) {
1253 if (ret == -1)
1254 perror("unable to read pipe");
1255 exit(ret);
1256 }
1083 1257
1084 execvp(argv[0], (char **)argv); 1258 execvp(argv[0], (char **)argv);
1085 1259
@@ -1202,7 +1376,7 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused,
1202 int err, char *buf, size_t size) 1376 int err, char *buf, size_t size)
1203{ 1377{
1204 int printed, value; 1378 int printed, value;
1205 char sbuf[128], *emsg = strerror_r(err, sbuf, sizeof(sbuf)); 1379 char sbuf[STRERR_BUFSIZE], *emsg = strerror_r(err, sbuf, sizeof(sbuf));
1206 1380
1207 switch (err) { 1381 switch (err) {
1208 case EACCES: 1382 case EACCES:
@@ -1250,3 +1424,19 @@ void perf_evlist__to_front(struct perf_evlist *evlist,
1250 1424
1251 list_splice(&move, &evlist->entries); 1425 list_splice(&move, &evlist->entries);
1252} 1426}
1427
1428void perf_evlist__set_tracking_event(struct perf_evlist *evlist,
1429 struct perf_evsel *tracking_evsel)
1430{
1431 struct perf_evsel *evsel;
1432
1433 if (tracking_evsel->tracking)
1434 return;
1435
1436 evlist__for_each(evlist, evsel) {
1437 if (evsel != tracking_evsel)
1438 evsel->tracking = false;
1439 }
1440
1441 tracking_evsel->tracking = true;
1442}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index f5173cd63693..bd312b01e876 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -2,6 +2,7 @@
2#define __PERF_EVLIST_H 1 2#define __PERF_EVLIST_H 1
3 3
4#include <linux/list.h> 4#include <linux/list.h>
5#include <api/fd/array.h>
5#include <stdio.h> 6#include <stdio.h>
6#include "../perf.h" 7#include "../perf.h"
7#include "event.h" 8#include "event.h"
@@ -17,9 +18,15 @@ struct record_opts;
17#define PERF_EVLIST__HLIST_BITS 8 18#define PERF_EVLIST__HLIST_BITS 8
18#define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS) 19#define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS)
19 20
21/**
22 * struct perf_mmap - perf's ring buffer mmap details
23 *
24 * @refcnt - e.g. code using PERF_EVENT_IOC_SET_OUTPUT to share this
25 */
20struct perf_mmap { 26struct perf_mmap {
21 void *base; 27 void *base;
22 int mask; 28 int mask;
29 int refcnt;
23 unsigned int prev; 30 unsigned int prev;
24 char event_copy[PERF_SAMPLE_MAX_SIZE]; 31 char event_copy[PERF_SAMPLE_MAX_SIZE];
25}; 32};
@@ -29,7 +36,6 @@ struct perf_evlist {
29 struct hlist_head heads[PERF_EVLIST__HLIST_SIZE]; 36 struct hlist_head heads[PERF_EVLIST__HLIST_SIZE];
30 int nr_entries; 37 int nr_entries;
31 int nr_groups; 38 int nr_groups;
32 int nr_fds;
33 int nr_mmaps; 39 int nr_mmaps;
34 size_t mmap_len; 40 size_t mmap_len;
35 int id_pos; 41 int id_pos;
@@ -40,8 +46,8 @@ struct perf_evlist {
40 pid_t pid; 46 pid_t pid;
41 } workload; 47 } workload;
42 bool overwrite; 48 bool overwrite;
49 struct fdarray pollfd;
43 struct perf_mmap *mmap; 50 struct perf_mmap *mmap;
44 struct pollfd *pollfd;
45 struct thread_map *threads; 51 struct thread_map *threads;
46 struct cpu_map *cpus; 52 struct cpu_map *cpus;
47 struct perf_evsel *selected; 53 struct perf_evsel *selected;
@@ -82,7 +88,11 @@ perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist,
82void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel, 88void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
83 int cpu, int thread, u64 id); 89 int cpu, int thread, u64 id);
84 90
85void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd); 91int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd);
92int perf_evlist__alloc_pollfd(struct perf_evlist *evlist);
93int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask);
94
95int perf_evlist__poll(struct perf_evlist *evlist, int timeout);
86 96
87struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id); 97struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id);
88 98
@@ -122,6 +132,8 @@ int perf_evlist__disable_event(struct perf_evlist *evlist,
122 struct perf_evsel *evsel); 132 struct perf_evsel *evsel);
123int perf_evlist__enable_event(struct perf_evlist *evlist, 133int perf_evlist__enable_event(struct perf_evlist *evlist,
124 struct perf_evsel *evsel); 134 struct perf_evsel *evsel);
135int perf_evlist__enable_event_idx(struct perf_evlist *evlist,
136 struct perf_evsel *evsel, int idx);
125 137
126void perf_evlist__set_selected(struct perf_evlist *evlist, 138void perf_evlist__set_selected(struct perf_evlist *evlist,
127 struct perf_evsel *evsel); 139 struct perf_evsel *evsel);
@@ -262,4 +274,7 @@ void perf_evlist__to_front(struct perf_evlist *evlist,
262#define evlist__for_each_safe(evlist, tmp, evsel) \ 274#define evlist__for_each_safe(evlist, tmp, evsel) \
263 __evlist__for_each_safe(&(evlist)->entries, tmp, evsel) 275 __evlist__for_each_safe(&(evlist)->entries, tmp, evsel)
264 276
277void perf_evlist__set_tracking_event(struct perf_evlist *evlist,
278 struct perf_evsel *tracking_evsel);
279
265#endif /* __PERF_EVLIST_H */ 280#endif /* __PERF_EVLIST_H */
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 21a373ebea22..e0868a901c4a 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -162,6 +162,7 @@ void perf_evsel__init(struct perf_evsel *evsel,
162 struct perf_event_attr *attr, int idx) 162 struct perf_event_attr *attr, int idx)
163{ 163{
164 evsel->idx = idx; 164 evsel->idx = idx;
165 evsel->tracking = !idx;
165 evsel->attr = *attr; 166 evsel->attr = *attr;
166 evsel->leader = evsel; 167 evsel->leader = evsel;
167 evsel->unit = ""; 168 evsel->unit = "";
@@ -502,20 +503,19 @@ int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size)
502} 503}
503 504
504static void 505static void
505perf_evsel__config_callgraph(struct perf_evsel *evsel, 506perf_evsel__config_callgraph(struct perf_evsel *evsel)
506 struct record_opts *opts)
507{ 507{
508 bool function = perf_evsel__is_function_event(evsel); 508 bool function = perf_evsel__is_function_event(evsel);
509 struct perf_event_attr *attr = &evsel->attr; 509 struct perf_event_attr *attr = &evsel->attr;
510 510
511 perf_evsel__set_sample_bit(evsel, CALLCHAIN); 511 perf_evsel__set_sample_bit(evsel, CALLCHAIN);
512 512
513 if (opts->call_graph == CALLCHAIN_DWARF) { 513 if (callchain_param.record_mode == CALLCHAIN_DWARF) {
514 if (!function) { 514 if (!function) {
515 perf_evsel__set_sample_bit(evsel, REGS_USER); 515 perf_evsel__set_sample_bit(evsel, REGS_USER);
516 perf_evsel__set_sample_bit(evsel, STACK_USER); 516 perf_evsel__set_sample_bit(evsel, STACK_USER);
517 attr->sample_regs_user = PERF_REGS_MASK; 517 attr->sample_regs_user = PERF_REGS_MASK;
518 attr->sample_stack_user = opts->stack_dump_size; 518 attr->sample_stack_user = callchain_param.dump_size;
519 attr->exclude_callchain_user = 1; 519 attr->exclude_callchain_user = 1;
520 } else { 520 } else {
521 pr_info("Cannot use DWARF unwind for function trace event," 521 pr_info("Cannot use DWARF unwind for function trace event,"
@@ -561,7 +561,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
561{ 561{
562 struct perf_evsel *leader = evsel->leader; 562 struct perf_evsel *leader = evsel->leader;
563 struct perf_event_attr *attr = &evsel->attr; 563 struct perf_event_attr *attr = &evsel->attr;
564 int track = !evsel->idx; /* only the first counter needs these */ 564 int track = evsel->tracking;
565 bool per_cpu = opts->target.default_per_cpu && !opts->target.per_thread; 565 bool per_cpu = opts->target.default_per_cpu && !opts->target.per_thread;
566 566
567 attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1; 567 attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1;
@@ -624,8 +624,8 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
624 attr->mmap_data = track; 624 attr->mmap_data = track;
625 } 625 }
626 626
627 if (opts->call_graph_enabled && !evsel->no_aux_samples) 627 if (callchain_param.enabled && !evsel->no_aux_samples)
628 perf_evsel__config_callgraph(evsel, opts); 628 perf_evsel__config_callgraph(evsel);
629 629
630 if (target__has_cpu(&opts->target)) 630 if (target__has_cpu(&opts->target))
631 perf_evsel__set_sample_bit(evsel, CPU); 631 perf_evsel__set_sample_bit(evsel, CPU);
@@ -633,9 +633,12 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
633 if (opts->period) 633 if (opts->period)
634 perf_evsel__set_sample_bit(evsel, PERIOD); 634 perf_evsel__set_sample_bit(evsel, PERIOD);
635 635
636 if (!perf_missing_features.sample_id_all && 636 /*
637 (opts->sample_time || !opts->no_inherit || 637 * When the user explicitely disabled time don't force it here.
638 target__has_cpu(&opts->target) || per_cpu)) 638 */
639 if (opts->sample_time &&
640 (!perf_missing_features.sample_id_all &&
641 (!opts->no_inherit || target__has_cpu(&opts->target) || per_cpu)))
639 perf_evsel__set_sample_bit(evsel, TIME); 642 perf_evsel__set_sample_bit(evsel, TIME);
640 643
641 if (opts->raw_samples && !evsel->no_aux_samples) { 644 if (opts->raw_samples && !evsel->no_aux_samples) {
@@ -692,6 +695,10 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
692int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) 695int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
693{ 696{
694 int cpu, thread; 697 int cpu, thread;
698
699 if (evsel->system_wide)
700 nthreads = 1;
701
695 evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int)); 702 evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int));
696 703
697 if (evsel->fd) { 704 if (evsel->fd) {
@@ -710,6 +717,9 @@ static int perf_evsel__run_ioctl(struct perf_evsel *evsel, int ncpus, int nthrea
710{ 717{
711 int cpu, thread; 718 int cpu, thread;
712 719
720 if (evsel->system_wide)
721 nthreads = 1;
722
713 for (cpu = 0; cpu < ncpus; cpu++) { 723 for (cpu = 0; cpu < ncpus; cpu++) {
714 for (thread = 0; thread < nthreads; thread++) { 724 for (thread = 0; thread < nthreads; thread++) {
715 int fd = FD(evsel, cpu, thread), 725 int fd = FD(evsel, cpu, thread),
@@ -740,6 +750,9 @@ int perf_evsel__enable(struct perf_evsel *evsel, int ncpus, int nthreads)
740 750
741int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads) 751int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)
742{ 752{
753 if (evsel->system_wide)
754 nthreads = 1;
755
743 evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id)); 756 evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id));
744 if (evsel->sample_id == NULL) 757 if (evsel->sample_id == NULL)
745 return -ENOMEM; 758 return -ENOMEM;
@@ -784,6 +797,9 @@ void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
784{ 797{
785 int cpu, thread; 798 int cpu, thread;
786 799
800 if (evsel->system_wide)
801 nthreads = 1;
802
787 for (cpu = 0; cpu < ncpus; cpu++) 803 for (cpu = 0; cpu < ncpus; cpu++)
788 for (thread = 0; thread < nthreads; ++thread) { 804 for (thread = 0; thread < nthreads; ++thread) {
789 close(FD(evsel, cpu, thread)); 805 close(FD(evsel, cpu, thread));
@@ -872,6 +888,9 @@ int __perf_evsel__read(struct perf_evsel *evsel,
872 int cpu, thread; 888 int cpu, thread;
873 struct perf_counts_values *aggr = &evsel->counts->aggr, count; 889 struct perf_counts_values *aggr = &evsel->counts->aggr, count;
874 890
891 if (evsel->system_wide)
892 nthreads = 1;
893
875 aggr->val = aggr->ena = aggr->run = 0; 894 aggr->val = aggr->ena = aggr->run = 0;
876 895
877 for (cpu = 0; cpu < ncpus; cpu++) { 896 for (cpu = 0; cpu < ncpus; cpu++) {
@@ -994,13 +1013,18 @@ static size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp)
994static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 1013static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
995 struct thread_map *threads) 1014 struct thread_map *threads)
996{ 1015{
997 int cpu, thread; 1016 int cpu, thread, nthreads;
998 unsigned long flags = PERF_FLAG_FD_CLOEXEC; 1017 unsigned long flags = PERF_FLAG_FD_CLOEXEC;
999 int pid = -1, err; 1018 int pid = -1, err;
1000 enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE; 1019 enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE;
1001 1020
1021 if (evsel->system_wide)
1022 nthreads = 1;
1023 else
1024 nthreads = threads->nr;
1025
1002 if (evsel->fd == NULL && 1026 if (evsel->fd == NULL &&
1003 perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0) 1027 perf_evsel__alloc_fd(evsel, cpus->nr, nthreads) < 0)
1004 return -ENOMEM; 1028 return -ENOMEM;
1005 1029
1006 if (evsel->cgrp) { 1030 if (evsel->cgrp) {
@@ -1024,10 +1048,10 @@ retry_sample_id:
1024 1048
1025 for (cpu = 0; cpu < cpus->nr; cpu++) { 1049 for (cpu = 0; cpu < cpus->nr; cpu++) {
1026 1050
1027 for (thread = 0; thread < threads->nr; thread++) { 1051 for (thread = 0; thread < nthreads; thread++) {
1028 int group_fd; 1052 int group_fd;
1029 1053
1030 if (!evsel->cgrp) 1054 if (!evsel->cgrp && !evsel->system_wide)
1031 pid = threads->map[thread]; 1055 pid = threads->map[thread];
1032 1056
1033 group_fd = get_group_fd(evsel, cpu, thread); 1057 group_fd = get_group_fd(evsel, cpu, thread);
@@ -1100,7 +1124,7 @@ out_close:
1100 close(FD(evsel, cpu, thread)); 1124 close(FD(evsel, cpu, thread));
1101 FD(evsel, cpu, thread) = -1; 1125 FD(evsel, cpu, thread) = -1;
1102 } 1126 }
1103 thread = threads->nr; 1127 thread = nthreads;
1104 } while (--cpu >= 0); 1128 } while (--cpu >= 0);
1105 return err; 1129 return err;
1106} 1130}
@@ -2002,6 +2026,8 @@ bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
2002int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target, 2026int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2003 int err, char *msg, size_t size) 2027 int err, char *msg, size_t size)
2004{ 2028{
2029 char sbuf[STRERR_BUFSIZE];
2030
2005 switch (err) { 2031 switch (err) {
2006 case EPERM: 2032 case EPERM:
2007 case EACCES: 2033 case EACCES:
@@ -2036,13 +2062,20 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2036 "No APIC? If so then you can boot the kernel with the \"lapic\" boot parameter to force-enable it."); 2062 "No APIC? If so then you can boot the kernel with the \"lapic\" boot parameter to force-enable it.");
2037#endif 2063#endif
2038 break; 2064 break;
2065 case EBUSY:
2066 if (find_process("oprofiled"))
2067 return scnprintf(msg, size,
2068 "The PMU counters are busy/taken by another profiler.\n"
2069 "We found oprofile daemon running, please stop it and try again.");
2070 break;
2039 default: 2071 default:
2040 break; 2072 break;
2041 } 2073 }
2042 2074
2043 return scnprintf(msg, size, 2075 return scnprintf(msg, size,
2044 "The sys_perf_event_open() syscall returned with %d (%s) for event (%s). \n" 2076 "The sys_perf_event_open() syscall returned with %d (%s) for event (%s).\n"
2045 "/bin/dmesg may provide additional information.\n" 2077 "/bin/dmesg may provide additional information.\n"
2046 "No CONFIG_PERF_EVENTS=y kernel support configured?\n", 2078 "No CONFIG_PERF_EVENTS=y kernel support configured?\n",
2047 err, strerror(err), perf_evsel__name(evsel)); 2079 err, strerror_r(err, sbuf, sizeof(sbuf)),
2080 perf_evsel__name(evsel));
2048} 2081}
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index d7f93ce0ebc1..7bc314be6a7b 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -85,6 +85,8 @@ struct perf_evsel {
85 bool needs_swap; 85 bool needs_swap;
86 bool no_aux_samples; 86 bool no_aux_samples;
87 bool immediate; 87 bool immediate;
88 bool system_wide;
89 bool tracking;
88 /* parse modifier helper */ 90 /* parse modifier helper */
89 int exclude_GH; 91 int exclude_GH;
90 int nr_members; 92 int nr_members;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 158c787ce0c4..ce0de00399da 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -214,11 +214,11 @@ static int machine__hit_all_dsos(struct machine *machine)
214{ 214{
215 int err; 215 int err;
216 216
217 err = __dsos__hit_all(&machine->kernel_dsos); 217 err = __dsos__hit_all(&machine->kernel_dsos.head);
218 if (err) 218 if (err)
219 return err; 219 return err;
220 220
221 return __dsos__hit_all(&machine->user_dsos); 221 return __dsos__hit_all(&machine->user_dsos.head);
222} 222}
223 223
224int dsos__hit_all(struct perf_session *session) 224int dsos__hit_all(struct perf_session *session)
@@ -288,11 +288,12 @@ static int machine__write_buildid_table(struct machine *machine, int fd)
288 umisc = PERF_RECORD_MISC_GUEST_USER; 288 umisc = PERF_RECORD_MISC_GUEST_USER;
289 } 289 }
290 290
291 err = __dsos__write_buildid_table(&machine->kernel_dsos, machine, 291 err = __dsos__write_buildid_table(&machine->kernel_dsos.head, machine,
292 machine->pid, kmisc, fd); 292 machine->pid, kmisc, fd);
293 if (err == 0) 293 if (err == 0)
294 err = __dsos__write_buildid_table(&machine->user_dsos, machine, 294 err = __dsos__write_buildid_table(&machine->user_dsos.head,
295 machine->pid, umisc, fd); 295 machine, machine->pid, umisc,
296 fd);
296 return err; 297 return err;
297} 298}
298 299
@@ -455,9 +456,10 @@ static int __dsos__cache_build_ids(struct list_head *head,
455 456
456static int machine__cache_build_ids(struct machine *machine, const char *debugdir) 457static int machine__cache_build_ids(struct machine *machine, const char *debugdir)
457{ 458{
458 int ret = __dsos__cache_build_ids(&machine->kernel_dsos, machine, 459 int ret = __dsos__cache_build_ids(&machine->kernel_dsos.head, machine,
459 debugdir); 460 debugdir);
460 ret |= __dsos__cache_build_ids(&machine->user_dsos, machine, debugdir); 461 ret |= __dsos__cache_build_ids(&machine->user_dsos.head, machine,
462 debugdir);
461 return ret; 463 return ret;
462} 464}
463 465
@@ -483,8 +485,10 @@ static int perf_session__cache_build_ids(struct perf_session *session)
483 485
484static bool machine__read_build_ids(struct machine *machine, bool with_hits) 486static bool machine__read_build_ids(struct machine *machine, bool with_hits)
485{ 487{
486 bool ret = __dsos__read_build_ids(&machine->kernel_dsos, with_hits); 488 bool ret;
487 ret |= __dsos__read_build_ids(&machine->user_dsos, with_hits); 489
490 ret = __dsos__read_build_ids(&machine->kernel_dsos.head, with_hits);
491 ret |= __dsos__read_build_ids(&machine->user_dsos.head, with_hits);
488 return ret; 492 return ret;
489} 493}
490 494
@@ -1548,7 +1552,7 @@ static int __event_process_build_id(struct build_id_event *bev,
1548 struct perf_session *session) 1552 struct perf_session *session)
1549{ 1553{
1550 int err = -1; 1554 int err = -1;
1551 struct list_head *head; 1555 struct dsos *dsos;
1552 struct machine *machine; 1556 struct machine *machine;
1553 u16 misc; 1557 u16 misc;
1554 struct dso *dso; 1558 struct dso *dso;
@@ -1563,22 +1567,22 @@ static int __event_process_build_id(struct build_id_event *bev,
1563 switch (misc) { 1567 switch (misc) {
1564 case PERF_RECORD_MISC_KERNEL: 1568 case PERF_RECORD_MISC_KERNEL:
1565 dso_type = DSO_TYPE_KERNEL; 1569 dso_type = DSO_TYPE_KERNEL;
1566 head = &machine->kernel_dsos; 1570 dsos = &machine->kernel_dsos;
1567 break; 1571 break;
1568 case PERF_RECORD_MISC_GUEST_KERNEL: 1572 case PERF_RECORD_MISC_GUEST_KERNEL:
1569 dso_type = DSO_TYPE_GUEST_KERNEL; 1573 dso_type = DSO_TYPE_GUEST_KERNEL;
1570 head = &machine->kernel_dsos; 1574 dsos = &machine->kernel_dsos;
1571 break; 1575 break;
1572 case PERF_RECORD_MISC_USER: 1576 case PERF_RECORD_MISC_USER:
1573 case PERF_RECORD_MISC_GUEST_USER: 1577 case PERF_RECORD_MISC_GUEST_USER:
1574 dso_type = DSO_TYPE_USER; 1578 dso_type = DSO_TYPE_USER;
1575 head = &machine->user_dsos; 1579 dsos = &machine->user_dsos;
1576 break; 1580 break;
1577 default: 1581 default:
1578 goto out; 1582 goto out;
1579 } 1583 }
1580 1584
1581 dso = __dsos__findnew(head, filename); 1585 dso = __dsos__findnew(dsos, filename);
1582 if (dso != NULL) { 1586 if (dso != NULL) {
1583 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 1587 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
1584 1588
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 30df6187ee02..86569fa3651d 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -277,6 +277,28 @@ void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel)
277 } 277 }
278} 278}
279 279
280void hists__delete_entries(struct hists *hists)
281{
282 struct rb_node *next = rb_first(&hists->entries);
283 struct hist_entry *n;
284
285 while (next) {
286 n = rb_entry(next, struct hist_entry, rb_node);
287 next = rb_next(&n->rb_node);
288
289 rb_erase(&n->rb_node, &hists->entries);
290
291 if (sort__need_collapse)
292 rb_erase(&n->rb_node_in, &hists->entries_collapsed);
293
294 --hists->nr_entries;
295 if (!n->filtered)
296 --hists->nr_non_filtered_entries;
297
298 hist_entry__free(n);
299 }
300}
301
280/* 302/*
281 * histogram, sorted on item, collects periods 303 * histogram, sorted on item, collects periods
282 */ 304 */
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 742f49a85725..8c9c70e18cbb 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -152,6 +152,7 @@ void hists__output_resort(struct hists *hists);
152void hists__collapse_resort(struct hists *hists, struct ui_progress *prog); 152void hists__collapse_resort(struct hists *hists, struct ui_progress *prog);
153 153
154void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel); 154void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel);
155void hists__delete_entries(struct hists *hists);
155void hists__output_recalc_col_len(struct hists *hists, int max_rows); 156void hists__output_recalc_col_len(struct hists *hists, int max_rows);
156 157
157u64 hists__total_period(struct hists *hists); 158u64 hists__total_period(struct hists *hists);
@@ -192,6 +193,7 @@ struct perf_hpp {
192}; 193};
193 194
194struct perf_hpp_fmt { 195struct perf_hpp_fmt {
196 const char *name;
195 int (*header)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 197 int (*header)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
196 struct perf_evsel *evsel); 198 struct perf_evsel *evsel);
197 int (*width)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 199 int (*width)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
@@ -207,6 +209,8 @@ struct perf_hpp_fmt {
207 struct list_head list; 209 struct list_head list;
208 struct list_head sort_list; 210 struct list_head sort_list;
209 bool elide; 211 bool elide;
212 int len;
213 int user_len;
210}; 214};
211 215
212extern struct list_head perf_hpp__list; 216extern struct list_head perf_hpp__list;
@@ -261,17 +265,19 @@ static inline bool perf_hpp__should_skip(struct perf_hpp_fmt *format)
261} 265}
262 266
263void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists); 267void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists);
268void perf_hpp__reset_sort_width(struct perf_hpp_fmt *fmt, struct hists *hists);
269void perf_hpp__set_user_width(const char *width_list_str);
264 270
265typedef u64 (*hpp_field_fn)(struct hist_entry *he); 271typedef u64 (*hpp_field_fn)(struct hist_entry *he);
266typedef int (*hpp_callback_fn)(struct perf_hpp *hpp, bool front); 272typedef int (*hpp_callback_fn)(struct perf_hpp *hpp, bool front);
267typedef int (*hpp_snprint_fn)(struct perf_hpp *hpp, const char *fmt, ...); 273typedef int (*hpp_snprint_fn)(struct perf_hpp *hpp, const char *fmt, ...);
268 274
269int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he, 275int hpp__fmt(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
270 hpp_field_fn get_field, const char *fmt, 276 struct hist_entry *he, hpp_field_fn get_field,
271 hpp_snprint_fn print_fn, bool fmt_percent); 277 const char *fmtstr, hpp_snprint_fn print_fn, bool fmt_percent);
272int __hpp__fmt_acc(struct perf_hpp *hpp, struct hist_entry *he, 278int hpp__fmt_acc(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
273 hpp_field_fn get_field, const char *fmt, 279 struct hist_entry *he, hpp_field_fn get_field,
274 hpp_snprint_fn print_fn, bool fmt_percent); 280 const char *fmtstr, hpp_snprint_fn print_fn, bool fmt_percent);
275 281
276static inline void advance_hpp(struct perf_hpp *hpp, int inc) 282static inline void advance_hpp(struct perf_hpp *hpp, int inc)
277{ 283{
diff --git a/tools/perf/util/kvm-stat.h b/tools/perf/util/kvm-stat.h
index 0b5a8cd2ee79..cf1d7913783b 100644
--- a/tools/perf/util/kvm-stat.h
+++ b/tools/perf/util/kvm-stat.h
@@ -92,7 +92,6 @@ struct perf_kvm_stat {
92 u64 lost_events; 92 u64 lost_events;
93 u64 duration; 93 u64 duration;
94 94
95 const char *pid_str;
96 struct intlist *pid_list; 95 struct intlist *pid_list;
97 96
98 struct rb_root result; 97 struct rb_root result;
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 16bba9fff2c8..b7d477fbda02 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -17,8 +17,8 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
17{ 17{
18 map_groups__init(&machine->kmaps); 18 map_groups__init(&machine->kmaps);
19 RB_CLEAR_NODE(&machine->rb_node); 19 RB_CLEAR_NODE(&machine->rb_node);
20 INIT_LIST_HEAD(&machine->user_dsos); 20 INIT_LIST_HEAD(&machine->user_dsos.head);
21 INIT_LIST_HEAD(&machine->kernel_dsos); 21 INIT_LIST_HEAD(&machine->kernel_dsos.head);
22 22
23 machine->threads = RB_ROOT; 23 machine->threads = RB_ROOT;
24 INIT_LIST_HEAD(&machine->dead_threads); 24 INIT_LIST_HEAD(&machine->dead_threads);
@@ -31,6 +31,8 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
31 31
32 machine->symbol_filter = NULL; 32 machine->symbol_filter = NULL;
33 machine->id_hdr_size = 0; 33 machine->id_hdr_size = 0;
34 machine->comm_exec = false;
35 machine->kernel_start = 0;
34 36
35 machine->root_dir = strdup(root_dir); 37 machine->root_dir = strdup(root_dir);
36 if (machine->root_dir == NULL) 38 if (machine->root_dir == NULL)
@@ -70,11 +72,12 @@ out_delete:
70 return NULL; 72 return NULL;
71} 73}
72 74
73static void dsos__delete(struct list_head *dsos) 75static void dsos__delete(struct dsos *dsos)
74{ 76{
75 struct dso *pos, *n; 77 struct dso *pos, *n;
76 78
77 list_for_each_entry_safe(pos, n, dsos, node) { 79 list_for_each_entry_safe(pos, n, &dsos->head, node) {
80 RB_CLEAR_NODE(&pos->rb_node);
78 list_del(&pos->node); 81 list_del(&pos->node);
79 dso__delete(pos); 82 dso__delete(pos);
80 } 83 }
@@ -179,6 +182,19 @@ void machines__set_symbol_filter(struct machines *machines,
179 } 182 }
180} 183}
181 184
185void machines__set_comm_exec(struct machines *machines, bool comm_exec)
186{
187 struct rb_node *nd;
188
189 machines->host.comm_exec = comm_exec;
190
191 for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) {
192 struct machine *machine = rb_entry(nd, struct machine, rb_node);
193
194 machine->comm_exec = comm_exec;
195 }
196}
197
182struct machine *machines__find(struct machines *machines, pid_t pid) 198struct machine *machines__find(struct machines *machines, pid_t pid)
183{ 199{
184 struct rb_node **p = &machines->guests.rb_node; 200 struct rb_node **p = &machines->guests.rb_node;
@@ -398,17 +414,31 @@ struct thread *machine__find_thread(struct machine *machine, pid_t pid,
398 return __machine__findnew_thread(machine, pid, tid, false); 414 return __machine__findnew_thread(machine, pid, tid, false);
399} 415}
400 416
417struct comm *machine__thread_exec_comm(struct machine *machine,
418 struct thread *thread)
419{
420 if (machine->comm_exec)
421 return thread__exec_comm(thread);
422 else
423 return thread__comm(thread);
424}
425
401int machine__process_comm_event(struct machine *machine, union perf_event *event, 426int machine__process_comm_event(struct machine *machine, union perf_event *event,
402 struct perf_sample *sample) 427 struct perf_sample *sample)
403{ 428{
404 struct thread *thread = machine__findnew_thread(machine, 429 struct thread *thread = machine__findnew_thread(machine,
405 event->comm.pid, 430 event->comm.pid,
406 event->comm.tid); 431 event->comm.tid);
432 bool exec = event->header.misc & PERF_RECORD_MISC_COMM_EXEC;
433
434 if (exec)
435 machine->comm_exec = true;
407 436
408 if (dump_trace) 437 if (dump_trace)
409 perf_event__fprintf_comm(event, stdout); 438 perf_event__fprintf_comm(event, stdout);
410 439
411 if (thread == NULL || thread__set_comm(thread, event->comm.comm, sample->time)) { 440 if (thread == NULL ||
441 __thread__set_comm(thread, event->comm.comm, sample->time, exec)) {
412 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n"); 442 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
413 return -1; 443 return -1;
414 } 444 }
@@ -448,23 +478,23 @@ struct map *machine__new_module(struct machine *machine, u64 start,
448size_t machines__fprintf_dsos(struct machines *machines, FILE *fp) 478size_t machines__fprintf_dsos(struct machines *machines, FILE *fp)
449{ 479{
450 struct rb_node *nd; 480 struct rb_node *nd;
451 size_t ret = __dsos__fprintf(&machines->host.kernel_dsos, fp) + 481 size_t ret = __dsos__fprintf(&machines->host.kernel_dsos.head, fp) +
452 __dsos__fprintf(&machines->host.user_dsos, fp); 482 __dsos__fprintf(&machines->host.user_dsos.head, fp);
453 483
454 for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) { 484 for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) {
455 struct machine *pos = rb_entry(nd, struct machine, rb_node); 485 struct machine *pos = rb_entry(nd, struct machine, rb_node);
456 ret += __dsos__fprintf(&pos->kernel_dsos, fp); 486 ret += __dsos__fprintf(&pos->kernel_dsos.head, fp);
457 ret += __dsos__fprintf(&pos->user_dsos, fp); 487 ret += __dsos__fprintf(&pos->user_dsos.head, fp);
458 } 488 }
459 489
460 return ret; 490 return ret;
461} 491}
462 492
463size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp, 493size_t machine__fprintf_dsos_buildid(struct machine *m, FILE *fp,
464 bool (skip)(struct dso *dso, int parm), int parm) 494 bool (skip)(struct dso *dso, int parm), int parm)
465{ 495{
466 return __dsos__fprintf_buildid(&machine->kernel_dsos, fp, skip, parm) + 496 return __dsos__fprintf_buildid(&m->kernel_dsos.head, fp, skip, parm) +
467 __dsos__fprintf_buildid(&machine->user_dsos, fp, skip, parm); 497 __dsos__fprintf_buildid(&m->user_dsos.head, fp, skip, parm);
468} 498}
469 499
470size_t machines__fprintf_dsos_buildid(struct machines *machines, FILE *fp, 500size_t machines__fprintf_dsos_buildid(struct machines *machines, FILE *fp,
@@ -565,8 +595,8 @@ const char *ref_reloc_sym_names[] = {"_text", "_stext", NULL};
565 * Returns the name of the start symbol in *symbol_name. Pass in NULL as 595 * Returns the name of the start symbol in *symbol_name. Pass in NULL as
566 * symbol_name if it's not that important. 596 * symbol_name if it's not that important.
567 */ 597 */
568static u64 machine__get_kernel_start_addr(struct machine *machine, 598static u64 machine__get_running_kernel_start(struct machine *machine,
569 const char **symbol_name) 599 const char **symbol_name)
570{ 600{
571 char filename[PATH_MAX]; 601 char filename[PATH_MAX];
572 int i; 602 int i;
@@ -593,7 +623,7 @@ static u64 machine__get_kernel_start_addr(struct machine *machine,
593int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel) 623int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
594{ 624{
595 enum map_type type; 625 enum map_type type;
596 u64 start = machine__get_kernel_start_addr(machine, NULL); 626 u64 start = machine__get_running_kernel_start(machine, NULL);
597 627
598 for (type = 0; type < MAP__NR_TYPES; ++type) { 628 for (type = 0; type < MAP__NR_TYPES; ++type) {
599 struct kmap *kmap; 629 struct kmap *kmap;
@@ -912,7 +942,7 @@ int machine__create_kernel_maps(struct machine *machine)
912{ 942{
913 struct dso *kernel = machine__get_kernel(machine); 943 struct dso *kernel = machine__get_kernel(machine);
914 const char *name; 944 const char *name;
915 u64 addr = machine__get_kernel_start_addr(machine, &name); 945 u64 addr = machine__get_running_kernel_start(machine, &name);
916 if (!addr) 946 if (!addr)
917 return -1; 947 return -1;
918 948
@@ -965,7 +995,7 @@ static bool machine__uses_kcore(struct machine *machine)
965{ 995{
966 struct dso *dso; 996 struct dso *dso;
967 997
968 list_for_each_entry(dso, &machine->kernel_dsos, node) { 998 list_for_each_entry(dso, &machine->kernel_dsos.head, node) {
969 if (dso__is_kcore(dso)) 999 if (dso__is_kcore(dso))
970 return true; 1000 return true;
971 } 1001 }
@@ -1285,6 +1315,16 @@ static void ip__resolve_data(struct machine *machine, struct thread *thread,
1285 1315
1286 thread__find_addr_location(thread, machine, m, MAP__VARIABLE, addr, 1316 thread__find_addr_location(thread, machine, m, MAP__VARIABLE, addr,
1287 &al); 1317 &al);
1318 if (al.map == NULL) {
1319 /*
1320 * some shared data regions have execute bit set which puts
1321 * their mapping in the MAP__FUNCTION type array.
1322 * Check there as a fallback option before dropping the sample.
1323 */
1324 thread__find_addr_location(thread, machine, m, MAP__FUNCTION, addr,
1325 &al);
1326 }
1327
1288 ams->addr = addr; 1328 ams->addr = addr;
1289 ams->al_addr = al.addr; 1329 ams->al_addr = al.addr;
1290 ams->sym = al.sym; 1330 ams->sym = al.sym;
@@ -1531,3 +1571,25 @@ int machine__set_current_tid(struct machine *machine, int cpu, pid_t pid,
1531 1571
1532 return 0; 1572 return 0;
1533} 1573}
1574
1575int machine__get_kernel_start(struct machine *machine)
1576{
1577 struct map *map = machine__kernel_map(machine, MAP__FUNCTION);
1578 int err = 0;
1579
1580 /*
1581 * The only addresses above 2^63 are kernel addresses of a 64-bit
1582 * kernel. Note that addresses are unsigned so that on a 32-bit system
1583 * all addresses including kernel addresses are less than 2^32. In
1584 * that case (32-bit system), if the kernel mapping is unknown, all
1585 * addresses will be assumed to be in user space - see
1586 * machine__kernel_ip().
1587 */
1588 machine->kernel_start = 1ULL << 63;
1589 if (map) {
1590 err = map__load(map, machine->symbol_filter);
1591 if (map->start)
1592 machine->kernel_start = map->start;
1593 }
1594 return err;
1595}
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index b972824e6294..2b651a7f5d0d 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -4,6 +4,7 @@
4#include <sys/types.h> 4#include <sys/types.h>
5#include <linux/rbtree.h> 5#include <linux/rbtree.h>
6#include "map.h" 6#include "map.h"
7#include "dso.h"
7#include "event.h" 8#include "event.h"
8 9
9struct addr_location; 10struct addr_location;
@@ -26,15 +27,17 @@ struct machine {
26 struct rb_node rb_node; 27 struct rb_node rb_node;
27 pid_t pid; 28 pid_t pid;
28 u16 id_hdr_size; 29 u16 id_hdr_size;
30 bool comm_exec;
29 char *root_dir; 31 char *root_dir;
30 struct rb_root threads; 32 struct rb_root threads;
31 struct list_head dead_threads; 33 struct list_head dead_threads;
32 struct thread *last_match; 34 struct thread *last_match;
33 struct vdso_info *vdso_info; 35 struct vdso_info *vdso_info;
34 struct list_head user_dsos; 36 struct dsos user_dsos;
35 struct list_head kernel_dsos; 37 struct dsos kernel_dsos;
36 struct map_groups kmaps; 38 struct map_groups kmaps;
37 struct map *vmlinux_maps[MAP__NR_TYPES]; 39 struct map *vmlinux_maps[MAP__NR_TYPES];
40 u64 kernel_start;
38 symbol_filter_t symbol_filter; 41 symbol_filter_t symbol_filter;
39 pid_t *current_tid; 42 pid_t *current_tid;
40}; 43};
@@ -45,8 +48,26 @@ struct map *machine__kernel_map(struct machine *machine, enum map_type type)
45 return machine->vmlinux_maps[type]; 48 return machine->vmlinux_maps[type];
46} 49}
47 50
51int machine__get_kernel_start(struct machine *machine);
52
53static inline u64 machine__kernel_start(struct machine *machine)
54{
55 if (!machine->kernel_start)
56 machine__get_kernel_start(machine);
57 return machine->kernel_start;
58}
59
60static inline bool machine__kernel_ip(struct machine *machine, u64 ip)
61{
62 u64 kernel_start = machine__kernel_start(machine);
63
64 return ip >= kernel_start;
65}
66
48struct thread *machine__find_thread(struct machine *machine, pid_t pid, 67struct thread *machine__find_thread(struct machine *machine, pid_t pid,
49 pid_t tid); 68 pid_t tid);
69struct comm *machine__thread_exec_comm(struct machine *machine,
70 struct thread *thread);
50 71
51int machine__process_comm_event(struct machine *machine, union perf_event *event, 72int machine__process_comm_event(struct machine *machine, union perf_event *event,
52 struct perf_sample *sample); 73 struct perf_sample *sample);
@@ -88,6 +109,7 @@ char *machine__mmap_name(struct machine *machine, char *bf, size_t size);
88 109
89void machines__set_symbol_filter(struct machines *machines, 110void machines__set_symbol_filter(struct machines *machines,
90 symbol_filter_t symbol_filter); 111 symbol_filter_t symbol_filter);
112void machines__set_comm_exec(struct machines *machines, bool comm_exec);
91 113
92struct machine *machine__new_host(void); 114struct machine *machine__new_host(void);
93int machine__init(struct machine *machine, const char *root_dir, pid_t pid); 115int machine__init(struct machine *machine, const char *root_dir, pid_t pid);
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 31b8905dd863..b7090596ac50 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -31,6 +31,7 @@ static inline int is_anon_memory(const char *filename)
31static inline int is_no_dso_memory(const char *filename) 31static inline int is_no_dso_memory(const char *filename)
32{ 32{
33 return !strncmp(filename, "[stack", 6) || 33 return !strncmp(filename, "[stack", 6) ||
34 !strncmp(filename, "/SYSV",5) ||
34 !strcmp(filename, "[heap]"); 35 !strcmp(filename, "[heap]");
35} 36}
36 37
diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c
new file mode 100644
index 000000000000..706ce1a66169
--- /dev/null
+++ b/tools/perf/util/ordered-events.c
@@ -0,0 +1,245 @@
1#include <linux/list.h>
2#include <linux/compiler.h>
3#include "ordered-events.h"
4#include "evlist.h"
5#include "session.h"
6#include "asm/bug.h"
7#include "debug.h"
8
9#define pr_N(n, fmt, ...) \
10 eprintf(n, debug_ordered_events, fmt, ##__VA_ARGS__)
11
12#define pr(fmt, ...) pr_N(1, pr_fmt(fmt), ##__VA_ARGS__)
13
14static void queue_event(struct ordered_events *oe, struct ordered_event *new)
15{
16 struct ordered_event *last = oe->last;
17 u64 timestamp = new->timestamp;
18 struct list_head *p;
19
20 ++oe->nr_events;
21 oe->last = new;
22
23 pr_oe_time2(timestamp, "queue_event nr_events %u\n", oe->nr_events);
24
25 if (!last) {
26 list_add(&new->list, &oe->events);
27 oe->max_timestamp = timestamp;
28 return;
29 }
30
31 /*
32 * last event might point to some random place in the list as it's
33 * the last queued event. We expect that the new event is close to
34 * this.
35 */
36 if (last->timestamp <= timestamp) {
37 while (last->timestamp <= timestamp) {
38 p = last->list.next;
39 if (p == &oe->events) {
40 list_add_tail(&new->list, &oe->events);
41 oe->max_timestamp = timestamp;
42 return;
43 }
44 last = list_entry(p, struct ordered_event, list);
45 }
46 list_add_tail(&new->list, &last->list);
47 } else {
48 while (last->timestamp > timestamp) {
49 p = last->list.prev;
50 if (p == &oe->events) {
51 list_add(&new->list, &oe->events);
52 return;
53 }
54 last = list_entry(p, struct ordered_event, list);
55 }
56 list_add(&new->list, &last->list);
57 }
58}
59
60#define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct ordered_event))
61static struct ordered_event *alloc_event(struct ordered_events *oe)
62{
63 struct list_head *cache = &oe->cache;
64 struct ordered_event *new = NULL;
65
66 if (!list_empty(cache)) {
67 new = list_entry(cache->next, struct ordered_event, list);
68 list_del(&new->list);
69 } else if (oe->buffer) {
70 new = oe->buffer + oe->buffer_idx;
71 if (++oe->buffer_idx == MAX_SAMPLE_BUFFER)
72 oe->buffer = NULL;
73 } else if (oe->cur_alloc_size < oe->max_alloc_size) {
74 size_t size = MAX_SAMPLE_BUFFER * sizeof(*new);
75
76 oe->buffer = malloc(size);
77 if (!oe->buffer)
78 return NULL;
79
80 pr("alloc size %" PRIu64 "B (+%zu), max %" PRIu64 "B\n",
81 oe->cur_alloc_size, size, oe->max_alloc_size);
82
83 oe->cur_alloc_size += size;
84 list_add(&oe->buffer->list, &oe->to_free);
85
86 /* First entry is abused to maintain the to_free list. */
87 oe->buffer_idx = 2;
88 new = oe->buffer + 1;
89 } else {
90 pr("allocation limit reached %" PRIu64 "B\n", oe->max_alloc_size);
91 }
92
93 return new;
94}
95
96struct ordered_event *
97ordered_events__new(struct ordered_events *oe, u64 timestamp)
98{
99 struct ordered_event *new;
100
101 new = alloc_event(oe);
102 if (new) {
103 new->timestamp = timestamp;
104 queue_event(oe, new);
105 }
106
107 return new;
108}
109
110void ordered_events__delete(struct ordered_events *oe, struct ordered_event *event)
111{
112 list_move(&event->list, &oe->cache);
113 oe->nr_events--;
114}
115
116static int __ordered_events__flush(struct perf_session *s,
117 struct perf_tool *tool)
118{
119 struct ordered_events *oe = &s->ordered_events;
120 struct list_head *head = &oe->events;
121 struct ordered_event *tmp, *iter;
122 struct perf_sample sample;
123 u64 limit = oe->next_flush;
124 u64 last_ts = oe->last ? oe->last->timestamp : 0ULL;
125 bool show_progress = limit == ULLONG_MAX;
126 struct ui_progress prog;
127 int ret;
128
129 if (!tool->ordered_events || !limit)
130 return 0;
131
132 if (show_progress)
133 ui_progress__init(&prog, oe->nr_events, "Processing time ordered events...");
134
135 list_for_each_entry_safe(iter, tmp, head, list) {
136 if (session_done())
137 return 0;
138
139 if (iter->timestamp > limit)
140 break;
141
142 ret = perf_evlist__parse_sample(s->evlist, iter->event, &sample);
143 if (ret)
144 pr_err("Can't parse sample, err = %d\n", ret);
145 else {
146 ret = perf_session__deliver_event(s, iter->event, &sample, tool,
147 iter->file_offset);
148 if (ret)
149 return ret;
150 }
151
152 ordered_events__delete(oe, iter);
153 oe->last_flush = iter->timestamp;
154
155 if (show_progress)
156 ui_progress__update(&prog, 1);
157 }
158
159 if (list_empty(head))
160 oe->last = NULL;
161 else if (last_ts <= limit)
162 oe->last = list_entry(head->prev, struct ordered_event, list);
163
164 return 0;
165}
166
167int ordered_events__flush(struct perf_session *s, struct perf_tool *tool,
168 enum oe_flush how)
169{
170 struct ordered_events *oe = &s->ordered_events;
171 static const char * const str[] = {
172 "NONE",
173 "FINAL",
174 "ROUND",
175 "HALF ",
176 };
177 int err;
178
179 switch (how) {
180 case OE_FLUSH__FINAL:
181 oe->next_flush = ULLONG_MAX;
182 break;
183
184 case OE_FLUSH__HALF:
185 {
186 struct ordered_event *first, *last;
187 struct list_head *head = &oe->events;
188
189 first = list_entry(head->next, struct ordered_event, list);
190 last = oe->last;
191
192 /* Warn if we are called before any event got allocated. */
193 if (WARN_ONCE(!last || list_empty(head), "empty queue"))
194 return 0;
195
196 oe->next_flush = first->timestamp;
197 oe->next_flush += (last->timestamp - first->timestamp) / 2;
198 break;
199 }
200
201 case OE_FLUSH__ROUND:
202 case OE_FLUSH__NONE:
203 default:
204 break;
205 };
206
207 pr_oe_time(oe->next_flush, "next_flush - ordered_events__flush PRE %s, nr_events %u\n",
208 str[how], oe->nr_events);
209 pr_oe_time(oe->max_timestamp, "max_timestamp\n");
210
211 err = __ordered_events__flush(s, tool);
212
213 if (!err) {
214 if (how == OE_FLUSH__ROUND)
215 oe->next_flush = oe->max_timestamp;
216
217 oe->last_flush_type = how;
218 }
219
220 pr_oe_time(oe->next_flush, "next_flush - ordered_events__flush POST %s, nr_events %u\n",
221 str[how], oe->nr_events);
222 pr_oe_time(oe->last_flush, "last_flush\n");
223
224 return err;
225}
226
227void ordered_events__init(struct ordered_events *oe)
228{
229 INIT_LIST_HEAD(&oe->events);
230 INIT_LIST_HEAD(&oe->cache);
231 INIT_LIST_HEAD(&oe->to_free);
232 oe->max_alloc_size = (u64) -1;
233 oe->cur_alloc_size = 0;
234}
235
236void ordered_events__free(struct ordered_events *oe)
237{
238 while (!list_empty(&oe->to_free)) {
239 struct ordered_event *event;
240
241 event = list_entry(oe->to_free.next, struct ordered_event, list);
242 list_del(&event->list);
243 free(event);
244 }
245}
diff --git a/tools/perf/util/ordered-events.h b/tools/perf/util/ordered-events.h
new file mode 100644
index 000000000000..3b2f20542a01
--- /dev/null
+++ b/tools/perf/util/ordered-events.h
@@ -0,0 +1,51 @@
1#ifndef __ORDERED_EVENTS_H
2#define __ORDERED_EVENTS_H
3
4#include <linux/types.h>
5#include "tool.h"
6
7struct perf_session;
8
9struct ordered_event {
10 u64 timestamp;
11 u64 file_offset;
12 union perf_event *event;
13 struct list_head list;
14};
15
16enum oe_flush {
17 OE_FLUSH__NONE,
18 OE_FLUSH__FINAL,
19 OE_FLUSH__ROUND,
20 OE_FLUSH__HALF,
21};
22
23struct ordered_events {
24 u64 last_flush;
25 u64 next_flush;
26 u64 max_timestamp;
27 u64 max_alloc_size;
28 u64 cur_alloc_size;
29 struct list_head events;
30 struct list_head cache;
31 struct list_head to_free;
32 struct ordered_event *buffer;
33 struct ordered_event *last;
34 int buffer_idx;
35 unsigned int nr_events;
36 enum oe_flush last_flush_type;
37};
38
39struct ordered_event *ordered_events__new(struct ordered_events *oe, u64 timestamp);
40void ordered_events__delete(struct ordered_events *oe, struct ordered_event *event);
41int ordered_events__flush(struct perf_session *s, struct perf_tool *tool,
42 enum oe_flush how);
43void ordered_events__init(struct ordered_events *oe);
44void ordered_events__free(struct ordered_events *oe);
45
46static inline
47void ordered_events__set_alloc_size(struct ordered_events *oe, u64 size)
48{
49 oe->max_alloc_size = size;
50}
51#endif /* __ORDERED_EVENTS_H */
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 1e15df10a88c..d76aa30cb1fb 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -10,6 +10,7 @@
10#include "symbol.h" 10#include "symbol.h"
11#include "cache.h" 11#include "cache.h"
12#include "header.h" 12#include "header.h"
13#include "debug.h"
13#include <api/fs/debugfs.h> 14#include <api/fs/debugfs.h>
14#include "parse-events-bison.h" 15#include "parse-events-bison.h"
15#define YY_EXTRA_TYPE int 16#define YY_EXTRA_TYPE int
@@ -633,18 +634,28 @@ int parse_events_add_pmu(struct list_head *list, int *idx,
633 char *name, struct list_head *head_config) 634 char *name, struct list_head *head_config)
634{ 635{
635 struct perf_event_attr attr; 636 struct perf_event_attr attr;
637 struct perf_pmu_info info;
636 struct perf_pmu *pmu; 638 struct perf_pmu *pmu;
637 struct perf_evsel *evsel; 639 struct perf_evsel *evsel;
638 const char *unit;
639 double scale;
640 640
641 pmu = perf_pmu__find(name); 641 pmu = perf_pmu__find(name);
642 if (!pmu) 642 if (!pmu)
643 return -EINVAL; 643 return -EINVAL;
644 644
645 memset(&attr, 0, sizeof(attr)); 645 if (pmu->default_config) {
646 memcpy(&attr, pmu->default_config,
647 sizeof(struct perf_event_attr));
648 } else {
649 memset(&attr, 0, sizeof(attr));
650 }
651
652 if (!head_config) {
653 attr.type = pmu->type;
654 evsel = __add_event(list, idx, &attr, NULL, pmu->cpus);
655 return evsel ? 0 : -ENOMEM;
656 }
646 657
647 if (perf_pmu__check_alias(pmu, head_config, &unit, &scale)) 658 if (perf_pmu__check_alias(pmu, head_config, &info))
648 return -EINVAL; 659 return -EINVAL;
649 660
650 /* 661 /*
@@ -659,8 +670,8 @@ int parse_events_add_pmu(struct list_head *list, int *idx,
659 evsel = __add_event(list, idx, &attr, pmu_event_name(head_config), 670 evsel = __add_event(list, idx, &attr, pmu_event_name(head_config),
660 pmu->cpus); 671 pmu->cpus);
661 if (evsel) { 672 if (evsel) {
662 evsel->unit = unit; 673 evsel->unit = info.unit;
663 evsel->scale = scale; 674 evsel->scale = info.scale;
664 } 675 }
665 676
666 return evsel ? 0 : -ENOMEM; 677 return evsel ? 0 : -ENOMEM;
@@ -973,7 +984,7 @@ int parse_filter(const struct option *opt, const char *str,
973 984
974 if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) { 985 if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) {
975 fprintf(stderr, 986 fprintf(stderr,
976 "-F option should follow a -e tracepoint option\n"); 987 "--filter option should follow a -e tracepoint option\n");
977 return -1; 988 return -1;
978 } 989 }
979 990
@@ -1006,9 +1017,11 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
1006 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; 1017 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
1007 char evt_path[MAXPATHLEN]; 1018 char evt_path[MAXPATHLEN];
1008 char dir_path[MAXPATHLEN]; 1019 char dir_path[MAXPATHLEN];
1020 char sbuf[STRERR_BUFSIZE];
1009 1021
1010 if (debugfs_valid_mountpoint(tracing_events_path)) { 1022 if (debugfs_valid_mountpoint(tracing_events_path)) {
1011 printf(" [ Tracepoints not available: %s ]\n", strerror(errno)); 1023 printf(" [ Tracepoints not available: %s ]\n",
1024 strerror_r(errno, sbuf, sizeof(sbuf)));
1012 return; 1025 return;
1013 } 1026 }
1014 1027
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 0bc87ba46bf3..55fab6ad609a 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -210,6 +210,16 @@ PE_NAME '/' event_config '/'
210 parse_events__free_terms($3); 210 parse_events__free_terms($3);
211 $$ = list; 211 $$ = list;
212} 212}
213|
214PE_NAME '/' '/'
215{
216 struct parse_events_evlist *data = _data;
217 struct list_head *list;
218
219 ALLOC_LIST(list);
220 ABORT_ON(parse_events_add_pmu(list, &data->idx, $1, NULL));
221 $$ = list;
222}
213 223
214value_sym: 224value_sym:
215PE_VALUE_SYM_HW 225PE_VALUE_SYM_HW
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 7a811eb61f75..93a41ca96b8e 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -2,6 +2,8 @@
2#include <sys/types.h> 2#include <sys/types.h>
3#include <unistd.h> 3#include <unistd.h>
4#include <stdio.h> 4#include <stdio.h>
5#include <stdbool.h>
6#include <stdarg.h>
5#include <dirent.h> 7#include <dirent.h>
6#include <api/fs/fs.h> 8#include <api/fs/fs.h>
7#include <locale.h> 9#include <locale.h>
@@ -14,8 +16,8 @@
14 16
15struct perf_pmu_alias { 17struct perf_pmu_alias {
16 char *name; 18 char *name;
17 struct list_head terms; 19 struct list_head terms; /* HEAD struct parse_events_term -> list */
18 struct list_head list; 20 struct list_head list; /* ELEM */
19 char unit[UNIT_MAX_LEN+1]; 21 char unit[UNIT_MAX_LEN+1];
20 double scale; 22 double scale;
21}; 23};
@@ -208,6 +210,19 @@ static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FI
208 return 0; 210 return 0;
209} 211}
210 212
213static inline bool pmu_alias_info_file(char *name)
214{
215 size_t len;
216
217 len = strlen(name);
218 if (len > 5 && !strcmp(name + len - 5, ".unit"))
219 return true;
220 if (len > 6 && !strcmp(name + len - 6, ".scale"))
221 return true;
222
223 return false;
224}
225
211/* 226/*
212 * Process all the sysfs attributes located under the directory 227 * Process all the sysfs attributes located under the directory
213 * specified in 'dir' parameter. 228 * specified in 'dir' parameter.
@@ -216,7 +231,6 @@ static int pmu_aliases_parse(char *dir, struct list_head *head)
216{ 231{
217 struct dirent *evt_ent; 232 struct dirent *evt_ent;
218 DIR *event_dir; 233 DIR *event_dir;
219 size_t len;
220 int ret = 0; 234 int ret = 0;
221 235
222 event_dir = opendir(dir); 236 event_dir = opendir(dir);
@@ -232,13 +246,9 @@ static int pmu_aliases_parse(char *dir, struct list_head *head)
232 continue; 246 continue;
233 247
234 /* 248 /*
235 * skip .unit and .scale info files 249 * skip info files parsed in perf_pmu__new_alias()
236 * parsed in perf_pmu__new_alias()
237 */ 250 */
238 len = strlen(name); 251 if (pmu_alias_info_file(name))
239 if (len > 5 && !strcmp(name + len - 5, ".unit"))
240 continue;
241 if (len > 6 && !strcmp(name + len - 6, ".scale"))
242 continue; 252 continue;
243 253
244 snprintf(path, PATH_MAX, "%s/%s", dir, name); 254 snprintf(path, PATH_MAX, "%s/%s", dir, name);
@@ -387,6 +397,12 @@ static struct cpu_map *pmu_cpumask(const char *name)
387 return cpus; 397 return cpus;
388} 398}
389 399
400struct perf_event_attr *__attribute__((weak))
401perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
402{
403 return NULL;
404}
405
390static struct perf_pmu *pmu_lookup(const char *name) 406static struct perf_pmu *pmu_lookup(const char *name)
391{ 407{
392 struct perf_pmu *pmu; 408 struct perf_pmu *pmu;
@@ -421,6 +437,9 @@ static struct perf_pmu *pmu_lookup(const char *name)
421 pmu->name = strdup(name); 437 pmu->name = strdup(name);
422 pmu->type = type; 438 pmu->type = type;
423 list_add_tail(&pmu->list, &pmus); 439 list_add_tail(&pmu->list, &pmus);
440
441 pmu->default_config = perf_pmu__get_default_config(pmu);
442
424 return pmu; 443 return pmu;
425} 444}
426 445
@@ -479,28 +498,24 @@ pmu_find_format(struct list_head *formats, char *name)
479} 498}
480 499
481/* 500/*
482 * Returns value based on the format definition (format parameter) 501 * Sets value based on the format definition (format parameter)
483 * and unformated value (value parameter). 502 * and unformated value (value parameter).
484 *
485 * TODO maybe optimize a little ;)
486 */ 503 */
487static __u64 pmu_format_value(unsigned long *format, __u64 value) 504static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v,
505 bool zero)
488{ 506{
489 unsigned long fbit, vbit; 507 unsigned long fbit, vbit;
490 __u64 v = 0;
491 508
492 for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) { 509 for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) {
493 510
494 if (!test_bit(fbit, format)) 511 if (!test_bit(fbit, format))
495 continue; 512 continue;
496 513
497 if (!(value & (1llu << vbit++))) 514 if (value & (1llu << vbit++))
498 continue; 515 *v |= (1llu << fbit);
499 516 else if (zero)
500 v |= (1llu << fbit); 517 *v &= ~(1llu << fbit);
501 } 518 }
502
503 return v;
504} 519}
505 520
506/* 521/*
@@ -509,7 +524,8 @@ static __u64 pmu_format_value(unsigned long *format, __u64 value)
509 */ 524 */
510static int pmu_config_term(struct list_head *formats, 525static int pmu_config_term(struct list_head *formats,
511 struct perf_event_attr *attr, 526 struct perf_event_attr *attr,
512 struct parse_events_term *term) 527 struct parse_events_term *term,
528 bool zero)
513{ 529{
514 struct perf_pmu_format *format; 530 struct perf_pmu_format *format;
515 __u64 *vp; 531 __u64 *vp;
@@ -548,18 +564,19 @@ static int pmu_config_term(struct list_head *formats,
548 * non-hardcoded terms, here's the place to translate 564 * non-hardcoded terms, here's the place to translate
549 * them into value. 565 * them into value.
550 */ 566 */
551 *vp |= pmu_format_value(format->bits, term->val.num); 567 pmu_format_value(format->bits, term->val.num, vp, zero);
552 return 0; 568 return 0;
553} 569}
554 570
555int perf_pmu__config_terms(struct list_head *formats, 571int perf_pmu__config_terms(struct list_head *formats,
556 struct perf_event_attr *attr, 572 struct perf_event_attr *attr,
557 struct list_head *head_terms) 573 struct list_head *head_terms,
574 bool zero)
558{ 575{
559 struct parse_events_term *term; 576 struct parse_events_term *term;
560 577
561 list_for_each_entry(term, head_terms, list) 578 list_for_each_entry(term, head_terms, list)
562 if (pmu_config_term(formats, attr, term)) 579 if (pmu_config_term(formats, attr, term, zero))
563 return -EINVAL; 580 return -EINVAL;
564 581
565 return 0; 582 return 0;
@@ -573,8 +590,10 @@ int perf_pmu__config_terms(struct list_head *formats,
573int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, 590int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
574 struct list_head *head_terms) 591 struct list_head *head_terms)
575{ 592{
593 bool zero = !!pmu->default_config;
594
576 attr->type = pmu->type; 595 attr->type = pmu->type;
577 return perf_pmu__config_terms(&pmu->format, attr, head_terms); 596 return perf_pmu__config_terms(&pmu->format, attr, head_terms, zero);
578} 597}
579 598
580static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu, 599static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
@@ -634,7 +653,7 @@ static int check_unit_scale(struct perf_pmu_alias *alias,
634 * defined for the alias 653 * defined for the alias
635 */ 654 */
636int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, 655int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
637 const char **unit, double *scale) 656 struct perf_pmu_info *info)
638{ 657{
639 struct parse_events_term *term, *h; 658 struct parse_events_term *term, *h;
640 struct perf_pmu_alias *alias; 659 struct perf_pmu_alias *alias;
@@ -644,8 +663,8 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
644 * Mark unit and scale as not set 663 * Mark unit and scale as not set
645 * (different from default values, see below) 664 * (different from default values, see below)
646 */ 665 */
647 *unit = NULL; 666 info->unit = NULL;
648 *scale = 0.0; 667 info->scale = 0.0;
649 668
650 list_for_each_entry_safe(term, h, head_terms, list) { 669 list_for_each_entry_safe(term, h, head_terms, list) {
651 alias = pmu_find_alias(pmu, term); 670 alias = pmu_find_alias(pmu, term);
@@ -655,7 +674,7 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
655 if (ret) 674 if (ret)
656 return ret; 675 return ret;
657 676
658 ret = check_unit_scale(alias, unit, scale); 677 ret = check_unit_scale(alias, &info->unit, &info->scale);
659 if (ret) 678 if (ret)
660 return ret; 679 return ret;
661 680
@@ -668,11 +687,11 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
668 * set defaults as for evsel 687 * set defaults as for evsel
669 * unit cannot left to NULL 688 * unit cannot left to NULL
670 */ 689 */
671 if (*unit == NULL) 690 if (info->unit == NULL)
672 *unit = ""; 691 info->unit = "";
673 692
674 if (*scale == 0.0) 693 if (info->scale == 0.0)
675 *scale = 1.0; 694 info->scale = 1.0;
676 695
677 return 0; 696 return 0;
678} 697}
@@ -794,3 +813,39 @@ bool pmu_have_event(const char *pname, const char *name)
794 } 813 }
795 return false; 814 return false;
796} 815}
816
817static FILE *perf_pmu__open_file(struct perf_pmu *pmu, const char *name)
818{
819 struct stat st;
820 char path[PATH_MAX];
821 const char *sysfs;
822
823 sysfs = sysfs__mountpoint();
824 if (!sysfs)
825 return NULL;
826
827 snprintf(path, PATH_MAX,
828 "%s" EVENT_SOURCE_DEVICE_PATH "%s/%s", sysfs, pmu->name, name);
829
830 if (stat(path, &st) < 0)
831 return NULL;
832
833 return fopen(path, "r");
834}
835
836int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
837 ...)
838{
839 va_list args;
840 FILE *file;
841 int ret = EOF;
842
843 va_start(args, fmt);
844 file = perf_pmu__open_file(pmu, name);
845 if (file) {
846 ret = vfscanf(file, fmt, args);
847 fclose(file);
848 }
849 va_end(args);
850 return ret;
851}
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index c14a543ce1f3..fe90a012c003 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -13,13 +13,21 @@ enum {
13 13
14#define PERF_PMU_FORMAT_BITS 64 14#define PERF_PMU_FORMAT_BITS 64
15 15
16struct perf_event_attr;
17
16struct perf_pmu { 18struct perf_pmu {
17 char *name; 19 char *name;
18 __u32 type; 20 __u32 type;
21 struct perf_event_attr *default_config;
19 struct cpu_map *cpus; 22 struct cpu_map *cpus;
20 struct list_head format; 23 struct list_head format; /* HEAD struct perf_pmu_format -> list */
21 struct list_head aliases; 24 struct list_head aliases; /* HEAD struct perf_pmu_alias -> list */
22 struct list_head list; 25 struct list_head list; /* ELEM */
26};
27
28struct perf_pmu_info {
29 const char *unit;
30 double scale;
23}; 31};
24 32
25struct perf_pmu *perf_pmu__find(const char *name); 33struct perf_pmu *perf_pmu__find(const char *name);
@@ -27,9 +35,10 @@ int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
27 struct list_head *head_terms); 35 struct list_head *head_terms);
28int perf_pmu__config_terms(struct list_head *formats, 36int perf_pmu__config_terms(struct list_head *formats,
29 struct perf_event_attr *attr, 37 struct perf_event_attr *attr,
30 struct list_head *head_terms); 38 struct list_head *head_terms,
39 bool zero);
31int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, 40int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
32 const char **unit, double *scale); 41 struct perf_pmu_info *info);
33struct list_head *perf_pmu__alias(struct perf_pmu *pmu, 42struct list_head *perf_pmu__alias(struct perf_pmu *pmu,
34 struct list_head *head_terms); 43 struct list_head *head_terms);
35int perf_pmu_wrap(void); 44int perf_pmu_wrap(void);
@@ -45,5 +54,11 @@ struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu);
45void print_pmu_events(const char *event_glob, bool name_only); 54void print_pmu_events(const char *event_glob, bool name_only);
46bool pmu_have_event(const char *pname, const char *name); 55bool pmu_have_event(const char *pname, const char *name);
47 56
57int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
58 ...) __attribute__((format(scanf, 3, 4)));
59
48int perf_pmu__test(void); 60int perf_pmu__test(void);
61
62struct perf_event_attr *perf_pmu__get_default_config(struct perf_pmu *pmu);
63
49#endif /* __PMU_H */ 64#endif /* __PMU_H */
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 9a0a1839a377..c150ca4343eb 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -79,7 +79,7 @@ static int init_symbol_maps(bool user_only)
79 int ret; 79 int ret;
80 80
81 symbol_conf.sort_by_name = true; 81 symbol_conf.sort_by_name = true;
82 ret = symbol__init(); 82 ret = symbol__init(NULL);
83 if (ret < 0) { 83 if (ret < 0) {
84 pr_debug("Failed to init symbol map.\n"); 84 pr_debug("Failed to init symbol map.\n");
85 goto out; 85 goto out;
@@ -184,7 +184,8 @@ static struct dso *kernel_get_module_dso(const char *module)
184 const char *vmlinux_name; 184 const char *vmlinux_name;
185 185
186 if (module) { 186 if (module) {
187 list_for_each_entry(dso, &host_machine->kernel_dsos, node) { 187 list_for_each_entry(dso, &host_machine->kernel_dsos.head,
188 node) {
188 if (strncmp(dso->short_name + 1, module, 189 if (strncmp(dso->short_name + 1, module,
189 dso->short_name_len - 2) == 0) 190 dso->short_name_len - 2) == 0)
190 goto found; 191 goto found;
@@ -258,21 +259,33 @@ static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
258#ifdef HAVE_DWARF_SUPPORT 259#ifdef HAVE_DWARF_SUPPORT
259 260
260/* Open new debuginfo of given module */ 261/* Open new debuginfo of given module */
261static struct debuginfo *open_debuginfo(const char *module) 262static struct debuginfo *open_debuginfo(const char *module, bool silent)
262{ 263{
263 const char *path = module; 264 const char *path = module;
265 struct debuginfo *ret;
264 266
265 if (!module || !strchr(module, '/')) { 267 if (!module || !strchr(module, '/')) {
266 path = kernel_get_module_path(module); 268 path = kernel_get_module_path(module);
267 if (!path) { 269 if (!path) {
268 pr_err("Failed to find path of %s module.\n", 270 if (!silent)
269 module ?: "kernel"); 271 pr_err("Failed to find path of %s module.\n",
272 module ?: "kernel");
270 return NULL; 273 return NULL;
271 } 274 }
272 } 275 }
273 return debuginfo__new(path); 276 ret = debuginfo__new(path);
277 if (!ret && !silent) {
278 pr_warning("The %s file has no debug information.\n", path);
279 if (!module || !strtailcmp(path, ".ko"))
280 pr_warning("Rebuild with CONFIG_DEBUG_INFO=y, ");
281 else
282 pr_warning("Rebuild with -g, ");
283 pr_warning("or install an appropriate debuginfo package.\n");
284 }
285 return ret;
274} 286}
275 287
288
276static int get_text_start_address(const char *exec, unsigned long *address) 289static int get_text_start_address(const char *exec, unsigned long *address)
277{ 290{
278 Elf *elf; 291 Elf *elf;
@@ -333,15 +346,13 @@ static int find_perf_probe_point_from_dwarf(struct probe_trace_point *tp,
333 pr_debug("try to find information at %" PRIx64 " in %s\n", addr, 346 pr_debug("try to find information at %" PRIx64 " in %s\n", addr,
334 tp->module ? : "kernel"); 347 tp->module ? : "kernel");
335 348
336 dinfo = open_debuginfo(tp->module); 349 dinfo = open_debuginfo(tp->module, verbose == 0);
337 if (dinfo) { 350 if (dinfo) {
338 ret = debuginfo__find_probe_point(dinfo, 351 ret = debuginfo__find_probe_point(dinfo,
339 (unsigned long)addr, pp); 352 (unsigned long)addr, pp);
340 debuginfo__delete(dinfo); 353 debuginfo__delete(dinfo);
341 } else { 354 } else
342 pr_debug("Failed to open debuginfo at 0x%" PRIx64 "\n", addr);
343 ret = -ENOENT; 355 ret = -ENOENT;
344 }
345 356
346 if (ret > 0) { 357 if (ret > 0) {
347 pp->retprobe = tp->retprobe; 358 pp->retprobe = tp->retprobe;
@@ -457,13 +468,11 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
457 struct debuginfo *dinfo; 468 struct debuginfo *dinfo;
458 int ntevs, ret = 0; 469 int ntevs, ret = 0;
459 470
460 dinfo = open_debuginfo(target); 471 dinfo = open_debuginfo(target, !need_dwarf);
461 472
462 if (!dinfo) { 473 if (!dinfo) {
463 if (need_dwarf) { 474 if (need_dwarf)
464 pr_warning("Failed to open debuginfo file.\n");
465 return -ENOENT; 475 return -ENOENT;
466 }
467 pr_debug("Could not open debuginfo. Try to use symbols.\n"); 476 pr_debug("Could not open debuginfo. Try to use symbols.\n");
468 return 0; 477 return 0;
469 } 478 }
@@ -565,7 +574,7 @@ static int get_real_path(const char *raw_path, const char *comp_dir,
565 574
566static int __show_one_line(FILE *fp, int l, bool skip, bool show_num) 575static int __show_one_line(FILE *fp, int l, bool skip, bool show_num)
567{ 576{
568 char buf[LINEBUF_SIZE]; 577 char buf[LINEBUF_SIZE], sbuf[STRERR_BUFSIZE];
569 const char *color = show_num ? "" : PERF_COLOR_BLUE; 578 const char *color = show_num ? "" : PERF_COLOR_BLUE;
570 const char *prefix = NULL; 579 const char *prefix = NULL;
571 580
@@ -585,7 +594,8 @@ static int __show_one_line(FILE *fp, int l, bool skip, bool show_num)
585 return 1; 594 return 1;
586error: 595error:
587 if (ferror(fp)) { 596 if (ferror(fp)) {
588 pr_warning("File read error: %s\n", strerror(errno)); 597 pr_warning("File read error: %s\n",
598 strerror_r(errno, sbuf, sizeof(sbuf)));
589 return -1; 599 return -1;
590 } 600 }
591 return 0; 601 return 0;
@@ -618,13 +628,12 @@ static int __show_line_range(struct line_range *lr, const char *module)
618 FILE *fp; 628 FILE *fp;
619 int ret; 629 int ret;
620 char *tmp; 630 char *tmp;
631 char sbuf[STRERR_BUFSIZE];
621 632
622 /* Search a line range */ 633 /* Search a line range */
623 dinfo = open_debuginfo(module); 634 dinfo = open_debuginfo(module, false);
624 if (!dinfo) { 635 if (!dinfo)
625 pr_warning("Failed to open debuginfo file.\n");
626 return -ENOENT; 636 return -ENOENT;
627 }
628 637
629 ret = debuginfo__find_line_range(dinfo, lr); 638 ret = debuginfo__find_line_range(dinfo, lr);
630 debuginfo__delete(dinfo); 639 debuginfo__delete(dinfo);
@@ -656,7 +665,7 @@ static int __show_line_range(struct line_range *lr, const char *module)
656 fp = fopen(lr->path, "r"); 665 fp = fopen(lr->path, "r");
657 if (fp == NULL) { 666 if (fp == NULL) {
658 pr_warning("Failed to open %s: %s\n", lr->path, 667 pr_warning("Failed to open %s: %s\n", lr->path,
659 strerror(errno)); 668 strerror_r(errno, sbuf, sizeof(sbuf)));
660 return -errno; 669 return -errno;
661 } 670 }
662 /* Skip to starting line number */ 671 /* Skip to starting line number */
@@ -689,11 +698,11 @@ end:
689 return ret; 698 return ret;
690} 699}
691 700
692int show_line_range(struct line_range *lr, const char *module) 701int show_line_range(struct line_range *lr, const char *module, bool user)
693{ 702{
694 int ret; 703 int ret;
695 704
696 ret = init_symbol_maps(false); 705 ret = init_symbol_maps(user);
697 if (ret < 0) 706 if (ret < 0)
698 return ret; 707 return ret;
699 ret = __show_line_range(lr, module); 708 ret = __show_line_range(lr, module);
@@ -768,13 +777,12 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
768 int i, ret = 0; 777 int i, ret = 0;
769 struct debuginfo *dinfo; 778 struct debuginfo *dinfo;
770 779
771 ret = init_symbol_maps(false); 780 ret = init_symbol_maps(pevs->uprobes);
772 if (ret < 0) 781 if (ret < 0)
773 return ret; 782 return ret;
774 783
775 dinfo = open_debuginfo(module); 784 dinfo = open_debuginfo(module, false);
776 if (!dinfo) { 785 if (!dinfo) {
777 pr_warning("Failed to open debuginfo file.\n");
778 ret = -ENOENT; 786 ret = -ENOENT;
779 goto out; 787 goto out;
780 } 788 }
@@ -815,7 +823,8 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
815} 823}
816 824
817int show_line_range(struct line_range *lr __maybe_unused, 825int show_line_range(struct line_range *lr __maybe_unused,
818 const char *module __maybe_unused) 826 const char *module __maybe_unused,
827 bool user __maybe_unused)
819{ 828{
820 pr_warning("Debuginfo-analysis is not supported.\n"); 829 pr_warning("Debuginfo-analysis is not supported.\n");
821 return -ENOSYS; 830 return -ENOSYS;
@@ -1405,8 +1414,7 @@ int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len)
1405 1414
1406 return tmp - buf; 1415 return tmp - buf;
1407error: 1416error:
1408 pr_debug("Failed to synthesize perf probe argument: %s\n", 1417 pr_debug("Failed to synthesize perf probe argument: %d\n", ret);
1409 strerror(-ret));
1410 return ret; 1418 return ret;
1411} 1419}
1412 1420
@@ -1455,8 +1463,7 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
1455 1463
1456 return buf; 1464 return buf;
1457error: 1465error:
1458 pr_debug("Failed to synthesize perf probe point: %s\n", 1466 pr_debug("Failed to synthesize perf probe point: %d\n", ret);
1459 strerror(-ret));
1460 free(buf); 1467 free(buf);
1461 return NULL; 1468 return NULL;
1462} 1469}
@@ -1780,10 +1787,11 @@ static void clear_probe_trace_event(struct probe_trace_event *tev)
1780 memset(tev, 0, sizeof(*tev)); 1787 memset(tev, 0, sizeof(*tev));
1781} 1788}
1782 1789
1783static void print_warn_msg(const char *file, bool is_kprobe) 1790static void print_open_warning(int err, bool is_kprobe)
1784{ 1791{
1792 char sbuf[STRERR_BUFSIZE];
1785 1793
1786 if (errno == ENOENT) { 1794 if (err == -ENOENT) {
1787 const char *config; 1795 const char *config;
1788 1796
1789 if (!is_kprobe) 1797 if (!is_kprobe)
@@ -1791,25 +1799,43 @@ static void print_warn_msg(const char *file, bool is_kprobe)
1791 else 1799 else
1792 config = "CONFIG_KPROBE_EVENTS"; 1800 config = "CONFIG_KPROBE_EVENTS";
1793 1801
1794 pr_warning("%s file does not exist - please rebuild kernel" 1802 pr_warning("%cprobe_events file does not exist"
1795 " with %s.\n", file, config); 1803 " - please rebuild kernel with %s.\n",
1796 } else 1804 is_kprobe ? 'k' : 'u', config);
1797 pr_warning("Failed to open %s file: %s\n", file, 1805 } else if (err == -ENOTSUP)
1798 strerror(errno)); 1806 pr_warning("Debugfs is not mounted.\n");
1807 else
1808 pr_warning("Failed to open %cprobe_events: %s\n",
1809 is_kprobe ? 'k' : 'u',
1810 strerror_r(-err, sbuf, sizeof(sbuf)));
1811}
1812
1813static void print_both_open_warning(int kerr, int uerr)
1814{
1815 /* Both kprobes and uprobes are disabled, warn it. */
1816 if (kerr == -ENOTSUP && uerr == -ENOTSUP)
1817 pr_warning("Debugfs is not mounted.\n");
1818 else if (kerr == -ENOENT && uerr == -ENOENT)
1819 pr_warning("Please rebuild kernel with CONFIG_KPROBE_EVENTS "
1820 "or/and CONFIG_UPROBE_EVENTS.\n");
1821 else {
1822 char sbuf[STRERR_BUFSIZE];
1823 pr_warning("Failed to open kprobe events: %s.\n",
1824 strerror_r(-kerr, sbuf, sizeof(sbuf)));
1825 pr_warning("Failed to open uprobe events: %s.\n",
1826 strerror_r(-uerr, sbuf, sizeof(sbuf)));
1827 }
1799} 1828}
1800 1829
1801static int open_probe_events(const char *trace_file, bool readwrite, 1830static int open_probe_events(const char *trace_file, bool readwrite)
1802 bool is_kprobe)
1803{ 1831{
1804 char buf[PATH_MAX]; 1832 char buf[PATH_MAX];
1805 const char *__debugfs; 1833 const char *__debugfs;
1806 int ret; 1834 int ret;
1807 1835
1808 __debugfs = debugfs_find_mountpoint(); 1836 __debugfs = debugfs_find_mountpoint();
1809 if (__debugfs == NULL) { 1837 if (__debugfs == NULL)
1810 pr_warning("Debugfs is not mounted.\n"); 1838 return -ENOTSUP;
1811 return -ENOENT;
1812 }
1813 1839
1814 ret = e_snprintf(buf, PATH_MAX, "%s/%s", __debugfs, trace_file); 1840 ret = e_snprintf(buf, PATH_MAX, "%s/%s", __debugfs, trace_file);
1815 if (ret >= 0) { 1841 if (ret >= 0) {
@@ -1820,19 +1846,19 @@ static int open_probe_events(const char *trace_file, bool readwrite,
1820 ret = open(buf, O_RDONLY, 0); 1846 ret = open(buf, O_RDONLY, 0);
1821 1847
1822 if (ret < 0) 1848 if (ret < 0)
1823 print_warn_msg(buf, is_kprobe); 1849 ret = -errno;
1824 } 1850 }
1825 return ret; 1851 return ret;
1826} 1852}
1827 1853
1828static int open_kprobe_events(bool readwrite) 1854static int open_kprobe_events(bool readwrite)
1829{ 1855{
1830 return open_probe_events("tracing/kprobe_events", readwrite, true); 1856 return open_probe_events("tracing/kprobe_events", readwrite);
1831} 1857}
1832 1858
1833static int open_uprobe_events(bool readwrite) 1859static int open_uprobe_events(bool readwrite)
1834{ 1860{
1835 return open_probe_events("tracing/uprobe_events", readwrite, false); 1861 return open_probe_events("tracing/uprobe_events", readwrite);
1836} 1862}
1837 1863
1838/* Get raw string list of current kprobe_events or uprobe_events */ 1864/* Get raw string list of current kprobe_events or uprobe_events */
@@ -1857,7 +1883,7 @@ static struct strlist *get_probe_trace_command_rawlist(int fd)
1857 p[idx] = '\0'; 1883 p[idx] = '\0';
1858 ret = strlist__add(sl, buf); 1884 ret = strlist__add(sl, buf);
1859 if (ret < 0) { 1885 if (ret < 0) {
1860 pr_debug("strlist__add failed: %s\n", strerror(-ret)); 1886 pr_debug("strlist__add failed (%d)\n", ret);
1861 strlist__delete(sl); 1887 strlist__delete(sl);
1862 return NULL; 1888 return NULL;
1863 } 1889 }
@@ -1916,7 +1942,7 @@ static int __show_perf_probe_events(int fd, bool is_kprobe)
1916 1942
1917 rawlist = get_probe_trace_command_rawlist(fd); 1943 rawlist = get_probe_trace_command_rawlist(fd);
1918 if (!rawlist) 1944 if (!rawlist)
1919 return -ENOENT; 1945 return -ENOMEM;
1920 1946
1921 strlist__for_each(ent, rawlist) { 1947 strlist__for_each(ent, rawlist) {
1922 ret = parse_probe_trace_command(ent->s, &tev); 1948 ret = parse_probe_trace_command(ent->s, &tev);
@@ -1940,27 +1966,34 @@ static int __show_perf_probe_events(int fd, bool is_kprobe)
1940/* List up current perf-probe events */ 1966/* List up current perf-probe events */
1941int show_perf_probe_events(void) 1967int show_perf_probe_events(void)
1942{ 1968{
1943 int fd, ret; 1969 int kp_fd, up_fd, ret;
1944 1970
1945 setup_pager(); 1971 setup_pager();
1946 fd = open_kprobe_events(false);
1947
1948 if (fd < 0)
1949 return fd;
1950 1972
1951 ret = init_symbol_maps(false); 1973 ret = init_symbol_maps(false);
1952 if (ret < 0) 1974 if (ret < 0)
1953 return ret; 1975 return ret;
1954 1976
1955 ret = __show_perf_probe_events(fd, true); 1977 kp_fd = open_kprobe_events(false);
1956 close(fd); 1978 if (kp_fd >= 0) {
1979 ret = __show_perf_probe_events(kp_fd, true);
1980 close(kp_fd);
1981 if (ret < 0)
1982 goto out;
1983 }
1957 1984
1958 fd = open_uprobe_events(false); 1985 up_fd = open_uprobe_events(false);
1959 if (fd >= 0) { 1986 if (kp_fd < 0 && up_fd < 0) {
1960 ret = __show_perf_probe_events(fd, false); 1987 print_both_open_warning(kp_fd, up_fd);
1961 close(fd); 1988 ret = kp_fd;
1989 goto out;
1962 } 1990 }
1963 1991
1992 if (up_fd >= 0) {
1993 ret = __show_perf_probe_events(up_fd, false);
1994 close(up_fd);
1995 }
1996out:
1964 exit_symbol_maps(); 1997 exit_symbol_maps();
1965 return ret; 1998 return ret;
1966} 1999}
@@ -1976,6 +2009,8 @@ static struct strlist *get_probe_trace_event_names(int fd, bool include_group)
1976 2009
1977 memset(&tev, 0, sizeof(tev)); 2010 memset(&tev, 0, sizeof(tev));
1978 rawlist = get_probe_trace_command_rawlist(fd); 2011 rawlist = get_probe_trace_command_rawlist(fd);
2012 if (!rawlist)
2013 return NULL;
1979 sl = strlist__new(true, NULL); 2014 sl = strlist__new(true, NULL);
1980 strlist__for_each(ent, rawlist) { 2015 strlist__for_each(ent, rawlist) {
1981 ret = parse_probe_trace_command(ent->s, &tev); 2016 ret = parse_probe_trace_command(ent->s, &tev);
@@ -2005,6 +2040,7 @@ static int write_probe_trace_event(int fd, struct probe_trace_event *tev)
2005{ 2040{
2006 int ret = 0; 2041 int ret = 0;
2007 char *buf = synthesize_probe_trace_command(tev); 2042 char *buf = synthesize_probe_trace_command(tev);
2043 char sbuf[STRERR_BUFSIZE];
2008 2044
2009 if (!buf) { 2045 if (!buf) {
2010 pr_debug("Failed to synthesize probe trace event.\n"); 2046 pr_debug("Failed to synthesize probe trace event.\n");
@@ -2016,7 +2052,7 @@ static int write_probe_trace_event(int fd, struct probe_trace_event *tev)
2016 ret = write(fd, buf, strlen(buf)); 2052 ret = write(fd, buf, strlen(buf));
2017 if (ret <= 0) 2053 if (ret <= 0)
2018 pr_warning("Failed to write event: %s\n", 2054 pr_warning("Failed to write event: %s\n",
2019 strerror(errno)); 2055 strerror_r(errno, sbuf, sizeof(sbuf)));
2020 } 2056 }
2021 free(buf); 2057 free(buf);
2022 return ret; 2058 return ret;
@@ -2030,7 +2066,7 @@ static int get_new_event_name(char *buf, size_t len, const char *base,
2030 /* Try no suffix */ 2066 /* Try no suffix */
2031 ret = e_snprintf(buf, len, "%s", base); 2067 ret = e_snprintf(buf, len, "%s", base);
2032 if (ret < 0) { 2068 if (ret < 0) {
2033 pr_debug("snprintf() failed: %s\n", strerror(-ret)); 2069 pr_debug("snprintf() failed: %d\n", ret);
2034 return ret; 2070 return ret;
2035 } 2071 }
2036 if (!strlist__has_entry(namelist, buf)) 2072 if (!strlist__has_entry(namelist, buf))
@@ -2046,7 +2082,7 @@ static int get_new_event_name(char *buf, size_t len, const char *base,
2046 for (i = 1; i < MAX_EVENT_INDEX; i++) { 2082 for (i = 1; i < MAX_EVENT_INDEX; i++) {
2047 ret = e_snprintf(buf, len, "%s_%d", base, i); 2083 ret = e_snprintf(buf, len, "%s_%d", base, i);
2048 if (ret < 0) { 2084 if (ret < 0) {
2049 pr_debug("snprintf() failed: %s\n", strerror(-ret)); 2085 pr_debug("snprintf() failed: %d\n", ret);
2050 return ret; 2086 return ret;
2051 } 2087 }
2052 if (!strlist__has_entry(namelist, buf)) 2088 if (!strlist__has_entry(namelist, buf))
@@ -2075,8 +2111,11 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2075 else 2111 else
2076 fd = open_kprobe_events(true); 2112 fd = open_kprobe_events(true);
2077 2113
2078 if (fd < 0) 2114 if (fd < 0) {
2115 print_open_warning(fd, !pev->uprobes);
2079 return fd; 2116 return fd;
2117 }
2118
2080 /* Get current event names */ 2119 /* Get current event names */
2081 namelist = get_probe_trace_event_names(fd, false); 2120 namelist = get_probe_trace_event_names(fd, false);
2082 if (!namelist) { 2121 if (!namelist) {
@@ -2408,7 +2447,8 @@ static int __del_trace_probe_event(int fd, struct str_node *ent)
2408 printf("Removed event: %s\n", ent->s); 2447 printf("Removed event: %s\n", ent->s);
2409 return 0; 2448 return 0;
2410error: 2449error:
2411 pr_warning("Failed to delete event: %s\n", strerror(-ret)); 2450 pr_warning("Failed to delete event: %s\n",
2451 strerror_r(-ret, buf, sizeof(buf)));
2412 return ret; 2452 return ret;
2413} 2453}
2414 2454
@@ -2449,15 +2489,18 @@ int del_perf_probe_events(struct strlist *dellist)
2449 2489
2450 /* Get current event names */ 2490 /* Get current event names */
2451 kfd = open_kprobe_events(true); 2491 kfd = open_kprobe_events(true);
2452 if (kfd < 0) 2492 if (kfd >= 0)
2453 return kfd; 2493 namelist = get_probe_trace_event_names(kfd, true);
2454 2494
2455 namelist = get_probe_trace_event_names(kfd, true);
2456 ufd = open_uprobe_events(true); 2495 ufd = open_uprobe_events(true);
2457
2458 if (ufd >= 0) 2496 if (ufd >= 0)
2459 unamelist = get_probe_trace_event_names(ufd, true); 2497 unamelist = get_probe_trace_event_names(ufd, true);
2460 2498
2499 if (kfd < 0 && ufd < 0) {
2500 print_both_open_warning(kfd, ufd);
2501 goto error;
2502 }
2503
2461 if (namelist == NULL && unamelist == NULL) 2504 if (namelist == NULL && unamelist == NULL)
2462 goto error; 2505 goto error;
2463 2506
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 776c9347a3b6..e01e9943139f 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -128,7 +128,8 @@ extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
128 bool force_add); 128 bool force_add);
129extern int del_perf_probe_events(struct strlist *dellist); 129extern int del_perf_probe_events(struct strlist *dellist);
130extern int show_perf_probe_events(void); 130extern int show_perf_probe_events(void);
131extern int show_line_range(struct line_range *lr, const char *module); 131extern int show_line_range(struct line_range *lr, const char *module,
132 bool user);
132extern int show_available_vars(struct perf_probe_event *pevs, int npevs, 133extern int show_available_vars(struct perf_probe_event *pevs, int npevs,
133 int max_probe_points, const char *module, 134 int max_probe_points, const char *module,
134 struct strfilter *filter, bool externs); 135 struct strfilter *filter, bool externs);
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index dca9145d704c..c7918f83b300 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -281,6 +281,7 @@ static int convert_variable_type(Dwarf_Die *vr_die,
281 struct probe_trace_arg_ref **ref_ptr = &tvar->ref; 281 struct probe_trace_arg_ref **ref_ptr = &tvar->ref;
282 Dwarf_Die type; 282 Dwarf_Die type;
283 char buf[16]; 283 char buf[16];
284 char sbuf[STRERR_BUFSIZE];
284 int bsize, boffs, total; 285 int bsize, boffs, total;
285 int ret; 286 int ret;
286 287
@@ -367,7 +368,7 @@ formatted:
367 if (ret >= 16) 368 if (ret >= 16)
368 ret = -E2BIG; 369 ret = -E2BIG;
369 pr_warning("Failed to convert variable type: %s\n", 370 pr_warning("Failed to convert variable type: %s\n",
370 strerror(-ret)); 371 strerror_r(-ret, sbuf, sizeof(sbuf)));
371 return ret; 372 return ret;
372 } 373 }
373 tvar->type = strdup(buf); 374 tvar->type = strdup(buf);
@@ -608,14 +609,18 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod,
608 return -EINVAL; 609 return -EINVAL;
609 } 610 }
610 611
611 /* Get an appropriate symbol from symtab */ 612 symbol = dwarf_diename(sp_die);
612 symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL);
613 if (!symbol) { 613 if (!symbol) {
614 pr_warning("Failed to find symbol at 0x%lx\n", 614 /* Try to get the symbol name from symtab */
615 (unsigned long)paddr); 615 symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL);
616 return -ENOENT; 616 if (!symbol) {
617 pr_warning("Failed to find symbol at 0x%lx\n",
618 (unsigned long)paddr);
619 return -ENOENT;
620 }
621 eaddr = sym.st_value;
617 } 622 }
618 tp->offset = (unsigned long)(paddr - sym.st_value); 623 tp->offset = (unsigned long)(paddr - eaddr);
619 tp->address = (unsigned long)paddr; 624 tp->address = (unsigned long)paddr;
620 tp->symbol = strdup(symbol); 625 tp->symbol = strdup(symbol);
621 if (!tp->symbol) 626 if (!tp->symbol)
@@ -779,10 +784,12 @@ static int find_lazy_match_lines(struct intlist *list,
779 size_t line_len; 784 size_t line_len;
780 ssize_t len; 785 ssize_t len;
781 int count = 0, linenum = 1; 786 int count = 0, linenum = 1;
787 char sbuf[STRERR_BUFSIZE];
782 788
783 fp = fopen(fname, "r"); 789 fp = fopen(fname, "r");
784 if (!fp) { 790 if (!fp) {
785 pr_warning("Failed to open %s: %s\n", fname, strerror(errno)); 791 pr_warning("Failed to open %s: %s\n", fname,
792 strerror_r(errno, sbuf, sizeof(sbuf)));
786 return -errno; 793 return -errno;
787 } 794 }
788 795
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 12aa9b0d0ba1..3dda85ca50c1 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -736,7 +736,7 @@ static PyObject *pyrf_evlist__poll(struct pyrf_evlist *pevlist,
736 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", kwlist, &timeout)) 736 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", kwlist, &timeout))
737 return NULL; 737 return NULL;
738 738
739 n = poll(evlist->pollfd, evlist->nr_fds, timeout); 739 n = perf_evlist__poll(evlist, timeout);
740 if (n < 0) { 740 if (n < 0) {
741 PyErr_SetFromErrno(PyExc_OSError); 741 PyErr_SetFromErrno(PyExc_OSError);
742 return NULL; 742 return NULL;
@@ -753,9 +753,9 @@ static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist,
753 PyObject *list = PyList_New(0); 753 PyObject *list = PyList_New(0);
754 int i; 754 int i;
755 755
756 for (i = 0; i < evlist->nr_fds; ++i) { 756 for (i = 0; i < evlist->pollfd.nr; ++i) {
757 PyObject *file; 757 PyObject *file;
758 FILE *fp = fdopen(evlist->pollfd[i].fd, "r"); 758 FILE *fp = fdopen(evlist->pollfd.entries[i].fd, "r");
759 759
760 if (fp == NULL) 760 if (fp == NULL)
761 goto free_list; 761 goto free_list;
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c
index fe8079edbdc1..cf69325b985f 100644
--- a/tools/perf/util/record.c
+++ b/tools/perf/util/record.c
@@ -14,6 +14,7 @@ static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str)
14 struct perf_evsel *evsel; 14 struct perf_evsel *evsel;
15 unsigned long flags = perf_event_open_cloexec_flag(); 15 unsigned long flags = perf_event_open_cloexec_flag();
16 int err = -EAGAIN, fd; 16 int err = -EAGAIN, fd;
17 static pid_t pid = -1;
17 18
18 evlist = perf_evlist__new(); 19 evlist = perf_evlist__new();
19 if (!evlist) 20 if (!evlist)
@@ -24,14 +25,22 @@ static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str)
24 25
25 evsel = perf_evlist__first(evlist); 26 evsel = perf_evlist__first(evlist);
26 27
27 fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, flags); 28 while (1) {
28 if (fd < 0) 29 fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1, flags);
29 goto out_delete; 30 if (fd < 0) {
31 if (pid == -1 && errno == EACCES) {
32 pid = 0;
33 continue;
34 }
35 goto out_delete;
36 }
37 break;
38 }
30 close(fd); 39 close(fd);
31 40
32 fn(evsel); 41 fn(evsel);
33 42
34 fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, flags); 43 fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1, flags);
35 if (fd < 0) { 44 if (fd < 0) {
36 if (errno == EINVAL) 45 if (errno == EINVAL)
37 err = -EINVAL; 46 err = -EINVAL;
@@ -47,7 +56,7 @@ out_delete:
47 56
48static bool perf_probe_api(setup_probe_fn_t fn) 57static bool perf_probe_api(setup_probe_fn_t fn)
49{ 58{
50 const char *try[] = {"cycles:u", "instructions:u", "cpu-clock", NULL}; 59 const char *try[] = {"cycles:u", "instructions:u", "cpu-clock:u", NULL};
51 struct cpu_map *cpus; 60 struct cpu_map *cpus;
52 int cpu, ret, i = 0; 61 int cpu, ret, i = 0;
53 62
@@ -106,7 +115,7 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts)
106 115
107 evlist__for_each(evlist, evsel) { 116 evlist__for_each(evlist, evsel) {
108 perf_evsel__config(evsel, opts); 117 perf_evsel__config(evsel, opts);
109 if (!evsel->idx && use_comm_exec) 118 if (evsel->tracking && use_comm_exec)
110 evsel->attr.comm_exec = 1; 119 evsel->attr.comm_exec = 1;
111 } 120 }
112 121
@@ -201,6 +210,7 @@ bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str)
201 struct perf_evsel *evsel; 210 struct perf_evsel *evsel;
202 int err, fd, cpu; 211 int err, fd, cpu;
203 bool ret = false; 212 bool ret = false;
213 pid_t pid = -1;
204 214
205 temp_evlist = perf_evlist__new(); 215 temp_evlist = perf_evlist__new();
206 if (!temp_evlist) 216 if (!temp_evlist)
@@ -221,12 +231,20 @@ bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str)
221 cpu = evlist->cpus->map[0]; 231 cpu = evlist->cpus->map[0];
222 } 232 }
223 233
224 fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, 234 while (1) {
225 perf_event_open_cloexec_flag()); 235 fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1,
226 if (fd >= 0) { 236 perf_event_open_cloexec_flag());
227 close(fd); 237 if (fd < 0) {
228 ret = true; 238 if (pid == -1 && errno == EACCES) {
239 pid = 0;
240 continue;
241 }
242 goto out_delete;
243 }
244 break;
229 } 245 }
246 close(fd);
247 ret = true;
230 248
231out_delete: 249out_delete:
232 perf_evlist__delete(temp_evlist); 250 perf_evlist__delete(temp_evlist);
diff --git a/tools/perf/util/run-command.c b/tools/perf/util/run-command.c
index da8e9b285f51..34622b53e733 100644
--- a/tools/perf/util/run-command.c
+++ b/tools/perf/util/run-command.c
@@ -1,6 +1,7 @@
1#include "cache.h" 1#include "cache.h"
2#include "run-command.h" 2#include "run-command.h"
3#include "exec_cmd.h" 3#include "exec_cmd.h"
4#include "debug.h"
4 5
5static inline void close_pair(int fd[2]) 6static inline void close_pair(int fd[2])
6{ 7{
@@ -19,6 +20,7 @@ int start_command(struct child_process *cmd)
19{ 20{
20 int need_in, need_out, need_err; 21 int need_in, need_out, need_err;
21 int fdin[2], fdout[2], fderr[2]; 22 int fdin[2], fdout[2], fderr[2];
23 char sbuf[STRERR_BUFSIZE];
22 24
23 /* 25 /*
24 * In case of errors we must keep the promise to close FDs 26 * In case of errors we must keep the promise to close FDs
@@ -99,7 +101,7 @@ int start_command(struct child_process *cmd)
99 101
100 if (cmd->dir && chdir(cmd->dir)) 102 if (cmd->dir && chdir(cmd->dir))
101 die("exec %s: cd to %s failed (%s)", cmd->argv[0], 103 die("exec %s: cd to %s failed (%s)", cmd->argv[0],
102 cmd->dir, strerror(errno)); 104 cmd->dir, strerror_r(errno, sbuf, sizeof(sbuf)));
103 if (cmd->env) { 105 if (cmd->env) {
104 for (; *cmd->env; cmd->env++) { 106 for (; *cmd->env; cmd->env++) {
105 if (strchr(*cmd->env, '=')) 107 if (strchr(*cmd->env, '='))
@@ -153,6 +155,8 @@ int start_command(struct child_process *cmd)
153 155
154static int wait_or_whine(pid_t pid) 156static int wait_or_whine(pid_t pid)
155{ 157{
158 char sbuf[STRERR_BUFSIZE];
159
156 for (;;) { 160 for (;;) {
157 int status, code; 161 int status, code;
158 pid_t waiting = waitpid(pid, &status, 0); 162 pid_t waiting = waitpid(pid, &status, 0);
@@ -160,7 +164,8 @@ static int wait_or_whine(pid_t pid)
160 if (waiting < 0) { 164 if (waiting < 0) {
161 if (errno == EINTR) 165 if (errno == EINTR)
162 continue; 166 continue;
163 error("waitpid failed (%s)", strerror(errno)); 167 error("waitpid failed (%s)",
168 strerror_r(errno, sbuf, sizeof(sbuf)));
164 return -ERR_RUN_COMMAND_WAITPID; 169 return -ERR_RUN_COMMAND_WAITPID;
165 } 170 }
166 if (waiting != pid) 171 if (waiting != pid)
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index b2dba9c0a3a1..0a01bac4ce02 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -432,6 +432,11 @@ error:
432 return err; 432 return err;
433} 433}
434 434
435static int perl_flush_script(void)
436{
437 return 0;
438}
439
435/* 440/*
436 * Stop trace script 441 * Stop trace script
437 */ 442 */
@@ -633,6 +638,7 @@ static int perl_generate_script(struct pevent *pevent, const char *outfile)
633struct scripting_ops perl_scripting_ops = { 638struct scripting_ops perl_scripting_ops = {
634 .name = "Perl", 639 .name = "Perl",
635 .start_script = perl_start_script, 640 .start_script = perl_start_script,
641 .flush_script = perl_flush_script,
636 .stop_script = perl_stop_script, 642 .stop_script = perl_stop_script,
637 .process_event = perl_process_event, 643 .process_event = perl_process_event,
638 .generate_script = perl_generate_script, 644 .generate_script = perl_generate_script,
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index cbce2545da45..56ba07cce549 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -73,6 +73,35 @@ static void pydict_set_item_string_decref(PyObject *dict, const char *key, PyObj
73 Py_DECREF(val); 73 Py_DECREF(val);
74} 74}
75 75
76static PyObject *get_handler(const char *handler_name)
77{
78 PyObject *handler;
79
80 handler = PyDict_GetItemString(main_dict, handler_name);
81 if (handler && !PyCallable_Check(handler))
82 return NULL;
83 return handler;
84}
85
86static void call_object(PyObject *handler, PyObject *args, const char *die_msg)
87{
88 PyObject *retval;
89
90 retval = PyObject_CallObject(handler, args);
91 if (retval == NULL)
92 handler_call_die(die_msg);
93 Py_DECREF(retval);
94}
95
96static void try_call_object(const char *handler_name, PyObject *args)
97{
98 PyObject *handler;
99
100 handler = get_handler(handler_name);
101 if (handler)
102 call_object(handler, args, handler_name);
103}
104
76static void define_value(enum print_arg_type field_type, 105static void define_value(enum print_arg_type field_type,
77 const char *ev_name, 106 const char *ev_name,
78 const char *field_name, 107 const char *field_name,
@@ -80,7 +109,7 @@ static void define_value(enum print_arg_type field_type,
80 const char *field_str) 109 const char *field_str)
81{ 110{
82 const char *handler_name = "define_flag_value"; 111 const char *handler_name = "define_flag_value";
83 PyObject *handler, *t, *retval; 112 PyObject *t;
84 unsigned long long value; 113 unsigned long long value;
85 unsigned n = 0; 114 unsigned n = 0;
86 115
@@ -98,13 +127,7 @@ static void define_value(enum print_arg_type field_type,
98 PyTuple_SetItem(t, n++, PyInt_FromLong(value)); 127 PyTuple_SetItem(t, n++, PyInt_FromLong(value));
99 PyTuple_SetItem(t, n++, PyString_FromString(field_str)); 128 PyTuple_SetItem(t, n++, PyString_FromString(field_str));
100 129
101 handler = PyDict_GetItemString(main_dict, handler_name); 130 try_call_object(handler_name, t);
102 if (handler && PyCallable_Check(handler)) {
103 retval = PyObject_CallObject(handler, t);
104 if (retval == NULL)
105 handler_call_die(handler_name);
106 Py_DECREF(retval);
107 }
108 131
109 Py_DECREF(t); 132 Py_DECREF(t);
110} 133}
@@ -127,7 +150,7 @@ static void define_field(enum print_arg_type field_type,
127 const char *delim) 150 const char *delim)
128{ 151{
129 const char *handler_name = "define_flag_field"; 152 const char *handler_name = "define_flag_field";
130 PyObject *handler, *t, *retval; 153 PyObject *t;
131 unsigned n = 0; 154 unsigned n = 0;
132 155
133 if (field_type == PRINT_SYMBOL) 156 if (field_type == PRINT_SYMBOL)
@@ -145,13 +168,7 @@ static void define_field(enum print_arg_type field_type,
145 if (field_type == PRINT_FLAGS) 168 if (field_type == PRINT_FLAGS)
146 PyTuple_SetItem(t, n++, PyString_FromString(delim)); 169 PyTuple_SetItem(t, n++, PyString_FromString(delim));
147 170
148 handler = PyDict_GetItemString(main_dict, handler_name); 171 try_call_object(handler_name, t);
149 if (handler && PyCallable_Check(handler)) {
150 retval = PyObject_CallObject(handler, t);
151 if (retval == NULL)
152 handler_call_die(handler_name);
153 Py_DECREF(retval);
154 }
155 172
156 Py_DECREF(t); 173 Py_DECREF(t);
157} 174}
@@ -362,7 +379,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
362 struct thread *thread, 379 struct thread *thread,
363 struct addr_location *al) 380 struct addr_location *al)
364{ 381{
365 PyObject *handler, *retval, *context, *t, *obj, *callchain; 382 PyObject *handler, *context, *t, *obj, *callchain;
366 PyObject *dict = NULL; 383 PyObject *dict = NULL;
367 static char handler_name[256]; 384 static char handler_name[256];
368 struct format_field *field; 385 struct format_field *field;
@@ -387,9 +404,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
387 404
388 sprintf(handler_name, "%s__%s", event->system, event->name); 405 sprintf(handler_name, "%s__%s", event->system, event->name);
389 406
390 handler = PyDict_GetItemString(main_dict, handler_name); 407 handler = get_handler(handler_name);
391 if (handler && !PyCallable_Check(handler))
392 handler = NULL;
393 if (!handler) { 408 if (!handler) {
394 dict = PyDict_New(); 409 dict = PyDict_New();
395 if (!dict) 410 if (!dict)
@@ -450,19 +465,9 @@ static void python_process_tracepoint(struct perf_sample *sample,
450 Py_FatalError("error resizing Python tuple"); 465 Py_FatalError("error resizing Python tuple");
451 466
452 if (handler) { 467 if (handler) {
453 retval = PyObject_CallObject(handler, t); 468 call_object(handler, t, handler_name);
454 if (retval == NULL)
455 handler_call_die(handler_name);
456 Py_DECREF(retval);
457 } else { 469 } else {
458 handler = PyDict_GetItemString(main_dict, "trace_unhandled"); 470 try_call_object("trace_unhandled", t);
459 if (handler && PyCallable_Check(handler)) {
460
461 retval = PyObject_CallObject(handler, t);
462 if (retval == NULL)
463 handler_call_die("trace_unhandled");
464 Py_DECREF(retval);
465 }
466 Py_DECREF(dict); 471 Py_DECREF(dict);
467 } 472 }
468 473
@@ -474,7 +479,7 @@ static void python_process_general_event(struct perf_sample *sample,
474 struct thread *thread, 479 struct thread *thread,
475 struct addr_location *al) 480 struct addr_location *al)
476{ 481{
477 PyObject *handler, *retval, *t, *dict, *callchain, *dict_sample; 482 PyObject *handler, *t, *dict, *callchain, *dict_sample;
478 static char handler_name[64]; 483 static char handler_name[64];
479 unsigned n = 0; 484 unsigned n = 0;
480 485
@@ -496,8 +501,8 @@ static void python_process_general_event(struct perf_sample *sample,
496 501
497 snprintf(handler_name, sizeof(handler_name), "%s", "process_event"); 502 snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
498 503
499 handler = PyDict_GetItemString(main_dict, handler_name); 504 handler = get_handler(handler_name);
500 if (!handler || !PyCallable_Check(handler)) 505 if (!handler)
501 goto exit; 506 goto exit;
502 507
503 pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel))); 508 pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel)));
@@ -539,10 +544,7 @@ static void python_process_general_event(struct perf_sample *sample,
539 if (_PyTuple_Resize(&t, n) == -1) 544 if (_PyTuple_Resize(&t, n) == -1)
540 Py_FatalError("error resizing Python tuple"); 545 Py_FatalError("error resizing Python tuple");
541 546
542 retval = PyObject_CallObject(handler, t); 547 call_object(handler, t, handler_name);
543 if (retval == NULL)
544 handler_call_die(handler_name);
545 Py_DECREF(retval);
546exit: 548exit:
547 Py_DECREF(dict); 549 Py_DECREF(dict);
548 Py_DECREF(t); 550 Py_DECREF(t);
@@ -566,36 +568,24 @@ static void python_process_event(union perf_event *event __maybe_unused,
566 568
567static int run_start_sub(void) 569static int run_start_sub(void)
568{ 570{
569 PyObject *handler, *retval;
570 int err = 0;
571
572 main_module = PyImport_AddModule("__main__"); 571 main_module = PyImport_AddModule("__main__");
573 if (main_module == NULL) 572 if (main_module == NULL)
574 return -1; 573 return -1;
575 Py_INCREF(main_module); 574 Py_INCREF(main_module);
576 575
577 main_dict = PyModule_GetDict(main_module); 576 main_dict = PyModule_GetDict(main_module);
578 if (main_dict == NULL) { 577 if (main_dict == NULL)
579 err = -1;
580 goto error; 578 goto error;
581 }
582 Py_INCREF(main_dict); 579 Py_INCREF(main_dict);
583 580
584 handler = PyDict_GetItemString(main_dict, "trace_begin"); 581 try_call_object("trace_begin", NULL);
585 if (handler == NULL || !PyCallable_Check(handler))
586 goto out;
587 582
588 retval = PyObject_CallObject(handler, NULL); 583 return 0;
589 if (retval == NULL)
590 handler_call_die("trace_begin");
591 584
592 Py_DECREF(retval);
593 return err;
594error: 585error:
595 Py_XDECREF(main_dict); 586 Py_XDECREF(main_dict);
596 Py_XDECREF(main_module); 587 Py_XDECREF(main_module);
597out: 588 return -1;
598 return err;
599} 589}
600 590
601/* 591/*
@@ -649,28 +639,23 @@ error:
649 return err; 639 return err;
650} 640}
651 641
642static int python_flush_script(void)
643{
644 return 0;
645}
646
652/* 647/*
653 * Stop trace script 648 * Stop trace script
654 */ 649 */
655static int python_stop_script(void) 650static int python_stop_script(void)
656{ 651{
657 PyObject *handler, *retval; 652 try_call_object("trace_end", NULL);
658 int err = 0;
659 653
660 handler = PyDict_GetItemString(main_dict, "trace_end");
661 if (handler == NULL || !PyCallable_Check(handler))
662 goto out;
663
664 retval = PyObject_CallObject(handler, NULL);
665 if (retval == NULL)
666 handler_call_die("trace_end");
667 Py_DECREF(retval);
668out:
669 Py_XDECREF(main_dict); 654 Py_XDECREF(main_dict);
670 Py_XDECREF(main_module); 655 Py_XDECREF(main_module);
671 Py_Finalize(); 656 Py_Finalize();
672 657
673 return err; 658 return 0;
674} 659}
675 660
676static int python_generate_script(struct pevent *pevent, const char *outfile) 661static int python_generate_script(struct pevent *pevent, const char *outfile)
@@ -843,6 +828,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
843struct scripting_ops python_scripting_ops = { 828struct scripting_ops python_scripting_ops = {
844 .name = "Python", 829 .name = "Python",
845 .start_script = python_start_script, 830 .start_script = python_start_script,
831 .flush_script = python_flush_script,
846 .stop_script = python_stop_script, 832 .stop_script = python_stop_script,
847 .process_event = python_process_event, 833 .process_event = python_process_event,
848 .generate_script = python_generate_script, 834 .generate_script = python_generate_script,
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 88dfef70c13d..883406f4b381 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -14,6 +14,7 @@
14#include "util.h" 14#include "util.h"
15#include "cpumap.h" 15#include "cpumap.h"
16#include "perf_regs.h" 16#include "perf_regs.h"
17#include "asm/bug.h"
17 18
18static int perf_session__open(struct perf_session *session) 19static int perf_session__open(struct perf_session *session)
19{ 20{
@@ -66,6 +67,25 @@ static void perf_session__destroy_kernel_maps(struct perf_session *session)
66 machines__destroy_kernel_maps(&session->machines); 67 machines__destroy_kernel_maps(&session->machines);
67} 68}
68 69
70static bool perf_session__has_comm_exec(struct perf_session *session)
71{
72 struct perf_evsel *evsel;
73
74 evlist__for_each(session->evlist, evsel) {
75 if (evsel->attr.comm_exec)
76 return true;
77 }
78
79 return false;
80}
81
82static void perf_session__set_comm_exec(struct perf_session *session)
83{
84 bool comm_exec = perf_session__has_comm_exec(session);
85
86 machines__set_comm_exec(&session->machines, comm_exec);
87}
88
69struct perf_session *perf_session__new(struct perf_data_file *file, 89struct perf_session *perf_session__new(struct perf_data_file *file,
70 bool repipe, struct perf_tool *tool) 90 bool repipe, struct perf_tool *tool)
71{ 91{
@@ -75,9 +95,7 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
75 goto out; 95 goto out;
76 96
77 session->repipe = repipe; 97 session->repipe = repipe;
78 INIT_LIST_HEAD(&session->ordered_samples.samples); 98 ordered_events__init(&session->ordered_events);
79 INIT_LIST_HEAD(&session->ordered_samples.sample_cache);
80 INIT_LIST_HEAD(&session->ordered_samples.to_free);
81 machines__init(&session->machines); 99 machines__init(&session->machines);
82 100
83 if (file) { 101 if (file) {
@@ -91,6 +109,7 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
91 goto out_close; 109 goto out_close;
92 110
93 perf_session__set_id_hdr_size(session); 111 perf_session__set_id_hdr_size(session);
112 perf_session__set_comm_exec(session);
94 } 113 }
95 } 114 }
96 115
@@ -100,13 +119,13 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
100 * kernel MMAP event, in perf_event__process_mmap(). 119 * kernel MMAP event, in perf_event__process_mmap().
101 */ 120 */
102 if (perf_session__create_kernel_maps(session) < 0) 121 if (perf_session__create_kernel_maps(session) < 0)
103 goto out_delete; 122 pr_warning("Cannot read kernel map\n");
104 } 123 }
105 124
106 if (tool && tool->ordering_requires_timestamps && 125 if (tool && tool->ordering_requires_timestamps &&
107 tool->ordered_samples && !perf_evlist__sample_id_all(session->evlist)) { 126 tool->ordered_events && !perf_evlist__sample_id_all(session->evlist)) {
108 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); 127 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
109 tool->ordered_samples = false; 128 tool->ordered_events = false;
110 } 129 }
111 130
112 return session; 131 return session;
@@ -238,7 +257,7 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
238 if (tool->build_id == NULL) 257 if (tool->build_id == NULL)
239 tool->build_id = process_finished_round_stub; 258 tool->build_id = process_finished_round_stub;
240 if (tool->finished_round == NULL) { 259 if (tool->finished_round == NULL) {
241 if (tool->ordered_samples) 260 if (tool->ordered_events)
242 tool->finished_round = process_finished_round; 261 tool->finished_round = process_finished_round;
243 else 262 else
244 tool->finished_round = process_finished_round_stub; 263 tool->finished_round = process_finished_round_stub;
@@ -444,87 +463,6 @@ static perf_event__swap_op perf_event__swap_ops[] = {
444 [PERF_RECORD_HEADER_MAX] = NULL, 463 [PERF_RECORD_HEADER_MAX] = NULL,
445}; 464};
446 465
447struct sample_queue {
448 u64 timestamp;
449 u64 file_offset;
450 union perf_event *event;
451 struct list_head list;
452};
453
454static void perf_session_free_sample_buffers(struct perf_session *session)
455{
456 struct ordered_samples *os = &session->ordered_samples;
457
458 while (!list_empty(&os->to_free)) {
459 struct sample_queue *sq;
460
461 sq = list_entry(os->to_free.next, struct sample_queue, list);
462 list_del(&sq->list);
463 free(sq);
464 }
465}
466
467static int perf_session_deliver_event(struct perf_session *session,
468 union perf_event *event,
469 struct perf_sample *sample,
470 struct perf_tool *tool,
471 u64 file_offset);
472
473static int flush_sample_queue(struct perf_session *s,
474 struct perf_tool *tool)
475{
476 struct ordered_samples *os = &s->ordered_samples;
477 struct list_head *head = &os->samples;
478 struct sample_queue *tmp, *iter;
479 struct perf_sample sample;
480 u64 limit = os->next_flush;
481 u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL;
482 bool show_progress = limit == ULLONG_MAX;
483 struct ui_progress prog;
484 int ret;
485
486 if (!tool->ordered_samples || !limit)
487 return 0;
488
489 if (show_progress)
490 ui_progress__init(&prog, os->nr_samples, "Processing time ordered events...");
491
492 list_for_each_entry_safe(iter, tmp, head, list) {
493 if (session_done())
494 return 0;
495
496 if (iter->timestamp > limit)
497 break;
498
499 ret = perf_evlist__parse_sample(s->evlist, iter->event, &sample);
500 if (ret)
501 pr_err("Can't parse sample, err = %d\n", ret);
502 else {
503 ret = perf_session_deliver_event(s, iter->event, &sample, tool,
504 iter->file_offset);
505 if (ret)
506 return ret;
507 }
508
509 os->last_flush = iter->timestamp;
510 list_del(&iter->list);
511 list_add(&iter->list, &os->sample_cache);
512 os->nr_samples--;
513
514 if (show_progress)
515 ui_progress__update(&prog, 1);
516 }
517
518 if (list_empty(head)) {
519 os->last_sample = NULL;
520 } else if (last_ts <= limit) {
521 os->last_sample =
522 list_entry(head->prev, struct sample_queue, list);
523 }
524
525 return 0;
526}
527
528/* 466/*
529 * When perf record finishes a pass on every buffers, it records this pseudo 467 * When perf record finishes a pass on every buffers, it records this pseudo
530 * event. 468 * event.
@@ -568,99 +506,43 @@ static int process_finished_round(struct perf_tool *tool,
568 union perf_event *event __maybe_unused, 506 union perf_event *event __maybe_unused,
569 struct perf_session *session) 507 struct perf_session *session)
570{ 508{
571 int ret = flush_sample_queue(session, tool); 509 return ordered_events__flush(session, tool, OE_FLUSH__ROUND);
572 if (!ret)
573 session->ordered_samples.next_flush = session->ordered_samples.max_timestamp;
574
575 return ret;
576}
577
578/* The queue is ordered by time */
579static void __queue_event(struct sample_queue *new, struct perf_session *s)
580{
581 struct ordered_samples *os = &s->ordered_samples;
582 struct sample_queue *sample = os->last_sample;
583 u64 timestamp = new->timestamp;
584 struct list_head *p;
585
586 ++os->nr_samples;
587 os->last_sample = new;
588
589 if (!sample) {
590 list_add(&new->list, &os->samples);
591 os->max_timestamp = timestamp;
592 return;
593 }
594
595 /*
596 * last_sample might point to some random place in the list as it's
597 * the last queued event. We expect that the new event is close to
598 * this.
599 */
600 if (sample->timestamp <= timestamp) {
601 while (sample->timestamp <= timestamp) {
602 p = sample->list.next;
603 if (p == &os->samples) {
604 list_add_tail(&new->list, &os->samples);
605 os->max_timestamp = timestamp;
606 return;
607 }
608 sample = list_entry(p, struct sample_queue, list);
609 }
610 list_add_tail(&new->list, &sample->list);
611 } else {
612 while (sample->timestamp > timestamp) {
613 p = sample->list.prev;
614 if (p == &os->samples) {
615 list_add(&new->list, &os->samples);
616 return;
617 }
618 sample = list_entry(p, struct sample_queue, list);
619 }
620 list_add(&new->list, &sample->list);
621 }
622} 510}
623 511
624#define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct sample_queue))
625
626int perf_session_queue_event(struct perf_session *s, union perf_event *event, 512int perf_session_queue_event(struct perf_session *s, union perf_event *event,
627 struct perf_sample *sample, u64 file_offset) 513 struct perf_tool *tool, struct perf_sample *sample,
514 u64 file_offset)
628{ 515{
629 struct ordered_samples *os = &s->ordered_samples; 516 struct ordered_events *oe = &s->ordered_events;
630 struct list_head *sc = &os->sample_cache;
631 u64 timestamp = sample->time; 517 u64 timestamp = sample->time;
632 struct sample_queue *new; 518 struct ordered_event *new;
633 519
634 if (!timestamp || timestamp == ~0ULL) 520 if (!timestamp || timestamp == ~0ULL)
635 return -ETIME; 521 return -ETIME;
636 522
637 if (timestamp < s->ordered_samples.last_flush) { 523 if (timestamp < oe->last_flush) {
638 printf("Warning: Timestamp below last timeslice flush\n"); 524 WARN_ONCE(1, "Timestamp below last timeslice flush\n");
639 return -EINVAL; 525
526 pr_oe_time(timestamp, "out of order event");
527 pr_oe_time(oe->last_flush, "last flush, last_flush_type %d\n",
528 oe->last_flush_type);
529
530 /* We could get out of order messages after forced flush. */
531 if (oe->last_flush_type != OE_FLUSH__HALF)
532 return -EINVAL;
640 } 533 }
641 534
642 if (!list_empty(sc)) { 535 new = ordered_events__new(oe, timestamp);
643 new = list_entry(sc->next, struct sample_queue, list); 536 if (!new) {
644 list_del(&new->list); 537 ordered_events__flush(s, tool, OE_FLUSH__HALF);
645 } else if (os->sample_buffer) { 538 new = ordered_events__new(oe, timestamp);
646 new = os->sample_buffer + os->sample_buffer_idx;
647 if (++os->sample_buffer_idx == MAX_SAMPLE_BUFFER)
648 os->sample_buffer = NULL;
649 } else {
650 os->sample_buffer = malloc(MAX_SAMPLE_BUFFER * sizeof(*new));
651 if (!os->sample_buffer)
652 return -ENOMEM;
653 list_add(&os->sample_buffer->list, &os->to_free);
654 os->sample_buffer_idx = 2;
655 new = os->sample_buffer + 1;
656 } 539 }
657 540
658 new->timestamp = timestamp; 541 if (!new)
542 return -ENOMEM;
543
659 new->file_offset = file_offset; 544 new->file_offset = file_offset;
660 new->event = event; 545 new->event = event;
661
662 __queue_event(new, s);
663
664 return 0; 546 return 0;
665} 547}
666 548
@@ -920,11 +802,10 @@ perf_session__deliver_sample(struct perf_session *session,
920 &sample->read.one, machine); 802 &sample->read.one, machine);
921} 803}
922 804
923static int perf_session_deliver_event(struct perf_session *session, 805int perf_session__deliver_event(struct perf_session *session,
924 union perf_event *event, 806 union perf_event *event,
925 struct perf_sample *sample, 807 struct perf_sample *sample,
926 struct perf_tool *tool, 808 struct perf_tool *tool, u64 file_offset)
927 u64 file_offset)
928{ 809{
929 struct perf_evsel *evsel; 810 struct perf_evsel *evsel;
930 struct machine *machine; 811 struct machine *machine;
@@ -1005,8 +886,10 @@ static s64 perf_session__process_user_event(struct perf_session *session,
1005 switch (event->header.type) { 886 switch (event->header.type) {
1006 case PERF_RECORD_HEADER_ATTR: 887 case PERF_RECORD_HEADER_ATTR:
1007 err = tool->attr(tool, event, &session->evlist); 888 err = tool->attr(tool, event, &session->evlist);
1008 if (err == 0) 889 if (err == 0) {
1009 perf_session__set_id_hdr_size(session); 890 perf_session__set_id_hdr_size(session);
891 perf_session__set_comm_exec(session);
892 }
1010 return err; 893 return err;
1011 case PERF_RECORD_HEADER_EVENT_TYPE: 894 case PERF_RECORD_HEADER_EVENT_TYPE:
1012 /* 895 /*
@@ -1036,6 +919,61 @@ static void event_swap(union perf_event *event, bool sample_id_all)
1036 swap(event, sample_id_all); 919 swap(event, sample_id_all);
1037} 920}
1038 921
922int perf_session__peek_event(struct perf_session *session, off_t file_offset,
923 void *buf, size_t buf_sz,
924 union perf_event **event_ptr,
925 struct perf_sample *sample)
926{
927 union perf_event *event;
928 size_t hdr_sz, rest;
929 int fd;
930
931 if (session->one_mmap && !session->header.needs_swap) {
932 event = file_offset - session->one_mmap_offset +
933 session->one_mmap_addr;
934 goto out_parse_sample;
935 }
936
937 if (perf_data_file__is_pipe(session->file))
938 return -1;
939
940 fd = perf_data_file__fd(session->file);
941 hdr_sz = sizeof(struct perf_event_header);
942
943 if (buf_sz < hdr_sz)
944 return -1;
945
946 if (lseek(fd, file_offset, SEEK_SET) == (off_t)-1 ||
947 readn(fd, &buf, hdr_sz) != (ssize_t)hdr_sz)
948 return -1;
949
950 event = (union perf_event *)buf;
951
952 if (session->header.needs_swap)
953 perf_event_header__bswap(&event->header);
954
955 if (event->header.size < hdr_sz)
956 return -1;
957
958 rest = event->header.size - hdr_sz;
959
960 if (readn(fd, &buf, rest) != (ssize_t)rest)
961 return -1;
962
963 if (session->header.needs_swap)
964 event_swap(event, perf_evlist__sample_id_all(session->evlist));
965
966out_parse_sample:
967
968 if (sample && event->header.type < PERF_RECORD_USER_TYPE_START &&
969 perf_evlist__parse_sample(session->evlist, event, sample))
970 return -1;
971
972 *event_ptr = event;
973
974 return 0;
975}
976
1039static s64 perf_session__process_event(struct perf_session *session, 977static s64 perf_session__process_event(struct perf_session *session,
1040 union perf_event *event, 978 union perf_event *event,
1041 struct perf_tool *tool, 979 struct perf_tool *tool,
@@ -1062,15 +1000,15 @@ static s64 perf_session__process_event(struct perf_session *session,
1062 if (ret) 1000 if (ret)
1063 return ret; 1001 return ret;
1064 1002
1065 if (tool->ordered_samples) { 1003 if (tool->ordered_events) {
1066 ret = perf_session_queue_event(session, event, &sample, 1004 ret = perf_session_queue_event(session, event, tool, &sample,
1067 file_offset); 1005 file_offset);
1068 if (ret != -ETIME) 1006 if (ret != -ETIME)
1069 return ret; 1007 return ret;
1070 } 1008 }
1071 1009
1072 return perf_session_deliver_event(session, event, &sample, tool, 1010 return perf_session__deliver_event(session, event, &sample, tool,
1073 file_offset); 1011 file_offset);
1074} 1012}
1075 1013
1076void perf_event_header__bswap(struct perf_event_header *hdr) 1014void perf_event_header__bswap(struct perf_event_header *hdr)
@@ -1222,12 +1160,11 @@ more:
1222 goto more; 1160 goto more;
1223done: 1161done:
1224 /* do the final flush for ordered samples */ 1162 /* do the final flush for ordered samples */
1225 session->ordered_samples.next_flush = ULLONG_MAX; 1163 err = ordered_events__flush(session, tool, OE_FLUSH__FINAL);
1226 err = flush_sample_queue(session, tool);
1227out_err: 1164out_err:
1228 free(buf); 1165 free(buf);
1229 perf_session__warn_about_errors(session, tool); 1166 perf_session__warn_about_errors(session, tool);
1230 perf_session_free_sample_buffers(session); 1167 ordered_events__free(&session->ordered_events);
1231 return err; 1168 return err;
1232} 1169}
1233 1170
@@ -1368,12 +1305,11 @@ more:
1368 1305
1369out: 1306out:
1370 /* do the final flush for ordered samples */ 1307 /* do the final flush for ordered samples */
1371 session->ordered_samples.next_flush = ULLONG_MAX; 1308 err = ordered_events__flush(session, tool, OE_FLUSH__FINAL);
1372 err = flush_sample_queue(session, tool);
1373out_err: 1309out_err:
1374 ui_progress__finish(); 1310 ui_progress__finish();
1375 perf_session__warn_about_errors(session, tool); 1311 perf_session__warn_about_errors(session, tool);
1376 perf_session_free_sample_buffers(session); 1312 ordered_events__free(&session->ordered_events);
1377 session->one_mmap = false; 1313 session->one_mmap = false;
1378 return err; 1314 return err;
1379} 1315}
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 0321013bd9fd..ffb440462008 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -9,26 +9,13 @@
9#include "symbol.h" 9#include "symbol.h"
10#include "thread.h" 10#include "thread.h"
11#include "data.h" 11#include "data.h"
12#include "ordered-events.h"
12#include <linux/rbtree.h> 13#include <linux/rbtree.h>
13#include <linux/perf_event.h> 14#include <linux/perf_event.h>
14 15
15struct sample_queue;
16struct ip_callchain; 16struct ip_callchain;
17struct thread; 17struct thread;
18 18
19struct ordered_samples {
20 u64 last_flush;
21 u64 next_flush;
22 u64 max_timestamp;
23 struct list_head samples;
24 struct list_head sample_cache;
25 struct list_head to_free;
26 struct sample_queue *sample_buffer;
27 struct sample_queue *last_sample;
28 int sample_buffer_idx;
29 unsigned int nr_samples;
30};
31
32struct perf_session { 19struct perf_session {
33 struct perf_header header; 20 struct perf_header header;
34 struct machines machines; 21 struct machines machines;
@@ -39,7 +26,7 @@ struct perf_session {
39 bool one_mmap; 26 bool one_mmap;
40 void *one_mmap_addr; 27 void *one_mmap_addr;
41 u64 one_mmap_offset; 28 u64 one_mmap_offset;
42 struct ordered_samples ordered_samples; 29 struct ordered_events ordered_events;
43 struct perf_data_file *file; 30 struct perf_data_file *file;
44}; 31};
45 32
@@ -58,6 +45,11 @@ void perf_session__delete(struct perf_session *session);
58 45
59void perf_event_header__bswap(struct perf_event_header *hdr); 46void perf_event_header__bswap(struct perf_event_header *hdr);
60 47
48int perf_session__peek_event(struct perf_session *session, off_t file_offset,
49 void *buf, size_t buf_sz,
50 union perf_event **event_ptr,
51 struct perf_sample *sample);
52
61int __perf_session__process_events(struct perf_session *session, 53int __perf_session__process_events(struct perf_session *session,
62 u64 data_offset, u64 data_size, u64 size, 54 u64 data_offset, u64 data_size, u64 size,
63 struct perf_tool *tool); 55 struct perf_tool *tool);
@@ -65,10 +57,16 @@ int perf_session__process_events(struct perf_session *session,
65 struct perf_tool *tool); 57 struct perf_tool *tool);
66 58
67int perf_session_queue_event(struct perf_session *s, union perf_event *event, 59int perf_session_queue_event(struct perf_session *s, union perf_event *event,
68 struct perf_sample *sample, u64 file_offset); 60 struct perf_tool *tool, struct perf_sample *sample,
61 u64 file_offset);
69 62
70void perf_tool__fill_defaults(struct perf_tool *tool); 63void perf_tool__fill_defaults(struct perf_tool *tool);
71 64
65int perf_session__deliver_event(struct perf_session *session,
66 union perf_event *event,
67 struct perf_sample *sample,
68 struct perf_tool *tool, u64 file_offset);
69
72int perf_session__resolve_callchain(struct perf_session *session, 70int perf_session__resolve_callchain(struct perf_session *session,
73 struct perf_evsel *evsel, 71 struct perf_evsel *evsel,
74 struct thread *thread, 72 struct thread *thread,
@@ -128,5 +126,5 @@ int __perf_session__set_tracepoints_handlers(struct perf_session *session,
128 126
129extern volatile int session_done; 127extern volatile int session_done;
130 128
131#define session_done() (*(volatile int *)(&session_done)) 129#define session_done() ACCESS_ONCE(session_done)
132#endif /* __PERF_SESSION_H */ 130#endif /* __PERF_SESSION_H */
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 14e5a039bc45..289df9d1e65a 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -70,12 +70,14 @@ static int hist_entry__thread_snprintf(struct hist_entry *he, char *bf,
70 size_t size, unsigned int width) 70 size_t size, unsigned int width)
71{ 71{
72 const char *comm = thread__comm_str(he->thread); 72 const char *comm = thread__comm_str(he->thread);
73 return repsep_snprintf(bf, size, "%*s:%5d", width - 6, 73
74 comm ?: "", he->thread->tid); 74 width = max(7U, width) - 6;
75 return repsep_snprintf(bf, size, "%5d:%-*.*s", he->thread->tid,
76 width, width, comm ?: "");
75} 77}
76 78
77struct sort_entry sort_thread = { 79struct sort_entry sort_thread = {
78 .se_header = "Command: Pid", 80 .se_header = " Pid:Command",
79 .se_cmp = sort__thread_cmp, 81 .se_cmp = sort__thread_cmp,
80 .se_snprintf = hist_entry__thread_snprintf, 82 .se_snprintf = hist_entry__thread_snprintf,
81 .se_width_idx = HISTC_THREAD, 83 .se_width_idx = HISTC_THREAD,
@@ -106,7 +108,7 @@ sort__comm_sort(struct hist_entry *left, struct hist_entry *right)
106static int hist_entry__comm_snprintf(struct hist_entry *he, char *bf, 108static int hist_entry__comm_snprintf(struct hist_entry *he, char *bf,
107 size_t size, unsigned int width) 109 size_t size, unsigned int width)
108{ 110{
109 return repsep_snprintf(bf, size, "%*s", width, comm__str(he->comm)); 111 return repsep_snprintf(bf, size, "%-*.*s", width, width, comm__str(he->comm));
110} 112}
111 113
112struct sort_entry sort_comm = { 114struct sort_entry sort_comm = {
@@ -152,10 +154,10 @@ static int _hist_entry__dso_snprintf(struct map *map, char *bf,
152 if (map && map->dso) { 154 if (map && map->dso) {
153 const char *dso_name = !verbose ? map->dso->short_name : 155 const char *dso_name = !verbose ? map->dso->short_name :
154 map->dso->long_name; 156 map->dso->long_name;
155 return repsep_snprintf(bf, size, "%-*s", width, dso_name); 157 return repsep_snprintf(bf, size, "%-*.*s", width, width, dso_name);
156 } 158 }
157 159
158 return repsep_snprintf(bf, size, "%-*s", width, "[unknown]"); 160 return repsep_snprintf(bf, size, "%-*.*s", width, width, "[unknown]");
159} 161}
160 162
161static int hist_entry__dso_snprintf(struct hist_entry *he, char *bf, 163static int hist_entry__dso_snprintf(struct hist_entry *he, char *bf,
@@ -257,7 +259,10 @@ static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym,
257 width - ret, ""); 259 width - ret, "");
258 } 260 }
259 261
260 return ret; 262 if (ret > width)
263 bf[width] = '\0';
264
265 return width;
261} 266}
262 267
263static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf, 268static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf,
@@ -302,10 +307,9 @@ sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
302} 307}
303 308
304static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf, 309static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf,
305 size_t size, 310 size_t size, unsigned int width)
306 unsigned int width __maybe_unused)
307{ 311{
308 return repsep_snprintf(bf, size, "%s", he->srcline); 312 return repsep_snprintf(bf, size, "%*.*-s", width, width, he->srcline);
309} 313}
310 314
311struct sort_entry sort_srcline = { 315struct sort_entry sort_srcline = {
@@ -332,7 +336,7 @@ sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
332static int hist_entry__parent_snprintf(struct hist_entry *he, char *bf, 336static int hist_entry__parent_snprintf(struct hist_entry *he, char *bf,
333 size_t size, unsigned int width) 337 size_t size, unsigned int width)
334{ 338{
335 return repsep_snprintf(bf, size, "%-*s", width, 339 return repsep_snprintf(bf, size, "%-*.*s", width, width,
336 he->parent ? he->parent->name : "[other]"); 340 he->parent ? he->parent->name : "[other]");
337} 341}
338 342
@@ -354,7 +358,7 @@ sort__cpu_cmp(struct hist_entry *left, struct hist_entry *right)
354static int hist_entry__cpu_snprintf(struct hist_entry *he, char *bf, 358static int hist_entry__cpu_snprintf(struct hist_entry *he, char *bf,
355 size_t size, unsigned int width) 359 size_t size, unsigned int width)
356{ 360{
357 return repsep_snprintf(bf, size, "%*d", width, he->cpu); 361 return repsep_snprintf(bf, size, "%*.*d", width, width, he->cpu);
358} 362}
359 363
360struct sort_entry sort_cpu = { 364struct sort_entry sort_cpu = {
@@ -484,7 +488,7 @@ static int hist_entry__mispredict_snprintf(struct hist_entry *he, char *bf,
484 else if (he->branch_info->flags.mispred) 488 else if (he->branch_info->flags.mispred)
485 out = "Y"; 489 out = "Y";
486 490
487 return repsep_snprintf(bf, size, "%-*s", width, out); 491 return repsep_snprintf(bf, size, "%-*.*s", width, width, out);
488} 492}
489 493
490/* --sort daddr_sym */ 494/* --sort daddr_sym */
@@ -1194,7 +1198,7 @@ bool perf_hpp__same_sort_entry(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b)
1194 return hse_a->se == hse_b->se; 1198 return hse_a->se == hse_b->se;
1195} 1199}
1196 1200
1197void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists) 1201void perf_hpp__reset_sort_width(struct perf_hpp_fmt *fmt, struct hists *hists)
1198{ 1202{
1199 struct hpp_sort_entry *hse; 1203 struct hpp_sort_entry *hse;
1200 1204
@@ -1202,20 +1206,21 @@ void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists)
1202 return; 1206 return;
1203 1207
1204 hse = container_of(fmt, struct hpp_sort_entry, hpp); 1208 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1205 hists__new_col_len(hists, hse->se->se_width_idx, 1209 hists__new_col_len(hists, hse->se->se_width_idx, strlen(fmt->name));
1206 strlen(hse->se->se_header));
1207} 1210}
1208 1211
1209static int __sort__hpp_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 1212static int __sort__hpp_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1210 struct perf_evsel *evsel) 1213 struct perf_evsel *evsel)
1211{ 1214{
1212 struct hpp_sort_entry *hse; 1215 struct hpp_sort_entry *hse;
1213 size_t len; 1216 size_t len = fmt->user_len;
1214 1217
1215 hse = container_of(fmt, struct hpp_sort_entry, hpp); 1218 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1216 len = hists__col_len(&evsel->hists, hse->se->se_width_idx);
1217 1219
1218 return scnprintf(hpp->buf, hpp->size, "%-*s", len, hse->se->se_header); 1220 if (!len)
1221 len = hists__col_len(&evsel->hists, hse->se->se_width_idx);
1222
1223 return scnprintf(hpp->buf, hpp->size, "%-*.*s", len, len, fmt->name);
1219} 1224}
1220 1225
1221static int __sort__hpp_width(struct perf_hpp_fmt *fmt, 1226static int __sort__hpp_width(struct perf_hpp_fmt *fmt,
@@ -1223,20 +1228,26 @@ static int __sort__hpp_width(struct perf_hpp_fmt *fmt,
1223 struct perf_evsel *evsel) 1228 struct perf_evsel *evsel)
1224{ 1229{
1225 struct hpp_sort_entry *hse; 1230 struct hpp_sort_entry *hse;
1231 size_t len = fmt->user_len;
1226 1232
1227 hse = container_of(fmt, struct hpp_sort_entry, hpp); 1233 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1228 1234
1229 return hists__col_len(&evsel->hists, hse->se->se_width_idx); 1235 if (!len)
1236 len = hists__col_len(&evsel->hists, hse->se->se_width_idx);
1237
1238 return len;
1230} 1239}
1231 1240
1232static int __sort__hpp_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 1241static int __sort__hpp_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1233 struct hist_entry *he) 1242 struct hist_entry *he)
1234{ 1243{
1235 struct hpp_sort_entry *hse; 1244 struct hpp_sort_entry *hse;
1236 size_t len; 1245 size_t len = fmt->user_len;
1237 1246
1238 hse = container_of(fmt, struct hpp_sort_entry, hpp); 1247 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1239 len = hists__col_len(he->hists, hse->se->se_width_idx); 1248
1249 if (!len)
1250 len = hists__col_len(he->hists, hse->se->se_width_idx);
1240 1251
1241 return hse->se->se_snprintf(he, hpp->buf, hpp->size, len); 1252 return hse->se->se_snprintf(he, hpp->buf, hpp->size, len);
1242} 1253}
@@ -1253,6 +1264,7 @@ __sort_dimension__alloc_hpp(struct sort_dimension *sd)
1253 } 1264 }
1254 1265
1255 hse->se = sd->entry; 1266 hse->se = sd->entry;
1267 hse->hpp.name = sd->entry->se_header;
1256 hse->hpp.header = __sort__hpp_header; 1268 hse->hpp.header = __sort__hpp_header;
1257 hse->hpp.width = __sort__hpp_width; 1269 hse->hpp.width = __sort__hpp_width;
1258 hse->hpp.entry = __sort__hpp_entry; 1270 hse->hpp.entry = __sort__hpp_entry;
@@ -1265,6 +1277,8 @@ __sort_dimension__alloc_hpp(struct sort_dimension *sd)
1265 INIT_LIST_HEAD(&hse->hpp.list); 1277 INIT_LIST_HEAD(&hse->hpp.list);
1266 INIT_LIST_HEAD(&hse->hpp.sort_list); 1278 INIT_LIST_HEAD(&hse->hpp.sort_list);
1267 hse->hpp.elide = false; 1279 hse->hpp.elide = false;
1280 hse->hpp.len = 0;
1281 hse->hpp.user_len = 0;
1268 1282
1269 return hse; 1283 return hse;
1270} 1284}
@@ -1432,14 +1446,49 @@ static const char *get_default_sort_order(void)
1432 return default_sort_orders[sort__mode]; 1446 return default_sort_orders[sort__mode];
1433} 1447}
1434 1448
1449static int setup_sort_order(void)
1450{
1451 char *new_sort_order;
1452
1453 /*
1454 * Append '+'-prefixed sort order to the default sort
1455 * order string.
1456 */
1457 if (!sort_order || is_strict_order(sort_order))
1458 return 0;
1459
1460 if (sort_order[1] == '\0') {
1461 error("Invalid --sort key: `+'");
1462 return -EINVAL;
1463 }
1464
1465 /*
1466 * We allocate new sort_order string, but we never free it,
1467 * because it's checked over the rest of the code.
1468 */
1469 if (asprintf(&new_sort_order, "%s,%s",
1470 get_default_sort_order(), sort_order + 1) < 0) {
1471 error("Not enough memory to set up --sort");
1472 return -ENOMEM;
1473 }
1474
1475 sort_order = new_sort_order;
1476 return 0;
1477}
1478
1435static int __setup_sorting(void) 1479static int __setup_sorting(void)
1436{ 1480{
1437 char *tmp, *tok, *str; 1481 char *tmp, *tok, *str;
1438 const char *sort_keys = sort_order; 1482 const char *sort_keys;
1439 int ret = 0; 1483 int ret = 0;
1440 1484
1485 ret = setup_sort_order();
1486 if (ret)
1487 return ret;
1488
1489 sort_keys = sort_order;
1441 if (sort_keys == NULL) { 1490 if (sort_keys == NULL) {
1442 if (field_order) { 1491 if (is_strict_order(field_order)) {
1443 /* 1492 /*
1444 * If user specified field order but no sort order, 1493 * If user specified field order but no sort order,
1445 * we'll honor it and not add default sort orders. 1494 * we'll honor it and not add default sort orders.
@@ -1625,23 +1674,36 @@ static void reset_dimensions(void)
1625 memory_sort_dimensions[i].taken = 0; 1674 memory_sort_dimensions[i].taken = 0;
1626} 1675}
1627 1676
1677bool is_strict_order(const char *order)
1678{
1679 return order && (*order != '+');
1680}
1681
1628static int __setup_output_field(void) 1682static int __setup_output_field(void)
1629{ 1683{
1630 char *tmp, *tok, *str; 1684 char *tmp, *tok, *str, *strp;
1631 int ret = 0; 1685 int ret = -EINVAL;
1632 1686
1633 if (field_order == NULL) 1687 if (field_order == NULL)
1634 return 0; 1688 return 0;
1635 1689
1636 reset_dimensions(); 1690 reset_dimensions();
1637 1691
1638 str = strdup(field_order); 1692 strp = str = strdup(field_order);
1639 if (str == NULL) { 1693 if (str == NULL) {
1640 error("Not enough memory to setup output fields"); 1694 error("Not enough memory to setup output fields");
1641 return -ENOMEM; 1695 return -ENOMEM;
1642 } 1696 }
1643 1697
1644 for (tok = strtok_r(str, ", ", &tmp); 1698 if (!is_strict_order(field_order))
1699 strp++;
1700
1701 if (!strlen(strp)) {
1702 error("Invalid --fields key: `+'");
1703 goto out;
1704 }
1705
1706 for (tok = strtok_r(strp, ", ", &tmp);
1645 tok; tok = strtok_r(NULL, ", ", &tmp)) { 1707 tok; tok = strtok_r(NULL, ", ", &tmp)) {
1646 ret = output_field_add(tok); 1708 ret = output_field_add(tok);
1647 if (ret == -EINVAL) { 1709 if (ret == -EINVAL) {
@@ -1653,6 +1715,7 @@ static int __setup_output_field(void)
1653 } 1715 }
1654 } 1716 }
1655 1717
1718out:
1656 free(str); 1719 free(str);
1657 return ret; 1720 return ret;
1658} 1721}
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 041f0c9cea2b..c03e4ff8beff 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -218,4 +218,5 @@ void perf_hpp__set_elide(int idx, bool elide);
218 218
219int report_parse_ignore_callees_opt(const struct option *opt, const char *arg, int unset); 219int report_parse_ignore_callees_opt(const struct option *opt, const char *arg, int unset);
220 220
221bool is_strict_order(const char *order);
221#endif /* __PERF_SORT_H */ 222#endif /* __PERF_SORT_H */
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index 2553e5b55b89..d87767f76903 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -9,78 +9,48 @@
9 */ 9 */
10s64 perf_atoll(const char *str) 10s64 perf_atoll(const char *str)
11{ 11{
12 unsigned int i; 12 s64 length;
13 s64 length = -1, unit = 1; 13 char *p;
14 char c;
14 15
15 if (!isdigit(str[0])) 16 if (!isdigit(str[0]))
16 goto out_err; 17 goto out_err;
17 18
18 for (i = 1; i < strlen(str); i++) { 19 length = strtoll(str, &p, 10);
19 switch (str[i]) { 20 switch (c = *p++) {
20 case 'B': 21 case 'b': case 'B':
21 case 'b': 22 if (*p)
22 break;
23 case 'K':
24 if (str[i + 1] != 'B')
25 goto out_err;
26 else
27 goto kilo;
28 case 'k':
29 if (str[i + 1] != 'b')
30 goto out_err;
31kilo:
32 unit = K;
33 break;
34 case 'M':
35 if (str[i + 1] != 'B')
36 goto out_err;
37 else
38 goto mega;
39 case 'm':
40 if (str[i + 1] != 'b')
41 goto out_err; 23 goto out_err;
42mega: 24 case '\0':
43 unit = K * K; 25 return length;
26 default:
27 goto out_err;
28 /* two-letter suffices */
29 case 'k': case 'K':
30 length <<= 10;
44 break; 31 break;
45 case 'G': 32 case 'm': case 'M':
46 if (str[i + 1] != 'B') 33 length <<= 20;
47 goto out_err;
48 else
49 goto giga;
50 case 'g':
51 if (str[i + 1] != 'b')
52 goto out_err;
53giga:
54 unit = K * K * K;
55 break; 34 break;
56 case 'T': 35 case 'g': case 'G':
57 if (str[i + 1] != 'B') 36 length <<= 30;
58 goto out_err;
59 else
60 goto tera;
61 case 't':
62 if (str[i + 1] != 'b')
63 goto out_err;
64tera:
65 unit = K * K * K * K;
66 break; 37 break;
67 case '\0': /* only specified figures */ 38 case 't': case 'T':
68 unit = 1; 39 length <<= 40;
69 break; 40 break;
70 default:
71 if (!isdigit(str[i]))
72 goto out_err;
73 break;
74 }
75 } 41 }
76 42 /* we want the cases to match */
77 length = atoll(str) * unit; 43 if (islower(c)) {
78 goto out; 44 if (strcmp(p, "b") != 0)
45 goto out_err;
46 } else {
47 if (strcmp(p, "B") != 0)
48 goto out_err;
49 }
50 return length;
79 51
80out_err: 52out_err:
81 length = -1; 53 return -1;
82out:
83 return length;
84} 54}
85 55
86/* 56/*
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index d75349979e65..1e23a5bfb044 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -6,6 +6,7 @@
6#include <inttypes.h> 6#include <inttypes.h>
7 7
8#include "symbol.h" 8#include "symbol.h"
9#include "machine.h"
9#include "vdso.h" 10#include "vdso.h"
10#include <symbol/kallsyms.h> 11#include <symbol/kallsyms.h>
11#include "debug.h" 12#include "debug.h"
@@ -680,6 +681,11 @@ static u64 ref_reloc(struct kmap *kmap)
680 return 0; 681 return 0;
681} 682}
682 683
684static bool want_demangle(bool is_kernel_sym)
685{
686 return is_kernel_sym ? symbol_conf.demangle_kernel : symbol_conf.demangle;
687}
688
683int dso__load_sym(struct dso *dso, struct map *map, 689int dso__load_sym(struct dso *dso, struct map *map,
684 struct symsrc *syms_ss, struct symsrc *runtime_ss, 690 struct symsrc *syms_ss, struct symsrc *runtime_ss,
685 symbol_filter_t filter, int kmodule) 691 symbol_filter_t filter, int kmodule)
@@ -712,6 +718,14 @@ int dso__load_sym(struct dso *dso, struct map *map,
712 symbols__delete(&dso->symbols[map->type]); 718 symbols__delete(&dso->symbols[map->type]);
713 719
714 if (!syms_ss->symtab) { 720 if (!syms_ss->symtab) {
721 /*
722 * If the vmlinux is stripped, fail so we will fall back
723 * to using kallsyms. The vmlinux runtime symbols aren't
724 * of much use.
725 */
726 if (dso->kernel)
727 goto out_elf_end;
728
715 syms_ss->symtab = syms_ss->dynsym; 729 syms_ss->symtab = syms_ss->dynsym;
716 syms_ss->symshdr = syms_ss->dynshdr; 730 syms_ss->symshdr = syms_ss->dynshdr;
717 } 731 }
@@ -736,7 +750,7 @@ int dso__load_sym(struct dso *dso, struct map *map,
736 if (symstrs == NULL) 750 if (symstrs == NULL)
737 goto out_elf_end; 751 goto out_elf_end;
738 752
739 sec_strndx = elf_getscn(elf, ehdr.e_shstrndx); 753 sec_strndx = elf_getscn(runtime_ss->elf, runtime_ss->ehdr.e_shstrndx);
740 if (sec_strndx == NULL) 754 if (sec_strndx == NULL)
741 goto out_elf_end; 755 goto out_elf_end;
742 756
@@ -916,7 +930,11 @@ int dso__load_sym(struct dso *dso, struct map *map,
916 } 930 }
917 curr_dso->symtab_type = dso->symtab_type; 931 curr_dso->symtab_type = dso->symtab_type;
918 map_groups__insert(kmap->kmaps, curr_map); 932 map_groups__insert(kmap->kmaps, curr_map);
919 dsos__add(&dso->node, curr_dso); 933 /*
934 * The new DSO should go to the kernel DSOS
935 */
936 dsos__add(&map->groups->machine->kernel_dsos,
937 curr_dso);
920 dso__set_loaded(curr_dso, map->type); 938 dso__set_loaded(curr_dso, map->type);
921 } else 939 } else
922 curr_dso = curr_map->dso; 940 curr_dso = curr_map->dso;
@@ -938,9 +956,12 @@ new_symbol:
938 * DWARF DW_compile_unit has this, but we don't always have access 956 * DWARF DW_compile_unit has this, but we don't always have access
939 * to it... 957 * to it...
940 */ 958 */
941 if (symbol_conf.demangle) { 959 if (want_demangle(dso->kernel || kmodule)) {
942 demangled = bfd_demangle(NULL, elf_name, 960 int demangle_flags = DMGL_NO_OPTS;
943 DMGL_PARAMS | DMGL_ANSI); 961 if (verbose)
962 demangle_flags = DMGL_PARAMS | DMGL_ANSI;
963
964 demangled = bfd_demangle(NULL, elf_name, demangle_flags);
944 if (demangled != NULL) 965 if (demangled != NULL)
945 elf_name = demangled; 966 elf_name = demangled;
946 } 967 }
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index eb06746b06b2..be84f7a9838b 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -15,6 +15,7 @@
15#include "machine.h" 15#include "machine.h"
16#include "symbol.h" 16#include "symbol.h"
17#include "strlist.h" 17#include "strlist.h"
18#include "header.h"
18 19
19#include <elf.h> 20#include <elf.h>
20#include <limits.h> 21#include <limits.h>
@@ -33,6 +34,7 @@ struct symbol_conf symbol_conf = {
33 .try_vmlinux_path = true, 34 .try_vmlinux_path = true,
34 .annotate_src = true, 35 .annotate_src = true,
35 .demangle = true, 36 .demangle = true,
37 .demangle_kernel = false,
36 .cumulate_callchain = true, 38 .cumulate_callchain = true,
37 .show_hist_headers = true, 39 .show_hist_headers = true,
38 .symfs = "", 40 .symfs = "",
@@ -523,10 +525,15 @@ struct process_kallsyms_args {
523 struct dso *dso; 525 struct dso *dso;
524}; 526};
525 527
528/*
529 * These are symbols in the kernel image, so make sure that
530 * sym is from a kernel DSO.
531 */
526bool symbol__is_idle(struct symbol *sym) 532bool symbol__is_idle(struct symbol *sym)
527{ 533{
528 const char * const idle_symbols[] = { 534 const char * const idle_symbols[] = {
529 "cpu_idle", 535 "cpu_idle",
536 "cpu_startup_entry",
530 "intel_idle", 537 "intel_idle",
531 "default_idle", 538 "default_idle",
532 "native_safe_halt", 539 "native_safe_halt",
@@ -1468,8 +1475,7 @@ int dso__load_vmlinux(struct dso *dso, struct map *map,
1468 if (vmlinux[0] == '/') 1475 if (vmlinux[0] == '/')
1469 snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s", vmlinux); 1476 snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s", vmlinux);
1470 else 1477 else
1471 snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s%s", 1478 symbol__join_symfs(symfs_vmlinux, vmlinux);
1472 symbol_conf.symfs, vmlinux);
1473 1479
1474 if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 1480 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
1475 symtab_type = DSO_BINARY_TYPE__GUEST_VMLINUX; 1481 symtab_type = DSO_BINARY_TYPE__GUEST_VMLINUX;
@@ -1745,12 +1751,13 @@ static void vmlinux_path__exit(void)
1745 zfree(&vmlinux_path); 1751 zfree(&vmlinux_path);
1746} 1752}
1747 1753
1748static int vmlinux_path__init(void) 1754static int vmlinux_path__init(struct perf_session_env *env)
1749{ 1755{
1750 struct utsname uts; 1756 struct utsname uts;
1751 char bf[PATH_MAX]; 1757 char bf[PATH_MAX];
1758 char *kernel_version;
1752 1759
1753 vmlinux_path = malloc(sizeof(char *) * 5); 1760 vmlinux_path = malloc(sizeof(char *) * 6);
1754 if (vmlinux_path == NULL) 1761 if (vmlinux_path == NULL)
1755 return -1; 1762 return -1;
1756 1763
@@ -1763,25 +1770,37 @@ static int vmlinux_path__init(void)
1763 goto out_fail; 1770 goto out_fail;
1764 ++vmlinux_path__nr_entries; 1771 ++vmlinux_path__nr_entries;
1765 1772
1766 /* only try running kernel version if no symfs was given */ 1773 /* only try kernel version if no symfs was given */
1767 if (symbol_conf.symfs[0] != 0) 1774 if (symbol_conf.symfs[0] != 0)
1768 return 0; 1775 return 0;
1769 1776
1770 if (uname(&uts) < 0) 1777 if (env) {
1771 return -1; 1778 kernel_version = env->os_release;
1779 } else {
1780 if (uname(&uts) < 0)
1781 goto out_fail;
1772 1782
1773 snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", uts.release); 1783 kernel_version = uts.release;
1784 }
1785
1786 snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", kernel_version);
1774 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); 1787 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1775 if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 1788 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1776 goto out_fail; 1789 goto out_fail;
1777 ++vmlinux_path__nr_entries; 1790 ++vmlinux_path__nr_entries;
1778 snprintf(bf, sizeof(bf), "/lib/modules/%s/build/vmlinux", uts.release); 1791 snprintf(bf, sizeof(bf), "/usr/lib/debug/boot/vmlinux-%s",
1792 kernel_version);
1793 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1794 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1795 goto out_fail;
1796 ++vmlinux_path__nr_entries;
1797 snprintf(bf, sizeof(bf), "/lib/modules/%s/build/vmlinux", kernel_version);
1779 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); 1798 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1780 if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 1799 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1781 goto out_fail; 1800 goto out_fail;
1782 ++vmlinux_path__nr_entries; 1801 ++vmlinux_path__nr_entries;
1783 snprintf(bf, sizeof(bf), "/usr/lib/debug/lib/modules/%s/vmlinux", 1802 snprintf(bf, sizeof(bf), "/usr/lib/debug/lib/modules/%s/vmlinux",
1784 uts.release); 1803 kernel_version);
1785 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); 1804 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1786 if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 1805 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1787 goto out_fail; 1806 goto out_fail;
@@ -1827,7 +1846,7 @@ static bool symbol__read_kptr_restrict(void)
1827 return value; 1846 return value;
1828} 1847}
1829 1848
1830int symbol__init(void) 1849int symbol__init(struct perf_session_env *env)
1831{ 1850{
1832 const char *symfs; 1851 const char *symfs;
1833 1852
@@ -1842,7 +1861,7 @@ int symbol__init(void)
1842 symbol_conf.priv_size += (sizeof(struct symbol_name_rb_node) - 1861 symbol_conf.priv_size += (sizeof(struct symbol_name_rb_node) -
1843 sizeof(struct symbol)); 1862 sizeof(struct symbol));
1844 1863
1845 if (symbol_conf.try_vmlinux_path && vmlinux_path__init() < 0) 1864 if (symbol_conf.try_vmlinux_path && vmlinux_path__init(env) < 0)
1846 return -1; 1865 return -1;
1847 1866
1848 if (symbol_conf.field_sep && *symbol_conf.field_sep == '.') { 1867 if (symbol_conf.field_sep && *symbol_conf.field_sep == '.') {
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index e7295e93cff9..bec4b7bd09de 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -13,6 +13,7 @@
13#include <libgen.h> 13#include <libgen.h>
14#include "build-id.h" 14#include "build-id.h"
15#include "event.h" 15#include "event.h"
16#include "util.h"
16 17
17#ifdef HAVE_LIBELF_SUPPORT 18#ifdef HAVE_LIBELF_SUPPORT
18#include <libelf.h> 19#include <libelf.h>
@@ -59,6 +60,7 @@ extern Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
59#endif 60#endif
60 61
61#ifndef DMGL_PARAMS 62#ifndef DMGL_PARAMS
63#define DMGL_NO_OPTS 0 /* For readability... */
62#define DMGL_PARAMS (1 << 0) /* Include function args */ 64#define DMGL_PARAMS (1 << 0) /* Include function args */
63#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ 65#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */
64#endif 66#endif
@@ -118,6 +120,7 @@ struct symbol_conf {
118 annotate_src, 120 annotate_src,
119 event_group, 121 event_group,
120 demangle, 122 demangle,
123 demangle_kernel,
121 filter_relative, 124 filter_relative,
122 show_hist_headers; 125 show_hist_headers;
123 const char *vmlinux_name, 126 const char *vmlinux_name,
@@ -143,6 +146,14 @@ struct symbol_conf {
143}; 146};
144 147
145extern struct symbol_conf symbol_conf; 148extern struct symbol_conf symbol_conf;
149
150static inline int __symbol__join_symfs(char *bf, size_t size, const char *path)
151{
152 return path__join(bf, size, symbol_conf.symfs, path);
153}
154
155#define symbol__join_symfs(bf, path) __symbol__join_symfs(bf, sizeof(bf), path)
156
146extern int vmlinux_path__nr_entries; 157extern int vmlinux_path__nr_entries;
147extern char **vmlinux_path; 158extern char **vmlinux_path;
148 159
@@ -253,7 +264,8 @@ int modules__parse(const char *filename, void *arg,
253int filename__read_debuglink(const char *filename, char *debuglink, 264int filename__read_debuglink(const char *filename, char *debuglink,
254 size_t size); 265 size_t size);
255 266
256int symbol__init(void); 267struct perf_session_env;
268int symbol__init(struct perf_session_env *env);
257void symbol__exit(void); 269void symbol__exit(void);
258void symbol__elf_init(void); 270void symbol__elf_init(void);
259struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name); 271struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name);
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 12c7a253a63c..a9df7f2c6dc9 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -42,7 +42,7 @@ struct thread *thread__new(pid_t pid, pid_t tid)
42 goto err_thread; 42 goto err_thread;
43 43
44 snprintf(comm_str, 32, ":%d", tid); 44 snprintf(comm_str, 32, ":%d", tid);
45 comm = comm__new(comm_str, 0); 45 comm = comm__new(comm_str, 0, false);
46 free(comm_str); 46 free(comm_str);
47 if (!comm) 47 if (!comm)
48 goto err_thread; 48 goto err_thread;
@@ -81,19 +81,33 @@ struct comm *thread__comm(const struct thread *thread)
81 return list_first_entry(&thread->comm_list, struct comm, list); 81 return list_first_entry(&thread->comm_list, struct comm, list);
82} 82}
83 83
84struct comm *thread__exec_comm(const struct thread *thread)
85{
86 struct comm *comm, *last = NULL;
87
88 list_for_each_entry(comm, &thread->comm_list, list) {
89 if (comm->exec)
90 return comm;
91 last = comm;
92 }
93
94 return last;
95}
96
84/* CHECKME: time should always be 0 if event aren't ordered */ 97/* CHECKME: time should always be 0 if event aren't ordered */
85int thread__set_comm(struct thread *thread, const char *str, u64 timestamp) 98int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp,
99 bool exec)
86{ 100{
87 struct comm *new, *curr = thread__comm(thread); 101 struct comm *new, *curr = thread__comm(thread);
88 int err; 102 int err;
89 103
90 /* Override latest entry if it had no specific time coverage */ 104 /* Override latest entry if it had no specific time coverage */
91 if (!curr->start) { 105 if (!curr->start && !curr->exec) {
92 err = comm__override(curr, str, timestamp); 106 err = comm__override(curr, str, timestamp, exec);
93 if (err) 107 if (err)
94 return err; 108 return err;
95 } else { 109 } else {
96 new = comm__new(str, timestamp); 110 new = comm__new(str, timestamp, exec);
97 if (!new) 111 if (!new)
98 return -ENOMEM; 112 return -ENOMEM;
99 list_add(&new->list, &thread->comm_list); 113 list_add(&new->list, &thread->comm_list);
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 716b7723cce2..8c75fa774706 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -38,9 +38,17 @@ static inline void thread__exited(struct thread *thread)
38 thread->dead = true; 38 thread->dead = true;
39} 39}
40 40
41int thread__set_comm(struct thread *thread, const char *comm, u64 timestamp); 41int __thread__set_comm(struct thread *thread, const char *comm, u64 timestamp,
42 bool exec);
43static inline int thread__set_comm(struct thread *thread, const char *comm,
44 u64 timestamp)
45{
46 return __thread__set_comm(thread, comm, timestamp, false);
47}
48
42int thread__comm_len(struct thread *thread); 49int thread__comm_len(struct thread *thread);
43struct comm *thread__comm(const struct thread *thread); 50struct comm *thread__comm(const struct thread *thread);
51struct comm *thread__exec_comm(const struct thread *thread);
44const char *thread__comm_str(const struct thread *thread); 52const char *thread__comm_str(const struct thread *thread);
45void thread__insert_map(struct thread *thread, struct map *map); 53void thread__insert_map(struct thread *thread, struct map *map);
46int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp); 54int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp);
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index 4385816d3d49..f11636966a0f 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -40,7 +40,7 @@ struct perf_tool {
40 event_op2 tracing_data; 40 event_op2 tracing_data;
41 event_op2 finished_round, 41 event_op2 finished_round,
42 build_id; 42 build_id;
43 bool ordered_samples; 43 bool ordered_events;
44 bool ordering_requires_timestamps; 44 bool ordering_requires_timestamps;
45}; 45};
46 46
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
index 57aaccc1692e..5c9bdd1591a9 100644
--- a/tools/perf/util/trace-event-scripting.c
+++ b/tools/perf/util/trace-event-scripting.c
@@ -30,6 +30,11 @@
30 30
31struct scripting_context *scripting_context; 31struct scripting_context *scripting_context;
32 32
33static int flush_script_unsupported(void)
34{
35 return 0;
36}
37
33static int stop_script_unsupported(void) 38static int stop_script_unsupported(void)
34{ 39{
35 return 0; 40 return 0;
@@ -74,6 +79,7 @@ static int python_generate_script_unsupported(struct pevent *pevent
74struct scripting_ops python_scripting_unsupported_ops = { 79struct scripting_ops python_scripting_unsupported_ops = {
75 .name = "Python", 80 .name = "Python",
76 .start_script = python_start_script_unsupported, 81 .start_script = python_start_script_unsupported,
82 .flush_script = flush_script_unsupported,
77 .stop_script = stop_script_unsupported, 83 .stop_script = stop_script_unsupported,
78 .process_event = process_event_unsupported, 84 .process_event = process_event_unsupported,
79 .generate_script = python_generate_script_unsupported, 85 .generate_script = python_generate_script_unsupported,
@@ -137,6 +143,7 @@ static int perl_generate_script_unsupported(struct pevent *pevent
137struct scripting_ops perl_scripting_unsupported_ops = { 143struct scripting_ops perl_scripting_unsupported_ops = {
138 .name = "Perl", 144 .name = "Perl",
139 .start_script = perl_start_script_unsupported, 145 .start_script = perl_start_script_unsupported,
146 .flush_script = flush_script_unsupported,
140 .stop_script = stop_script_unsupported, 147 .stop_script = stop_script_unsupported,
141 .process_event = process_event_unsupported, 148 .process_event = process_event_unsupported,
142 .generate_script = perl_generate_script_unsupported, 149 .generate_script = perl_generate_script_unsupported,
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index 7b6d68688327..52aaa19e1eb1 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -64,6 +64,7 @@ struct perf_session;
64struct scripting_ops { 64struct scripting_ops {
65 const char *name; 65 const char *name;
66 int (*start_script) (const char *script, int argc, const char **argv); 66 int (*start_script) (const char *script, int argc, const char **argv);
67 int (*flush_script) (void);
67 int (*stop_script) (void); 68 int (*stop_script) (void);
68 void (*process_event) (union perf_event *event, 69 void (*process_event) (union perf_event *event,
69 struct perf_sample *sample, 70 struct perf_sample *sample,
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index e52e7461911b..24e8d871b74e 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -13,6 +13,7 @@
13#include <limits.h> 13#include <limits.h>
14#include <byteswap.h> 14#include <byteswap.h>
15#include <linux/kernel.h> 15#include <linux/kernel.h>
16#include <unistd.h>
16 17
17/* 18/*
18 * XXX We need to find a better place for these things... 19 * XXX We need to find a better place for these things...
@@ -282,6 +283,18 @@ void get_term_dimensions(struct winsize *ws)
282 ws->ws_col = 80; 283 ws->ws_col = 80;
283} 284}
284 285
286void set_term_quiet_input(struct termios *old)
287{
288 struct termios tc;
289
290 tcgetattr(0, old);
291 tc = *old;
292 tc.c_lflag &= ~(ICANON | ECHO);
293 tc.c_cc[VMIN] = 0;
294 tc.c_cc[VTIME] = 0;
295 tcsetattr(0, TCSANOW, &tc);
296}
297
285static void set_tracing_events_path(const char *mountpoint) 298static void set_tracing_events_path(const char *mountpoint)
286{ 299{
287 snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s", 300 snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s",
@@ -443,6 +456,7 @@ int filename__read_str(const char *filename, char **buf, size_t *sizep)
443 size_t size = 0, alloc_size = 0; 456 size_t size = 0, alloc_size = 0;
444 void *bf = NULL, *nbf; 457 void *bf = NULL, *nbf;
445 int fd, n, err = 0; 458 int fd, n, err = 0;
459 char sbuf[STRERR_BUFSIZE];
446 460
447 fd = open(filename, O_RDONLY); 461 fd = open(filename, O_RDONLY);
448 if (fd < 0) 462 if (fd < 0)
@@ -463,8 +477,8 @@ int filename__read_str(const char *filename, char **buf, size_t *sizep)
463 n = read(fd, bf + size, alloc_size - size); 477 n = read(fd, bf + size, alloc_size - size);
464 if (n < 0) { 478 if (n < 0) {
465 if (size) { 479 if (size) {
466 pr_warning("read failed %d: %s\n", 480 pr_warning("read failed %d: %s\n", errno,
467 errno, strerror(errno)); 481 strerror_r(errno, sbuf, sizeof(sbuf)));
468 err = 0; 482 err = 0;
469 } else 483 } else
470 err = -errno; 484 err = -errno;
@@ -536,3 +550,39 @@ void mem_bswap_64(void *src, int byte_size)
536 ++m; 550 ++m;
537 } 551 }
538} 552}
553
554bool find_process(const char *name)
555{
556 size_t len = strlen(name);
557 DIR *dir;
558 struct dirent *d;
559 int ret = -1;
560
561 dir = opendir(procfs__mountpoint());
562 if (!dir)
563 return -1;
564
565 /* Walk through the directory. */
566 while (ret && (d = readdir(dir)) != NULL) {
567 char path[PATH_MAX];
568 char *data;
569 size_t size;
570
571 if ((d->d_type != DT_DIR) ||
572 !strcmp(".", d->d_name) ||
573 !strcmp("..", d->d_name))
574 continue;
575
576 scnprintf(path, sizeof(path), "%s/%s/comm",
577 procfs__mountpoint(), d->d_name);
578
579 if (filename__read_str(path, &data, &size))
580 continue;
581
582 ret = strncmp(name, data, len);
583 free(data);
584 }
585
586 closedir(dir);
587 return ret ? false : true;
588}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 66864364ccb4..80bfdaa0e2a4 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -39,6 +39,8 @@
39 39
40#define _ALL_SOURCE 1 40#define _ALL_SOURCE 1
41#define _BSD_SOURCE 1 41#define _BSD_SOURCE 1
42/* glibc 2.20 deprecates _BSD_SOURCE in favour of _DEFAULT_SOURCE */
43#define _DEFAULT_SOURCE 1
42#define HAS_BOOL 44#define HAS_BOOL
43 45
44#include <unistd.h> 46#include <unistd.h>
@@ -64,16 +66,18 @@
64#include <regex.h> 66#include <regex.h>
65#include <utime.h> 67#include <utime.h>
66#include <sys/wait.h> 68#include <sys/wait.h>
67#include <sys/poll.h> 69#include <poll.h>
68#include <sys/socket.h> 70#include <sys/socket.h>
69#include <sys/ioctl.h> 71#include <sys/ioctl.h>
70#include <inttypes.h> 72#include <inttypes.h>
73#include <linux/kernel.h>
71#include <linux/magic.h> 74#include <linux/magic.h>
72#include <linux/types.h> 75#include <linux/types.h>
73#include <sys/ttydefaults.h> 76#include <sys/ttydefaults.h>
74#include <api/fs/debugfs.h> 77#include <api/fs/debugfs.h>
75#include <termios.h> 78#include <termios.h>
76#include <linux/bitops.h> 79#include <linux/bitops.h>
80#include <termios.h>
77 81
78extern const char *graph_line; 82extern const char *graph_line;
79extern const char *graph_dotted_line; 83extern const char *graph_dotted_line;
@@ -307,6 +311,7 @@ extern unsigned int page_size;
307extern int cacheline_size; 311extern int cacheline_size;
308 312
309void get_term_dimensions(struct winsize *ws); 313void get_term_dimensions(struct winsize *ws);
314void set_term_quiet_input(struct termios *old);
310 315
311struct parse_tag { 316struct parse_tag {
312 char tag; 317 char tag;
@@ -317,6 +322,21 @@ unsigned long parse_tag_value(const char *str, struct parse_tag *tags);
317 322
318#define SRCLINE_UNKNOWN ((char *) "??:0") 323#define SRCLINE_UNKNOWN ((char *) "??:0")
319 324
325static inline int path__join(char *bf, size_t size,
326 const char *path1, const char *path2)
327{
328 return scnprintf(bf, size, "%s%s%s", path1, path1[0] ? "/" : "", path2);
329}
330
331static inline int path__join3(char *bf, size_t size,
332 const char *path1, const char *path2,
333 const char *path3)
334{
335 return scnprintf(bf, size, "%s%s%s%s%s",
336 path1, path1[0] ? "/" : "",
337 path2, path2[0] ? "/" : "", path3);
338}
339
320struct dso; 340struct dso;
321 341
322char *get_srcline(struct dso *dso, unsigned long addr); 342char *get_srcline(struct dso *dso, unsigned long addr);
@@ -330,4 +350,5 @@ void mem_bswap_64(void *src, int byte_size);
330void mem_bswap_32(void *src, int byte_size); 350void mem_bswap_32(void *src, int byte_size);
331 351
332const char *get_filename_for_perf_kvm(void); 352const char *get_filename_for_perf_kvm(void);
353bool find_process(const char *name);
333#endif /* GIT_COMPAT_UTIL_H */ 354#endif /* GIT_COMPAT_UTIL_H */