aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2014-12-08 05:50:24 -0500
committerIngo Molnar <mingo@kernel.org>2014-12-08 05:50:24 -0500
commit2a2662bf88e693d477ef08351d03934f7bc0b51c (patch)
treecef243df159cc12ada7e97998a253df7c0abb2a2 /tools/perf/util
parentb2776bf7149bddd1f4161f14f79520f17fc1d71d (diff)
parent36748b9518a2437beffe861b47dff6d12b736b3f (diff)
Merge branch 'perf/core-v3' of git://git.kernel.org/pub/scm/linux/kernel/git/frederic/linux-dynticks into perf/hw_breakpoints
Pull AMD range breakpoints support from Frederic Weisbecker: " - Extend breakpoint tools and core to support address range through perf event with initial backend support for AMD extended breakpoints. Syntax is: perf record -e mem:addr/len:type For example set write breakpoint from 0x1000 to 0x1200 (0x1000 + 512) perf record -e mem:0x1000/512:w - Clean up a bit breakpoint code validation It has been acked by Jiri and Oleg. " Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/annotate.c32
-rw-r--r--tools/perf/util/annotate.h1
-rw-r--r--tools/perf/util/build-id.c348
-rw-r--r--tools/perf/util/build-id.h12
-rw-r--r--tools/perf/util/callchain.c23
-rw-r--r--tools/perf/util/callchain.h9
-rw-r--r--tools/perf/util/comm.h4
-rw-r--r--tools/perf/util/db-export.c428
-rw-r--r--tools/perf/util/db-export.h107
-rw-r--r--tools/perf/util/dso.c71
-rw-r--r--tools/perf/util/dso.h13
-rw-r--r--tools/perf/util/event.c20
-rw-r--r--tools/perf/util/event.h43
-rw-r--r--tools/perf/util/evlist.c38
-rw-r--r--tools/perf/util/evsel.c56
-rw-r--r--tools/perf/util/evsel.h5
-rw-r--r--tools/perf/util/find-vdso-map.c30
-rw-r--r--tools/perf/util/header.c361
-rw-r--r--tools/perf/util/header.h8
-rw-r--r--tools/perf/util/include/linux/bitmap.h17
-rw-r--r--tools/perf/util/include/linux/bitops.h2
-rw-r--r--tools/perf/util/machine.c142
-rw-r--r--tools/perf/util/machine.h17
-rw-r--r--tools/perf/util/map.c8
-rw-r--r--tools/perf/util/map.h4
-rw-r--r--tools/perf/util/parse-events.c21
-rw-r--r--tools/perf/util/parse-events.h2
-rw-r--r--tools/perf/util/parse-events.l1
-rw-r--r--tools/perf/util/parse-events.y26
-rw-r--r--tools/perf/util/parse-options.c78
-rw-r--r--tools/perf/util/parse-options.h4
-rw-r--r--tools/perf/util/pmu.c41
-rw-r--r--tools/perf/util/pmu.h1
-rw-r--r--tools/perf/util/probe-event.c18
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c29
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c440
-rw-r--r--tools/perf/util/session.c185
-rw-r--r--tools/perf/util/session.h15
-rw-r--r--tools/perf/util/sort.c2
-rw-r--r--tools/perf/util/srcline.c2
-rw-r--r--tools/perf/util/symbol-elf.c35
-rw-r--r--tools/perf/util/symbol-minimal.c1
-rw-r--r--tools/perf/util/symbol.c19
-rw-r--r--tools/perf/util/symbol.h1
-rw-r--r--tools/perf/util/thread-stack.c747
-rw-r--r--tools/perf/util/thread-stack.h111
-rw-r--r--tools/perf/util/thread.c14
-rw-r--r--tools/perf/util/thread.h9
-rw-r--r--tools/perf/util/tool.h3
-rw-r--r--tools/perf/util/unwind-libdw.c8
-rw-r--r--tools/perf/util/unwind-libunwind.c17
-rw-r--r--tools/perf/util/unwind.h2
-rw-r--r--tools/perf/util/util.h6
-rw-r--r--tools/perf/util/vdso.c217
-rw-r--r--tools/perf/util/vdso.h4
-rw-r--r--tools/perf/util/zlib.c78
56 files changed, 3302 insertions, 634 deletions
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 7dabde14ea54..e5670f1af737 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -17,11 +17,13 @@
17#include "debug.h" 17#include "debug.h"
18#include "annotate.h" 18#include "annotate.h"
19#include "evsel.h" 19#include "evsel.h"
20#include <regex.h>
20#include <pthread.h> 21#include <pthread.h>
21#include <linux/bitops.h> 22#include <linux/bitops.h>
22 23
23const char *disassembler_style; 24const char *disassembler_style;
24const char *objdump_path; 25const char *objdump_path;
26static regex_t file_lineno;
25 27
26static struct ins *ins__find(const char *name); 28static struct ins *ins__find(const char *name);
27static int disasm_line__parse(char *line, char **namep, char **rawp); 29static int disasm_line__parse(char *line, char **namep, char **rawp);
@@ -570,13 +572,15 @@ out_free_name:
570 return -1; 572 return -1;
571} 573}
572 574
573static struct disasm_line *disasm_line__new(s64 offset, char *line, size_t privsize) 575static struct disasm_line *disasm_line__new(s64 offset, char *line,
576 size_t privsize, int line_nr)
574{ 577{
575 struct disasm_line *dl = zalloc(sizeof(*dl) + privsize); 578 struct disasm_line *dl = zalloc(sizeof(*dl) + privsize);
576 579
577 if (dl != NULL) { 580 if (dl != NULL) {
578 dl->offset = offset; 581 dl->offset = offset;
579 dl->line = strdup(line); 582 dl->line = strdup(line);
583 dl->line_nr = line_nr;
580 if (dl->line == NULL) 584 if (dl->line == NULL)
581 goto out_delete; 585 goto out_delete;
582 586
@@ -788,13 +792,15 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
788 * The ops.raw part will be parsed further according to type of the instruction. 792 * The ops.raw part will be parsed further according to type of the instruction.
789 */ 793 */
790static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, 794static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
791 FILE *file, size_t privsize) 795 FILE *file, size_t privsize,
796 int *line_nr)
792{ 797{
793 struct annotation *notes = symbol__annotation(sym); 798 struct annotation *notes = symbol__annotation(sym);
794 struct disasm_line *dl; 799 struct disasm_line *dl;
795 char *line = NULL, *parsed_line, *tmp, *tmp2, *c; 800 char *line = NULL, *parsed_line, *tmp, *tmp2, *c;
796 size_t line_len; 801 size_t line_len;
797 s64 line_ip, offset = -1; 802 s64 line_ip, offset = -1;
803 regmatch_t match[2];
798 804
799 if (getline(&line, &line_len, file) < 0) 805 if (getline(&line, &line_len, file) < 0)
800 return -1; 806 return -1;
@@ -812,6 +818,12 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
812 line_ip = -1; 818 line_ip = -1;
813 parsed_line = line; 819 parsed_line = line;
814 820
821 /* /filename:linenr ? Save line number and ignore. */
822 if (regexec(&file_lineno, line, 2, match, 0) == 0) {
823 *line_nr = atoi(line + match[1].rm_so);
824 return 0;
825 }
826
815 /* 827 /*
816 * Strip leading spaces: 828 * Strip leading spaces:
817 */ 829 */
@@ -842,8 +854,9 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
842 parsed_line = tmp2 + 1; 854 parsed_line = tmp2 + 1;
843 } 855 }
844 856
845 dl = disasm_line__new(offset, parsed_line, privsize); 857 dl = disasm_line__new(offset, parsed_line, privsize, *line_nr);
846 free(line); 858 free(line);
859 (*line_nr)++;
847 860
848 if (dl == NULL) 861 if (dl == NULL)
849 return -1; 862 return -1;
@@ -869,6 +882,11 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
869 return 0; 882 return 0;
870} 883}
871 884
885static __attribute__((constructor)) void symbol__init_regexpr(void)
886{
887 regcomp(&file_lineno, "^/[^:]+:([0-9]+)", REG_EXTENDED);
888}
889
872static void delete_last_nop(struct symbol *sym) 890static void delete_last_nop(struct symbol *sym)
873{ 891{
874 struct annotation *notes = symbol__annotation(sym); 892 struct annotation *notes = symbol__annotation(sym);
@@ -904,6 +922,7 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
904 char symfs_filename[PATH_MAX]; 922 char symfs_filename[PATH_MAX];
905 struct kcore_extract kce; 923 struct kcore_extract kce;
906 bool delete_extract = false; 924 bool delete_extract = false;
925 int lineno = 0;
907 926
908 if (filename) 927 if (filename)
909 symbol__join_symfs(symfs_filename, filename); 928 symbol__join_symfs(symfs_filename, filename);
@@ -915,6 +934,8 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
915 return -ENOMEM; 934 return -ENOMEM;
916 } 935 }
917 goto fallback; 936 goto fallback;
937 } else if (dso__is_kcore(dso)) {
938 goto fallback;
918 } else if (readlink(symfs_filename, command, sizeof(command)) < 0 || 939 } else if (readlink(symfs_filename, command, sizeof(command)) < 0 ||
919 strstr(command, "[kernel.kallsyms]") || 940 strstr(command, "[kernel.kallsyms]") ||
920 access(symfs_filename, R_OK)) { 941 access(symfs_filename, R_OK)) {
@@ -982,7 +1003,7 @@ fallback:
982 snprintf(command, sizeof(command), 1003 snprintf(command, sizeof(command),
983 "%s %s%s --start-address=0x%016" PRIx64 1004 "%s %s%s --start-address=0x%016" PRIx64
984 " --stop-address=0x%016" PRIx64 1005 " --stop-address=0x%016" PRIx64
985 " -d %s %s -C %s 2>/dev/null|grep -v %s|expand", 1006 " -l -d %s %s -C %s 2>/dev/null|grep -v %s|expand",
986 objdump_path ? objdump_path : "objdump", 1007 objdump_path ? objdump_path : "objdump",
987 disassembler_style ? "-M " : "", 1008 disassembler_style ? "-M " : "",
988 disassembler_style ? disassembler_style : "", 1009 disassembler_style ? disassembler_style : "",
@@ -999,7 +1020,8 @@ fallback:
999 goto out_free_filename; 1020 goto out_free_filename;
1000 1021
1001 while (!feof(file)) 1022 while (!feof(file))
1002 if (symbol__parse_objdump_line(sym, map, file, privsize) < 0) 1023 if (symbol__parse_objdump_line(sym, map, file, privsize,
1024 &lineno) < 0)
1003 break; 1025 break;
1004 1026
1005 /* 1027 /*
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 112d6e268150..0784a9420528 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -58,6 +58,7 @@ struct disasm_line {
58 char *line; 58 char *line;
59 char *name; 59 char *name;
60 struct ins *ins; 60 struct ins *ins;
61 int line_nr;
61 struct ins_operands ops; 62 struct ins_operands ops;
62}; 63};
63 64
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index a904a4cfe7d3..e8d79e5bfaf7 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -15,6 +15,11 @@
15#include "debug.h" 15#include "debug.h"
16#include "session.h" 16#include "session.h"
17#include "tool.h" 17#include "tool.h"
18#include "header.h"
19#include "vdso.h"
20
21
22static bool no_buildid_cache;
18 23
19int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused, 24int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused,
20 union perf_event *event, 25 union perf_event *event,
@@ -33,8 +38,7 @@ int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused,
33 return -1; 38 return -1;
34 } 39 }
35 40
36 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, 41 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->ip, &al);
37 sample->ip, &al);
38 42
39 if (al.map != NULL) 43 if (al.map != NULL)
40 al.map->dso->hit = 1; 44 al.map->dso->hit = 1;
@@ -106,3 +110,343 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
106 build_id_hex, build_id_hex + 2); 110 build_id_hex, build_id_hex + 2);
107 return bf; 111 return bf;
108} 112}
113
114#define dsos__for_each_with_build_id(pos, head) \
115 list_for_each_entry(pos, head, node) \
116 if (!pos->has_build_id) \
117 continue; \
118 else
119
120static int write_buildid(const char *name, size_t name_len, u8 *build_id,
121 pid_t pid, u16 misc, int fd)
122{
123 int err;
124 struct build_id_event b;
125 size_t len;
126
127 len = name_len + 1;
128 len = PERF_ALIGN(len, NAME_ALIGN);
129
130 memset(&b, 0, sizeof(b));
131 memcpy(&b.build_id, build_id, BUILD_ID_SIZE);
132 b.pid = pid;
133 b.header.misc = misc;
134 b.header.size = sizeof(b) + len;
135
136 err = writen(fd, &b, sizeof(b));
137 if (err < 0)
138 return err;
139
140 return write_padded(fd, name, name_len + 1, len);
141}
142
143static int __dsos__write_buildid_table(struct list_head *head,
144 struct machine *machine,
145 pid_t pid, u16 misc, int fd)
146{
147 char nm[PATH_MAX];
148 struct dso *pos;
149
150 dsos__for_each_with_build_id(pos, head) {
151 int err;
152 const char *name;
153 size_t name_len;
154
155 if (!pos->hit)
156 continue;
157
158 if (dso__is_vdso(pos)) {
159 name = pos->short_name;
160 name_len = pos->short_name_len + 1;
161 } else if (dso__is_kcore(pos)) {
162 machine__mmap_name(machine, nm, sizeof(nm));
163 name = nm;
164 name_len = strlen(nm) + 1;
165 } else {
166 name = pos->long_name;
167 name_len = pos->long_name_len + 1;
168 }
169
170 err = write_buildid(name, name_len, pos->build_id,
171 pid, misc, fd);
172 if (err)
173 return err;
174 }
175
176 return 0;
177}
178
179static int machine__write_buildid_table(struct machine *machine, int fd)
180{
181 int err;
182 u16 kmisc = PERF_RECORD_MISC_KERNEL,
183 umisc = PERF_RECORD_MISC_USER;
184
185 if (!machine__is_host(machine)) {
186 kmisc = PERF_RECORD_MISC_GUEST_KERNEL;
187 umisc = PERF_RECORD_MISC_GUEST_USER;
188 }
189
190 err = __dsos__write_buildid_table(&machine->kernel_dsos.head, machine,
191 machine->pid, kmisc, fd);
192 if (err == 0)
193 err = __dsos__write_buildid_table(&machine->user_dsos.head,
194 machine, machine->pid, umisc,
195 fd);
196 return err;
197}
198
199int perf_session__write_buildid_table(struct perf_session *session, int fd)
200{
201 struct rb_node *nd;
202 int err = machine__write_buildid_table(&session->machines.host, fd);
203
204 if (err)
205 return err;
206
207 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
208 struct machine *pos = rb_entry(nd, struct machine, rb_node);
209 err = machine__write_buildid_table(pos, fd);
210 if (err)
211 break;
212 }
213 return err;
214}
215
216static int __dsos__hit_all(struct list_head *head)
217{
218 struct dso *pos;
219
220 list_for_each_entry(pos, head, node)
221 pos->hit = true;
222
223 return 0;
224}
225
226static int machine__hit_all_dsos(struct machine *machine)
227{
228 int err;
229
230 err = __dsos__hit_all(&machine->kernel_dsos.head);
231 if (err)
232 return err;
233
234 return __dsos__hit_all(&machine->user_dsos.head);
235}
236
237int dsos__hit_all(struct perf_session *session)
238{
239 struct rb_node *nd;
240 int err;
241
242 err = machine__hit_all_dsos(&session->machines.host);
243 if (err)
244 return err;
245
246 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
247 struct machine *pos = rb_entry(nd, struct machine, rb_node);
248
249 err = machine__hit_all_dsos(pos);
250 if (err)
251 return err;
252 }
253
254 return 0;
255}
256
257void disable_buildid_cache(void)
258{
259 no_buildid_cache = true;
260}
261
262int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
263 const char *name, bool is_kallsyms, bool is_vdso)
264{
265 const size_t size = PATH_MAX;
266 char *realname, *filename = zalloc(size),
267 *linkname = zalloc(size), *targetname;
268 int len, err = -1;
269 bool slash = is_kallsyms || is_vdso;
270
271 if (is_kallsyms) {
272 if (symbol_conf.kptr_restrict) {
273 pr_debug("Not caching a kptr_restrict'ed /proc/kallsyms\n");
274 err = 0;
275 goto out_free;
276 }
277 realname = (char *) name;
278 } else
279 realname = realpath(name, NULL);
280
281 if (realname == NULL || filename == NULL || linkname == NULL)
282 goto out_free;
283
284 len = scnprintf(filename, size, "%s%s%s",
285 debugdir, slash ? "/" : "",
286 is_vdso ? DSO__NAME_VDSO : realname);
287 if (mkdir_p(filename, 0755))
288 goto out_free;
289
290 snprintf(filename + len, size - len, "/%s", sbuild_id);
291
292 if (access(filename, F_OK)) {
293 if (is_kallsyms) {
294 if (copyfile("/proc/kallsyms", filename))
295 goto out_free;
296 } else if (link(realname, filename) && copyfile(name, filename))
297 goto out_free;
298 }
299
300 len = scnprintf(linkname, size, "%s/.build-id/%.2s",
301 debugdir, sbuild_id);
302
303 if (access(linkname, X_OK) && mkdir_p(linkname, 0755))
304 goto out_free;
305
306 snprintf(linkname + len, size - len, "/%s", sbuild_id + 2);
307 targetname = filename + strlen(debugdir) - 5;
308 memcpy(targetname, "../..", 5);
309
310 if (symlink(targetname, linkname) == 0)
311 err = 0;
312out_free:
313 if (!is_kallsyms)
314 free(realname);
315 free(filename);
316 free(linkname);
317 return err;
318}
319
320static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
321 const char *name, const char *debugdir,
322 bool is_kallsyms, bool is_vdso)
323{
324 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
325
326 build_id__sprintf(build_id, build_id_size, sbuild_id);
327
328 return build_id_cache__add_s(sbuild_id, debugdir, name,
329 is_kallsyms, is_vdso);
330}
331
332int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
333{
334 const size_t size = PATH_MAX;
335 char *filename = zalloc(size),
336 *linkname = zalloc(size);
337 int err = -1;
338
339 if (filename == NULL || linkname == NULL)
340 goto out_free;
341
342 snprintf(linkname, size, "%s/.build-id/%.2s/%s",
343 debugdir, sbuild_id, sbuild_id + 2);
344
345 if (access(linkname, F_OK))
346 goto out_free;
347
348 if (readlink(linkname, filename, size - 1) < 0)
349 goto out_free;
350
351 if (unlink(linkname))
352 goto out_free;
353
354 /*
355 * Since the link is relative, we must make it absolute:
356 */
357 snprintf(linkname, size, "%s/.build-id/%.2s/%s",
358 debugdir, sbuild_id, filename);
359
360 if (unlink(linkname))
361 goto out_free;
362
363 err = 0;
364out_free:
365 free(filename);
366 free(linkname);
367 return err;
368}
369
370static int dso__cache_build_id(struct dso *dso, struct machine *machine,
371 const char *debugdir)
372{
373 bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
374 bool is_vdso = dso__is_vdso(dso);
375 const char *name = dso->long_name;
376 char nm[PATH_MAX];
377
378 if (dso__is_kcore(dso)) {
379 is_kallsyms = true;
380 machine__mmap_name(machine, nm, sizeof(nm));
381 name = nm;
382 }
383 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name,
384 debugdir, is_kallsyms, is_vdso);
385}
386
387static int __dsos__cache_build_ids(struct list_head *head,
388 struct machine *machine, const char *debugdir)
389{
390 struct dso *pos;
391 int err = 0;
392
393 dsos__for_each_with_build_id(pos, head)
394 if (dso__cache_build_id(pos, machine, debugdir))
395 err = -1;
396
397 return err;
398}
399
400static int machine__cache_build_ids(struct machine *machine, const char *debugdir)
401{
402 int ret = __dsos__cache_build_ids(&machine->kernel_dsos.head, machine,
403 debugdir);
404 ret |= __dsos__cache_build_ids(&machine->user_dsos.head, machine,
405 debugdir);
406 return ret;
407}
408
409int perf_session__cache_build_ids(struct perf_session *session)
410{
411 struct rb_node *nd;
412 int ret;
413 char debugdir[PATH_MAX];
414
415 if (no_buildid_cache)
416 return 0;
417
418 snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir);
419
420 if (mkdir(debugdir, 0755) != 0 && errno != EEXIST)
421 return -1;
422
423 ret = machine__cache_build_ids(&session->machines.host, debugdir);
424
425 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
426 struct machine *pos = rb_entry(nd, struct machine, rb_node);
427 ret |= machine__cache_build_ids(pos, debugdir);
428 }
429 return ret ? -1 : 0;
430}
431
432static bool machine__read_build_ids(struct machine *machine, bool with_hits)
433{
434 bool ret;
435
436 ret = __dsos__read_build_ids(&machine->kernel_dsos.head, with_hits);
437 ret |= __dsos__read_build_ids(&machine->user_dsos.head, with_hits);
438 return ret;
439}
440
441bool perf_session__read_build_ids(struct perf_session *session, bool with_hits)
442{
443 struct rb_node *nd;
444 bool ret = machine__read_build_ids(&session->machines.host, with_hits);
445
446 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
447 struct machine *pos = rb_entry(nd, struct machine, rb_node);
448 ret |= machine__read_build_ids(pos, with_hits);
449 }
450
451 return ret;
452}
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index ae392561470b..8236319514d5 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -15,4 +15,16 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size);
15int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event, 15int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event,
16 struct perf_sample *sample, struct perf_evsel *evsel, 16 struct perf_sample *sample, struct perf_evsel *evsel,
17 struct machine *machine); 17 struct machine *machine);
18
19int dsos__hit_all(struct perf_session *session);
20
21bool perf_session__read_build_ids(struct perf_session *session, bool with_hits);
22int perf_session__write_buildid_table(struct perf_session *session, int fd);
23int perf_session__cache_build_ids(struct perf_session *session);
24
25int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
26 const char *name, bool is_kallsyms, bool is_vdso);
27int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir);
28void disable_buildid_cache(void);
29
18#endif 30#endif
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index c84d3f8dcb75..38da69c8c1ff 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -754,8 +754,8 @@ int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent
754 754
755 if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain || 755 if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain ||
756 sort__has_parent) { 756 sort__has_parent) {
757 return machine__resolve_callchain(al->machine, evsel, al->thread, 757 return thread__resolve_callchain(al->thread, evsel, sample,
758 sample, parent, al, max_stack); 758 parent, al, max_stack);
759 } 759 }
760 return 0; 760 return 0;
761} 761}
@@ -808,3 +808,22 @@ int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *
808out: 808out:
809 return 1; 809 return 1;
810} 810}
811
812char *callchain_list__sym_name(struct callchain_list *cl,
813 char *bf, size_t bfsize, bool show_dso)
814{
815 int printed;
816
817 if (cl->ms.sym) {
818 printed = scnprintf(bf, bfsize, "%s", cl->ms.sym->name);
819 } else
820 printed = scnprintf(bf, bfsize, "%#" PRIx64, cl->ip);
821
822 if (show_dso)
823 scnprintf(bf + printed, bfsize - printed, " %s",
824 cl->ms.map ?
825 cl->ms.map->dso->short_name :
826 "unknown");
827
828 return bf;
829}
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 94cfefddf4db..3e1ed15d11f1 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -184,15 +184,16 @@ static inline void callchain_cursor_snapshot(struct callchain_cursor *dest,
184} 184}
185 185
186#ifdef HAVE_SKIP_CALLCHAIN_IDX 186#ifdef HAVE_SKIP_CALLCHAIN_IDX
187extern int arch_skip_callchain_idx(struct machine *machine, 187extern int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain);
188 struct thread *thread, struct ip_callchain *chain);
189#else 188#else
190static inline int arch_skip_callchain_idx(struct machine *machine __maybe_unused, 189static inline int arch_skip_callchain_idx(struct thread *thread __maybe_unused,
191 struct thread *thread __maybe_unused,
192 struct ip_callchain *chain __maybe_unused) 190 struct ip_callchain *chain __maybe_unused)
193{ 191{
194 return -1; 192 return -1;
195} 193}
196#endif 194#endif
197 195
196char *callchain_list__sym_name(struct callchain_list *cl,
197 char *bf, size_t bfsize, bool show_dso);
198
198#endif /* __PERF_CALLCHAIN_H */ 199#endif /* __PERF_CALLCHAIN_H */
diff --git a/tools/perf/util/comm.h b/tools/perf/util/comm.h
index 51c10ab257f8..71c9c39340d4 100644
--- a/tools/perf/util/comm.h
+++ b/tools/perf/util/comm.h
@@ -12,6 +12,10 @@ struct comm {
12 u64 start; 12 u64 start;
13 struct list_head list; 13 struct list_head list;
14 bool exec; 14 bool exec;
15 union { /* Tool specific area */
16 void *priv;
17 u64 db_id;
18 };
15}; 19};
16 20
17void comm__free(struct comm *comm); 21void comm__free(struct comm *comm);
diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c
new file mode 100644
index 000000000000..c81dae399763
--- /dev/null
+++ b/tools/perf/util/db-export.c
@@ -0,0 +1,428 @@
1/*
2 * db-export.c: Support for exporting data suitable for import to a database
3 * Copyright (c) 2014, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 */
15
16#include <errno.h>
17
18#include "evsel.h"
19#include "machine.h"
20#include "thread.h"
21#include "comm.h"
22#include "symbol.h"
23#include "event.h"
24#include "util.h"
25#include "thread-stack.h"
26#include "db-export.h"
27
28struct deferred_export {
29 struct list_head node;
30 struct comm *comm;
31};
32
33static int db_export__deferred(struct db_export *dbe)
34{
35 struct deferred_export *de;
36 int err;
37
38 while (!list_empty(&dbe->deferred)) {
39 de = list_entry(dbe->deferred.next, struct deferred_export,
40 node);
41 err = dbe->export_comm(dbe, de->comm);
42 list_del(&de->node);
43 free(de);
44 if (err)
45 return err;
46 }
47
48 return 0;
49}
50
51static void db_export__free_deferred(struct db_export *dbe)
52{
53 struct deferred_export *de;
54
55 while (!list_empty(&dbe->deferred)) {
56 de = list_entry(dbe->deferred.next, struct deferred_export,
57 node);
58 list_del(&de->node);
59 free(de);
60 }
61}
62
63static int db_export__defer_comm(struct db_export *dbe, struct comm *comm)
64{
65 struct deferred_export *de;
66
67 de = zalloc(sizeof(struct deferred_export));
68 if (!de)
69 return -ENOMEM;
70
71 de->comm = comm;
72 list_add_tail(&de->node, &dbe->deferred);
73
74 return 0;
75}
76
77int db_export__init(struct db_export *dbe)
78{
79 memset(dbe, 0, sizeof(struct db_export));
80 INIT_LIST_HEAD(&dbe->deferred);
81 return 0;
82}
83
84int db_export__flush(struct db_export *dbe)
85{
86 return db_export__deferred(dbe);
87}
88
89void db_export__exit(struct db_export *dbe)
90{
91 db_export__free_deferred(dbe);
92 call_return_processor__free(dbe->crp);
93 dbe->crp = NULL;
94}
95
96int db_export__evsel(struct db_export *dbe, struct perf_evsel *evsel)
97{
98 if (evsel->db_id)
99 return 0;
100
101 evsel->db_id = ++dbe->evsel_last_db_id;
102
103 if (dbe->export_evsel)
104 return dbe->export_evsel(dbe, evsel);
105
106 return 0;
107}
108
109int db_export__machine(struct db_export *dbe, struct machine *machine)
110{
111 if (machine->db_id)
112 return 0;
113
114 machine->db_id = ++dbe->machine_last_db_id;
115
116 if (dbe->export_machine)
117 return dbe->export_machine(dbe, machine);
118
119 return 0;
120}
121
122int db_export__thread(struct db_export *dbe, struct thread *thread,
123 struct machine *machine, struct comm *comm)
124{
125 u64 main_thread_db_id = 0;
126 int err;
127
128 if (thread->db_id)
129 return 0;
130
131 thread->db_id = ++dbe->thread_last_db_id;
132
133 if (thread->pid_ != -1) {
134 struct thread *main_thread;
135
136 if (thread->pid_ == thread->tid) {
137 main_thread = thread;
138 } else {
139 main_thread = machine__findnew_thread(machine,
140 thread->pid_,
141 thread->pid_);
142 if (!main_thread)
143 return -ENOMEM;
144 err = db_export__thread(dbe, main_thread, machine,
145 comm);
146 if (err)
147 return err;
148 if (comm) {
149 err = db_export__comm_thread(dbe, comm, thread);
150 if (err)
151 return err;
152 }
153 }
154 main_thread_db_id = main_thread->db_id;
155 }
156
157 if (dbe->export_thread)
158 return dbe->export_thread(dbe, thread, main_thread_db_id,
159 machine);
160
161 return 0;
162}
163
164int db_export__comm(struct db_export *dbe, struct comm *comm,
165 struct thread *main_thread)
166{
167 int err;
168
169 if (comm->db_id)
170 return 0;
171
172 comm->db_id = ++dbe->comm_last_db_id;
173
174 if (dbe->export_comm) {
175 if (main_thread->comm_set)
176 err = dbe->export_comm(dbe, comm);
177 else
178 err = db_export__defer_comm(dbe, comm);
179 if (err)
180 return err;
181 }
182
183 return db_export__comm_thread(dbe, comm, main_thread);
184}
185
186int db_export__comm_thread(struct db_export *dbe, struct comm *comm,
187 struct thread *thread)
188{
189 u64 db_id;
190
191 db_id = ++dbe->comm_thread_last_db_id;
192
193 if (dbe->export_comm_thread)
194 return dbe->export_comm_thread(dbe, db_id, comm, thread);
195
196 return 0;
197}
198
199int db_export__dso(struct db_export *dbe, struct dso *dso,
200 struct machine *machine)
201{
202 if (dso->db_id)
203 return 0;
204
205 dso->db_id = ++dbe->dso_last_db_id;
206
207 if (dbe->export_dso)
208 return dbe->export_dso(dbe, dso, machine);
209
210 return 0;
211}
212
213int db_export__symbol(struct db_export *dbe, struct symbol *sym,
214 struct dso *dso)
215{
216 u64 *sym_db_id = symbol__priv(sym);
217
218 if (*sym_db_id)
219 return 0;
220
221 *sym_db_id = ++dbe->symbol_last_db_id;
222
223 if (dbe->export_symbol)
224 return dbe->export_symbol(dbe, sym, dso);
225
226 return 0;
227}
228
229static struct thread *get_main_thread(struct machine *machine, struct thread *thread)
230{
231 if (thread->pid_ == thread->tid)
232 return thread;
233
234 if (thread->pid_ == -1)
235 return NULL;
236
237 return machine__find_thread(machine, thread->pid_, thread->pid_);
238}
239
240static int db_ids_from_al(struct db_export *dbe, struct addr_location *al,
241 u64 *dso_db_id, u64 *sym_db_id, u64 *offset)
242{
243 int err;
244
245 if (al->map) {
246 struct dso *dso = al->map->dso;
247
248 err = db_export__dso(dbe, dso, al->machine);
249 if (err)
250 return err;
251 *dso_db_id = dso->db_id;
252
253 if (!al->sym) {
254 al->sym = symbol__new(al->addr, 0, 0, "unknown");
255 if (al->sym)
256 symbols__insert(&dso->symbols[al->map->type],
257 al->sym);
258 }
259
260 if (al->sym) {
261 u64 *db_id = symbol__priv(al->sym);
262
263 err = db_export__symbol(dbe, al->sym, dso);
264 if (err)
265 return err;
266 *sym_db_id = *db_id;
267 *offset = al->addr - al->sym->start;
268 }
269 }
270
271 return 0;
272}
273
274int db_export__branch_type(struct db_export *dbe, u32 branch_type,
275 const char *name)
276{
277 if (dbe->export_branch_type)
278 return dbe->export_branch_type(dbe, branch_type, name);
279
280 return 0;
281}
282
283int db_export__sample(struct db_export *dbe, union perf_event *event,
284 struct perf_sample *sample, struct perf_evsel *evsel,
285 struct thread *thread, struct addr_location *al)
286{
287 struct export_sample es = {
288 .event = event,
289 .sample = sample,
290 .evsel = evsel,
291 .thread = thread,
292 .al = al,
293 };
294 struct thread *main_thread;
295 struct comm *comm = NULL;
296 int err;
297
298 err = db_export__evsel(dbe, evsel);
299 if (err)
300 return err;
301
302 err = db_export__machine(dbe, al->machine);
303 if (err)
304 return err;
305
306 main_thread = get_main_thread(al->machine, thread);
307 if (main_thread)
308 comm = machine__thread_exec_comm(al->machine, main_thread);
309
310 err = db_export__thread(dbe, thread, al->machine, comm);
311 if (err)
312 return err;
313
314 if (comm) {
315 err = db_export__comm(dbe, comm, main_thread);
316 if (err)
317 return err;
318 es.comm_db_id = comm->db_id;
319 }
320
321 es.db_id = ++dbe->sample_last_db_id;
322
323 err = db_ids_from_al(dbe, al, &es.dso_db_id, &es.sym_db_id, &es.offset);
324 if (err)
325 return err;
326
327 if ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
328 sample_addr_correlates_sym(&evsel->attr)) {
329 struct addr_location addr_al;
330
331 perf_event__preprocess_sample_addr(event, sample, thread, &addr_al);
332 err = db_ids_from_al(dbe, &addr_al, &es.addr_dso_db_id,
333 &es.addr_sym_db_id, &es.addr_offset);
334 if (err)
335 return err;
336 if (dbe->crp) {
337 err = thread_stack__process(thread, comm, sample, al,
338 &addr_al, es.db_id,
339 dbe->crp);
340 if (err)
341 return err;
342 }
343 }
344
345 if (dbe->export_sample)
346 return dbe->export_sample(dbe, &es);
347
348 return 0;
349}
350
351static struct {
352 u32 branch_type;
353 const char *name;
354} branch_types[] = {
355 {0, "no branch"},
356 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL, "call"},
357 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN, "return"},
358 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CONDITIONAL, "conditional jump"},
359 {PERF_IP_FLAG_BRANCH, "unconditional jump"},
360 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_INTERRUPT,
361 "software interrupt"},
362 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_INTERRUPT,
363 "return from interrupt"},
364 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_SYSCALLRET,
365 "system call"},
366 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_SYSCALLRET,
367 "return from system call"},
368 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_ASYNC, "asynchronous branch"},
369 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_ASYNC |
370 PERF_IP_FLAG_INTERRUPT, "hardware interrupt"},
371 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TX_ABORT, "transaction abort"},
372 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_BEGIN, "trace begin"},
373 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_END, "trace end"},
374 {0, NULL}
375};
376
377int db_export__branch_types(struct db_export *dbe)
378{
379 int i, err = 0;
380
381 for (i = 0; branch_types[i].name ; i++) {
382 err = db_export__branch_type(dbe, branch_types[i].branch_type,
383 branch_types[i].name);
384 if (err)
385 break;
386 }
387 return err;
388}
389
390int db_export__call_path(struct db_export *dbe, struct call_path *cp)
391{
392 int err;
393
394 if (cp->db_id)
395 return 0;
396
397 if (cp->parent) {
398 err = db_export__call_path(dbe, cp->parent);
399 if (err)
400 return err;
401 }
402
403 cp->db_id = ++dbe->call_path_last_db_id;
404
405 if (dbe->export_call_path)
406 return dbe->export_call_path(dbe, cp);
407
408 return 0;
409}
410
411int db_export__call_return(struct db_export *dbe, struct call_return *cr)
412{
413 int err;
414
415 if (cr->db_id)
416 return 0;
417
418 err = db_export__call_path(dbe, cr->cp);
419 if (err)
420 return err;
421
422 cr->db_id = ++dbe->call_return_last_db_id;
423
424 if (dbe->export_call_return)
425 return dbe->export_call_return(dbe, cr);
426
427 return 0;
428}
diff --git a/tools/perf/util/db-export.h b/tools/perf/util/db-export.h
new file mode 100644
index 000000000000..adbd22d66798
--- /dev/null
+++ b/tools/perf/util/db-export.h
@@ -0,0 +1,107 @@
1/*
2 * db-export.h: Support for exporting data suitable for import to a database
3 * Copyright (c) 2014, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 */
15
16#ifndef __PERF_DB_EXPORT_H
17#define __PERF_DB_EXPORT_H
18
19#include <linux/types.h>
20#include <linux/list.h>
21
22struct perf_evsel;
23struct machine;
24struct thread;
25struct comm;
26struct dso;
27struct perf_sample;
28struct addr_location;
29struct call_return_processor;
30struct call_path;
31struct call_return;
32
33struct export_sample {
34 union perf_event *event;
35 struct perf_sample *sample;
36 struct perf_evsel *evsel;
37 struct thread *thread;
38 struct addr_location *al;
39 u64 db_id;
40 u64 comm_db_id;
41 u64 dso_db_id;
42 u64 sym_db_id;
43 u64 offset; /* ip offset from symbol start */
44 u64 addr_dso_db_id;
45 u64 addr_sym_db_id;
46 u64 addr_offset; /* addr offset from symbol start */
47};
48
49struct db_export {
50 int (*export_evsel)(struct db_export *dbe, struct perf_evsel *evsel);
51 int (*export_machine)(struct db_export *dbe, struct machine *machine);
52 int (*export_thread)(struct db_export *dbe, struct thread *thread,
53 u64 main_thread_db_id, struct machine *machine);
54 int (*export_comm)(struct db_export *dbe, struct comm *comm);
55 int (*export_comm_thread)(struct db_export *dbe, u64 db_id,
56 struct comm *comm, struct thread *thread);
57 int (*export_dso)(struct db_export *dbe, struct dso *dso,
58 struct machine *machine);
59 int (*export_symbol)(struct db_export *dbe, struct symbol *sym,
60 struct dso *dso);
61 int (*export_branch_type)(struct db_export *dbe, u32 branch_type,
62 const char *name);
63 int (*export_sample)(struct db_export *dbe, struct export_sample *es);
64 int (*export_call_path)(struct db_export *dbe, struct call_path *cp);
65 int (*export_call_return)(struct db_export *dbe,
66 struct call_return *cr);
67 struct call_return_processor *crp;
68 u64 evsel_last_db_id;
69 u64 machine_last_db_id;
70 u64 thread_last_db_id;
71 u64 comm_last_db_id;
72 u64 comm_thread_last_db_id;
73 u64 dso_last_db_id;
74 u64 symbol_last_db_id;
75 u64 sample_last_db_id;
76 u64 call_path_last_db_id;
77 u64 call_return_last_db_id;
78 struct list_head deferred;
79};
80
81int db_export__init(struct db_export *dbe);
82int db_export__flush(struct db_export *dbe);
83void db_export__exit(struct db_export *dbe);
84int db_export__evsel(struct db_export *dbe, struct perf_evsel *evsel);
85int db_export__machine(struct db_export *dbe, struct machine *machine);
86int db_export__thread(struct db_export *dbe, struct thread *thread,
87 struct machine *machine, struct comm *comm);
88int db_export__comm(struct db_export *dbe, struct comm *comm,
89 struct thread *main_thread);
90int db_export__comm_thread(struct db_export *dbe, struct comm *comm,
91 struct thread *thread);
92int db_export__dso(struct db_export *dbe, struct dso *dso,
93 struct machine *machine);
94int db_export__symbol(struct db_export *dbe, struct symbol *sym,
95 struct dso *dso);
96int db_export__branch_type(struct db_export *dbe, u32 branch_type,
97 const char *name);
98int db_export__sample(struct db_export *dbe, union perf_event *event,
99 struct perf_sample *sample, struct perf_evsel *evsel,
100 struct thread *thread, struct addr_location *al);
101
102int db_export__branch_types(struct db_export *dbe);
103
104int db_export__call_path(struct db_export *dbe, struct call_path *cp);
105int db_export__call_return(struct db_export *dbe, struct call_return *cr);
106
107#endif
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 0247acfdfaca..45be944d450a 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -21,8 +21,10 @@ char dso__symtab_origin(const struct dso *dso)
21 [DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b', 21 [DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b',
22 [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd', 22 [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd',
23 [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K', 23 [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K',
24 [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP] = 'm',
24 [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g', 25 [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g',
25 [DSO_BINARY_TYPE__GUEST_KMODULE] = 'G', 26 [DSO_BINARY_TYPE__GUEST_KMODULE] = 'G',
27 [DSO_BINARY_TYPE__GUEST_KMODULE_COMP] = 'M',
26 [DSO_BINARY_TYPE__GUEST_VMLINUX] = 'V', 28 [DSO_BINARY_TYPE__GUEST_VMLINUX] = 'V',
27 }; 29 };
28 30
@@ -112,11 +114,13 @@ int dso__read_binary_type_filename(const struct dso *dso,
112 break; 114 break;
113 115
114 case DSO_BINARY_TYPE__GUEST_KMODULE: 116 case DSO_BINARY_TYPE__GUEST_KMODULE:
117 case DSO_BINARY_TYPE__GUEST_KMODULE_COMP:
115 path__join3(filename, size, symbol_conf.symfs, 118 path__join3(filename, size, symbol_conf.symfs,
116 root_dir, dso->long_name); 119 root_dir, dso->long_name);
117 break; 120 break;
118 121
119 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE: 122 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
123 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP:
120 __symbol__join_symfs(filename, size, dso->long_name); 124 __symbol__join_symfs(filename, size, dso->long_name);
121 break; 125 break;
122 126
@@ -137,6 +141,73 @@ int dso__read_binary_type_filename(const struct dso *dso,
137 return ret; 141 return ret;
138} 142}
139 143
144static const struct {
145 const char *fmt;
146 int (*decompress)(const char *input, int output);
147} compressions[] = {
148#ifdef HAVE_ZLIB_SUPPORT
149 { "gz", gzip_decompress_to_file },
150#endif
151 { NULL, NULL },
152};
153
154bool is_supported_compression(const char *ext)
155{
156 unsigned i;
157
158 for (i = 0; compressions[i].fmt; i++) {
159 if (!strcmp(ext, compressions[i].fmt))
160 return true;
161 }
162 return false;
163}
164
165bool is_kmodule_extension(const char *ext)
166{
167 if (strncmp(ext, "ko", 2))
168 return false;
169
170 if (ext[2] == '\0' || (ext[2] == '.' && is_supported_compression(ext+3)))
171 return true;
172
173 return false;
174}
175
176bool is_kernel_module(const char *pathname, bool *compressed)
177{
178 const char *ext = strrchr(pathname, '.');
179
180 if (ext == NULL)
181 return false;
182
183 if (is_supported_compression(ext + 1)) {
184 if (compressed)
185 *compressed = true;
186 ext -= 3;
187 } else if (compressed)
188 *compressed = false;
189
190 return is_kmodule_extension(ext + 1);
191}
192
193bool decompress_to_file(const char *ext, const char *filename, int output_fd)
194{
195 unsigned i;
196
197 for (i = 0; compressions[i].fmt; i++) {
198 if (!strcmp(ext, compressions[i].fmt))
199 return !compressions[i].decompress(filename,
200 output_fd);
201 }
202 return false;
203}
204
205bool dso__needs_decompress(struct dso *dso)
206{
207 return dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP ||
208 dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP;
209}
210
140/* 211/*
141 * Global list of open DSOs and the counter. 212 * Global list of open DSOs and the counter.
142 */ 213 */
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index acb651acc7fd..3782c82c6e44 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -22,7 +22,9 @@ enum dso_binary_type {
22 DSO_BINARY_TYPE__BUILDID_DEBUGINFO, 22 DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
23 DSO_BINARY_TYPE__SYSTEM_PATH_DSO, 23 DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
24 DSO_BINARY_TYPE__GUEST_KMODULE, 24 DSO_BINARY_TYPE__GUEST_KMODULE,
25 DSO_BINARY_TYPE__GUEST_KMODULE_COMP,
25 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE, 26 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
27 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP,
26 DSO_BINARY_TYPE__KCORE, 28 DSO_BINARY_TYPE__KCORE,
27 DSO_BINARY_TYPE__GUEST_KCORE, 29 DSO_BINARY_TYPE__GUEST_KCORE,
28 DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO, 30 DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
@@ -127,6 +129,7 @@ struct dso {
127 const char *long_name; 129 const char *long_name;
128 u16 long_name_len; 130 u16 long_name_len;
129 u16 short_name_len; 131 u16 short_name_len;
132 void *dwfl; /* DWARF debug info */
130 133
131 /* dso data file */ 134 /* dso data file */
132 struct { 135 struct {
@@ -138,6 +141,11 @@ struct dso {
138 struct list_head open_entry; 141 struct list_head open_entry;
139 } data; 142 } data;
140 143
144 union { /* Tool specific area */
145 void *priv;
146 u64 db_id;
147 };
148
141 char name[0]; 149 char name[0];
142}; 150};
143 151
@@ -179,6 +187,11 @@ int dso__kernel_module_get_build_id(struct dso *dso, const char *root_dir);
179char dso__symtab_origin(const struct dso *dso); 187char dso__symtab_origin(const struct dso *dso);
180int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type type, 188int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type type,
181 char *root_dir, char *filename, size_t size); 189 char *root_dir, char *filename, size_t size);
190bool is_supported_compression(const char *ext);
191bool is_kmodule_extension(const char *ext);
192bool is_kernel_module(const char *pathname, bool *compressed);
193bool decompress_to_file(const char *ext, const char *filename, int output_fd);
194bool dso__needs_decompress(struct dso *dso);
182 195
183/* 196/*
184 * The dso__data_* external interface provides following functions: 197 * The dso__data_* external interface provides following functions:
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 4af6b279e34a..6c6d044e959a 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -28,6 +28,7 @@ static const char *perf_event__names[] = {
28 [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA", 28 [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA",
29 [PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID", 29 [PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID",
30 [PERF_RECORD_FINISHED_ROUND] = "FINISHED_ROUND", 30 [PERF_RECORD_FINISHED_ROUND] = "FINISHED_ROUND",
31 [PERF_RECORD_ID_INDEX] = "ID_INDEX",
31}; 32};
32 33
33const char *perf_event__name(unsigned int id) 34const char *perf_event__name(unsigned int id)
@@ -730,12 +731,12 @@ int perf_event__process(struct perf_tool *tool __maybe_unused,
730 return machine__process_event(machine, event, sample); 731 return machine__process_event(machine, event, sample);
731} 732}
732 733
733void thread__find_addr_map(struct thread *thread, 734void thread__find_addr_map(struct thread *thread, u8 cpumode,
734 struct machine *machine, u8 cpumode,
735 enum map_type type, u64 addr, 735 enum map_type type, u64 addr,
736 struct addr_location *al) 736 struct addr_location *al)
737{ 737{
738 struct map_groups *mg = thread->mg; 738 struct map_groups *mg = thread->mg;
739 struct machine *machine = mg->machine;
739 bool load_map = false; 740 bool load_map = false;
740 741
741 al->machine = machine; 742 al->machine = machine;
@@ -806,14 +807,14 @@ try_again:
806 } 807 }
807} 808}
808 809
809void thread__find_addr_location(struct thread *thread, struct machine *machine, 810void thread__find_addr_location(struct thread *thread,
810 u8 cpumode, enum map_type type, u64 addr, 811 u8 cpumode, enum map_type type, u64 addr,
811 struct addr_location *al) 812 struct addr_location *al)
812{ 813{
813 thread__find_addr_map(thread, machine, cpumode, type, addr, al); 814 thread__find_addr_map(thread, cpumode, type, addr, al);
814 if (al->map != NULL) 815 if (al->map != NULL)
815 al->sym = map__find_symbol(al->map, al->addr, 816 al->sym = map__find_symbol(al->map, al->addr,
816 machine->symbol_filter); 817 thread->mg->machine->symbol_filter);
817 else 818 else
818 al->sym = NULL; 819 al->sym = NULL;
819} 820}
@@ -842,8 +843,7 @@ int perf_event__preprocess_sample(const union perf_event *event,
842 machine->vmlinux_maps[MAP__FUNCTION] == NULL) 843 machine->vmlinux_maps[MAP__FUNCTION] == NULL)
843 machine__create_kernel_maps(machine); 844 machine__create_kernel_maps(machine);
844 845
845 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, 846 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->ip, al);
846 sample->ip, al);
847 dump_printf(" ...... dso: %s\n", 847 dump_printf(" ...... dso: %s\n",
848 al->map ? al->map->dso->long_name : 848 al->map ? al->map->dso->long_name :
849 al->level == 'H' ? "[hypervisor]" : "<not found>"); 849 al->level == 'H' ? "[hypervisor]" : "<not found>");
@@ -902,16 +902,14 @@ bool sample_addr_correlates_sym(struct perf_event_attr *attr)
902 902
903void perf_event__preprocess_sample_addr(union perf_event *event, 903void perf_event__preprocess_sample_addr(union perf_event *event,
904 struct perf_sample *sample, 904 struct perf_sample *sample,
905 struct machine *machine,
906 struct thread *thread, 905 struct thread *thread,
907 struct addr_location *al) 906 struct addr_location *al)
908{ 907{
909 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 908 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
910 909
911 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, 910 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->addr, al);
912 sample->addr, al);
913 if (!al->map) 911 if (!al->map)
914 thread__find_addr_map(thread, machine, cpumode, MAP__VARIABLE, 912 thread__find_addr_map(thread, cpumode, MAP__VARIABLE,
915 sample->addr, al); 913 sample->addr, al);
916 914
917 al->cpu = sample->cpu; 915 al->cpu = sample->cpu;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 5699e7e2a790..09b9e8d3fcf7 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -143,6 +143,32 @@ struct branch_stack {
143 struct branch_entry entries[0]; 143 struct branch_entry entries[0];
144}; 144};
145 145
146enum {
147 PERF_IP_FLAG_BRANCH = 1ULL << 0,
148 PERF_IP_FLAG_CALL = 1ULL << 1,
149 PERF_IP_FLAG_RETURN = 1ULL << 2,
150 PERF_IP_FLAG_CONDITIONAL = 1ULL << 3,
151 PERF_IP_FLAG_SYSCALLRET = 1ULL << 4,
152 PERF_IP_FLAG_ASYNC = 1ULL << 5,
153 PERF_IP_FLAG_INTERRUPT = 1ULL << 6,
154 PERF_IP_FLAG_TX_ABORT = 1ULL << 7,
155 PERF_IP_FLAG_TRACE_BEGIN = 1ULL << 8,
156 PERF_IP_FLAG_TRACE_END = 1ULL << 9,
157 PERF_IP_FLAG_IN_TX = 1ULL << 10,
158};
159
160#define PERF_BRANCH_MASK (\
161 PERF_IP_FLAG_BRANCH |\
162 PERF_IP_FLAG_CALL |\
163 PERF_IP_FLAG_RETURN |\
164 PERF_IP_FLAG_CONDITIONAL |\
165 PERF_IP_FLAG_SYSCALLRET |\
166 PERF_IP_FLAG_ASYNC |\
167 PERF_IP_FLAG_INTERRUPT |\
168 PERF_IP_FLAG_TX_ABORT |\
169 PERF_IP_FLAG_TRACE_BEGIN |\
170 PERF_IP_FLAG_TRACE_END)
171
146struct perf_sample { 172struct perf_sample {
147 u64 ip; 173 u64 ip;
148 u32 pid, tid; 174 u32 pid, tid;
@@ -162,6 +188,7 @@ struct perf_sample {
162 struct ip_callchain *callchain; 188 struct ip_callchain *callchain;
163 struct branch_stack *branch_stack; 189 struct branch_stack *branch_stack;
164 struct regs_dump user_regs; 190 struct regs_dump user_regs;
191 struct regs_dump intr_regs;
165 struct stack_dump user_stack; 192 struct stack_dump user_stack;
166 struct sample_read read; 193 struct sample_read read;
167}; 194};
@@ -187,6 +214,7 @@ enum perf_user_event_type { /* above any possible kernel type */
187 PERF_RECORD_HEADER_TRACING_DATA = 66, 214 PERF_RECORD_HEADER_TRACING_DATA = 66,
188 PERF_RECORD_HEADER_BUILD_ID = 67, 215 PERF_RECORD_HEADER_BUILD_ID = 67,
189 PERF_RECORD_FINISHED_ROUND = 68, 216 PERF_RECORD_FINISHED_ROUND = 68,
217 PERF_RECORD_ID_INDEX = 69,
190 PERF_RECORD_HEADER_MAX 218 PERF_RECORD_HEADER_MAX
191}; 219};
192 220
@@ -239,6 +267,19 @@ struct tracing_data_event {
239 u32 size; 267 u32 size;
240}; 268};
241 269
270struct id_index_entry {
271 u64 id;
272 u64 idx;
273 u64 cpu;
274 u64 tid;
275};
276
277struct id_index_event {
278 struct perf_event_header header;
279 u64 nr;
280 struct id_index_entry entries[0];
281};
282
242union perf_event { 283union perf_event {
243 struct perf_event_header header; 284 struct perf_event_header header;
244 struct mmap_event mmap; 285 struct mmap_event mmap;
@@ -253,6 +294,7 @@ union perf_event {
253 struct event_type_event event_type; 294 struct event_type_event event_type;
254 struct tracing_data_event tracing_data; 295 struct tracing_data_event tracing_data;
255 struct build_id_event build_id; 296 struct build_id_event build_id;
297 struct id_index_event id_index;
256}; 298};
257 299
258void perf_event__print_totals(void); 300void perf_event__print_totals(void);
@@ -322,7 +364,6 @@ bool is_bts_event(struct perf_event_attr *attr);
322bool sample_addr_correlates_sym(struct perf_event_attr *attr); 364bool sample_addr_correlates_sym(struct perf_event_attr *attr);
323void perf_event__preprocess_sample_addr(union perf_event *event, 365void perf_event__preprocess_sample_addr(union perf_event *event,
324 struct perf_sample *sample, 366 struct perf_sample *sample,
325 struct machine *machine,
326 struct thread *thread, 367 struct thread *thread,
327 struct addr_location *al); 368 struct addr_location *al);
328 369
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 3c9e77d6b4c2..cfbe2b99b9aa 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -413,7 +413,7 @@ int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
413 int nfds = 0; 413 int nfds = 0;
414 struct perf_evsel *evsel; 414 struct perf_evsel *evsel;
415 415
416 list_for_each_entry(evsel, &evlist->entries, node) { 416 evlist__for_each(evlist, evsel) {
417 if (evsel->system_wide) 417 if (evsel->system_wide)
418 nfds += nr_cpus; 418 nfds += nr_cpus;
419 else 419 else
@@ -527,6 +527,22 @@ static int perf_evlist__id_add_fd(struct perf_evlist *evlist,
527 return 0; 527 return 0;
528} 528}
529 529
530static void perf_evlist__set_sid_idx(struct perf_evlist *evlist,
531 struct perf_evsel *evsel, int idx, int cpu,
532 int thread)
533{
534 struct perf_sample_id *sid = SID(evsel, cpu, thread);
535 sid->idx = idx;
536 if (evlist->cpus && cpu >= 0)
537 sid->cpu = evlist->cpus->map[cpu];
538 else
539 sid->cpu = -1;
540 if (!evsel->system_wide && evlist->threads && thread >= 0)
541 sid->tid = evlist->threads->map[thread];
542 else
543 sid->tid = -1;
544}
545
530struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id) 546struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id)
531{ 547{
532 struct hlist_head *head; 548 struct hlist_head *head;
@@ -800,14 +816,26 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
800 perf_evlist__mmap_get(evlist, idx); 816 perf_evlist__mmap_get(evlist, idx);
801 } 817 }
802 818
803 if (__perf_evlist__add_pollfd(evlist, fd, idx) < 0) { 819 /*
820 * The system_wide flag causes a selected event to be opened
821 * always without a pid. Consequently it will never get a
822 * POLLHUP, but it is used for tracking in combination with
823 * other events, so it should not need to be polled anyway.
824 * Therefore don't add it for polling.
825 */
826 if (!evsel->system_wide &&
827 __perf_evlist__add_pollfd(evlist, fd, idx) < 0) {
804 perf_evlist__mmap_put(evlist, idx); 828 perf_evlist__mmap_put(evlist, idx);
805 return -1; 829 return -1;
806 } 830 }
807 831
808 if ((evsel->attr.read_format & PERF_FORMAT_ID) && 832 if (evsel->attr.read_format & PERF_FORMAT_ID) {
809 perf_evlist__id_add_fd(evlist, evsel, cpu, thread, fd) < 0) 833 if (perf_evlist__id_add_fd(evlist, evsel, cpu, thread,
810 return -1; 834 fd) < 0)
835 return -1;
836 perf_evlist__set_sid_idx(evlist, evsel, idx, cpu,
837 thread);
838 }
811 } 839 }
812 840
813 return 0; 841 return 0;
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 2f9e68025ede..f2dc91fb87fa 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -658,9 +658,22 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
658 attr->mmap_data = track; 658 attr->mmap_data = track;
659 } 659 }
660 660
661 /*
662 * We don't allow user space callchains for function trace
663 * event, due to issues with page faults while tracing page
664 * fault handler and its overall trickiness nature.
665 */
666 if (perf_evsel__is_function_event(evsel))
667 evsel->attr.exclude_callchain_user = 1;
668
661 if (callchain_param.enabled && !evsel->no_aux_samples) 669 if (callchain_param.enabled && !evsel->no_aux_samples)
662 perf_evsel__config_callgraph(evsel); 670 perf_evsel__config_callgraph(evsel);
663 671
672 if (opts->sample_intr_regs) {
673 attr->sample_regs_intr = PERF_REGS_MASK;
674 perf_evsel__set_sample_bit(evsel, REGS_INTR);
675 }
676
664 if (target__has_cpu(&opts->target)) 677 if (target__has_cpu(&opts->target))
665 perf_evsel__set_sample_bit(evsel, CPU); 678 perf_evsel__set_sample_bit(evsel, CPU);
666 679
@@ -853,8 +866,6 @@ void perf_evsel__exit(struct perf_evsel *evsel)
853 perf_evsel__free_id(evsel); 866 perf_evsel__free_id(evsel);
854 close_cgroup(evsel->cgrp); 867 close_cgroup(evsel->cgrp);
855 zfree(&evsel->group_name); 868 zfree(&evsel->group_name);
856 if (evsel->tp_format)
857 pevent_free_format(evsel->tp_format);
858 zfree(&evsel->name); 869 zfree(&evsel->name);
859 perf_evsel__object.fini(evsel); 870 perf_evsel__object.fini(evsel);
860} 871}
@@ -1039,6 +1050,7 @@ static size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp)
1039 ret += PRINT_ATTR_X64(branch_sample_type); 1050 ret += PRINT_ATTR_X64(branch_sample_type);
1040 ret += PRINT_ATTR_X64(sample_regs_user); 1051 ret += PRINT_ATTR_X64(sample_regs_user);
1041 ret += PRINT_ATTR_U32(sample_stack_user); 1052 ret += PRINT_ATTR_U32(sample_stack_user);
1053 ret += PRINT_ATTR_X64(sample_regs_intr);
1042 1054
1043 ret += fprintf(fp, "%.60s\n", graph_dotted_line); 1055 ret += fprintf(fp, "%.60s\n", graph_dotted_line);
1044 1056
@@ -1538,6 +1550,23 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
1538 array++; 1550 array++;
1539 } 1551 }
1540 1552
1553 data->intr_regs.abi = PERF_SAMPLE_REGS_ABI_NONE;
1554 if (type & PERF_SAMPLE_REGS_INTR) {
1555 OVERFLOW_CHECK_u64(array);
1556 data->intr_regs.abi = *array;
1557 array++;
1558
1559 if (data->intr_regs.abi != PERF_SAMPLE_REGS_ABI_NONE) {
1560 u64 mask = evsel->attr.sample_regs_intr;
1561
1562 sz = hweight_long(mask) * sizeof(u64);
1563 OVERFLOW_CHECK(array, sz, max_size);
1564 data->intr_regs.mask = mask;
1565 data->intr_regs.regs = (u64 *)array;
1566 array = (void *)array + sz;
1567 }
1568 }
1569
1541 return 0; 1570 return 0;
1542} 1571}
1543 1572
@@ -1633,6 +1662,16 @@ size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
1633 if (type & PERF_SAMPLE_TRANSACTION) 1662 if (type & PERF_SAMPLE_TRANSACTION)
1634 result += sizeof(u64); 1663 result += sizeof(u64);
1635 1664
1665 if (type & PERF_SAMPLE_REGS_INTR) {
1666 if (sample->intr_regs.abi) {
1667 result += sizeof(u64);
1668 sz = hweight_long(sample->intr_regs.mask) * sizeof(u64);
1669 result += sz;
1670 } else {
1671 result += sizeof(u64);
1672 }
1673 }
1674
1636 return result; 1675 return result;
1637} 1676}
1638 1677
@@ -1811,6 +1850,17 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
1811 array++; 1850 array++;
1812 } 1851 }
1813 1852
1853 if (type & PERF_SAMPLE_REGS_INTR) {
1854 if (sample->intr_regs.abi) {
1855 *array++ = sample->intr_regs.abi;
1856 sz = hweight_long(sample->intr_regs.mask) * sizeof(u64);
1857 memcpy(array, sample->intr_regs.regs, sz);
1858 array = (void *)array + sz;
1859 } else {
1860 *array++ = 0;
1861 }
1862 }
1863
1814 return 0; 1864 return 0;
1815} 1865}
1816 1866
@@ -1940,7 +1990,7 @@ static int sample_type__fprintf(FILE *fp, bool *first, u64 value)
1940 bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU), 1990 bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU),
1941 bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW), 1991 bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW),
1942 bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER), 1992 bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER),
1943 bit_name(IDENTIFIER), 1993 bit_name(IDENTIFIER), bit_name(REGS_INTR),
1944 { .name = NULL, } 1994 { .name = NULL, }
1945 }; 1995 };
1946#undef bit_name 1996#undef bit_name
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 163c5604e5d1..979790951bfb 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -36,6 +36,9 @@ struct perf_sample_id {
36 struct hlist_node node; 36 struct hlist_node node;
37 u64 id; 37 u64 id;
38 struct perf_evsel *evsel; 38 struct perf_evsel *evsel;
39 int idx;
40 int cpu;
41 pid_t tid;
39 42
40 /* Holds total ID period value for PERF_SAMPLE_READ processing. */ 43 /* Holds total ID period value for PERF_SAMPLE_READ processing. */
41 u64 period; 44 u64 period;
@@ -54,6 +57,7 @@ struct cgroup_sel;
54 * @is_pos: the position (counting backwards) of the event id (PERF_SAMPLE_ID or 57 * @is_pos: the position (counting backwards) of the event id (PERF_SAMPLE_ID or
55 * PERF_SAMPLE_IDENTIFIER) in a non-sample event i.e. if sample_id_all 58 * PERF_SAMPLE_IDENTIFIER) in a non-sample event i.e. if sample_id_all
56 * is used there is an id sample appended to non-sample events 59 * is used there is an id sample appended to non-sample events
60 * @priv: And what is in its containing unnamed union are tool specific
57 */ 61 */
58struct perf_evsel { 62struct perf_evsel {
59 struct list_head node; 63 struct list_head node;
@@ -73,6 +77,7 @@ struct perf_evsel {
73 union { 77 union {
74 void *priv; 78 void *priv;
75 off_t id_offset; 79 off_t id_offset;
80 u64 db_id;
76 }; 81 };
77 struct cgroup_sel *cgrp; 82 struct cgroup_sel *cgrp;
78 void *handler; 83 void *handler;
diff --git a/tools/perf/util/find-vdso-map.c b/tools/perf/util/find-vdso-map.c
new file mode 100644
index 000000000000..95ef1cffc056
--- /dev/null
+++ b/tools/perf/util/find-vdso-map.c
@@ -0,0 +1,30 @@
1static int find_vdso_map(void **start, void **end)
2{
3 FILE *maps;
4 char line[128];
5 int found = 0;
6
7 maps = fopen("/proc/self/maps", "r");
8 if (!maps) {
9 fprintf(stderr, "vdso: cannot open maps\n");
10 return -1;
11 }
12
13 while (!found && fgets(line, sizeof(line), maps)) {
14 int m = -1;
15
16 /* We care only about private r-x mappings. */
17 if (2 != sscanf(line, "%p-%p r-xp %*x %*x:%*x %*u %n",
18 start, end, &m))
19 continue;
20 if (m < 0)
21 continue;
22
23 if (!strncmp(&line[m], VDSO__MAP_NAME,
24 sizeof(VDSO__MAP_NAME) - 1))
25 found = 1;
26 }
27
28 fclose(maps);
29 return !found;
30}
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 26f5b2fe5dc8..b20e40c74468 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -24,8 +24,6 @@
24#include "build-id.h" 24#include "build-id.h"
25#include "data.h" 25#include "data.h"
26 26
27static bool no_buildid_cache = false;
28
29static u32 header_argc; 27static u32 header_argc;
30static const char **header_argv; 28static const char **header_argv;
31 29
@@ -79,10 +77,7 @@ static int do_write(int fd, const void *buf, size_t size)
79 return 0; 77 return 0;
80} 78}
81 79
82#define NAME_ALIGN 64 80int write_padded(int fd, const void *bf, size_t count, size_t count_aligned)
83
84static int write_padded(int fd, const void *bf, size_t count,
85 size_t count_aligned)
86{ 81{
87 static const char zero_buf[NAME_ALIGN]; 82 static const char zero_buf[NAME_ALIGN];
88 int err = do_write(fd, bf, count); 83 int err = do_write(fd, bf, count);
@@ -171,340 +166,6 @@ perf_header__set_cmdline(int argc, const char **argv)
171 return 0; 166 return 0;
172} 167}
173 168
174#define dsos__for_each_with_build_id(pos, head) \
175 list_for_each_entry(pos, head, node) \
176 if (!pos->has_build_id) \
177 continue; \
178 else
179
180static int write_buildid(const char *name, size_t name_len, u8 *build_id,
181 pid_t pid, u16 misc, int fd)
182{
183 int err;
184 struct build_id_event b;
185 size_t len;
186
187 len = name_len + 1;
188 len = PERF_ALIGN(len, NAME_ALIGN);
189
190 memset(&b, 0, sizeof(b));
191 memcpy(&b.build_id, build_id, BUILD_ID_SIZE);
192 b.pid = pid;
193 b.header.misc = misc;
194 b.header.size = sizeof(b) + len;
195
196 err = do_write(fd, &b, sizeof(b));
197 if (err < 0)
198 return err;
199
200 return write_padded(fd, name, name_len + 1, len);
201}
202
203static int __dsos__hit_all(struct list_head *head)
204{
205 struct dso *pos;
206
207 list_for_each_entry(pos, head, node)
208 pos->hit = true;
209
210 return 0;
211}
212
213static int machine__hit_all_dsos(struct machine *machine)
214{
215 int err;
216
217 err = __dsos__hit_all(&machine->kernel_dsos.head);
218 if (err)
219 return err;
220
221 return __dsos__hit_all(&machine->user_dsos.head);
222}
223
224int dsos__hit_all(struct perf_session *session)
225{
226 struct rb_node *nd;
227 int err;
228
229 err = machine__hit_all_dsos(&session->machines.host);
230 if (err)
231 return err;
232
233 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
234 struct machine *pos = rb_entry(nd, struct machine, rb_node);
235
236 err = machine__hit_all_dsos(pos);
237 if (err)
238 return err;
239 }
240
241 return 0;
242}
243
244static int __dsos__write_buildid_table(struct list_head *head,
245 struct machine *machine,
246 pid_t pid, u16 misc, int fd)
247{
248 char nm[PATH_MAX];
249 struct dso *pos;
250
251 dsos__for_each_with_build_id(pos, head) {
252 int err;
253 const char *name;
254 size_t name_len;
255
256 if (!pos->hit)
257 continue;
258
259 if (dso__is_vdso(pos)) {
260 name = pos->short_name;
261 name_len = pos->short_name_len + 1;
262 } else if (dso__is_kcore(pos)) {
263 machine__mmap_name(machine, nm, sizeof(nm));
264 name = nm;
265 name_len = strlen(nm) + 1;
266 } else {
267 name = pos->long_name;
268 name_len = pos->long_name_len + 1;
269 }
270
271 err = write_buildid(name, name_len, pos->build_id,
272 pid, misc, fd);
273 if (err)
274 return err;
275 }
276
277 return 0;
278}
279
280static int machine__write_buildid_table(struct machine *machine, int fd)
281{
282 int err;
283 u16 kmisc = PERF_RECORD_MISC_KERNEL,
284 umisc = PERF_RECORD_MISC_USER;
285
286 if (!machine__is_host(machine)) {
287 kmisc = PERF_RECORD_MISC_GUEST_KERNEL;
288 umisc = PERF_RECORD_MISC_GUEST_USER;
289 }
290
291 err = __dsos__write_buildid_table(&machine->kernel_dsos.head, machine,
292 machine->pid, kmisc, fd);
293 if (err == 0)
294 err = __dsos__write_buildid_table(&machine->user_dsos.head,
295 machine, machine->pid, umisc,
296 fd);
297 return err;
298}
299
300static int dsos__write_buildid_table(struct perf_header *header, int fd)
301{
302 struct perf_session *session = container_of(header,
303 struct perf_session, header);
304 struct rb_node *nd;
305 int err = machine__write_buildid_table(&session->machines.host, fd);
306
307 if (err)
308 return err;
309
310 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
311 struct machine *pos = rb_entry(nd, struct machine, rb_node);
312 err = machine__write_buildid_table(pos, fd);
313 if (err)
314 break;
315 }
316 return err;
317}
318
319int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
320 const char *name, bool is_kallsyms, bool is_vdso)
321{
322 const size_t size = PATH_MAX;
323 char *realname, *filename = zalloc(size),
324 *linkname = zalloc(size), *targetname;
325 int len, err = -1;
326 bool slash = is_kallsyms || is_vdso;
327
328 if (is_kallsyms) {
329 if (symbol_conf.kptr_restrict) {
330 pr_debug("Not caching a kptr_restrict'ed /proc/kallsyms\n");
331 err = 0;
332 goto out_free;
333 }
334 realname = (char *) name;
335 } else
336 realname = realpath(name, NULL);
337
338 if (realname == NULL || filename == NULL || linkname == NULL)
339 goto out_free;
340
341 len = scnprintf(filename, size, "%s%s%s",
342 debugdir, slash ? "/" : "",
343 is_vdso ? DSO__NAME_VDSO : realname);
344 if (mkdir_p(filename, 0755))
345 goto out_free;
346
347 snprintf(filename + len, size - len, "/%s", sbuild_id);
348
349 if (access(filename, F_OK)) {
350 if (is_kallsyms) {
351 if (copyfile("/proc/kallsyms", filename))
352 goto out_free;
353 } else if (link(realname, filename) && copyfile(name, filename))
354 goto out_free;
355 }
356
357 len = scnprintf(linkname, size, "%s/.build-id/%.2s",
358 debugdir, sbuild_id);
359
360 if (access(linkname, X_OK) && mkdir_p(linkname, 0755))
361 goto out_free;
362
363 snprintf(linkname + len, size - len, "/%s", sbuild_id + 2);
364 targetname = filename + strlen(debugdir) - 5;
365 memcpy(targetname, "../..", 5);
366
367 if (symlink(targetname, linkname) == 0)
368 err = 0;
369out_free:
370 if (!is_kallsyms)
371 free(realname);
372 free(filename);
373 free(linkname);
374 return err;
375}
376
377static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
378 const char *name, const char *debugdir,
379 bool is_kallsyms, bool is_vdso)
380{
381 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
382
383 build_id__sprintf(build_id, build_id_size, sbuild_id);
384
385 return build_id_cache__add_s(sbuild_id, debugdir, name,
386 is_kallsyms, is_vdso);
387}
388
389int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
390{
391 const size_t size = PATH_MAX;
392 char *filename = zalloc(size),
393 *linkname = zalloc(size);
394 int err = -1;
395
396 if (filename == NULL || linkname == NULL)
397 goto out_free;
398
399 snprintf(linkname, size, "%s/.build-id/%.2s/%s",
400 debugdir, sbuild_id, sbuild_id + 2);
401
402 if (access(linkname, F_OK))
403 goto out_free;
404
405 if (readlink(linkname, filename, size - 1) < 0)
406 goto out_free;
407
408 if (unlink(linkname))
409 goto out_free;
410
411 /*
412 * Since the link is relative, we must make it absolute:
413 */
414 snprintf(linkname, size, "%s/.build-id/%.2s/%s",
415 debugdir, sbuild_id, filename);
416
417 if (unlink(linkname))
418 goto out_free;
419
420 err = 0;
421out_free:
422 free(filename);
423 free(linkname);
424 return err;
425}
426
427static int dso__cache_build_id(struct dso *dso, struct machine *machine,
428 const char *debugdir)
429{
430 bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
431 bool is_vdso = dso__is_vdso(dso);
432 const char *name = dso->long_name;
433 char nm[PATH_MAX];
434
435 if (dso__is_kcore(dso)) {
436 is_kallsyms = true;
437 machine__mmap_name(machine, nm, sizeof(nm));
438 name = nm;
439 }
440 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name,
441 debugdir, is_kallsyms, is_vdso);
442}
443
444static int __dsos__cache_build_ids(struct list_head *head,
445 struct machine *machine, const char *debugdir)
446{
447 struct dso *pos;
448 int err = 0;
449
450 dsos__for_each_with_build_id(pos, head)
451 if (dso__cache_build_id(pos, machine, debugdir))
452 err = -1;
453
454 return err;
455}
456
457static int machine__cache_build_ids(struct machine *machine, const char *debugdir)
458{
459 int ret = __dsos__cache_build_ids(&machine->kernel_dsos.head, machine,
460 debugdir);
461 ret |= __dsos__cache_build_ids(&machine->user_dsos.head, machine,
462 debugdir);
463 return ret;
464}
465
466static int perf_session__cache_build_ids(struct perf_session *session)
467{
468 struct rb_node *nd;
469 int ret;
470 char debugdir[PATH_MAX];
471
472 snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir);
473
474 if (mkdir(debugdir, 0755) != 0 && errno != EEXIST)
475 return -1;
476
477 ret = machine__cache_build_ids(&session->machines.host, debugdir);
478
479 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
480 struct machine *pos = rb_entry(nd, struct machine, rb_node);
481 ret |= machine__cache_build_ids(pos, debugdir);
482 }
483 return ret ? -1 : 0;
484}
485
486static bool machine__read_build_ids(struct machine *machine, bool with_hits)
487{
488 bool ret;
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);
492 return ret;
493}
494
495static bool perf_session__read_build_ids(struct perf_session *session, bool with_hits)
496{
497 struct rb_node *nd;
498 bool ret = machine__read_build_ids(&session->machines.host, with_hits);
499
500 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
501 struct machine *pos = rb_entry(nd, struct machine, rb_node);
502 ret |= machine__read_build_ids(pos, with_hits);
503 }
504
505 return ret;
506}
507
508static int write_tracing_data(int fd, struct perf_header *h __maybe_unused, 169static int write_tracing_data(int fd, struct perf_header *h __maybe_unused,
509 struct perf_evlist *evlist) 170 struct perf_evlist *evlist)
510{ 171{
@@ -523,13 +184,12 @@ static int write_build_id(int fd, struct perf_header *h,
523 if (!perf_session__read_build_ids(session, true)) 184 if (!perf_session__read_build_ids(session, true))
524 return -1; 185 return -1;
525 186
526 err = dsos__write_buildid_table(h, fd); 187 err = perf_session__write_buildid_table(session, fd);
527 if (err < 0) { 188 if (err < 0) {
528 pr_debug("failed to write buildid table\n"); 189 pr_debug("failed to write buildid table\n");
529 return err; 190 return err;
530 } 191 }
531 if (!no_buildid_cache) 192 perf_session__cache_build_ids(session);
532 perf_session__cache_build_ids(session);
533 193
534 return 0; 194 return 0;
535} 195}
@@ -601,8 +261,10 @@ static int __write_cpudesc(int fd, const char *cpuinfo_proc)
601 break; 261 break;
602 } 262 }
603 263
604 if (ret) 264 if (ret) {
265 ret = -1;
605 goto done; 266 goto done;
267 }
606 268
607 s = buf; 269 s = buf;
608 270
@@ -965,7 +627,8 @@ static int write_total_mem(int fd, struct perf_header *h __maybe_unused,
965 n = sscanf(buf, "%*s %"PRIu64, &mem); 627 n = sscanf(buf, "%*s %"PRIu64, &mem);
966 if (n == 1) 628 if (n == 1)
967 ret = do_write(fd, &mem, sizeof(mem)); 629 ret = do_write(fd, &mem, sizeof(mem));
968 } 630 } else
631 ret = -1;
969 free(buf); 632 free(buf);
970 fclose(fp); 633 fclose(fp);
971 return ret; 634 return ret;
@@ -1603,7 +1266,7 @@ static int __event_process_build_id(struct build_id_event *bev,
1603 1266
1604 dso__set_build_id(dso, &bev->build_id); 1267 dso__set_build_id(dso, &bev->build_id);
1605 1268
1606 if (filename[0] == '[') 1269 if (!is_kernel_module(filename, NULL))
1607 dso->kernel = dso_type; 1270 dso->kernel = dso_type;
1608 1271
1609 build_id__sprintf(dso->build_id, sizeof(dso->build_id), 1272 build_id__sprintf(dso->build_id, sizeof(dso->build_id),
@@ -2477,6 +2140,7 @@ static const int attr_file_abi_sizes[] = {
2477 [1] = PERF_ATTR_SIZE_VER1, 2140 [1] = PERF_ATTR_SIZE_VER1,
2478 [2] = PERF_ATTR_SIZE_VER2, 2141 [2] = PERF_ATTR_SIZE_VER2,
2479 [3] = PERF_ATTR_SIZE_VER3, 2142 [3] = PERF_ATTR_SIZE_VER3,
2143 [4] = PERF_ATTR_SIZE_VER4,
2480 0, 2144 0,
2481}; 2145};
2482 2146
@@ -3124,8 +2788,3 @@ int perf_event__process_build_id(struct perf_tool *tool __maybe_unused,
3124 session); 2788 session);
3125 return 0; 2789 return 0;
3126} 2790}
3127
3128void disable_buildid_cache(void)
3129{
3130 no_buildid_cache = true;
3131}
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 8f5cbaea64a5..3bb90ac172a1 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -122,10 +122,6 @@ int perf_header__process_sections(struct perf_header *header, int fd,
122 122
123int perf_header__fprintf_info(struct perf_session *s, FILE *fp, bool full); 123int perf_header__fprintf_info(struct perf_session *s, FILE *fp, bool full);
124 124
125int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
126 const char *name, bool is_kallsyms, bool is_vdso);
127int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir);
128
129int perf_event__synthesize_attr(struct perf_tool *tool, 125int perf_event__synthesize_attr(struct perf_tool *tool,
130 struct perf_event_attr *attr, u32 ids, u64 *id, 126 struct perf_event_attr *attr, u32 ids, u64 *id,
131 perf_event__handler_t process); 127 perf_event__handler_t process);
@@ -151,7 +147,9 @@ int perf_event__process_build_id(struct perf_tool *tool,
151 struct perf_session *session); 147 struct perf_session *session);
152bool is_perf_magic(u64 magic); 148bool is_perf_magic(u64 magic);
153 149
154int dsos__hit_all(struct perf_session *session); 150#define NAME_ALIGN 64
151
152int write_padded(int fd, const void *bf, size_t count, size_t count_aligned);
155 153
156/* 154/*
157 * arch specific callback 155 * arch specific callback
diff --git a/tools/perf/util/include/linux/bitmap.h b/tools/perf/util/include/linux/bitmap.h
index 01ffd12dc791..40bd21488032 100644
--- a/tools/perf/util/include/linux/bitmap.h
+++ b/tools/perf/util/include/linux/bitmap.h
@@ -46,4 +46,21 @@ static inline void bitmap_or(unsigned long *dst, const unsigned long *src1,
46 __bitmap_or(dst, src1, src2, nbits); 46 __bitmap_or(dst, src1, src2, nbits);
47} 47}
48 48
49/**
50 * test_and_set_bit - Set a bit and return its old value
51 * @nr: Bit to set
52 * @addr: Address to count from
53 */
54static inline int test_and_set_bit(int nr, unsigned long *addr)
55{
56 unsigned long mask = BIT_MASK(nr);
57 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
58 unsigned long old;
59
60 old = *p;
61 *p = old | mask;
62
63 return (old & mask) != 0;
64}
65
49#endif /* _PERF_BITOPS_H */ 66#endif /* _PERF_BITOPS_H */
diff --git a/tools/perf/util/include/linux/bitops.h b/tools/perf/util/include/linux/bitops.h
index dadfa7e54287..c3294163de17 100644
--- a/tools/perf/util/include/linux/bitops.h
+++ b/tools/perf/util/include/linux/bitops.h
@@ -15,6 +15,8 @@
15#define BITS_TO_U64(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u64)) 15#define BITS_TO_U64(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u64))
16#define BITS_TO_U32(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u32)) 16#define BITS_TO_U32(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u32))
17#define BITS_TO_BYTES(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE) 17#define BITS_TO_BYTES(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE)
18#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
19#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
18 20
19#define for_each_set_bit(bit, addr, size) \ 21#define for_each_set_bit(bit, addr, size) \
20 for ((bit) = find_first_bit((addr), (size)); \ 22 for ((bit) = find_first_bit((addr), (size)); \
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 34fc7c8672e4..d97309c87bd6 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -21,7 +21,7 @@ static void dsos__init(struct dsos *dsos)
21 21
22int machine__init(struct machine *machine, const char *root_dir, pid_t pid) 22int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
23{ 23{
24 map_groups__init(&machine->kmaps); 24 map_groups__init(&machine->kmaps, machine);
25 RB_CLEAR_NODE(&machine->rb_node); 25 RB_CLEAR_NODE(&machine->rb_node);
26 dsos__init(&machine->user_dsos); 26 dsos__init(&machine->user_dsos);
27 dsos__init(&machine->kernel_dsos); 27 dsos__init(&machine->kernel_dsos);
@@ -32,7 +32,6 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
32 32
33 machine->vdso_info = NULL; 33 machine->vdso_info = NULL;
34 34
35 machine->kmaps.machine = machine;
36 machine->pid = pid; 35 machine->pid = pid;
37 36
38 machine->symbol_filter = NULL; 37 machine->symbol_filter = NULL;
@@ -319,7 +318,7 @@ static void machine__update_thread_pid(struct machine *machine,
319 goto out_err; 318 goto out_err;
320 319
321 if (!leader->mg) 320 if (!leader->mg)
322 leader->mg = map_groups__new(); 321 leader->mg = map_groups__new(machine);
323 322
324 if (!leader->mg) 323 if (!leader->mg)
325 goto out_err; 324 goto out_err;
@@ -465,6 +464,7 @@ struct map *machine__new_module(struct machine *machine, u64 start,
465{ 464{
466 struct map *map; 465 struct map *map;
467 struct dso *dso = __dsos__findnew(&machine->kernel_dsos, filename); 466 struct dso *dso = __dsos__findnew(&machine->kernel_dsos, filename);
467 bool compressed;
468 468
469 if (dso == NULL) 469 if (dso == NULL)
470 return NULL; 470 return NULL;
@@ -477,6 +477,11 @@ struct map *machine__new_module(struct machine *machine, u64 start,
477 dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE; 477 dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE;
478 else 478 else
479 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE; 479 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
480
481 /* _KMODULE_COMP should be next to _KMODULE */
482 if (is_kernel_module(filename, &compressed) && compressed)
483 dso->symtab_type++;
484
480 map_groups__insert(&machine->kmaps, map); 485 map_groups__insert(&machine->kmaps, map);
481 return map; 486 return map;
482} 487}
@@ -862,8 +867,14 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg,
862 struct map *map; 867 struct map *map;
863 char *long_name; 868 char *long_name;
864 869
865 if (dot == NULL || strcmp(dot, ".ko")) 870 if (dot == NULL)
866 continue; 871 continue;
872
873 /* On some system, modules are compressed like .ko.gz */
874 if (is_supported_compression(dot + 1) &&
875 is_kmodule_extension(dot - 2))
876 dot -= 3;
877
867 snprintf(dso_name, sizeof(dso_name), "[%.*s]", 878 snprintf(dso_name, sizeof(dso_name), "[%.*s]",
868 (int)(dot - dent->d_name), dent->d_name); 879 (int)(dot - dent->d_name), dent->d_name);
869 880
@@ -1045,6 +1056,11 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1045 dot = strrchr(name, '.'); 1056 dot = strrchr(name, '.');
1046 if (dot == NULL) 1057 if (dot == NULL)
1047 goto out_problem; 1058 goto out_problem;
1059 /* On some system, modules are compressed like .ko.gz */
1060 if (is_supported_compression(dot + 1))
1061 dot -= 3;
1062 if (!is_kmodule_extension(dot + 1))
1063 goto out_problem;
1048 snprintf(short_module_name, sizeof(short_module_name), 1064 snprintf(short_module_name, sizeof(short_module_name),
1049 "[%.*s]", (int)(dot - name), name); 1065 "[%.*s]", (int)(dot - name), name);
1050 strxfrchar(short_module_name, '-', '_'); 1066 strxfrchar(short_module_name, '-', '_');
@@ -1069,8 +1085,20 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1069 * Should be there already, from the build-id table in 1085 * Should be there already, from the build-id table in
1070 * the header. 1086 * the header.
1071 */ 1087 */
1072 struct dso *kernel = __dsos__findnew(&machine->kernel_dsos, 1088 struct dso *kernel = NULL;
1073 kmmap_prefix); 1089 struct dso *dso;
1090
1091 list_for_each_entry(dso, &machine->kernel_dsos.head, node) {
1092 if (is_kernel_module(dso->long_name, NULL))
1093 continue;
1094
1095 kernel = dso;
1096 break;
1097 }
1098
1099 if (kernel == NULL)
1100 kernel = __dsos__findnew(&machine->kernel_dsos,
1101 kmmap_prefix);
1074 if (kernel == NULL) 1102 if (kernel == NULL)
1075 goto out_problem; 1103 goto out_problem;
1076 1104
@@ -1078,6 +1106,9 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1078 if (__machine__create_kernel_maps(machine, kernel) < 0) 1106 if (__machine__create_kernel_maps(machine, kernel) < 0)
1079 goto out_problem; 1107 goto out_problem;
1080 1108
1109 if (strstr(dso->long_name, "vmlinux"))
1110 dso__set_short_name(dso, "[kernel.vmlinux]", false);
1111
1081 machine__set_kernel_mmap_len(machine, event); 1112 machine__set_kernel_mmap_len(machine, event);
1082 1113
1083 /* 1114 /*
@@ -1290,7 +1321,7 @@ static bool symbol__match_regex(struct symbol *sym, regex_t *regex)
1290 return 0; 1321 return 0;
1291} 1322}
1292 1323
1293static void ip__resolve_ams(struct machine *machine, struct thread *thread, 1324static void ip__resolve_ams(struct thread *thread,
1294 struct addr_map_symbol *ams, 1325 struct addr_map_symbol *ams,
1295 u64 ip) 1326 u64 ip)
1296{ 1327{
@@ -1304,7 +1335,7 @@ static void ip__resolve_ams(struct machine *machine, struct thread *thread,
1304 * Thus, we have to try consecutively until we find a match 1335 * Thus, we have to try consecutively until we find a match
1305 * or else, the symbol is unknown 1336 * or else, the symbol is unknown
1306 */ 1337 */
1307 thread__find_cpumode_addr_location(thread, machine, MAP__FUNCTION, ip, &al); 1338 thread__find_cpumode_addr_location(thread, MAP__FUNCTION, ip, &al);
1308 1339
1309 ams->addr = ip; 1340 ams->addr = ip;
1310 ams->al_addr = al.addr; 1341 ams->al_addr = al.addr;
@@ -1312,23 +1343,21 @@ static void ip__resolve_ams(struct machine *machine, struct thread *thread,
1312 ams->map = al.map; 1343 ams->map = al.map;
1313} 1344}
1314 1345
1315static void ip__resolve_data(struct machine *machine, struct thread *thread, 1346static void ip__resolve_data(struct thread *thread,
1316 u8 m, struct addr_map_symbol *ams, u64 addr) 1347 u8 m, struct addr_map_symbol *ams, u64 addr)
1317{ 1348{
1318 struct addr_location al; 1349 struct addr_location al;
1319 1350
1320 memset(&al, 0, sizeof(al)); 1351 memset(&al, 0, sizeof(al));
1321 1352
1322 thread__find_addr_location(thread, machine, m, MAP__VARIABLE, addr, 1353 thread__find_addr_location(thread, m, MAP__VARIABLE, addr, &al);
1323 &al);
1324 if (al.map == NULL) { 1354 if (al.map == NULL) {
1325 /* 1355 /*
1326 * some shared data regions have execute bit set which puts 1356 * some shared data regions have execute bit set which puts
1327 * their mapping in the MAP__FUNCTION type array. 1357 * their mapping in the MAP__FUNCTION type array.
1328 * Check there as a fallback option before dropping the sample. 1358 * Check there as a fallback option before dropping the sample.
1329 */ 1359 */
1330 thread__find_addr_location(thread, machine, m, MAP__FUNCTION, addr, 1360 thread__find_addr_location(thread, m, MAP__FUNCTION, addr, &al);
1331 &al);
1332 } 1361 }
1333 1362
1334 ams->addr = addr; 1363 ams->addr = addr;
@@ -1345,14 +1374,41 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample,
1345 if (!mi) 1374 if (!mi)
1346 return NULL; 1375 return NULL;
1347 1376
1348 ip__resolve_ams(al->machine, al->thread, &mi->iaddr, sample->ip); 1377 ip__resolve_ams(al->thread, &mi->iaddr, sample->ip);
1349 ip__resolve_data(al->machine, al->thread, al->cpumode, 1378 ip__resolve_data(al->thread, al->cpumode, &mi->daddr, sample->addr);
1350 &mi->daddr, sample->addr);
1351 mi->data_src.val = sample->data_src; 1379 mi->data_src.val = sample->data_src;
1352 1380
1353 return mi; 1381 return mi;
1354} 1382}
1355 1383
1384static int add_callchain_ip(struct thread *thread,
1385 struct symbol **parent,
1386 struct addr_location *root_al,
1387 int cpumode,
1388 u64 ip)
1389{
1390 struct addr_location al;
1391
1392 al.filtered = 0;
1393 al.sym = NULL;
1394 thread__find_addr_location(thread, cpumode, MAP__FUNCTION,
1395 ip, &al);
1396 if (al.sym != NULL) {
1397 if (sort__has_parent && !*parent &&
1398 symbol__match_regex(al.sym, &parent_regex))
1399 *parent = al.sym;
1400 else if (have_ignore_callees && root_al &&
1401 symbol__match_regex(al.sym, &ignore_callees_regex)) {
1402 /* Treat this symbol as the root,
1403 forgetting its callees. */
1404 *root_al = al;
1405 callchain_cursor_reset(&callchain_cursor);
1406 }
1407 }
1408
1409 return callchain_cursor_append(&callchain_cursor, al.addr, al.map, al.sym);
1410}
1411
1356struct branch_info *sample__resolve_bstack(struct perf_sample *sample, 1412struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
1357 struct addr_location *al) 1413 struct addr_location *al)
1358{ 1414{
@@ -1364,15 +1420,14 @@ struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
1364 return NULL; 1420 return NULL;
1365 1421
1366 for (i = 0; i < bs->nr; i++) { 1422 for (i = 0; i < bs->nr; i++) {
1367 ip__resolve_ams(al->machine, al->thread, &bi[i].to, bs->entries[i].to); 1423 ip__resolve_ams(al->thread, &bi[i].to, bs->entries[i].to);
1368 ip__resolve_ams(al->machine, al->thread, &bi[i].from, bs->entries[i].from); 1424 ip__resolve_ams(al->thread, &bi[i].from, bs->entries[i].from);
1369 bi[i].flags = bs->entries[i].flags; 1425 bi[i].flags = bs->entries[i].flags;
1370 } 1426 }
1371 return bi; 1427 return bi;
1372} 1428}
1373 1429
1374static int machine__resolve_callchain_sample(struct machine *machine, 1430static int thread__resolve_callchain_sample(struct thread *thread,
1375 struct thread *thread,
1376 struct ip_callchain *chain, 1431 struct ip_callchain *chain,
1377 struct symbol **parent, 1432 struct symbol **parent,
1378 struct addr_location *root_al, 1433 struct addr_location *root_al,
@@ -1396,11 +1451,10 @@ static int machine__resolve_callchain_sample(struct machine *machine,
1396 * Based on DWARF debug information, some architectures skip 1451 * Based on DWARF debug information, some architectures skip
1397 * a callchain entry saved by the kernel. 1452 * a callchain entry saved by the kernel.
1398 */ 1453 */
1399 skip_idx = arch_skip_callchain_idx(machine, thread, chain); 1454 skip_idx = arch_skip_callchain_idx(thread, chain);
1400 1455
1401 for (i = 0; i < chain_nr; i++) { 1456 for (i = 0; i < chain_nr; i++) {
1402 u64 ip; 1457 u64 ip;
1403 struct addr_location al;
1404 1458
1405 if (callchain_param.order == ORDER_CALLEE) 1459 if (callchain_param.order == ORDER_CALLEE)
1406 j = i; 1460 j = i;
@@ -1437,24 +1491,10 @@ static int machine__resolve_callchain_sample(struct machine *machine,
1437 continue; 1491 continue;
1438 } 1492 }
1439 1493
1440 al.filtered = 0; 1494 err = add_callchain_ip(thread, parent, root_al,
1441 thread__find_addr_location(thread, machine, cpumode, 1495 cpumode, ip);
1442 MAP__FUNCTION, ip, &al); 1496 if (err == -EINVAL)
1443 if (al.sym != NULL) { 1497 break;
1444 if (sort__has_parent && !*parent &&
1445 symbol__match_regex(al.sym, &parent_regex))
1446 *parent = al.sym;
1447 else if (have_ignore_callees && root_al &&
1448 symbol__match_regex(al.sym, &ignore_callees_regex)) {
1449 /* Treat this symbol as the root,
1450 forgetting its callees. */
1451 *root_al = al;
1452 callchain_cursor_reset(&callchain_cursor);
1453 }
1454 }
1455
1456 err = callchain_cursor_append(&callchain_cursor,
1457 ip, al.map, al.sym);
1458 if (err) 1498 if (err)
1459 return err; 1499 return err;
1460 } 1500 }
@@ -1469,19 +1509,15 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
1469 entry->map, entry->sym); 1509 entry->map, entry->sym);
1470} 1510}
1471 1511
1472int machine__resolve_callchain(struct machine *machine, 1512int thread__resolve_callchain(struct thread *thread,
1473 struct perf_evsel *evsel, 1513 struct perf_evsel *evsel,
1474 struct thread *thread, 1514 struct perf_sample *sample,
1475 struct perf_sample *sample, 1515 struct symbol **parent,
1476 struct symbol **parent, 1516 struct addr_location *root_al,
1477 struct addr_location *root_al, 1517 int max_stack)
1478 int max_stack)
1479{ 1518{
1480 int ret; 1519 int ret = thread__resolve_callchain_sample(thread, sample->callchain,
1481 1520 parent, root_al, max_stack);
1482 ret = machine__resolve_callchain_sample(machine, thread,
1483 sample->callchain, parent,
1484 root_al, max_stack);
1485 if (ret) 1521 if (ret)
1486 return ret; 1522 return ret;
1487 1523
@@ -1495,7 +1531,7 @@ int machine__resolve_callchain(struct machine *machine,
1495 (!sample->user_stack.size)) 1531 (!sample->user_stack.size))
1496 return 0; 1532 return 0;
1497 1533
1498 return unwind__get_entries(unwind_entry, &callchain_cursor, machine, 1534 return unwind__get_entries(unwind_entry, &callchain_cursor,
1499 thread, sample, max_stack); 1535 thread, sample, max_stack);
1500 1536
1501} 1537}
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 2b651a7f5d0d..e8b7779a0a3f 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -40,6 +40,10 @@ struct machine {
40 u64 kernel_start; 40 u64 kernel_start;
41 symbol_filter_t symbol_filter; 41 symbol_filter_t symbol_filter;
42 pid_t *current_tid; 42 pid_t *current_tid;
43 union { /* Tool specific area */
44 void *priv;
45 u64 db_id;
46 };
43}; 47};
44 48
45static inline 49static inline
@@ -122,13 +126,12 @@ struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
122 struct addr_location *al); 126 struct addr_location *al);
123struct mem_info *sample__resolve_mem(struct perf_sample *sample, 127struct mem_info *sample__resolve_mem(struct perf_sample *sample,
124 struct addr_location *al); 128 struct addr_location *al);
125int machine__resolve_callchain(struct machine *machine, 129int thread__resolve_callchain(struct thread *thread,
126 struct perf_evsel *evsel, 130 struct perf_evsel *evsel,
127 struct thread *thread, 131 struct perf_sample *sample,
128 struct perf_sample *sample, 132 struct symbol **parent,
129 struct symbol **parent, 133 struct addr_location *root_al,
130 struct addr_location *root_al, 134 int max_stack);
131 int max_stack);
132 135
133/* 136/*
134 * Default guest kernel is defined by parameter --guestkallsyms 137 * Default guest kernel is defined by parameter --guestkallsyms
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 2137c4596ec7..040a785c857b 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -413,14 +413,14 @@ u64 map__objdump_2mem(struct map *map, u64 ip)
413 return ip + map->reloc; 413 return ip + map->reloc;
414} 414}
415 415
416void map_groups__init(struct map_groups *mg) 416void map_groups__init(struct map_groups *mg, struct machine *machine)
417{ 417{
418 int i; 418 int i;
419 for (i = 0; i < MAP__NR_TYPES; ++i) { 419 for (i = 0; i < MAP__NR_TYPES; ++i) {
420 mg->maps[i] = RB_ROOT; 420 mg->maps[i] = RB_ROOT;
421 INIT_LIST_HEAD(&mg->removed_maps[i]); 421 INIT_LIST_HEAD(&mg->removed_maps[i]);
422 } 422 }
423 mg->machine = NULL; 423 mg->machine = machine;
424 mg->refcnt = 1; 424 mg->refcnt = 1;
425} 425}
426 426
@@ -471,12 +471,12 @@ bool map_groups__empty(struct map_groups *mg)
471 return true; 471 return true;
472} 472}
473 473
474struct map_groups *map_groups__new(void) 474struct map_groups *map_groups__new(struct machine *machine)
475{ 475{
476 struct map_groups *mg = malloc(sizeof(*mg)); 476 struct map_groups *mg = malloc(sizeof(*mg));
477 477
478 if (mg != NULL) 478 if (mg != NULL)
479 map_groups__init(mg); 479 map_groups__init(mg, machine);
480 480
481 return mg; 481 return mg;
482} 482}
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 2f83954af050..6951a9d42339 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -64,7 +64,7 @@ struct map_groups {
64 int refcnt; 64 int refcnt;
65}; 65};
66 66
67struct map_groups *map_groups__new(void); 67struct map_groups *map_groups__new(struct machine *machine);
68void map_groups__delete(struct map_groups *mg); 68void map_groups__delete(struct map_groups *mg);
69bool map_groups__empty(struct map_groups *mg); 69bool map_groups__empty(struct map_groups *mg);
70 70
@@ -150,7 +150,7 @@ void maps__remove(struct rb_root *maps, struct map *map);
150struct map *maps__find(struct rb_root *maps, u64 addr); 150struct map *maps__find(struct rb_root *maps, u64 addr);
151struct map *maps__first(struct rb_root *maps); 151struct map *maps__first(struct rb_root *maps);
152struct map *maps__next(struct map *map); 152struct map *maps__next(struct map *map);
153void map_groups__init(struct map_groups *mg); 153void map_groups__init(struct map_groups *mg, struct machine *machine);
154void map_groups__exit(struct map_groups *mg); 154void map_groups__exit(struct map_groups *mg);
155int map_groups__clone(struct map_groups *mg, 155int map_groups__clone(struct map_groups *mg,
156 struct map_groups *parent, enum map_type type); 156 struct map_groups *parent, enum map_type type);
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index c659a3ca1283..efa1ff4cca63 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -526,7 +526,7 @@ do { \
526} 526}
527 527
528int parse_events_add_breakpoint(struct list_head *list, int *idx, 528int parse_events_add_breakpoint(struct list_head *list, int *idx,
529 void *ptr, char *type) 529 void *ptr, char *type, u64 len)
530{ 530{
531 struct perf_event_attr attr; 531 struct perf_event_attr attr;
532 532
@@ -536,14 +536,15 @@ int parse_events_add_breakpoint(struct list_head *list, int *idx,
536 if (parse_breakpoint_type(type, &attr)) 536 if (parse_breakpoint_type(type, &attr))
537 return -EINVAL; 537 return -EINVAL;
538 538
539 /* 539 /* Provide some defaults if len is not specified */
540 * We should find a nice way to override the access length 540 if (!len) {
541 * Provide some defaults for now 541 if (attr.bp_type == HW_BREAKPOINT_X)
542 */ 542 len = sizeof(long);
543 if (attr.bp_type == HW_BREAKPOINT_X) 543 else
544 attr.bp_len = sizeof(long); 544 len = HW_BREAKPOINT_LEN_4;
545 else 545 }
546 attr.bp_len = HW_BREAKPOINT_LEN_4; 546
547 attr.bp_len = len;
547 548
548 attr.type = PERF_TYPE_BREAKPOINT; 549 attr.type = PERF_TYPE_BREAKPOINT;
549 attr.sample_period = 1; 550 attr.sample_period = 1;
@@ -1364,7 +1365,7 @@ void print_events(const char *event_glob, bool name_only)
1364 printf("\n"); 1365 printf("\n");
1365 1366
1366 printf(" %-50s [%s]\n", 1367 printf(" %-50s [%s]\n",
1367 "mem:<addr>[:access]", 1368 "mem:<addr>[/len][:access]",
1368 event_type_descriptors[PERF_TYPE_BREAKPOINT]); 1369 event_type_descriptors[PERF_TYPE_BREAKPOINT]);
1369 printf("\n"); 1370 printf("\n");
1370 } 1371 }
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index db2cf78ff0f3..a19fbeb80943 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -104,7 +104,7 @@ int parse_events_add_numeric(struct list_head *list, int *idx,
104int parse_events_add_cache(struct list_head *list, int *idx, 104int parse_events_add_cache(struct list_head *list, int *idx,
105 char *type, char *op_result1, char *op_result2); 105 char *type, char *op_result1, char *op_result2);
106int parse_events_add_breakpoint(struct list_head *list, int *idx, 106int parse_events_add_breakpoint(struct list_head *list, int *idx,
107 void *ptr, char *type); 107 void *ptr, char *type, u64 len);
108int parse_events_add_pmu(struct list_head *list, int *idx, 108int parse_events_add_pmu(struct list_head *list, int *idx,
109 char *pmu , struct list_head *head_config); 109 char *pmu , struct list_head *head_config);
110enum perf_pmu_event_symbol_type 110enum perf_pmu_event_symbol_type
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 906630bbf8eb..94eacb6c1ef7 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -159,6 +159,7 @@ branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE
159<mem>{ 159<mem>{
160{modifier_bp} { return str(yyscanner, PE_MODIFIER_BP); } 160{modifier_bp} { return str(yyscanner, PE_MODIFIER_BP); }
161: { return ':'; } 161: { return ':'; }
162"/" { return '/'; }
162{num_dec} { return value(yyscanner, 10); } 163{num_dec} { return value(yyscanner, 10); }
163{num_hex} { return value(yyscanner, 16); } 164{num_hex} { return value(yyscanner, 16); }
164 /* 165 /*
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 93c4c9fbc922..72def077dbbf 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -326,6 +326,28 @@ PE_NAME_CACHE_TYPE
326} 326}
327 327
328event_legacy_mem: 328event_legacy_mem:
329PE_PREFIX_MEM PE_VALUE '/' PE_VALUE ':' PE_MODIFIER_BP sep_dc
330{
331 struct parse_events_evlist *data = _data;
332 struct list_head *list;
333
334 ALLOC_LIST(list);
335 ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
336 (void *) $2, $6, $4));
337 $$ = list;
338}
339|
340PE_PREFIX_MEM PE_VALUE '/' PE_VALUE sep_dc
341{
342 struct parse_events_evlist *data = _data;
343 struct list_head *list;
344
345 ALLOC_LIST(list);
346 ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
347 (void *) $2, NULL, $4));
348 $$ = list;
349}
350|
329PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc 351PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc
330{ 352{
331 struct parse_events_evlist *data = _data; 353 struct parse_events_evlist *data = _data;
@@ -333,7 +355,7 @@ PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc
333 355
334 ALLOC_LIST(list); 356 ALLOC_LIST(list);
335 ABORT_ON(parse_events_add_breakpoint(list, &data->idx, 357 ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
336 (void *) $2, $4)); 358 (void *) $2, $4, 0));
337 $$ = list; 359 $$ = list;
338} 360}
339| 361|
@@ -344,7 +366,7 @@ PE_PREFIX_MEM PE_VALUE sep_dc
344 366
345 ALLOC_LIST(list); 367 ALLOC_LIST(list);
346 ABORT_ON(parse_events_add_breakpoint(list, &data->idx, 368 ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
347 (void *) $2, NULL)); 369 (void *) $2, NULL, 0));
348 $$ = list; 370 $$ = list;
349} 371}
350 372
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
index bf48092983c6..f62dee7bd924 100644
--- a/tools/perf/util/parse-options.c
+++ b/tools/perf/util/parse-options.c
@@ -42,7 +42,26 @@ static int get_value(struct parse_opt_ctx_t *p,
42 return opterror(opt, "takes no value", flags); 42 return opterror(opt, "takes no value", flags);
43 if (unset && (opt->flags & PARSE_OPT_NONEG)) 43 if (unset && (opt->flags & PARSE_OPT_NONEG))
44 return opterror(opt, "isn't available", flags); 44 return opterror(opt, "isn't available", flags);
45 45 if (opt->flags & PARSE_OPT_DISABLED)
46 return opterror(opt, "is not usable", flags);
47
48 if (opt->flags & PARSE_OPT_EXCLUSIVE) {
49 if (p->excl_opt) {
50 char msg[128];
51
52 if (((flags & OPT_SHORT) && p->excl_opt->short_name) ||
53 p->excl_opt->long_name == NULL) {
54 scnprintf(msg, sizeof(msg), "cannot be used with switch `%c'",
55 p->excl_opt->short_name);
56 } else {
57 scnprintf(msg, sizeof(msg), "cannot be used with %s",
58 p->excl_opt->long_name);
59 }
60 opterror(opt, msg, flags);
61 return -3;
62 }
63 p->excl_opt = opt;
64 }
46 if (!(flags & OPT_SHORT) && p->opt) { 65 if (!(flags & OPT_SHORT) && p->opt) {
47 switch (opt->type) { 66 switch (opt->type) {
48 case OPTION_CALLBACK: 67 case OPTION_CALLBACK:
@@ -343,13 +362,14 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
343 const char * const usagestr[]) 362 const char * const usagestr[])
344{ 363{
345 int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP); 364 int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP);
365 int excl_short_opt = 1;
366 const char *arg;
346 367
347 /* we must reset ->opt, unknown short option leave it dangling */ 368 /* we must reset ->opt, unknown short option leave it dangling */
348 ctx->opt = NULL; 369 ctx->opt = NULL;
349 370
350 for (; ctx->argc; ctx->argc--, ctx->argv++) { 371 for (; ctx->argc; ctx->argc--, ctx->argv++) {
351 const char *arg = ctx->argv[0]; 372 arg = ctx->argv[0];
352
353 if (*arg != '-' || !arg[1]) { 373 if (*arg != '-' || !arg[1]) {
354 if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION) 374 if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION)
355 break; 375 break;
@@ -358,19 +378,21 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
358 } 378 }
359 379
360 if (arg[1] != '-') { 380 if (arg[1] != '-') {
361 ctx->opt = arg + 1; 381 ctx->opt = ++arg;
362 if (internal_help && *ctx->opt == 'h') 382 if (internal_help && *ctx->opt == 'h')
363 return usage_with_options_internal(usagestr, options, 0); 383 return usage_with_options_internal(usagestr, options, 0);
364 switch (parse_short_opt(ctx, options)) { 384 switch (parse_short_opt(ctx, options)) {
365 case -1: 385 case -1:
366 return parse_options_usage(usagestr, options, arg + 1, 1); 386 return parse_options_usage(usagestr, options, arg, 1);
367 case -2: 387 case -2:
368 goto unknown; 388 goto unknown;
389 case -3:
390 goto exclusive;
369 default: 391 default:
370 break; 392 break;
371 } 393 }
372 if (ctx->opt) 394 if (ctx->opt)
373 check_typos(arg + 1, options); 395 check_typos(arg, options);
374 while (ctx->opt) { 396 while (ctx->opt) {
375 if (internal_help && *ctx->opt == 'h') 397 if (internal_help && *ctx->opt == 'h')
376 return usage_with_options_internal(usagestr, options, 0); 398 return usage_with_options_internal(usagestr, options, 0);
@@ -387,6 +409,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
387 ctx->argv[0] = strdup(ctx->opt - 1); 409 ctx->argv[0] = strdup(ctx->opt - 1);
388 *(char *)ctx->argv[0] = '-'; 410 *(char *)ctx->argv[0] = '-';
389 goto unknown; 411 goto unknown;
412 case -3:
413 goto exclusive;
390 default: 414 default:
391 break; 415 break;
392 } 416 }
@@ -402,19 +426,23 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
402 break; 426 break;
403 } 427 }
404 428
405 if (internal_help && !strcmp(arg + 2, "help-all")) 429 arg += 2;
430 if (internal_help && !strcmp(arg, "help-all"))
406 return usage_with_options_internal(usagestr, options, 1); 431 return usage_with_options_internal(usagestr, options, 1);
407 if (internal_help && !strcmp(arg + 2, "help")) 432 if (internal_help && !strcmp(arg, "help"))
408 return usage_with_options_internal(usagestr, options, 0); 433 return usage_with_options_internal(usagestr, options, 0);
409 if (!strcmp(arg + 2, "list-opts")) 434 if (!strcmp(arg, "list-opts"))
410 return PARSE_OPT_LIST_OPTS; 435 return PARSE_OPT_LIST_OPTS;
411 if (!strcmp(arg + 2, "list-cmds")) 436 if (!strcmp(arg, "list-cmds"))
412 return PARSE_OPT_LIST_SUBCMDS; 437 return PARSE_OPT_LIST_SUBCMDS;
413 switch (parse_long_opt(ctx, arg + 2, options)) { 438 switch (parse_long_opt(ctx, arg, options)) {
414 case -1: 439 case -1:
415 return parse_options_usage(usagestr, options, arg + 2, 0); 440 return parse_options_usage(usagestr, options, arg, 0);
416 case -2: 441 case -2:
417 goto unknown; 442 goto unknown;
443 case -3:
444 excl_short_opt = 0;
445 goto exclusive;
418 default: 446 default:
419 break; 447 break;
420 } 448 }
@@ -426,6 +454,17 @@ unknown:
426 ctx->opt = NULL; 454 ctx->opt = NULL;
427 } 455 }
428 return PARSE_OPT_DONE; 456 return PARSE_OPT_DONE;
457
458exclusive:
459 parse_options_usage(usagestr, options, arg, excl_short_opt);
460 if ((excl_short_opt && ctx->excl_opt->short_name) ||
461 ctx->excl_opt->long_name == NULL) {
462 char opt = ctx->excl_opt->short_name;
463 parse_options_usage(NULL, options, &opt, 1);
464 } else {
465 parse_options_usage(NULL, options, ctx->excl_opt->long_name, 0);
466 }
467 return PARSE_OPT_HELP;
429} 468}
430 469
431int parse_options_end(struct parse_opt_ctx_t *ctx) 470int parse_options_end(struct parse_opt_ctx_t *ctx)
@@ -509,6 +548,8 @@ static void print_option_help(const struct option *opts, int full)
509 } 548 }
510 if (!full && (opts->flags & PARSE_OPT_HIDDEN)) 549 if (!full && (opts->flags & PARSE_OPT_HIDDEN))
511 return; 550 return;
551 if (opts->flags & PARSE_OPT_DISABLED)
552 return;
512 553
513 pos = fprintf(stderr, " "); 554 pos = fprintf(stderr, " ");
514 if (opts->short_name) 555 if (opts->short_name)
@@ -679,3 +720,16 @@ int parse_opt_verbosity_cb(const struct option *opt,
679 } 720 }
680 return 0; 721 return 0;
681} 722}
723
724void set_option_flag(struct option *opts, int shortopt, const char *longopt,
725 int flag)
726{
727 for (; opts->type != OPTION_END; opts++) {
728 if ((shortopt && opts->short_name == shortopt) ||
729 (opts->long_name && longopt &&
730 !strcmp(opts->long_name, longopt))) {
731 opts->flags |= flag;
732 break;
733 }
734 }
735}
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
index b59ba858e73d..97b153fb4999 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/perf/util/parse-options.h
@@ -38,6 +38,8 @@ enum parse_opt_option_flags {
38 PARSE_OPT_NONEG = 4, 38 PARSE_OPT_NONEG = 4,
39 PARSE_OPT_HIDDEN = 8, 39 PARSE_OPT_HIDDEN = 8,
40 PARSE_OPT_LASTARG_DEFAULT = 16, 40 PARSE_OPT_LASTARG_DEFAULT = 16,
41 PARSE_OPT_DISABLED = 32,
42 PARSE_OPT_EXCLUSIVE = 64,
41}; 43};
42 44
43struct option; 45struct option;
@@ -173,6 +175,7 @@ struct parse_opt_ctx_t {
173 const char **out; 175 const char **out;
174 int argc, cpidx; 176 int argc, cpidx;
175 const char *opt; 177 const char *opt;
178 const struct option *excl_opt;
176 int flags; 179 int flags;
177}; 180};
178 181
@@ -211,4 +214,5 @@ extern int parse_opt_verbosity_cb(const struct option *, const char *, int);
211 214
212extern const char *parse_options_fix_filename(const char *prefix, const char *file); 215extern const char *parse_options_fix_filename(const char *prefix, const char *file);
213 216
217void set_option_flag(struct option *opts, int sopt, const char *lopt, int flag);
214#endif /* __PERF_PARSE_OPTIONS_H */ 218#endif /* __PERF_PARSE_OPTIONS_H */
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index e243ad962a4d..881b75490533 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -747,15 +747,18 @@ void print_pmu_events(const char *event_glob, bool name_only)
747 747
748 pmu = NULL; 748 pmu = NULL;
749 len = 0; 749 len = 0;
750 while ((pmu = perf_pmu__scan(pmu)) != NULL) 750 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
751 list_for_each_entry(alias, &pmu->aliases, list) 751 list_for_each_entry(alias, &pmu->aliases, list)
752 len++; 752 len++;
753 aliases = malloc(sizeof(char *) * len); 753 if (pmu->selectable)
754 len++;
755 }
756 aliases = zalloc(sizeof(char *) * len);
754 if (!aliases) 757 if (!aliases)
755 return; 758 goto out_enomem;
756 pmu = NULL; 759 pmu = NULL;
757 j = 0; 760 j = 0;
758 while ((pmu = perf_pmu__scan(pmu)) != NULL) 761 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
759 list_for_each_entry(alias, &pmu->aliases, list) { 762 list_for_each_entry(alias, &pmu->aliases, list) {
760 char *name = format_alias(buf, sizeof(buf), pmu, alias); 763 char *name = format_alias(buf, sizeof(buf), pmu, alias);
761 bool is_cpu = !strcmp(pmu->name, "cpu"); 764 bool is_cpu = !strcmp(pmu->name, "cpu");
@@ -765,13 +768,23 @@ void print_pmu_events(const char *event_glob, bool name_only)
765 (!is_cpu && strglobmatch(alias->name, 768 (!is_cpu && strglobmatch(alias->name,
766 event_glob)))) 769 event_glob))))
767 continue; 770 continue;
768 aliases[j] = name; 771
769 if (is_cpu && !name_only) 772 if (is_cpu && !name_only)
770 aliases[j] = format_alias_or(buf, sizeof(buf), 773 name = format_alias_or(buf, sizeof(buf), pmu, alias);
771 pmu, alias); 774
772 aliases[j] = strdup(aliases[j]); 775 aliases[j] = strdup(name);
776 if (aliases[j] == NULL)
777 goto out_enomem;
773 j++; 778 j++;
774 } 779 }
780 if (pmu->selectable) {
781 char *s;
782 if (asprintf(&s, "%s//", pmu->name) < 0)
783 goto out_enomem;
784 aliases[j] = s;
785 j++;
786 }
787 }
775 len = j; 788 len = j;
776 qsort(aliases, len, sizeof(char *), cmp_string); 789 qsort(aliases, len, sizeof(char *), cmp_string);
777 for (j = 0; j < len; j++) { 790 for (j = 0; j < len; j++) {
@@ -780,12 +793,20 @@ void print_pmu_events(const char *event_glob, bool name_only)
780 continue; 793 continue;
781 } 794 }
782 printf(" %-50s [Kernel PMU event]\n", aliases[j]); 795 printf(" %-50s [Kernel PMU event]\n", aliases[j]);
783 zfree(&aliases[j]);
784 printed++; 796 printed++;
785 } 797 }
786 if (printed) 798 if (printed)
787 printf("\n"); 799 printf("\n");
788 free(aliases); 800out_free:
801 for (j = 0; j < len; j++)
802 zfree(&aliases[j]);
803 zfree(&aliases);
804 return;
805
806out_enomem:
807 printf("FATAL: not enough memory to print PMU events\n");
808 if (aliases)
809 goto out_free;
789} 810}
790 811
791bool pmu_have_event(const char *pname, const char *name) 812bool pmu_have_event(const char *pname, const char *name)
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index fe9dfbee8eed..8092de78e818 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -18,6 +18,7 @@ struct perf_event_attr;
18struct perf_pmu { 18struct perf_pmu {
19 char *name; 19 char *name;
20 __u32 type; 20 __u32 type;
21 bool selectable;
21 struct perf_event_attr *default_config; 22 struct perf_event_attr *default_config;
22 struct cpu_map *cpus; 23 struct cpu_map *cpus;
23 struct list_head format; /* HEAD struct perf_pmu_format -> list */ 24 struct list_head format; /* HEAD struct perf_pmu_format -> list */
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index c150ca4343eb..28eb1417cb2a 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -1910,21 +1910,21 @@ static int show_perf_probe_event(struct perf_probe_event *pev,
1910 if (ret < 0) 1910 if (ret < 0)
1911 return ret; 1911 return ret;
1912 1912
1913 printf(" %-20s (on %s", buf, place); 1913 pr_info(" %-20s (on %s", buf, place);
1914 if (module) 1914 if (module)
1915 printf(" in %s", module); 1915 pr_info(" in %s", module);
1916 1916
1917 if (pev->nargs > 0) { 1917 if (pev->nargs > 0) {
1918 printf(" with"); 1918 pr_info(" with");
1919 for (i = 0; i < pev->nargs; i++) { 1919 for (i = 0; i < pev->nargs; i++) {
1920 ret = synthesize_perf_probe_arg(&pev->args[i], 1920 ret = synthesize_perf_probe_arg(&pev->args[i],
1921 buf, 128); 1921 buf, 128);
1922 if (ret < 0) 1922 if (ret < 0)
1923 break; 1923 break;
1924 printf(" %s", buf); 1924 pr_info(" %s", buf);
1925 } 1925 }
1926 } 1926 }
1927 printf(")\n"); 1927 pr_info(")\n");
1928 free(place); 1928 free(place);
1929 return ret; 1929 return ret;
1930} 1930}
@@ -2124,7 +2124,7 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2124 } 2124 }
2125 2125
2126 ret = 0; 2126 ret = 0;
2127 printf("Added new event%s\n", (ntevs > 1) ? "s:" : ":"); 2127 pr_info("Added new event%s\n", (ntevs > 1) ? "s:" : ":");
2128 for (i = 0; i < ntevs; i++) { 2128 for (i = 0; i < ntevs; i++) {
2129 tev = &tevs[i]; 2129 tev = &tevs[i];
2130 if (pev->event) 2130 if (pev->event)
@@ -2179,8 +2179,8 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2179 2179
2180 if (ret >= 0) { 2180 if (ret >= 0) {
2181 /* Show how to use the event. */ 2181 /* Show how to use the event. */
2182 printf("\nYou can now use it in all perf tools, such as:\n\n"); 2182 pr_info("\nYou can now use it in all perf tools, such as:\n\n");
2183 printf("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group, 2183 pr_info("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group,
2184 tev->event); 2184 tev->event);
2185 } 2185 }
2186 2186
@@ -2444,7 +2444,7 @@ static int __del_trace_probe_event(int fd, struct str_node *ent)
2444 goto error; 2444 goto error;
2445 } 2445 }
2446 2446
2447 printf("Removed event: %s\n", ent->s); 2447 pr_info("Removed event: %s\n", ent->s);
2448 return 0; 2448 return 0;
2449error: 2449error:
2450 pr_warning("Failed to delete event: %s\n", 2450 pr_warning("Failed to delete event: %s\n",
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index 0a01bac4ce02..22ebc46226e7 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -24,6 +24,7 @@
24#include <string.h> 24#include <string.h>
25#include <ctype.h> 25#include <ctype.h>
26#include <errno.h> 26#include <errno.h>
27#include <linux/bitmap.h>
27 28
28#include "../util.h" 29#include "../util.h"
29#include <EXTERN.h> 30#include <EXTERN.h>
@@ -57,7 +58,7 @@ INTERP my_perl;
57#define FTRACE_MAX_EVENT \ 58#define FTRACE_MAX_EVENT \
58 ((1 << (sizeof(unsigned short) * 8)) - 1) 59 ((1 << (sizeof(unsigned short) * 8)) - 1)
59 60
60struct event_format *events[FTRACE_MAX_EVENT]; 61static DECLARE_BITMAP(events_defined, FTRACE_MAX_EVENT);
61 62
62extern struct scripting_context *scripting_context; 63extern struct scripting_context *scripting_context;
63 64
@@ -238,35 +239,15 @@ static void define_event_symbols(struct event_format *event,
238 define_event_symbols(event, ev_name, args->next); 239 define_event_symbols(event, ev_name, args->next);
239} 240}
240 241
241static inline struct event_format *find_cache_event(struct perf_evsel *evsel)
242{
243 static char ev_name[256];
244 struct event_format *event;
245 int type = evsel->attr.config;
246
247 if (events[type])
248 return events[type];
249
250 events[type] = event = evsel->tp_format;
251 if (!event)
252 return NULL;
253
254 sprintf(ev_name, "%s::%s", event->system, event->name);
255
256 define_event_symbols(event, ev_name, event->print_fmt.args);
257
258 return event;
259}
260
261static void perl_process_tracepoint(struct perf_sample *sample, 242static void perl_process_tracepoint(struct perf_sample *sample,
262 struct perf_evsel *evsel, 243 struct perf_evsel *evsel,
263 struct thread *thread) 244 struct thread *thread)
264{ 245{
246 struct event_format *event = evsel->tp_format;
265 struct format_field *field; 247 struct format_field *field;
266 static char handler[256]; 248 static char handler[256];
267 unsigned long long val; 249 unsigned long long val;
268 unsigned long s, ns; 250 unsigned long s, ns;
269 struct event_format *event;
270 int pid; 251 int pid;
271 int cpu = sample->cpu; 252 int cpu = sample->cpu;
272 void *data = sample->raw_data; 253 void *data = sample->raw_data;
@@ -278,7 +259,6 @@ static void perl_process_tracepoint(struct perf_sample *sample,
278 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) 259 if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
279 return; 260 return;
280 261
281 event = find_cache_event(evsel);
282 if (!event) 262 if (!event)
283 die("ug! no event found for type %" PRIu64, (u64)evsel->attr.config); 263 die("ug! no event found for type %" PRIu64, (u64)evsel->attr.config);
284 264
@@ -286,6 +266,9 @@ static void perl_process_tracepoint(struct perf_sample *sample,
286 266
287 sprintf(handler, "%s::%s", event->system, event->name); 267 sprintf(handler, "%s::%s", event->system, event->name);
288 268
269 if (!test_and_set_bit(event->id, events_defined))
270 define_event_symbols(event, handler, event->print_fmt.args);
271
289 s = nsecs / NSECS_PER_SEC; 272 s = nsecs / NSECS_PER_SEC;
290 ns = nsecs - s * NSECS_PER_SEC; 273 ns = nsecs - s * NSECS_PER_SEC;
291 274
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 496f21cadd97..d808a328f4dc 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -24,7 +24,9 @@
24#include <stdio.h> 24#include <stdio.h>
25#include <stdlib.h> 25#include <stdlib.h>
26#include <string.h> 26#include <string.h>
27#include <stdbool.h>
27#include <errno.h> 28#include <errno.h>
29#include <linux/bitmap.h>
28 30
29#include "../../perf.h" 31#include "../../perf.h"
30#include "../debug.h" 32#include "../debug.h"
@@ -33,6 +35,10 @@
33#include "../util.h" 35#include "../util.h"
34#include "../event.h" 36#include "../event.h"
35#include "../thread.h" 37#include "../thread.h"
38#include "../comm.h"
39#include "../machine.h"
40#include "../db-export.h"
41#include "../thread-stack.h"
36#include "../trace-event.h" 42#include "../trace-event.h"
37#include "../machine.h" 43#include "../machine.h"
38 44
@@ -41,7 +47,7 @@ PyMODINIT_FUNC initperf_trace_context(void);
41#define FTRACE_MAX_EVENT \ 47#define FTRACE_MAX_EVENT \
42 ((1 << (sizeof(unsigned short) * 8)) - 1) 48 ((1 << (sizeof(unsigned short) * 8)) - 1)
43 49
44struct event_format *events[FTRACE_MAX_EVENT]; 50static DECLARE_BITMAP(events_defined, FTRACE_MAX_EVENT);
45 51
46#define MAX_FIELDS 64 52#define MAX_FIELDS 64
47#define N_COMMON_FIELDS 7 53#define N_COMMON_FIELDS 7
@@ -53,6 +59,24 @@ static int zero_flag_atom;
53 59
54static PyObject *main_module, *main_dict; 60static PyObject *main_module, *main_dict;
55 61
62struct tables {
63 struct db_export dbe;
64 PyObject *evsel_handler;
65 PyObject *machine_handler;
66 PyObject *thread_handler;
67 PyObject *comm_handler;
68 PyObject *comm_thread_handler;
69 PyObject *dso_handler;
70 PyObject *symbol_handler;
71 PyObject *branch_type_handler;
72 PyObject *sample_handler;
73 PyObject *call_path_handler;
74 PyObject *call_return_handler;
75 bool db_export_mode;
76};
77
78static struct tables tables_global;
79
56static void handler_call_die(const char *handler_name) NORETURN; 80static void handler_call_die(const char *handler_name) NORETURN;
57static void handler_call_die(const char *handler_name) 81static void handler_call_die(const char *handler_name)
58{ 82{
@@ -232,31 +256,6 @@ static void define_event_symbols(struct event_format *event,
232 define_event_symbols(event, ev_name, args->next); 256 define_event_symbols(event, ev_name, args->next);
233} 257}
234 258
235static inline struct event_format *find_cache_event(struct perf_evsel *evsel)
236{
237 static char ev_name[256];
238 struct event_format *event;
239 int type = evsel->attr.config;
240
241 /*
242 * XXX: Do we really need to cache this since now we have evsel->tp_format
243 * cached already? Need to re-read this "cache" routine that as well calls
244 * define_event_symbols() :-\
245 */
246 if (events[type])
247 return events[type];
248
249 events[type] = event = evsel->tp_format;
250 if (!event)
251 return NULL;
252
253 sprintf(ev_name, "%s__%s", event->system, event->name);
254
255 define_event_symbols(event, ev_name, event->print_fmt.args);
256
257 return event;
258}
259
260static PyObject *get_field_numeric_entry(struct event_format *event, 259static PyObject *get_field_numeric_entry(struct event_format *event,
261 struct format_field *field, void *data) 260 struct format_field *field, void *data)
262{ 261{
@@ -312,9 +311,9 @@ static PyObject *python_process_callchain(struct perf_sample *sample,
312 if (!symbol_conf.use_callchain || !sample->callchain) 311 if (!symbol_conf.use_callchain || !sample->callchain)
313 goto exit; 312 goto exit;
314 313
315 if (machine__resolve_callchain(al->machine, evsel, al->thread, 314 if (thread__resolve_callchain(al->thread, evsel,
316 sample, NULL, NULL, 315 sample, NULL, NULL,
317 PERF_MAX_STACK_DEPTH) != 0) { 316 PERF_MAX_STACK_DEPTH) != 0) {
318 pr_err("Failed to resolve callchain. Skipping\n"); 317 pr_err("Failed to resolve callchain. Skipping\n");
319 goto exit; 318 goto exit;
320 } 319 }
@@ -380,12 +379,12 @@ static void python_process_tracepoint(struct perf_sample *sample,
380 struct thread *thread, 379 struct thread *thread,
381 struct addr_location *al) 380 struct addr_location *al)
382{ 381{
382 struct event_format *event = evsel->tp_format;
383 PyObject *handler, *context, *t, *obj, *callchain; 383 PyObject *handler, *context, *t, *obj, *callchain;
384 PyObject *dict = NULL; 384 PyObject *dict = NULL;
385 static char handler_name[256]; 385 static char handler_name[256];
386 struct format_field *field; 386 struct format_field *field;
387 unsigned long s, ns; 387 unsigned long s, ns;
388 struct event_format *event;
389 unsigned n = 0; 388 unsigned n = 0;
390 int pid; 389 int pid;
391 int cpu = sample->cpu; 390 int cpu = sample->cpu;
@@ -397,7 +396,6 @@ static void python_process_tracepoint(struct perf_sample *sample,
397 if (!t) 396 if (!t)
398 Py_FatalError("couldn't create Python tuple"); 397 Py_FatalError("couldn't create Python tuple");
399 398
400 event = find_cache_event(evsel);
401 if (!event) 399 if (!event)
402 die("ug! no event found for type %d", (int)evsel->attr.config); 400 die("ug! no event found for type %d", (int)evsel->attr.config);
403 401
@@ -405,6 +403,9 @@ static void python_process_tracepoint(struct perf_sample *sample,
405 403
406 sprintf(handler_name, "%s__%s", event->system, event->name); 404 sprintf(handler_name, "%s__%s", event->system, event->name);
407 405
406 if (!test_and_set_bit(event->id, events_defined))
407 define_event_symbols(event, handler_name, event->print_fmt.args);
408
408 handler = get_handler(handler_name); 409 handler = get_handler(handler_name);
409 if (!handler) { 410 if (!handler) {
410 dict = PyDict_New(); 411 dict = PyDict_New();
@@ -475,6 +476,289 @@ static void python_process_tracepoint(struct perf_sample *sample,
475 Py_DECREF(t); 476 Py_DECREF(t);
476} 477}
477 478
479static PyObject *tuple_new(unsigned int sz)
480{
481 PyObject *t;
482
483 t = PyTuple_New(sz);
484 if (!t)
485 Py_FatalError("couldn't create Python tuple");
486 return t;
487}
488
489static int tuple_set_u64(PyObject *t, unsigned int pos, u64 val)
490{
491#if BITS_PER_LONG == 64
492 return PyTuple_SetItem(t, pos, PyInt_FromLong(val));
493#endif
494#if BITS_PER_LONG == 32
495 return PyTuple_SetItem(t, pos, PyLong_FromLongLong(val));
496#endif
497}
498
499static int tuple_set_s32(PyObject *t, unsigned int pos, s32 val)
500{
501 return PyTuple_SetItem(t, pos, PyInt_FromLong(val));
502}
503
504static int tuple_set_string(PyObject *t, unsigned int pos, const char *s)
505{
506 return PyTuple_SetItem(t, pos, PyString_FromString(s));
507}
508
509static int python_export_evsel(struct db_export *dbe, struct perf_evsel *evsel)
510{
511 struct tables *tables = container_of(dbe, struct tables, dbe);
512 PyObject *t;
513
514 t = tuple_new(2);
515
516 tuple_set_u64(t, 0, evsel->db_id);
517 tuple_set_string(t, 1, perf_evsel__name(evsel));
518
519 call_object(tables->evsel_handler, t, "evsel_table");
520
521 Py_DECREF(t);
522
523 return 0;
524}
525
526static int python_export_machine(struct db_export *dbe,
527 struct machine *machine)
528{
529 struct tables *tables = container_of(dbe, struct tables, dbe);
530 PyObject *t;
531
532 t = tuple_new(3);
533
534 tuple_set_u64(t, 0, machine->db_id);
535 tuple_set_s32(t, 1, machine->pid);
536 tuple_set_string(t, 2, machine->root_dir ? machine->root_dir : "");
537
538 call_object(tables->machine_handler, t, "machine_table");
539
540 Py_DECREF(t);
541
542 return 0;
543}
544
545static int python_export_thread(struct db_export *dbe, struct thread *thread,
546 u64 main_thread_db_id, struct machine *machine)
547{
548 struct tables *tables = container_of(dbe, struct tables, dbe);
549 PyObject *t;
550
551 t = tuple_new(5);
552
553 tuple_set_u64(t, 0, thread->db_id);
554 tuple_set_u64(t, 1, machine->db_id);
555 tuple_set_u64(t, 2, main_thread_db_id);
556 tuple_set_s32(t, 3, thread->pid_);
557 tuple_set_s32(t, 4, thread->tid);
558
559 call_object(tables->thread_handler, t, "thread_table");
560
561 Py_DECREF(t);
562
563 return 0;
564}
565
566static int python_export_comm(struct db_export *dbe, struct comm *comm)
567{
568 struct tables *tables = container_of(dbe, struct tables, dbe);
569 PyObject *t;
570
571 t = tuple_new(2);
572
573 tuple_set_u64(t, 0, comm->db_id);
574 tuple_set_string(t, 1, comm__str(comm));
575
576 call_object(tables->comm_handler, t, "comm_table");
577
578 Py_DECREF(t);
579
580 return 0;
581}
582
583static int python_export_comm_thread(struct db_export *dbe, u64 db_id,
584 struct comm *comm, struct thread *thread)
585{
586 struct tables *tables = container_of(dbe, struct tables, dbe);
587 PyObject *t;
588
589 t = tuple_new(3);
590
591 tuple_set_u64(t, 0, db_id);
592 tuple_set_u64(t, 1, comm->db_id);
593 tuple_set_u64(t, 2, thread->db_id);
594
595 call_object(tables->comm_thread_handler, t, "comm_thread_table");
596
597 Py_DECREF(t);
598
599 return 0;
600}
601
602static int python_export_dso(struct db_export *dbe, struct dso *dso,
603 struct machine *machine)
604{
605 struct tables *tables = container_of(dbe, struct tables, dbe);
606 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
607 PyObject *t;
608
609 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
610
611 t = tuple_new(5);
612
613 tuple_set_u64(t, 0, dso->db_id);
614 tuple_set_u64(t, 1, machine->db_id);
615 tuple_set_string(t, 2, dso->short_name);
616 tuple_set_string(t, 3, dso->long_name);
617 tuple_set_string(t, 4, sbuild_id);
618
619 call_object(tables->dso_handler, t, "dso_table");
620
621 Py_DECREF(t);
622
623 return 0;
624}
625
626static int python_export_symbol(struct db_export *dbe, struct symbol *sym,
627 struct dso *dso)
628{
629 struct tables *tables = container_of(dbe, struct tables, dbe);
630 u64 *sym_db_id = symbol__priv(sym);
631 PyObject *t;
632
633 t = tuple_new(6);
634
635 tuple_set_u64(t, 0, *sym_db_id);
636 tuple_set_u64(t, 1, dso->db_id);
637 tuple_set_u64(t, 2, sym->start);
638 tuple_set_u64(t, 3, sym->end);
639 tuple_set_s32(t, 4, sym->binding);
640 tuple_set_string(t, 5, sym->name);
641
642 call_object(tables->symbol_handler, t, "symbol_table");
643
644 Py_DECREF(t);
645
646 return 0;
647}
648
649static int python_export_branch_type(struct db_export *dbe, u32 branch_type,
650 const char *name)
651{
652 struct tables *tables = container_of(dbe, struct tables, dbe);
653 PyObject *t;
654
655 t = tuple_new(2);
656
657 tuple_set_s32(t, 0, branch_type);
658 tuple_set_string(t, 1, name);
659
660 call_object(tables->branch_type_handler, t, "branch_type_table");
661
662 Py_DECREF(t);
663
664 return 0;
665}
666
667static int python_export_sample(struct db_export *dbe,
668 struct export_sample *es)
669{
670 struct tables *tables = container_of(dbe, struct tables, dbe);
671 PyObject *t;
672
673 t = tuple_new(21);
674
675 tuple_set_u64(t, 0, es->db_id);
676 tuple_set_u64(t, 1, es->evsel->db_id);
677 tuple_set_u64(t, 2, es->al->machine->db_id);
678 tuple_set_u64(t, 3, es->thread->db_id);
679 tuple_set_u64(t, 4, es->comm_db_id);
680 tuple_set_u64(t, 5, es->dso_db_id);
681 tuple_set_u64(t, 6, es->sym_db_id);
682 tuple_set_u64(t, 7, es->offset);
683 tuple_set_u64(t, 8, es->sample->ip);
684 tuple_set_u64(t, 9, es->sample->time);
685 tuple_set_s32(t, 10, es->sample->cpu);
686 tuple_set_u64(t, 11, es->addr_dso_db_id);
687 tuple_set_u64(t, 12, es->addr_sym_db_id);
688 tuple_set_u64(t, 13, es->addr_offset);
689 tuple_set_u64(t, 14, es->sample->addr);
690 tuple_set_u64(t, 15, es->sample->period);
691 tuple_set_u64(t, 16, es->sample->weight);
692 tuple_set_u64(t, 17, es->sample->transaction);
693 tuple_set_u64(t, 18, es->sample->data_src);
694 tuple_set_s32(t, 19, es->sample->flags & PERF_BRANCH_MASK);
695 tuple_set_s32(t, 20, !!(es->sample->flags & PERF_IP_FLAG_IN_TX));
696
697 call_object(tables->sample_handler, t, "sample_table");
698
699 Py_DECREF(t);
700
701 return 0;
702}
703
704static int python_export_call_path(struct db_export *dbe, struct call_path *cp)
705{
706 struct tables *tables = container_of(dbe, struct tables, dbe);
707 PyObject *t;
708 u64 parent_db_id, sym_db_id;
709
710 parent_db_id = cp->parent ? cp->parent->db_id : 0;
711 sym_db_id = cp->sym ? *(u64 *)symbol__priv(cp->sym) : 0;
712
713 t = tuple_new(4);
714
715 tuple_set_u64(t, 0, cp->db_id);
716 tuple_set_u64(t, 1, parent_db_id);
717 tuple_set_u64(t, 2, sym_db_id);
718 tuple_set_u64(t, 3, cp->ip);
719
720 call_object(tables->call_path_handler, t, "call_path_table");
721
722 Py_DECREF(t);
723
724 return 0;
725}
726
727static int python_export_call_return(struct db_export *dbe,
728 struct call_return *cr)
729{
730 struct tables *tables = container_of(dbe, struct tables, dbe);
731 u64 comm_db_id = cr->comm ? cr->comm->db_id : 0;
732 PyObject *t;
733
734 t = tuple_new(11);
735
736 tuple_set_u64(t, 0, cr->db_id);
737 tuple_set_u64(t, 1, cr->thread->db_id);
738 tuple_set_u64(t, 2, comm_db_id);
739 tuple_set_u64(t, 3, cr->cp->db_id);
740 tuple_set_u64(t, 4, cr->call_time);
741 tuple_set_u64(t, 5, cr->return_time);
742 tuple_set_u64(t, 6, cr->branch_count);
743 tuple_set_u64(t, 7, cr->call_ref);
744 tuple_set_u64(t, 8, cr->return_ref);
745 tuple_set_u64(t, 9, cr->cp->parent->db_id);
746 tuple_set_s32(t, 10, cr->flags);
747
748 call_object(tables->call_return_handler, t, "call_return_table");
749
750 Py_DECREF(t);
751
752 return 0;
753}
754
755static int python_process_call_return(struct call_return *cr, void *data)
756{
757 struct db_export *dbe = data;
758
759 return db_export__call_return(dbe, cr);
760}
761
478static void python_process_general_event(struct perf_sample *sample, 762static void python_process_general_event(struct perf_sample *sample,
479 struct perf_evsel *evsel, 763 struct perf_evsel *evsel,
480 struct thread *thread, 764 struct thread *thread,
@@ -551,19 +835,25 @@ exit:
551 Py_DECREF(t); 835 Py_DECREF(t);
552} 836}
553 837
554static void python_process_event(union perf_event *event __maybe_unused, 838static void python_process_event(union perf_event *event,
555 struct perf_sample *sample, 839 struct perf_sample *sample,
556 struct perf_evsel *evsel, 840 struct perf_evsel *evsel,
557 struct thread *thread, 841 struct thread *thread,
558 struct addr_location *al) 842 struct addr_location *al)
559{ 843{
844 struct tables *tables = &tables_global;
845
560 switch (evsel->attr.type) { 846 switch (evsel->attr.type) {
561 case PERF_TYPE_TRACEPOINT: 847 case PERF_TYPE_TRACEPOINT:
562 python_process_tracepoint(sample, evsel, thread, al); 848 python_process_tracepoint(sample, evsel, thread, al);
563 break; 849 break;
564 /* Reserve for future process_hw/sw/raw APIs */ 850 /* Reserve for future process_hw/sw/raw APIs */
565 default: 851 default:
566 python_process_general_event(sample, evsel, thread, al); 852 if (tables->db_export_mode)
853 db_export__sample(&tables->dbe, event, sample, evsel,
854 thread, al);
855 else
856 python_process_general_event(sample, evsel, thread, al);
567 } 857 }
568} 858}
569 859
@@ -589,11 +879,79 @@ error:
589 return -1; 879 return -1;
590} 880}
591 881
882#define SET_TABLE_HANDLER_(name, handler_name, table_name) do { \
883 tables->handler_name = get_handler(#table_name); \
884 if (tables->handler_name) \
885 tables->dbe.export_ ## name = python_export_ ## name; \
886} while (0)
887
888#define SET_TABLE_HANDLER(name) \
889 SET_TABLE_HANDLER_(name, name ## _handler, name ## _table)
890
891static void set_table_handlers(struct tables *tables)
892{
893 const char *perf_db_export_mode = "perf_db_export_mode";
894 const char *perf_db_export_calls = "perf_db_export_calls";
895 PyObject *db_export_mode, *db_export_calls;
896 bool export_calls = false;
897 int ret;
898
899 memset(tables, 0, sizeof(struct tables));
900 if (db_export__init(&tables->dbe))
901 Py_FatalError("failed to initialize export");
902
903 db_export_mode = PyDict_GetItemString(main_dict, perf_db_export_mode);
904 if (!db_export_mode)
905 return;
906
907 ret = PyObject_IsTrue(db_export_mode);
908 if (ret == -1)
909 handler_call_die(perf_db_export_mode);
910 if (!ret)
911 return;
912
913 tables->dbe.crp = NULL;
914 db_export_calls = PyDict_GetItemString(main_dict, perf_db_export_calls);
915 if (db_export_calls) {
916 ret = PyObject_IsTrue(db_export_calls);
917 if (ret == -1)
918 handler_call_die(perf_db_export_calls);
919 export_calls = !!ret;
920 }
921
922 if (export_calls) {
923 tables->dbe.crp =
924 call_return_processor__new(python_process_call_return,
925 &tables->dbe);
926 if (!tables->dbe.crp)
927 Py_FatalError("failed to create calls processor");
928 }
929
930 tables->db_export_mode = true;
931 /*
932 * Reserve per symbol space for symbol->db_id via symbol__priv()
933 */
934 symbol_conf.priv_size = sizeof(u64);
935
936 SET_TABLE_HANDLER(evsel);
937 SET_TABLE_HANDLER(machine);
938 SET_TABLE_HANDLER(thread);
939 SET_TABLE_HANDLER(comm);
940 SET_TABLE_HANDLER(comm_thread);
941 SET_TABLE_HANDLER(dso);
942 SET_TABLE_HANDLER(symbol);
943 SET_TABLE_HANDLER(branch_type);
944 SET_TABLE_HANDLER(sample);
945 SET_TABLE_HANDLER(call_path);
946 SET_TABLE_HANDLER(call_return);
947}
948
592/* 949/*
593 * Start trace script 950 * Start trace script
594 */ 951 */
595static int python_start_script(const char *script, int argc, const char **argv) 952static int python_start_script(const char *script, int argc, const char **argv)
596{ 953{
954 struct tables *tables = &tables_global;
597 const char **command_line; 955 const char **command_line;
598 char buf[PATH_MAX]; 956 char buf[PATH_MAX];
599 int i, err = 0; 957 int i, err = 0;
@@ -632,6 +990,14 @@ static int python_start_script(const char *script, int argc, const char **argv)
632 990
633 free(command_line); 991 free(command_line);
634 992
993 set_table_handlers(tables);
994
995 if (tables->db_export_mode) {
996 err = db_export__branch_types(&tables->dbe);
997 if (err)
998 goto error;
999 }
1000
635 return err; 1001 return err;
636error: 1002error:
637 Py_Finalize(); 1003 Py_Finalize();
@@ -642,7 +1008,9 @@ error:
642 1008
643static int python_flush_script(void) 1009static int python_flush_script(void)
644{ 1010{
645 return 0; 1011 struct tables *tables = &tables_global;
1012
1013 return db_export__flush(&tables->dbe);
646} 1014}
647 1015
648/* 1016/*
@@ -650,8 +1018,12 @@ static int python_flush_script(void)
650 */ 1018 */
651static int python_stop_script(void) 1019static int python_stop_script(void)
652{ 1020{
1021 struct tables *tables = &tables_global;
1022
653 try_call_object("trace_end", NULL); 1023 try_call_object("trace_end", NULL);
654 1024
1025 db_export__exit(&tables->dbe);
1026
655 Py_XDECREF(main_dict); 1027 Py_XDECREF(main_dict);
656 Py_XDECREF(main_module); 1028 Py_XDECREF(main_module);
657 Py_Finalize(); 1029 Py_Finalize();
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 6702ac28754b..6ac62ae6b8fa 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -228,6 +228,15 @@ static int process_finished_round(struct perf_tool *tool,
228 union perf_event *event, 228 union perf_event *event,
229 struct perf_session *session); 229 struct perf_session *session);
230 230
231static int process_id_index_stub(struct perf_tool *tool __maybe_unused,
232 union perf_event *event __maybe_unused,
233 struct perf_session *perf_session
234 __maybe_unused)
235{
236 dump_printf(": unhandled!\n");
237 return 0;
238}
239
231void perf_tool__fill_defaults(struct perf_tool *tool) 240void perf_tool__fill_defaults(struct perf_tool *tool)
232{ 241{
233 if (tool->sample == NULL) 242 if (tool->sample == NULL)
@@ -262,6 +271,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
262 else 271 else
263 tool->finished_round = process_finished_round_stub; 272 tool->finished_round = process_finished_round_stub;
264 } 273 }
274 if (tool->id_index == NULL)
275 tool->id_index = process_id_index_stub;
265} 276}
266 277
267static void swap_sample_id_all(union perf_event *event, void *data) 278static void swap_sample_id_all(union perf_event *event, void *data)
@@ -460,6 +471,7 @@ static perf_event__swap_op perf_event__swap_ops[] = {
460 [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap, 471 [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap,
461 [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap, 472 [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap,
462 [PERF_RECORD_HEADER_BUILD_ID] = NULL, 473 [PERF_RECORD_HEADER_BUILD_ID] = NULL,
474 [PERF_RECORD_ID_INDEX] = perf_event__all64_swap,
463 [PERF_RECORD_HEADER_MAX] = NULL, 475 [PERF_RECORD_HEADER_MAX] = NULL,
464}; 476};
465 477
@@ -580,15 +592,46 @@ static void regs_dump__printf(u64 mask, u64 *regs)
580 } 592 }
581} 593}
582 594
595static const char *regs_abi[] = {
596 [PERF_SAMPLE_REGS_ABI_NONE] = "none",
597 [PERF_SAMPLE_REGS_ABI_32] = "32-bit",
598 [PERF_SAMPLE_REGS_ABI_64] = "64-bit",
599};
600
601static inline const char *regs_dump_abi(struct regs_dump *d)
602{
603 if (d->abi > PERF_SAMPLE_REGS_ABI_64)
604 return "unknown";
605
606 return regs_abi[d->abi];
607}
608
609static void regs__printf(const char *type, struct regs_dump *regs)
610{
611 u64 mask = regs->mask;
612
613 printf("... %s regs: mask 0x%" PRIx64 " ABI %s\n",
614 type,
615 mask,
616 regs_dump_abi(regs));
617
618 regs_dump__printf(mask, regs->regs);
619}
620
583static void regs_user__printf(struct perf_sample *sample) 621static void regs_user__printf(struct perf_sample *sample)
584{ 622{
585 struct regs_dump *user_regs = &sample->user_regs; 623 struct regs_dump *user_regs = &sample->user_regs;
586 624
587 if (user_regs->regs) { 625 if (user_regs->regs)
588 u64 mask = user_regs->mask; 626 regs__printf("user", user_regs);
589 printf("... user regs: mask 0x%" PRIx64 "\n", mask); 627}
590 regs_dump__printf(mask, user_regs->regs); 628
591 } 629static void regs_intr__printf(struct perf_sample *sample)
630{
631 struct regs_dump *intr_regs = &sample->intr_regs;
632
633 if (intr_regs->regs)
634 regs__printf("intr", intr_regs);
592} 635}
593 636
594static void stack_user__printf(struct stack_dump *dump) 637static void stack_user__printf(struct stack_dump *dump)
@@ -687,6 +730,9 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
687 if (sample_type & PERF_SAMPLE_REGS_USER) 730 if (sample_type & PERF_SAMPLE_REGS_USER)
688 regs_user__printf(sample); 731 regs_user__printf(sample);
689 732
733 if (sample_type & PERF_SAMPLE_REGS_INTR)
734 regs_intr__printf(sample);
735
690 if (sample_type & PERF_SAMPLE_STACK_USER) 736 if (sample_type & PERF_SAMPLE_STACK_USER)
691 stack_user__printf(&sample->user_stack); 737 stack_user__printf(&sample->user_stack);
692 738
@@ -888,11 +934,26 @@ static s64 perf_session__process_user_event(struct perf_session *session,
888 return tool->build_id(tool, event, session); 934 return tool->build_id(tool, event, session);
889 case PERF_RECORD_FINISHED_ROUND: 935 case PERF_RECORD_FINISHED_ROUND:
890 return tool->finished_round(tool, event, session); 936 return tool->finished_round(tool, event, session);
937 case PERF_RECORD_ID_INDEX:
938 return tool->id_index(tool, event, session);
891 default: 939 default:
892 return -EINVAL; 940 return -EINVAL;
893 } 941 }
894} 942}
895 943
944int perf_session__deliver_synth_event(struct perf_session *session,
945 union perf_event *event,
946 struct perf_sample *sample,
947 struct perf_tool *tool)
948{
949 events_stats__inc(&session->stats, event->header.type);
950
951 if (event->header.type >= PERF_RECORD_USER_TYPE_START)
952 return perf_session__process_user_event(session, event, tool, 0);
953
954 return perf_session__deliver_event(session, event, sample, tool, 0);
955}
956
896static void event_swap(union perf_event *event, bool sample_id_all) 957static void event_swap(union perf_event *event, bool sample_id_all)
897{ 958{
898 perf_event__swap_op swap; 959 perf_event__swap_op swap;
@@ -1417,9 +1478,9 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample,
1417 if (symbol_conf.use_callchain && sample->callchain) { 1478 if (symbol_conf.use_callchain && sample->callchain) {
1418 struct addr_location node_al; 1479 struct addr_location node_al;
1419 1480
1420 if (machine__resolve_callchain(al->machine, evsel, al->thread, 1481 if (thread__resolve_callchain(al->thread, evsel,
1421 sample, NULL, NULL, 1482 sample, NULL, NULL,
1422 PERF_MAX_STACK_DEPTH) != 0) { 1483 PERF_MAX_STACK_DEPTH) != 0) {
1423 if (verbose) 1484 if (verbose)
1424 error("Failed to resolve callchain. Skipping\n"); 1485 error("Failed to resolve callchain. Skipping\n");
1425 return; 1486 return;
@@ -1594,3 +1655,111 @@ int __perf_session__set_tracepoints_handlers(struct perf_session *session,
1594out: 1655out:
1595 return err; 1656 return err;
1596} 1657}
1658
1659int perf_event__process_id_index(struct perf_tool *tool __maybe_unused,
1660 union perf_event *event,
1661 struct perf_session *session)
1662{
1663 struct perf_evlist *evlist = session->evlist;
1664 struct id_index_event *ie = &event->id_index;
1665 size_t i, nr, max_nr;
1666
1667 max_nr = (ie->header.size - sizeof(struct id_index_event)) /
1668 sizeof(struct id_index_entry);
1669 nr = ie->nr;
1670 if (nr > max_nr)
1671 return -EINVAL;
1672
1673 if (dump_trace)
1674 fprintf(stdout, " nr: %zu\n", nr);
1675
1676 for (i = 0; i < nr; i++) {
1677 struct id_index_entry *e = &ie->entries[i];
1678 struct perf_sample_id *sid;
1679
1680 if (dump_trace) {
1681 fprintf(stdout, " ... id: %"PRIu64, e->id);
1682 fprintf(stdout, " idx: %"PRIu64, e->idx);
1683 fprintf(stdout, " cpu: %"PRId64, e->cpu);
1684 fprintf(stdout, " tid: %"PRId64"\n", e->tid);
1685 }
1686
1687 sid = perf_evlist__id2sid(evlist, e->id);
1688 if (!sid)
1689 return -ENOENT;
1690 sid->idx = e->idx;
1691 sid->cpu = e->cpu;
1692 sid->tid = e->tid;
1693 }
1694 return 0;
1695}
1696
1697int perf_event__synthesize_id_index(struct perf_tool *tool,
1698 perf_event__handler_t process,
1699 struct perf_evlist *evlist,
1700 struct machine *machine)
1701{
1702 union perf_event *ev;
1703 struct perf_evsel *evsel;
1704 size_t nr = 0, i = 0, sz, max_nr, n;
1705 int err;
1706
1707 pr_debug2("Synthesizing id index\n");
1708
1709 max_nr = (UINT16_MAX - sizeof(struct id_index_event)) /
1710 sizeof(struct id_index_entry);
1711
1712 evlist__for_each(evlist, evsel)
1713 nr += evsel->ids;
1714
1715 n = nr > max_nr ? max_nr : nr;
1716 sz = sizeof(struct id_index_event) + n * sizeof(struct id_index_entry);
1717 ev = zalloc(sz);
1718 if (!ev)
1719 return -ENOMEM;
1720
1721 ev->id_index.header.type = PERF_RECORD_ID_INDEX;
1722 ev->id_index.header.size = sz;
1723 ev->id_index.nr = n;
1724
1725 evlist__for_each(evlist, evsel) {
1726 u32 j;
1727
1728 for (j = 0; j < evsel->ids; j++) {
1729 struct id_index_entry *e;
1730 struct perf_sample_id *sid;
1731
1732 if (i >= n) {
1733 err = process(tool, ev, NULL, machine);
1734 if (err)
1735 goto out_err;
1736 nr -= n;
1737 i = 0;
1738 }
1739
1740 e = &ev->id_index.entries[i++];
1741
1742 e->id = evsel->id[j];
1743
1744 sid = perf_evlist__id2sid(evlist, e->id);
1745 if (!sid) {
1746 free(ev);
1747 return -ENOENT;
1748 }
1749
1750 e->idx = sid->idx;
1751 e->cpu = sid->cpu;
1752 e->tid = sid->tid;
1753 }
1754 }
1755
1756 sz = sizeof(struct id_index_event) + nr * sizeof(struct id_index_entry);
1757 ev->id_index.header.size = sz;
1758 ev->id_index.nr = nr;
1759
1760 err = process(tool, ev, NULL, machine);
1761out_err:
1762 free(ev);
1763
1764 return err;
1765}
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index a4be851f1a90..dc26ebf60fe4 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -126,4 +126,19 @@ int __perf_session__set_tracepoints_handlers(struct perf_session *session,
126extern volatile int session_done; 126extern volatile int session_done;
127 127
128#define session_done() ACCESS_ONCE(session_done) 128#define session_done() ACCESS_ONCE(session_done)
129
130int perf_session__deliver_synth_event(struct perf_session *session,
131 union perf_event *event,
132 struct perf_sample *sample,
133 struct perf_tool *tool);
134
135int perf_event__process_id_index(struct perf_tool *tool,
136 union perf_event *event,
137 struct perf_session *session);
138
139int perf_event__synthesize_id_index(struct perf_tool *tool,
140 perf_event__handler_t process,
141 struct perf_evlist *evlist,
142 struct machine *machine);
143
129#endif /* __PERF_SESSION_H */ 144#endif /* __PERF_SESSION_H */
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 9402885a77f3..82a5596241a7 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -309,7 +309,7 @@ sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
309static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf, 309static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf,
310 size_t size, unsigned int width) 310 size_t size, unsigned int width)
311{ 311{
312 return repsep_snprintf(bf, size, "%*.*-s", width, width, he->srcline); 312 return repsep_snprintf(bf, size, "%-*.*s", width, width, he->srcline);
313} 313}
314 314
315struct sort_entry sort_srcline = { 315struct sort_entry sort_srcline = {
diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c
index f3e4bc5fe5d2..77c180637138 100644
--- a/tools/perf/util/srcline.c
+++ b/tools/perf/util/srcline.c
@@ -274,7 +274,7 @@ char *get_srcline(struct dso *dso, unsigned long addr)
274 if (!addr2line(dso_name, addr, &file, &line, dso)) 274 if (!addr2line(dso_name, addr, &file, &line, dso))
275 goto out; 275 goto out;
276 276
277 if (asprintf(&srcline, "%s:%u", file, line) < 0) { 277 if (asprintf(&srcline, "%s:%u", basename(file), line) < 0) {
278 free(file); 278 free(file);
279 goto out; 279 goto out;
280 } 280 }
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 1e23a5bfb044..efc7eb6b8f0f 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -546,6 +546,35 @@ static int dso__swap_init(struct dso *dso, unsigned char eidata)
546 return 0; 546 return 0;
547} 547}
548 548
549static int decompress_kmodule(struct dso *dso, const char *name,
550 enum dso_binary_type type)
551{
552 int fd;
553 const char *ext = strrchr(name, '.');
554 char tmpbuf[] = "/tmp/perf-kmod-XXXXXX";
555
556 if ((type != DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP &&
557 type != DSO_BINARY_TYPE__GUEST_KMODULE_COMP) ||
558 type != dso->symtab_type)
559 return -1;
560
561 if (!ext || !is_supported_compression(ext + 1))
562 return -1;
563
564 fd = mkstemp(tmpbuf);
565 if (fd < 0)
566 return -1;
567
568 if (!decompress_to_file(ext + 1, name, fd)) {
569 close(fd);
570 fd = -1;
571 }
572
573 unlink(tmpbuf);
574
575 return fd;
576}
577
549bool symsrc__possibly_runtime(struct symsrc *ss) 578bool symsrc__possibly_runtime(struct symsrc *ss)
550{ 579{
551 return ss->dynsym || ss->opdsec; 580 return ss->dynsym || ss->opdsec;
@@ -571,7 +600,11 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
571 Elf *elf; 600 Elf *elf;
572 int fd; 601 int fd;
573 602
574 fd = open(name, O_RDONLY); 603 if (dso__needs_decompress(dso))
604 fd = decompress_kmodule(dso, name, type);
605 else
606 fd = open(name, O_RDONLY);
607
575 if (fd < 0) 608 if (fd < 0)
576 return -1; 609 return -1;
577 610
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c
index c9541fea9514..fa585c63f56a 100644
--- a/tools/perf/util/symbol-minimal.c
+++ b/tools/perf/util/symbol-minimal.c
@@ -341,7 +341,6 @@ int dso__load_sym(struct dso *dso, struct map *map __maybe_unused,
341 341
342 if (filename__read_build_id(ss->name, build_id, BUILD_ID_SIZE) > 0) { 342 if (filename__read_build_id(ss->name, build_id, BUILD_ID_SIZE) > 0) {
343 dso__set_build_id(dso, build_id); 343 dso__set_build_id(dso, build_id);
344 return 1;
345 } 344 }
346 return 0; 345 return 0;
347} 346}
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 078331140d8c..c24c5b83156c 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -51,7 +51,9 @@ static enum dso_binary_type binary_type_symtab[] = {
51 DSO_BINARY_TYPE__BUILDID_DEBUGINFO, 51 DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
52 DSO_BINARY_TYPE__SYSTEM_PATH_DSO, 52 DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
53 DSO_BINARY_TYPE__GUEST_KMODULE, 53 DSO_BINARY_TYPE__GUEST_KMODULE,
54 DSO_BINARY_TYPE__GUEST_KMODULE_COMP,
54 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE, 55 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
56 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP,
55 DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO, 57 DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
56 DSO_BINARY_TYPE__NOT_FOUND, 58 DSO_BINARY_TYPE__NOT_FOUND,
57}; 59};
@@ -1300,7 +1302,9 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
1300 return dso->kernel == DSO_TYPE_GUEST_KERNEL; 1302 return dso->kernel == DSO_TYPE_GUEST_KERNEL;
1301 1303
1302 case DSO_BINARY_TYPE__GUEST_KMODULE: 1304 case DSO_BINARY_TYPE__GUEST_KMODULE:
1305 case DSO_BINARY_TYPE__GUEST_KMODULE_COMP:
1303 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE: 1306 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
1307 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP:
1304 /* 1308 /*
1305 * kernel modules know their symtab type - it's set when 1309 * kernel modules know their symtab type - it's set when
1306 * creating a module dso in machine__new_module(). 1310 * creating a module dso in machine__new_module().
@@ -1368,7 +1372,9 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1368 return -1; 1372 return -1;
1369 1373
1370 kmod = dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE || 1374 kmod = dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE ||
1371 dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE; 1375 dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP ||
1376 dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE ||
1377 dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP;
1372 1378
1373 /* 1379 /*
1374 * Iterate over candidate debug images. 1380 * Iterate over candidate debug images.
@@ -1505,12 +1511,10 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map,
1505 symbol_filter_t filter) 1511 symbol_filter_t filter)
1506{ 1512{
1507 int i, err = 0; 1513 int i, err = 0;
1508 char *filename; 1514 char *filename = NULL;
1509 1515
1510 pr_debug("Looking at the vmlinux_path (%d entries long)\n", 1516 if (!symbol_conf.ignore_vmlinux_buildid)
1511 vmlinux_path__nr_entries + 1); 1517 filename = dso__build_id_filename(dso, NULL, 0);
1512
1513 filename = dso__build_id_filename(dso, NULL, 0);
1514 if (filename != NULL) { 1518 if (filename != NULL) {
1515 err = dso__load_vmlinux(dso, map, filename, true, filter); 1519 err = dso__load_vmlinux(dso, map, filename, true, filter);
1516 if (err > 0) 1520 if (err > 0)
@@ -1518,6 +1522,9 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map,
1518 free(filename); 1522 free(filename);
1519 } 1523 }
1520 1524
1525 pr_debug("Looking at the vmlinux_path (%d entries long)\n",
1526 vmlinux_path__nr_entries + 1);
1527
1521 for (i = 0; i < vmlinux_path__nr_entries; ++i) { 1528 for (i = 0; i < vmlinux_path__nr_entries; ++i) {
1522 err = dso__load_vmlinux(dso, map, vmlinux_path[i], false, filter); 1529 err = dso__load_vmlinux(dso, map, vmlinux_path[i], false, filter);
1523 if (err > 0) 1530 if (err > 0)
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index eb2c19bf8d90..ded3ca7266de 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -105,6 +105,7 @@ struct symbol_conf {
105 unsigned short nr_events; 105 unsigned short nr_events;
106 bool try_vmlinux_path, 106 bool try_vmlinux_path,
107 ignore_vmlinux, 107 ignore_vmlinux,
108 ignore_vmlinux_buildid,
108 show_kernel_path, 109 show_kernel_path,
109 use_modules, 110 use_modules,
110 sort_by_name, 111 sort_by_name,
diff --git a/tools/perf/util/thread-stack.c b/tools/perf/util/thread-stack.c
new file mode 100644
index 000000000000..9ed59a452d1f
--- /dev/null
+++ b/tools/perf/util/thread-stack.c
@@ -0,0 +1,747 @@
1/*
2 * thread-stack.c: Synthesize a thread's stack using call / return events
3 * Copyright (c) 2014, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 */
15
16#include <linux/rbtree.h>
17#include <linux/list.h>
18#include "thread.h"
19#include "event.h"
20#include "machine.h"
21#include "util.h"
22#include "debug.h"
23#include "symbol.h"
24#include "comm.h"
25#include "thread-stack.h"
26
27#define CALL_PATH_BLOCK_SHIFT 8
28#define CALL_PATH_BLOCK_SIZE (1 << CALL_PATH_BLOCK_SHIFT)
29#define CALL_PATH_BLOCK_MASK (CALL_PATH_BLOCK_SIZE - 1)
30
31struct call_path_block {
32 struct call_path cp[CALL_PATH_BLOCK_SIZE];
33 struct list_head node;
34};
35
36/**
37 * struct call_path_root - root of all call paths.
38 * @call_path: root call path
39 * @blocks: list of blocks to store call paths
40 * @next: next free space
41 * @sz: number of spaces
42 */
43struct call_path_root {
44 struct call_path call_path;
45 struct list_head blocks;
46 size_t next;
47 size_t sz;
48};
49
50/**
51 * struct call_return_processor - provides a call-back to consume call-return
52 * information.
53 * @cpr: call path root
54 * @process: call-back that accepts call/return information
55 * @data: anonymous data for call-back
56 */
57struct call_return_processor {
58 struct call_path_root *cpr;
59 int (*process)(struct call_return *cr, void *data);
60 void *data;
61};
62
63#define STACK_GROWTH 2048
64
65/**
66 * struct thread_stack_entry - thread stack entry.
67 * @ret_addr: return address
68 * @timestamp: timestamp (if known)
69 * @ref: external reference (e.g. db_id of sample)
70 * @branch_count: the branch count when the entry was created
71 * @cp: call path
72 * @no_call: a 'call' was not seen
73 */
74struct thread_stack_entry {
75 u64 ret_addr;
76 u64 timestamp;
77 u64 ref;
78 u64 branch_count;
79 struct call_path *cp;
80 bool no_call;
81};
82
83/**
84 * struct thread_stack - thread stack constructed from 'call' and 'return'
85 * branch samples.
86 * @stack: array that holds the stack
87 * @cnt: number of entries in the stack
88 * @sz: current maximum stack size
89 * @trace_nr: current trace number
90 * @branch_count: running branch count
91 * @kernel_start: kernel start address
92 * @last_time: last timestamp
93 * @crp: call/return processor
94 * @comm: current comm
95 */
96struct thread_stack {
97 struct thread_stack_entry *stack;
98 size_t cnt;
99 size_t sz;
100 u64 trace_nr;
101 u64 branch_count;
102 u64 kernel_start;
103 u64 last_time;
104 struct call_return_processor *crp;
105 struct comm *comm;
106};
107
108static int thread_stack__grow(struct thread_stack *ts)
109{
110 struct thread_stack_entry *new_stack;
111 size_t sz, new_sz;
112
113 new_sz = ts->sz + STACK_GROWTH;
114 sz = new_sz * sizeof(struct thread_stack_entry);
115
116 new_stack = realloc(ts->stack, sz);
117 if (!new_stack)
118 return -ENOMEM;
119
120 ts->stack = new_stack;
121 ts->sz = new_sz;
122
123 return 0;
124}
125
126static struct thread_stack *thread_stack__new(struct thread *thread,
127 struct call_return_processor *crp)
128{
129 struct thread_stack *ts;
130
131 ts = zalloc(sizeof(struct thread_stack));
132 if (!ts)
133 return NULL;
134
135 if (thread_stack__grow(ts)) {
136 free(ts);
137 return NULL;
138 }
139
140 if (thread->mg && thread->mg->machine)
141 ts->kernel_start = machine__kernel_start(thread->mg->machine);
142 else
143 ts->kernel_start = 1ULL << 63;
144 ts->crp = crp;
145
146 return ts;
147}
148
149static int thread_stack__push(struct thread_stack *ts, u64 ret_addr)
150{
151 int err = 0;
152
153 if (ts->cnt == ts->sz) {
154 err = thread_stack__grow(ts);
155 if (err) {
156 pr_warning("Out of memory: discarding thread stack\n");
157 ts->cnt = 0;
158 }
159 }
160
161 ts->stack[ts->cnt++].ret_addr = ret_addr;
162
163 return err;
164}
165
166static void thread_stack__pop(struct thread_stack *ts, u64 ret_addr)
167{
168 size_t i;
169
170 /*
171 * In some cases there may be functions which are not seen to return.
172 * For example when setjmp / longjmp has been used. Or the perf context
173 * switch in the kernel which doesn't stop and start tracing in exactly
174 * the same code path. When that happens the return address will be
175 * further down the stack. If the return address is not found at all,
176 * we assume the opposite (i.e. this is a return for a call that wasn't
177 * seen for some reason) and leave the stack alone.
178 */
179 for (i = ts->cnt; i; ) {
180 if (ts->stack[--i].ret_addr == ret_addr) {
181 ts->cnt = i;
182 return;
183 }
184 }
185}
186
187static bool thread_stack__in_kernel(struct thread_stack *ts)
188{
189 if (!ts->cnt)
190 return false;
191
192 return ts->stack[ts->cnt - 1].cp->in_kernel;
193}
194
195static int thread_stack__call_return(struct thread *thread,
196 struct thread_stack *ts, size_t idx,
197 u64 timestamp, u64 ref, bool no_return)
198{
199 struct call_return_processor *crp = ts->crp;
200 struct thread_stack_entry *tse;
201 struct call_return cr = {
202 .thread = thread,
203 .comm = ts->comm,
204 .db_id = 0,
205 };
206
207 tse = &ts->stack[idx];
208 cr.cp = tse->cp;
209 cr.call_time = tse->timestamp;
210 cr.return_time = timestamp;
211 cr.branch_count = ts->branch_count - tse->branch_count;
212 cr.call_ref = tse->ref;
213 cr.return_ref = ref;
214 if (tse->no_call)
215 cr.flags |= CALL_RETURN_NO_CALL;
216 if (no_return)
217 cr.flags |= CALL_RETURN_NO_RETURN;
218
219 return crp->process(&cr, crp->data);
220}
221
222static int thread_stack__flush(struct thread *thread, struct thread_stack *ts)
223{
224 struct call_return_processor *crp = ts->crp;
225 int err;
226
227 if (!crp) {
228 ts->cnt = 0;
229 return 0;
230 }
231
232 while (ts->cnt) {
233 err = thread_stack__call_return(thread, ts, --ts->cnt,
234 ts->last_time, 0, true);
235 if (err) {
236 pr_err("Error flushing thread stack!\n");
237 ts->cnt = 0;
238 return err;
239 }
240 }
241
242 return 0;
243}
244
245int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip,
246 u64 to_ip, u16 insn_len, u64 trace_nr)
247{
248 if (!thread)
249 return -EINVAL;
250
251 if (!thread->ts) {
252 thread->ts = thread_stack__new(thread, NULL);
253 if (!thread->ts) {
254 pr_warning("Out of memory: no thread stack\n");
255 return -ENOMEM;
256 }
257 thread->ts->trace_nr = trace_nr;
258 }
259
260 /*
261 * When the trace is discontinuous, the trace_nr changes. In that case
262 * the stack might be completely invalid. Better to report nothing than
263 * to report something misleading, so flush the stack.
264 */
265 if (trace_nr != thread->ts->trace_nr) {
266 if (thread->ts->trace_nr)
267 thread_stack__flush(thread, thread->ts);
268 thread->ts->trace_nr = trace_nr;
269 }
270
271 /* Stop here if thread_stack__process() is in use */
272 if (thread->ts->crp)
273 return 0;
274
275 if (flags & PERF_IP_FLAG_CALL) {
276 u64 ret_addr;
277
278 if (!to_ip)
279 return 0;
280 ret_addr = from_ip + insn_len;
281 if (ret_addr == to_ip)
282 return 0; /* Zero-length calls are excluded */
283 return thread_stack__push(thread->ts, ret_addr);
284 } else if (flags & PERF_IP_FLAG_RETURN) {
285 if (!from_ip)
286 return 0;
287 thread_stack__pop(thread->ts, to_ip);
288 }
289
290 return 0;
291}
292
293void thread_stack__set_trace_nr(struct thread *thread, u64 trace_nr)
294{
295 if (!thread || !thread->ts)
296 return;
297
298 if (trace_nr != thread->ts->trace_nr) {
299 if (thread->ts->trace_nr)
300 thread_stack__flush(thread, thread->ts);
301 thread->ts->trace_nr = trace_nr;
302 }
303}
304
305void thread_stack__free(struct thread *thread)
306{
307 if (thread->ts) {
308 thread_stack__flush(thread, thread->ts);
309 zfree(&thread->ts->stack);
310 zfree(&thread->ts);
311 }
312}
313
314void thread_stack__sample(struct thread *thread, struct ip_callchain *chain,
315 size_t sz, u64 ip)
316{
317 size_t i;
318
319 if (!thread || !thread->ts)
320 chain->nr = 1;
321 else
322 chain->nr = min(sz, thread->ts->cnt + 1);
323
324 chain->ips[0] = ip;
325
326 for (i = 1; i < chain->nr; i++)
327 chain->ips[i] = thread->ts->stack[thread->ts->cnt - i].ret_addr;
328}
329
330static void call_path__init(struct call_path *cp, struct call_path *parent,
331 struct symbol *sym, u64 ip, bool in_kernel)
332{
333 cp->parent = parent;
334 cp->sym = sym;
335 cp->ip = sym ? 0 : ip;
336 cp->db_id = 0;
337 cp->in_kernel = in_kernel;
338 RB_CLEAR_NODE(&cp->rb_node);
339 cp->children = RB_ROOT;
340}
341
342static struct call_path_root *call_path_root__new(void)
343{
344 struct call_path_root *cpr;
345
346 cpr = zalloc(sizeof(struct call_path_root));
347 if (!cpr)
348 return NULL;
349 call_path__init(&cpr->call_path, NULL, NULL, 0, false);
350 INIT_LIST_HEAD(&cpr->blocks);
351 return cpr;
352}
353
354static void call_path_root__free(struct call_path_root *cpr)
355{
356 struct call_path_block *pos, *n;
357
358 list_for_each_entry_safe(pos, n, &cpr->blocks, node) {
359 list_del(&pos->node);
360 free(pos);
361 }
362 free(cpr);
363}
364
365static struct call_path *call_path__new(struct call_path_root *cpr,
366 struct call_path *parent,
367 struct symbol *sym, u64 ip,
368 bool in_kernel)
369{
370 struct call_path_block *cpb;
371 struct call_path *cp;
372 size_t n;
373
374 if (cpr->next < cpr->sz) {
375 cpb = list_last_entry(&cpr->blocks, struct call_path_block,
376 node);
377 } else {
378 cpb = zalloc(sizeof(struct call_path_block));
379 if (!cpb)
380 return NULL;
381 list_add_tail(&cpb->node, &cpr->blocks);
382 cpr->sz += CALL_PATH_BLOCK_SIZE;
383 }
384
385 n = cpr->next++ & CALL_PATH_BLOCK_MASK;
386 cp = &cpb->cp[n];
387
388 call_path__init(cp, parent, sym, ip, in_kernel);
389
390 return cp;
391}
392
393static struct call_path *call_path__findnew(struct call_path_root *cpr,
394 struct call_path *parent,
395 struct symbol *sym, u64 ip, u64 ks)
396{
397 struct rb_node **p;
398 struct rb_node *node_parent = NULL;
399 struct call_path *cp;
400 bool in_kernel = ip >= ks;
401
402 if (sym)
403 ip = 0;
404
405 if (!parent)
406 return call_path__new(cpr, parent, sym, ip, in_kernel);
407
408 p = &parent->children.rb_node;
409 while (*p != NULL) {
410 node_parent = *p;
411 cp = rb_entry(node_parent, struct call_path, rb_node);
412
413 if (cp->sym == sym && cp->ip == ip)
414 return cp;
415
416 if (sym < cp->sym || (sym == cp->sym && ip < cp->ip))
417 p = &(*p)->rb_left;
418 else
419 p = &(*p)->rb_right;
420 }
421
422 cp = call_path__new(cpr, parent, sym, ip, in_kernel);
423 if (!cp)
424 return NULL;
425
426 rb_link_node(&cp->rb_node, node_parent, p);
427 rb_insert_color(&cp->rb_node, &parent->children);
428
429 return cp;
430}
431
432struct call_return_processor *
433call_return_processor__new(int (*process)(struct call_return *cr, void *data),
434 void *data)
435{
436 struct call_return_processor *crp;
437
438 crp = zalloc(sizeof(struct call_return_processor));
439 if (!crp)
440 return NULL;
441 crp->cpr = call_path_root__new();
442 if (!crp->cpr)
443 goto out_free;
444 crp->process = process;
445 crp->data = data;
446 return crp;
447
448out_free:
449 free(crp);
450 return NULL;
451}
452
453void call_return_processor__free(struct call_return_processor *crp)
454{
455 if (crp) {
456 call_path_root__free(crp->cpr);
457 free(crp);
458 }
459}
460
461static int thread_stack__push_cp(struct thread_stack *ts, u64 ret_addr,
462 u64 timestamp, u64 ref, struct call_path *cp,
463 bool no_call)
464{
465 struct thread_stack_entry *tse;
466 int err;
467
468 if (ts->cnt == ts->sz) {
469 err = thread_stack__grow(ts);
470 if (err)
471 return err;
472 }
473
474 tse = &ts->stack[ts->cnt++];
475 tse->ret_addr = ret_addr;
476 tse->timestamp = timestamp;
477 tse->ref = ref;
478 tse->branch_count = ts->branch_count;
479 tse->cp = cp;
480 tse->no_call = no_call;
481
482 return 0;
483}
484
485static int thread_stack__pop_cp(struct thread *thread, struct thread_stack *ts,
486 u64 ret_addr, u64 timestamp, u64 ref,
487 struct symbol *sym)
488{
489 int err;
490
491 if (!ts->cnt)
492 return 1;
493
494 if (ts->cnt == 1) {
495 struct thread_stack_entry *tse = &ts->stack[0];
496
497 if (tse->cp->sym == sym)
498 return thread_stack__call_return(thread, ts, --ts->cnt,
499 timestamp, ref, false);
500 }
501
502 if (ts->stack[ts->cnt - 1].ret_addr == ret_addr) {
503 return thread_stack__call_return(thread, ts, --ts->cnt,
504 timestamp, ref, false);
505 } else {
506 size_t i = ts->cnt - 1;
507
508 while (i--) {
509 if (ts->stack[i].ret_addr != ret_addr)
510 continue;
511 i += 1;
512 while (ts->cnt > i) {
513 err = thread_stack__call_return(thread, ts,
514 --ts->cnt,
515 timestamp, ref,
516 true);
517 if (err)
518 return err;
519 }
520 return thread_stack__call_return(thread, ts, --ts->cnt,
521 timestamp, ref, false);
522 }
523 }
524
525 return 1;
526}
527
528static int thread_stack__bottom(struct thread *thread, struct thread_stack *ts,
529 struct perf_sample *sample,
530 struct addr_location *from_al,
531 struct addr_location *to_al, u64 ref)
532{
533 struct call_path_root *cpr = ts->crp->cpr;
534 struct call_path *cp;
535 struct symbol *sym;
536 u64 ip;
537
538 if (sample->ip) {
539 ip = sample->ip;
540 sym = from_al->sym;
541 } else if (sample->addr) {
542 ip = sample->addr;
543 sym = to_al->sym;
544 } else {
545 return 0;
546 }
547
548 cp = call_path__findnew(cpr, &cpr->call_path, sym, ip,
549 ts->kernel_start);
550 if (!cp)
551 return -ENOMEM;
552
553 return thread_stack__push_cp(thread->ts, ip, sample->time, ref, cp,
554 true);
555}
556
557static int thread_stack__no_call_return(struct thread *thread,
558 struct thread_stack *ts,
559 struct perf_sample *sample,
560 struct addr_location *from_al,
561 struct addr_location *to_al, u64 ref)
562{
563 struct call_path_root *cpr = ts->crp->cpr;
564 struct call_path *cp, *parent;
565 u64 ks = ts->kernel_start;
566 int err;
567
568 if (sample->ip >= ks && sample->addr < ks) {
569 /* Return to userspace, so pop all kernel addresses */
570 while (thread_stack__in_kernel(ts)) {
571 err = thread_stack__call_return(thread, ts, --ts->cnt,
572 sample->time, ref,
573 true);
574 if (err)
575 return err;
576 }
577
578 /* If the stack is empty, push the userspace address */
579 if (!ts->cnt) {
580 cp = call_path__findnew(cpr, &cpr->call_path,
581 to_al->sym, sample->addr,
582 ts->kernel_start);
583 if (!cp)
584 return -ENOMEM;
585 return thread_stack__push_cp(ts, 0, sample->time, ref,
586 cp, true);
587 }
588 } else if (thread_stack__in_kernel(ts) && sample->ip < ks) {
589 /* Return to userspace, so pop all kernel addresses */
590 while (thread_stack__in_kernel(ts)) {
591 err = thread_stack__call_return(thread, ts, --ts->cnt,
592 sample->time, ref,
593 true);
594 if (err)
595 return err;
596 }
597 }
598
599 if (ts->cnt)
600 parent = ts->stack[ts->cnt - 1].cp;
601 else
602 parent = &cpr->call_path;
603
604 /* This 'return' had no 'call', so push and pop top of stack */
605 cp = call_path__findnew(cpr, parent, from_al->sym, sample->ip,
606 ts->kernel_start);
607 if (!cp)
608 return -ENOMEM;
609
610 err = thread_stack__push_cp(ts, sample->addr, sample->time, ref, cp,
611 true);
612 if (err)
613 return err;
614
615 return thread_stack__pop_cp(thread, ts, sample->addr, sample->time, ref,
616 to_al->sym);
617}
618
619static int thread_stack__trace_begin(struct thread *thread,
620 struct thread_stack *ts, u64 timestamp,
621 u64 ref)
622{
623 struct thread_stack_entry *tse;
624 int err;
625
626 if (!ts->cnt)
627 return 0;
628
629 /* Pop trace end */
630 tse = &ts->stack[ts->cnt - 1];
631 if (tse->cp->sym == NULL && tse->cp->ip == 0) {
632 err = thread_stack__call_return(thread, ts, --ts->cnt,
633 timestamp, ref, false);
634 if (err)
635 return err;
636 }
637
638 return 0;
639}
640
641static int thread_stack__trace_end(struct thread_stack *ts,
642 struct perf_sample *sample, u64 ref)
643{
644 struct call_path_root *cpr = ts->crp->cpr;
645 struct call_path *cp;
646 u64 ret_addr;
647
648 /* No point having 'trace end' on the bottom of the stack */
649 if (!ts->cnt || (ts->cnt == 1 && ts->stack[0].ref == ref))
650 return 0;
651
652 cp = call_path__findnew(cpr, ts->stack[ts->cnt - 1].cp, NULL, 0,
653 ts->kernel_start);
654 if (!cp)
655 return -ENOMEM;
656
657 ret_addr = sample->ip + sample->insn_len;
658
659 return thread_stack__push_cp(ts, ret_addr, sample->time, ref, cp,
660 false);
661}
662
663int thread_stack__process(struct thread *thread, struct comm *comm,
664 struct perf_sample *sample,
665 struct addr_location *from_al,
666 struct addr_location *to_al, u64 ref,
667 struct call_return_processor *crp)
668{
669 struct thread_stack *ts = thread->ts;
670 int err = 0;
671
672 if (ts) {
673 if (!ts->crp) {
674 /* Supersede thread_stack__event() */
675 thread_stack__free(thread);
676 thread->ts = thread_stack__new(thread, crp);
677 if (!thread->ts)
678 return -ENOMEM;
679 ts = thread->ts;
680 ts->comm = comm;
681 }
682 } else {
683 thread->ts = thread_stack__new(thread, crp);
684 if (!thread->ts)
685 return -ENOMEM;
686 ts = thread->ts;
687 ts->comm = comm;
688 }
689
690 /* Flush stack on exec */
691 if (ts->comm != comm && thread->pid_ == thread->tid) {
692 err = thread_stack__flush(thread, ts);
693 if (err)
694 return err;
695 ts->comm = comm;
696 }
697
698 /* If the stack is empty, put the current symbol on the stack */
699 if (!ts->cnt) {
700 err = thread_stack__bottom(thread, ts, sample, from_al, to_al,
701 ref);
702 if (err)
703 return err;
704 }
705
706 ts->branch_count += 1;
707 ts->last_time = sample->time;
708
709 if (sample->flags & PERF_IP_FLAG_CALL) {
710 struct call_path_root *cpr = ts->crp->cpr;
711 struct call_path *cp;
712 u64 ret_addr;
713
714 if (!sample->ip || !sample->addr)
715 return 0;
716
717 ret_addr = sample->ip + sample->insn_len;
718 if (ret_addr == sample->addr)
719 return 0; /* Zero-length calls are excluded */
720
721 cp = call_path__findnew(cpr, ts->stack[ts->cnt - 1].cp,
722 to_al->sym, sample->addr,
723 ts->kernel_start);
724 if (!cp)
725 return -ENOMEM;
726 err = thread_stack__push_cp(ts, ret_addr, sample->time, ref,
727 cp, false);
728 } else if (sample->flags & PERF_IP_FLAG_RETURN) {
729 if (!sample->ip || !sample->addr)
730 return 0;
731
732 err = thread_stack__pop_cp(thread, ts, sample->addr,
733 sample->time, ref, from_al->sym);
734 if (err) {
735 if (err < 0)
736 return err;
737 err = thread_stack__no_call_return(thread, ts, sample,
738 from_al, to_al, ref);
739 }
740 } else if (sample->flags & PERF_IP_FLAG_TRACE_BEGIN) {
741 err = thread_stack__trace_begin(thread, ts, sample->time, ref);
742 } else if (sample->flags & PERF_IP_FLAG_TRACE_END) {
743 err = thread_stack__trace_end(ts, sample, ref);
744 }
745
746 return err;
747}
diff --git a/tools/perf/util/thread-stack.h b/tools/perf/util/thread-stack.h
new file mode 100644
index 000000000000..b843bbef8ba2
--- /dev/null
+++ b/tools/perf/util/thread-stack.h
@@ -0,0 +1,111 @@
1/*
2 * thread-stack.h: Synthesize a thread's stack using call / return events
3 * Copyright (c) 2014, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 */
15
16#ifndef __PERF_THREAD_STACK_H
17#define __PERF_THREAD_STACK_H
18
19#include <sys/types.h>
20
21#include <linux/types.h>
22#include <linux/rbtree.h>
23
24struct thread;
25struct comm;
26struct ip_callchain;
27struct symbol;
28struct dso;
29struct call_return_processor;
30struct comm;
31struct perf_sample;
32struct addr_location;
33
34/*
35 * Call/Return flags.
36 *
37 * CALL_RETURN_NO_CALL: 'return' but no matching 'call'
38 * CALL_RETURN_NO_RETURN: 'call' but no matching 'return'
39 */
40enum {
41 CALL_RETURN_NO_CALL = 1 << 0,
42 CALL_RETURN_NO_RETURN = 1 << 1,
43};
44
45/**
46 * struct call_return - paired call/return information.
47 * @thread: thread in which call/return occurred
48 * @comm: comm in which call/return occurred
49 * @cp: call path
50 * @call_time: timestamp of call (if known)
51 * @return_time: timestamp of return (if known)
52 * @branch_count: number of branches seen between call and return
53 * @call_ref: external reference to 'call' sample (e.g. db_id)
54 * @return_ref: external reference to 'return' sample (e.g. db_id)
55 * @db_id: id used for db-export
56 * @flags: Call/Return flags
57 */
58struct call_return {
59 struct thread *thread;
60 struct comm *comm;
61 struct call_path *cp;
62 u64 call_time;
63 u64 return_time;
64 u64 branch_count;
65 u64 call_ref;
66 u64 return_ref;
67 u64 db_id;
68 u32 flags;
69};
70
71/**
72 * struct call_path - node in list of calls leading to a function call.
73 * @parent: call path to the parent function call
74 * @sym: symbol of function called
75 * @ip: only if sym is null, the ip of the function
76 * @db_id: id used for db-export
77 * @in_kernel: whether function is a in the kernel
78 * @rb_node: node in parent's tree of called functions
79 * @children: tree of call paths of functions called
80 *
81 * In combination with the call_return structure, the call_path structure
82 * defines a context-sensitve call-graph.
83 */
84struct call_path {
85 struct call_path *parent;
86 struct symbol *sym;
87 u64 ip;
88 u64 db_id;
89 bool in_kernel;
90 struct rb_node rb_node;
91 struct rb_root children;
92};
93
94int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip,
95 u64 to_ip, u16 insn_len, u64 trace_nr);
96void thread_stack__set_trace_nr(struct thread *thread, u64 trace_nr);
97void thread_stack__sample(struct thread *thread, struct ip_callchain *chain,
98 size_t sz, u64 ip);
99void thread_stack__free(struct thread *thread);
100
101struct call_return_processor *
102call_return_processor__new(int (*process)(struct call_return *cr, void *data),
103 void *data);
104void call_return_processor__free(struct call_return_processor *crp);
105int thread_stack__process(struct thread *thread, struct comm *comm,
106 struct perf_sample *sample,
107 struct addr_location *from_al,
108 struct addr_location *to_al, u64 ref,
109 struct call_return_processor *crp);
110
111#endif
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index c41411726c7a..9ebc8b1f9be5 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -4,6 +4,7 @@
4#include <string.h> 4#include <string.h>
5#include "session.h" 5#include "session.h"
6#include "thread.h" 6#include "thread.h"
7#include "thread-stack.h"
7#include "util.h" 8#include "util.h"
8#include "debug.h" 9#include "debug.h"
9#include "comm.h" 10#include "comm.h"
@@ -15,7 +16,7 @@ int thread__init_map_groups(struct thread *thread, struct machine *machine)
15 pid_t pid = thread->pid_; 16 pid_t pid = thread->pid_;
16 17
17 if (pid == thread->tid || pid == -1) { 18 if (pid == thread->tid || pid == -1) {
18 thread->mg = map_groups__new(); 19 thread->mg = map_groups__new(machine);
19 } else { 20 } else {
20 leader = machine__findnew_thread(machine, pid, pid); 21 leader = machine__findnew_thread(machine, pid, pid);
21 if (leader) 22 if (leader)
@@ -66,6 +67,8 @@ void thread__delete(struct thread *thread)
66{ 67{
67 struct comm *comm, *tmp; 68 struct comm *comm, *tmp;
68 69
70 thread_stack__free(thread);
71
69 if (thread->mg) { 72 if (thread->mg) {
70 map_groups__put(thread->mg); 73 map_groups__put(thread->mg);
71 thread->mg = NULL; 74 thread->mg = NULL;
@@ -100,15 +103,14 @@ struct comm *thread__exec_comm(const struct thread *thread)
100 return last; 103 return last;
101} 104}
102 105
103/* CHECKME: time should always be 0 if event aren't ordered */
104int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp, 106int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp,
105 bool exec) 107 bool exec)
106{ 108{
107 struct comm *new, *curr = thread__comm(thread); 109 struct comm *new, *curr = thread__comm(thread);
108 int err; 110 int err;
109 111
110 /* Override latest entry if it had no specific time coverage */ 112 /* Override the default :tid entry */
111 if (!curr->start && !curr->exec) { 113 if (!thread->comm_set) {
112 err = comm__override(curr, str, timestamp, exec); 114 err = comm__override(curr, str, timestamp, exec);
113 if (err) 115 if (err)
114 return err; 116 return err;
@@ -198,7 +200,6 @@ int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp)
198} 200}
199 201
200void thread__find_cpumode_addr_location(struct thread *thread, 202void thread__find_cpumode_addr_location(struct thread *thread,
201 struct machine *machine,
202 enum map_type type, u64 addr, 203 enum map_type type, u64 addr,
203 struct addr_location *al) 204 struct addr_location *al)
204{ 205{
@@ -211,8 +212,7 @@ void thread__find_cpumode_addr_location(struct thread *thread,
211 }; 212 };
212 213
213 for (i = 0; i < ARRAY_SIZE(cpumodes); i++) { 214 for (i = 0; i < ARRAY_SIZE(cpumodes); i++) {
214 thread__find_addr_location(thread, machine, cpumodes[i], type, 215 thread__find_addr_location(thread, cpumodes[i], type, addr, al);
215 addr, al);
216 if (al->map) 216 if (al->map)
217 break; 217 break;
218 } 218 }
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 8c75fa774706..160fd066a7d1 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -8,6 +8,8 @@
8#include "symbol.h" 8#include "symbol.h"
9#include <strlist.h> 9#include <strlist.h>
10 10
11struct thread_stack;
12
11struct thread { 13struct thread {
12 union { 14 union {
13 struct rb_node rb_node; 15 struct rb_node rb_node;
@@ -23,8 +25,10 @@ struct thread {
23 bool dead; /* if set thread has exited */ 25 bool dead; /* if set thread has exited */
24 struct list_head comm_list; 26 struct list_head comm_list;
25 int comm_len; 27 int comm_len;
28 u64 db_id;
26 29
27 void *priv; 30 void *priv;
31 struct thread_stack *ts;
28}; 32};
29 33
30struct machine; 34struct machine;
@@ -54,16 +58,15 @@ void thread__insert_map(struct thread *thread, struct map *map);
54int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp); 58int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp);
55size_t thread__fprintf(struct thread *thread, FILE *fp); 59size_t thread__fprintf(struct thread *thread, FILE *fp);
56 60
57void thread__find_addr_map(struct thread *thread, struct machine *machine, 61void thread__find_addr_map(struct thread *thread,
58 u8 cpumode, enum map_type type, u64 addr, 62 u8 cpumode, enum map_type type, u64 addr,
59 struct addr_location *al); 63 struct addr_location *al);
60 64
61void thread__find_addr_location(struct thread *thread, struct machine *machine, 65void thread__find_addr_location(struct thread *thread,
62 u8 cpumode, enum map_type type, u64 addr, 66 u8 cpumode, enum map_type type, u64 addr,
63 struct addr_location *al); 67 struct addr_location *al);
64 68
65void thread__find_cpumode_addr_location(struct thread *thread, 69void thread__find_cpumode_addr_location(struct thread *thread,
66 struct machine *machine,
67 enum map_type type, u64 addr, 70 enum map_type type, u64 addr,
68 struct addr_location *al); 71 struct addr_location *al);
69 72
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index f11636966a0f..bb2708bbfaca 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -39,7 +39,8 @@ struct perf_tool {
39 event_attr_op attr; 39 event_attr_op attr;
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 id_index;
43 bool ordered_events; 44 bool ordered_events;
44 bool ordering_requires_timestamps; 45 bool ordering_requires_timestamps;
45}; 46};
diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c
index 7419768c38b1..2dcfe9a7c8d0 100644
--- a/tools/perf/util/unwind-libdw.c
+++ b/tools/perf/util/unwind-libdw.c
@@ -26,7 +26,7 @@ static int __report_module(struct addr_location *al, u64 ip,
26 Dwfl_Module *mod; 26 Dwfl_Module *mod;
27 struct dso *dso = NULL; 27 struct dso *dso = NULL;
28 28
29 thread__find_addr_location(ui->thread, ui->machine, 29 thread__find_addr_location(ui->thread,
30 PERF_RECORD_MISC_USER, 30 PERF_RECORD_MISC_USER,
31 MAP__FUNCTION, ip, al); 31 MAP__FUNCTION, ip, al);
32 32
@@ -89,7 +89,7 @@ static int access_dso_mem(struct unwind_info *ui, Dwarf_Addr addr,
89 struct addr_location al; 89 struct addr_location al;
90 ssize_t size; 90 ssize_t size;
91 91
92 thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER, 92 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
93 MAP__FUNCTION, addr, &al); 93 MAP__FUNCTION, addr, &al);
94 if (!al.map) { 94 if (!al.map) {
95 pr_debug("unwind: no map for %lx\n", (unsigned long)addr); 95 pr_debug("unwind: no map for %lx\n", (unsigned long)addr);
@@ -164,14 +164,14 @@ frame_callback(Dwfl_Frame *state, void *arg)
164} 164}
165 165
166int unwind__get_entries(unwind_entry_cb_t cb, void *arg, 166int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
167 struct machine *machine, struct thread *thread, 167 struct thread *thread,
168 struct perf_sample *data, 168 struct perf_sample *data,
169 int max_stack) 169 int max_stack)
170{ 170{
171 struct unwind_info ui = { 171 struct unwind_info ui = {
172 .sample = data, 172 .sample = data,
173 .thread = thread, 173 .thread = thread,
174 .machine = machine, 174 .machine = thread->mg->machine,
175 .cb = cb, 175 .cb = cb,
176 .arg = arg, 176 .arg = arg,
177 .max_stack = max_stack, 177 .max_stack = max_stack,
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c
index 4d45c0dfe343..371219a6daf1 100644
--- a/tools/perf/util/unwind-libunwind.c
+++ b/tools/perf/util/unwind-libunwind.c
@@ -284,7 +284,7 @@ static struct map *find_map(unw_word_t ip, struct unwind_info *ui)
284{ 284{
285 struct addr_location al; 285 struct addr_location al;
286 286
287 thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER, 287 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
288 MAP__FUNCTION, ip, &al); 288 MAP__FUNCTION, ip, &al);
289 return al.map; 289 return al.map;
290} 290}
@@ -374,7 +374,7 @@ static int access_dso_mem(struct unwind_info *ui, unw_word_t addr,
374 struct addr_location al; 374 struct addr_location al;
375 ssize_t size; 375 ssize_t size;
376 376
377 thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER, 377 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
378 MAP__FUNCTION, addr, &al); 378 MAP__FUNCTION, addr, &al);
379 if (!al.map) { 379 if (!al.map) {
380 pr_debug("unwind: no map for %lx\n", (unsigned long)addr); 380 pr_debug("unwind: no map for %lx\n", (unsigned long)addr);
@@ -476,14 +476,13 @@ static void put_unwind_info(unw_addr_space_t __maybe_unused as,
476 pr_debug("unwind: put_unwind_info called\n"); 476 pr_debug("unwind: put_unwind_info called\n");
477} 477}
478 478
479static int entry(u64 ip, struct thread *thread, struct machine *machine, 479static int entry(u64 ip, struct thread *thread,
480 unwind_entry_cb_t cb, void *arg) 480 unwind_entry_cb_t cb, void *arg)
481{ 481{
482 struct unwind_entry e; 482 struct unwind_entry e;
483 struct addr_location al; 483 struct addr_location al;
484 484
485 thread__find_addr_location(thread, machine, 485 thread__find_addr_location(thread, PERF_RECORD_MISC_USER,
486 PERF_RECORD_MISC_USER,
487 MAP__FUNCTION, ip, &al); 486 MAP__FUNCTION, ip, &al);
488 487
489 e.ip = ip; 488 e.ip = ip;
@@ -586,21 +585,21 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
586 unw_word_t ip; 585 unw_word_t ip;
587 586
588 unw_get_reg(&c, UNW_REG_IP, &ip); 587 unw_get_reg(&c, UNW_REG_IP, &ip);
589 ret = ip ? entry(ip, ui->thread, ui->machine, cb, arg) : 0; 588 ret = ip ? entry(ip, ui->thread, cb, arg) : 0;
590 } 589 }
591 590
592 return ret; 591 return ret;
593} 592}
594 593
595int unwind__get_entries(unwind_entry_cb_t cb, void *arg, 594int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
596 struct machine *machine, struct thread *thread, 595 struct thread *thread,
597 struct perf_sample *data, int max_stack) 596 struct perf_sample *data, int max_stack)
598{ 597{
599 u64 ip; 598 u64 ip;
600 struct unwind_info ui = { 599 struct unwind_info ui = {
601 .sample = data, 600 .sample = data,
602 .thread = thread, 601 .thread = thread,
603 .machine = machine, 602 .machine = thread->mg->machine,
604 }; 603 };
605 int ret; 604 int ret;
606 605
@@ -611,7 +610,7 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
611 if (ret) 610 if (ret)
612 return ret; 611 return ret;
613 612
614 ret = entry(ip, thread, machine, cb, arg); 613 ret = entry(ip, thread, cb, arg);
615 if (ret) 614 if (ret)
616 return -ENOMEM; 615 return -ENOMEM;
617 616
diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h
index f50b737235eb..12790cf94618 100644
--- a/tools/perf/util/unwind.h
+++ b/tools/perf/util/unwind.h
@@ -16,7 +16,6 @@ typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg);
16 16
17#ifdef HAVE_DWARF_UNWIND_SUPPORT 17#ifdef HAVE_DWARF_UNWIND_SUPPORT
18int unwind__get_entries(unwind_entry_cb_t cb, void *arg, 18int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
19 struct machine *machine,
20 struct thread *thread, 19 struct thread *thread,
21 struct perf_sample *data, int max_stack); 20 struct perf_sample *data, int max_stack);
22/* libunwind specific */ 21/* libunwind specific */
@@ -38,7 +37,6 @@ static inline void unwind__finish_access(struct thread *thread __maybe_unused) {
38static inline int 37static inline int
39unwind__get_entries(unwind_entry_cb_t cb __maybe_unused, 38unwind__get_entries(unwind_entry_cb_t cb __maybe_unused,
40 void *arg __maybe_unused, 39 void *arg __maybe_unused,
41 struct machine *machine __maybe_unused,
42 struct thread *thread __maybe_unused, 40 struct thread *thread __maybe_unused,
43 struct perf_sample *data __maybe_unused, 41 struct perf_sample *data __maybe_unused,
44 int max_stack __maybe_unused) 42 int max_stack __maybe_unused)
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 80bfdaa0e2a4..76d23d83eae5 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -154,7 +154,6 @@ extern void set_die_routine(void (*routine)(const char *err, va_list params) NOR
154 154
155extern int prefixcmp(const char *str, const char *prefix); 155extern int prefixcmp(const char *str, const char *prefix);
156extern void set_buildid_dir(void); 156extern void set_buildid_dir(void);
157extern void disable_buildid_cache(void);
158 157
159static inline const char *skip_prefix(const char *str, const char *prefix) 158static inline const char *skip_prefix(const char *str, const char *prefix)
160{ 159{
@@ -351,4 +350,9 @@ void mem_bswap_32(void *src, int byte_size);
351 350
352const char *get_filename_for_perf_kvm(void); 351const char *get_filename_for_perf_kvm(void);
353bool find_process(const char *name); 352bool find_process(const char *name);
353
354#ifdef HAVE_ZLIB_SUPPORT
355int gzip_decompress_to_file(const char *input, int output_fd);
356#endif
357
354#endif /* GIT_COMPAT_UTIL_H */ 358#endif /* GIT_COMPAT_UTIL_H */
diff --git a/tools/perf/util/vdso.c b/tools/perf/util/vdso.c
index adca69384fcc..5c7dd796979d 100644
--- a/tools/perf/util/vdso.c
+++ b/tools/perf/util/vdso.c
@@ -12,9 +12,16 @@
12#include "util.h" 12#include "util.h"
13#include "symbol.h" 13#include "symbol.h"
14#include "machine.h" 14#include "machine.h"
15#include "thread.h"
15#include "linux/string.h" 16#include "linux/string.h"
16#include "debug.h" 17#include "debug.h"
17 18
19/*
20 * Include definition of find_vdso_map() also used in perf-read-vdso.c for
21 * building perf-read-vdso32 and perf-read-vdsox32.
22 */
23#include "find-vdso-map.c"
24
18#define VDSO__TEMP_FILE_NAME "/tmp/perf-vdso.so-XXXXXX" 25#define VDSO__TEMP_FILE_NAME "/tmp/perf-vdso.so-XXXXXX"
19 26
20struct vdso_file { 27struct vdso_file {
@@ -22,10 +29,15 @@ struct vdso_file {
22 bool error; 29 bool error;
23 char temp_file_name[sizeof(VDSO__TEMP_FILE_NAME)]; 30 char temp_file_name[sizeof(VDSO__TEMP_FILE_NAME)];
24 const char *dso_name; 31 const char *dso_name;
32 const char *read_prog;
25}; 33};
26 34
27struct vdso_info { 35struct vdso_info {
28 struct vdso_file vdso; 36 struct vdso_file vdso;
37#if BITS_PER_LONG == 64
38 struct vdso_file vdso32;
39 struct vdso_file vdsox32;
40#endif
29}; 41};
30 42
31static struct vdso_info *vdso_info__new(void) 43static struct vdso_info *vdso_info__new(void)
@@ -35,42 +47,23 @@ static struct vdso_info *vdso_info__new(void)
35 .temp_file_name = VDSO__TEMP_FILE_NAME, 47 .temp_file_name = VDSO__TEMP_FILE_NAME,
36 .dso_name = DSO__NAME_VDSO, 48 .dso_name = DSO__NAME_VDSO,
37 }, 49 },
50#if BITS_PER_LONG == 64
51 .vdso32 = {
52 .temp_file_name = VDSO__TEMP_FILE_NAME,
53 .dso_name = DSO__NAME_VDSO32,
54 .read_prog = "perf-read-vdso32",
55 },
56 .vdsox32 = {
57 .temp_file_name = VDSO__TEMP_FILE_NAME,
58 .dso_name = DSO__NAME_VDSOX32,
59 .read_prog = "perf-read-vdsox32",
60 },
61#endif
38 }; 62 };
39 63
40 return memdup(&vdso_info_init, sizeof(vdso_info_init)); 64 return memdup(&vdso_info_init, sizeof(vdso_info_init));
41} 65}
42 66
43static int find_vdso_map(void **start, void **end)
44{
45 FILE *maps;
46 char line[128];
47 int found = 0;
48
49 maps = fopen("/proc/self/maps", "r");
50 if (!maps) {
51 pr_err("vdso: cannot open maps\n");
52 return -1;
53 }
54
55 while (!found && fgets(line, sizeof(line), maps)) {
56 int m = -1;
57
58 /* We care only about private r-x mappings. */
59 if (2 != sscanf(line, "%p-%p r-xp %*x %*x:%*x %*u %n",
60 start, end, &m))
61 continue;
62 if (m < 0)
63 continue;
64
65 if (!strncmp(&line[m], VDSO__MAP_NAME,
66 sizeof(VDSO__MAP_NAME) - 1))
67 found = 1;
68 }
69
70 fclose(maps);
71 return !found;
72}
73
74static char *get_file(struct vdso_file *vdso_file) 67static char *get_file(struct vdso_file *vdso_file)
75{ 68{
76 char *vdso = NULL; 69 char *vdso = NULL;
@@ -117,6 +110,12 @@ void vdso__exit(struct machine *machine)
117 110
118 if (vdso_info->vdso.found) 111 if (vdso_info->vdso.found)
119 unlink(vdso_info->vdso.temp_file_name); 112 unlink(vdso_info->vdso.temp_file_name);
113#if BITS_PER_LONG == 64
114 if (vdso_info->vdso32.found)
115 unlink(vdso_info->vdso32.temp_file_name);
116 if (vdso_info->vdsox32.found)
117 unlink(vdso_info->vdsox32.temp_file_name);
118#endif
120 119
121 zfree(&machine->vdso_info); 120 zfree(&machine->vdso_info);
122} 121}
@@ -135,6 +134,153 @@ static struct dso *vdso__new(struct machine *machine, const char *short_name,
135 return dso; 134 return dso;
136} 135}
137 136
137#if BITS_PER_LONG == 64
138
139static enum dso_type machine__thread_dso_type(struct machine *machine,
140 struct thread *thread)
141{
142 enum dso_type dso_type = DSO__TYPE_UNKNOWN;
143 struct map *map;
144 struct dso *dso;
145
146 map = map_groups__first(thread->mg, MAP__FUNCTION);
147 for (; map ; map = map_groups__next(map)) {
148 dso = map->dso;
149 if (!dso || dso->long_name[0] != '/')
150 continue;
151 dso_type = dso__type(dso, machine);
152 if (dso_type != DSO__TYPE_UNKNOWN)
153 break;
154 }
155
156 return dso_type;
157}
158
159static int vdso__do_copy_compat(FILE *f, int fd)
160{
161 char buf[4096];
162 size_t count;
163
164 while (1) {
165 count = fread(buf, 1, sizeof(buf), f);
166 if (ferror(f))
167 return -errno;
168 if (feof(f))
169 break;
170 if (count && writen(fd, buf, count) != (ssize_t)count)
171 return -errno;
172 }
173
174 return 0;
175}
176
177static int vdso__copy_compat(const char *prog, int fd)
178{
179 FILE *f;
180 int err;
181
182 f = popen(prog, "r");
183 if (!f)
184 return -errno;
185
186 err = vdso__do_copy_compat(f, fd);
187
188 if (pclose(f) == -1)
189 return -errno;
190
191 return err;
192}
193
194static int vdso__create_compat_file(const char *prog, char *temp_name)
195{
196 int fd, err;
197
198 fd = mkstemp(temp_name);
199 if (fd < 0)
200 return -errno;
201
202 err = vdso__copy_compat(prog, fd);
203
204 if (close(fd) == -1)
205 return -errno;
206
207 return err;
208}
209
210static const char *vdso__get_compat_file(struct vdso_file *vdso_file)
211{
212 int err;
213
214 if (vdso_file->found)
215 return vdso_file->temp_file_name;
216
217 if (vdso_file->error)
218 return NULL;
219
220 err = vdso__create_compat_file(vdso_file->read_prog,
221 vdso_file->temp_file_name);
222 if (err) {
223 pr_err("%s failed, error %d\n", vdso_file->read_prog, err);
224 vdso_file->error = true;
225 return NULL;
226 }
227
228 vdso_file->found = true;
229
230 return vdso_file->temp_file_name;
231}
232
233static struct dso *vdso__findnew_compat(struct machine *machine,
234 struct vdso_file *vdso_file)
235{
236 const char *file_name;
237 struct dso *dso;
238
239 dso = dsos__find(&machine->user_dsos, vdso_file->dso_name, true);
240 if (dso)
241 return dso;
242
243 file_name = vdso__get_compat_file(vdso_file);
244 if (!file_name)
245 return NULL;
246
247 return vdso__new(machine, vdso_file->dso_name, file_name);
248}
249
250static int vdso__dso_findnew_compat(struct machine *machine,
251 struct thread *thread,
252 struct vdso_info *vdso_info,
253 struct dso **dso)
254{
255 enum dso_type dso_type;
256
257 dso_type = machine__thread_dso_type(machine, thread);
258
259#ifndef HAVE_PERF_READ_VDSO32
260 if (dso_type == DSO__TYPE_32BIT)
261 return 0;
262#endif
263#ifndef HAVE_PERF_READ_VDSOX32
264 if (dso_type == DSO__TYPE_X32BIT)
265 return 0;
266#endif
267
268 switch (dso_type) {
269 case DSO__TYPE_32BIT:
270 *dso = vdso__findnew_compat(machine, &vdso_info->vdso32);
271 return 1;
272 case DSO__TYPE_X32BIT:
273 *dso = vdso__findnew_compat(machine, &vdso_info->vdsox32);
274 return 1;
275 case DSO__TYPE_UNKNOWN:
276 case DSO__TYPE_64BIT:
277 default:
278 return 0;
279 }
280}
281
282#endif
283
138struct dso *vdso__dso_findnew(struct machine *machine, 284struct dso *vdso__dso_findnew(struct machine *machine,
139 struct thread *thread __maybe_unused) 285 struct thread *thread __maybe_unused)
140{ 286{
@@ -148,6 +294,11 @@ struct dso *vdso__dso_findnew(struct machine *machine,
148 if (!vdso_info) 294 if (!vdso_info)
149 return NULL; 295 return NULL;
150 296
297#if BITS_PER_LONG == 64
298 if (vdso__dso_findnew_compat(machine, thread, vdso_info, &dso))
299 return dso;
300#endif
301
151 dso = dsos__find(&machine->user_dsos, DSO__NAME_VDSO, true); 302 dso = dsos__find(&machine->user_dsos, DSO__NAME_VDSO, true);
152 if (!dso) { 303 if (!dso) {
153 char *file; 304 char *file;
@@ -164,5 +315,7 @@ struct dso *vdso__dso_findnew(struct machine *machine,
164 315
165bool dso__is_vdso(struct dso *dso) 316bool dso__is_vdso(struct dso *dso)
166{ 317{
167 return !strcmp(dso->short_name, DSO__NAME_VDSO); 318 return !strcmp(dso->short_name, DSO__NAME_VDSO) ||
319 !strcmp(dso->short_name, DSO__NAME_VDSO32) ||
320 !strcmp(dso->short_name, DSO__NAME_VDSOX32);
168} 321}
diff --git a/tools/perf/util/vdso.h b/tools/perf/util/vdso.h
index af9d6929a215..d97da1616f0c 100644
--- a/tools/perf/util/vdso.h
+++ b/tools/perf/util/vdso.h
@@ -7,7 +7,9 @@
7 7
8#define VDSO__MAP_NAME "[vdso]" 8#define VDSO__MAP_NAME "[vdso]"
9 9
10#define DSO__NAME_VDSO "[vdso]" 10#define DSO__NAME_VDSO "[vdso]"
11#define DSO__NAME_VDSO32 "[vdso32]"
12#define DSO__NAME_VDSOX32 "[vdsox32]"
11 13
12static inline bool is_vdso_map(const char *filename) 14static inline bool is_vdso_map(const char *filename)
13{ 15{
diff --git a/tools/perf/util/zlib.c b/tools/perf/util/zlib.c
new file mode 100644
index 000000000000..495a449fc25c
--- /dev/null
+++ b/tools/perf/util/zlib.c
@@ -0,0 +1,78 @@
1#include <stdio.h>
2#include <unistd.h>
3#include <sys/stat.h>
4#include <sys/mman.h>
5#include <zlib.h>
6
7#include "util/util.h"
8#include "util/debug.h"
9
10
11#define CHUNK_SIZE 16384
12
13int gzip_decompress_to_file(const char *input, int output_fd)
14{
15 int ret = Z_STREAM_ERROR;
16 int input_fd;
17 void *ptr;
18 int len;
19 struct stat stbuf;
20 unsigned char buf[CHUNK_SIZE];
21 z_stream zs = {
22 .zalloc = Z_NULL,
23 .zfree = Z_NULL,
24 .opaque = Z_NULL,
25 .avail_in = 0,
26 .next_in = Z_NULL,
27 };
28
29 input_fd = open(input, O_RDONLY);
30 if (input_fd < 0)
31 return -1;
32
33 if (fstat(input_fd, &stbuf) < 0)
34 goto out_close;
35
36 ptr = mmap(NULL, stbuf.st_size, PROT_READ, MAP_PRIVATE, input_fd, 0);
37 if (ptr == MAP_FAILED)
38 goto out_close;
39
40 if (inflateInit2(&zs, 16 + MAX_WBITS) != Z_OK)
41 goto out_unmap;
42
43 zs.next_in = ptr;
44 zs.avail_in = stbuf.st_size;
45
46 do {
47 zs.next_out = buf;
48 zs.avail_out = CHUNK_SIZE;
49
50 ret = inflate(&zs, Z_NO_FLUSH);
51 switch (ret) {
52 case Z_NEED_DICT:
53 ret = Z_DATA_ERROR;
54 /* fall through */
55 case Z_DATA_ERROR:
56 case Z_MEM_ERROR:
57 goto out;
58 default:
59 break;
60 }
61
62 len = CHUNK_SIZE - zs.avail_out;
63 if (writen(output_fd, buf, len) != len) {
64 ret = Z_DATA_ERROR;
65 goto out;
66 }
67
68 } while (ret != Z_STREAM_END);
69
70out:
71 inflateEnd(&zs);
72out_unmap:
73 munmap(ptr, stbuf.st_size);
74out_close:
75 close(input_fd);
76
77 return ret == Z_STREAM_END ? 0 : -1;
78}