aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2012-01-31 09:13:14 -0500
committerTakashi Iwai <tiwai@suse.de>2012-01-31 09:13:14 -0500
commitea51e5040e24eefe44d70bc654a237ca1f0225b0 (patch)
treedf2e5922dcdfafae62a10d8cd97f98121064fc23 /tools/perf/util
parent3422a47041b8cb8f14ac1e3926bcf711121df6dc (diff)
parent8dbd52daee38adaae4d5a674bcca837e694a4f4c (diff)
Merge branch 'fix/asoc' into for-linus
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/annotate.c8
-rw-r--r--tools/perf/util/annotate.h5
-rw-r--r--tools/perf/util/build-id.c26
-rw-r--r--tools/perf/util/build-id.h2
-rw-r--r--tools/perf/util/callchain.h3
-rw-r--r--tools/perf/util/cgroup.c15
-rw-r--r--tools/perf/util/config.c5
-rw-r--r--tools/perf/util/debugfs.c35
-rw-r--r--tools/perf/util/debugfs.h31
-rw-r--r--tools/perf/util/event.c360
-rw-r--r--tools/perf/util/event.h68
-rw-r--r--tools/perf/util/evlist.c304
-rw-r--r--tools/perf/util/evlist.h43
-rw-r--r--tools/perf/util/evsel.c164
-rw-r--r--tools/perf/util/evsel.h8
-rw-r--r--tools/perf/util/header.c743
-rw-r--r--tools/perf/util/header.h51
-rw-r--r--tools/perf/util/hist.c141
-rw-r--r--tools/perf/util/hist.h12
-rw-r--r--tools/perf/util/include/linux/bitops.h118
-rw-r--r--tools/perf/util/map.c4
-rw-r--r--tools/perf/util/map.h19
-rw-r--r--tools/perf/util/parse-events.c45
-rw-r--r--tools/perf/util/parse-events.h1
-rw-r--r--tools/perf/util/probe-finder.h1
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c75
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c4
-rw-r--r--tools/perf/util/session.c346
-rw-r--r--tools/perf/util/session.h72
-rw-r--r--tools/perf/util/setup.py3
-rw-r--r--tools/perf/util/symbol.c11
-rw-r--r--tools/perf/util/symbol.h1
-rw-r--r--tools/perf/util/thread.c6
-rw-r--r--tools/perf/util/thread.h14
-rw-r--r--tools/perf/util/tool.h50
-rw-r--r--tools/perf/util/top.h20
-rw-r--r--tools/perf/util/trace-event-info.c27
-rw-r--r--tools/perf/util/trace-event-parse.c2
-rw-r--r--tools/perf/util/trace-event-scripting.c2
-rw-r--r--tools/perf/util/trace-event.h8
-rw-r--r--tools/perf/util/ui/browsers/annotate.c16
-rw-r--r--tools/perf/util/ui/browsers/hists.c2
-rw-r--r--tools/perf/util/ui/progress.c3
-rw-r--r--tools/perf/util/usage.c5
-rw-r--r--tools/perf/util/util.c15
-rw-r--r--tools/perf/util/util.h15
-rw-r--r--tools/perf/util/values.c1
47 files changed, 1892 insertions, 1018 deletions
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 119e996035c8..011ed2676604 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -25,17 +25,17 @@ int symbol__annotate_init(struct map *map __used, struct symbol *sym)
25 return 0; 25 return 0;
26} 26}
27 27
28int symbol__alloc_hist(struct symbol *sym, int nevents) 28int symbol__alloc_hist(struct symbol *sym)
29{ 29{
30 struct annotation *notes = symbol__annotation(sym); 30 struct annotation *notes = symbol__annotation(sym);
31 size_t sizeof_sym_hist = (sizeof(struct sym_hist) + 31 size_t sizeof_sym_hist = (sizeof(struct sym_hist) +
32 (sym->end - sym->start) * sizeof(u64)); 32 (sym->end - sym->start) * sizeof(u64));
33 33
34 notes->src = zalloc(sizeof(*notes->src) + nevents * sizeof_sym_hist); 34 notes->src = zalloc(sizeof(*notes->src) + symbol_conf.nr_events * sizeof_sym_hist);
35 if (notes->src == NULL) 35 if (notes->src == NULL)
36 return -1; 36 return -1;
37 notes->src->sizeof_sym_hist = sizeof_sym_hist; 37 notes->src->sizeof_sym_hist = sizeof_sym_hist;
38 notes->src->nr_histograms = nevents; 38 notes->src->nr_histograms = symbol_conf.nr_events;
39 INIT_LIST_HEAD(&notes->src->source); 39 INIT_LIST_HEAD(&notes->src->source);
40 return 0; 40 return 0;
41} 41}
@@ -334,7 +334,7 @@ fallback:
334 disassembler_style ? "-M " : "", 334 disassembler_style ? "-M " : "",
335 disassembler_style ? disassembler_style : "", 335 disassembler_style ? disassembler_style : "",
336 map__rip_2objdump(map, sym->start), 336 map__rip_2objdump(map, sym->start),
337 map__rip_2objdump(map, sym->end), 337 map__rip_2objdump(map, sym->end+1),
338 symbol_conf.annotate_asm_raw ? "" : "--no-show-raw", 338 symbol_conf.annotate_asm_raw ? "" : "--no-show-raw",
339 symbol_conf.annotate_src ? "-S" : "", 339 symbol_conf.annotate_src ? "-S" : "",
340 symfs_filename, filename); 340 symfs_filename, filename);
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index d9072523d342..efa5dc82bfae 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -72,7 +72,7 @@ static inline struct annotation *symbol__annotation(struct symbol *sym)
72 72
73int symbol__inc_addr_samples(struct symbol *sym, struct map *map, 73int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
74 int evidx, u64 addr); 74 int evidx, u64 addr);
75int symbol__alloc_hist(struct symbol *sym, int nevents); 75int symbol__alloc_hist(struct symbol *sym);
76void symbol__annotate_zero_histograms(struct symbol *sym); 76void symbol__annotate_zero_histograms(struct symbol *sym);
77 77
78int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize); 78int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize);
@@ -99,8 +99,7 @@ static inline int symbol__tui_annotate(struct symbol *sym __used,
99} 99}
100#else 100#else
101int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, 101int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
102 int nr_events, void(*timer)(void *arg), void *arg, 102 void(*timer)(void *arg), void *arg, int delay_secs);
103 int delay_secs);
104#endif 103#endif
105 104
106extern const char *disassembler_style; 105extern const char *disassembler_style;
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index a91cd99f26ea..dff9c7a725f4 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -13,15 +13,18 @@
13#include "symbol.h" 13#include "symbol.h"
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include "debug.h" 15#include "debug.h"
16#include "session.h"
17#include "tool.h"
16 18
17static int build_id__mark_dso_hit(union perf_event *event, 19static int build_id__mark_dso_hit(struct perf_tool *tool __used,
20 union perf_event *event,
18 struct perf_sample *sample __used, 21 struct perf_sample *sample __used,
19 struct perf_evsel *evsel __used, 22 struct perf_evsel *evsel __used,
20 struct perf_session *session) 23 struct machine *machine)
21{ 24{
22 struct addr_location al; 25 struct addr_location al;
23 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 26 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
24 struct thread *thread = perf_session__findnew(session, event->ip.pid); 27 struct thread *thread = machine__findnew_thread(machine, event->ip.pid);
25 28
26 if (thread == NULL) { 29 if (thread == NULL) {
27 pr_err("problem processing %d event, skipping it.\n", 30 pr_err("problem processing %d event, skipping it.\n",
@@ -29,8 +32,8 @@ static int build_id__mark_dso_hit(union perf_event *event,
29 return -1; 32 return -1;
30 } 33 }
31 34
32 thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION, 35 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
33 event->ip.pid, event->ip.ip, &al); 36 event->ip.ip, &al);
34 37
35 if (al.map != NULL) 38 if (al.map != NULL)
36 al.map->dso->hit = 1; 39 al.map->dso->hit = 1;
@@ -38,25 +41,26 @@ static int build_id__mark_dso_hit(union perf_event *event,
38 return 0; 41 return 0;
39} 42}
40 43
41static int perf_event__exit_del_thread(union perf_event *event, 44static int perf_event__exit_del_thread(struct perf_tool *tool __used,
45 union perf_event *event,
42 struct perf_sample *sample __used, 46 struct perf_sample *sample __used,
43 struct perf_session *session) 47 struct machine *machine)
44{ 48{
45 struct thread *thread = perf_session__findnew(session, event->fork.tid); 49 struct thread *thread = machine__findnew_thread(machine, event->fork.tid);
46 50
47 dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid, 51 dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid,
48 event->fork.ppid, event->fork.ptid); 52 event->fork.ppid, event->fork.ptid);
49 53
50 if (thread) { 54 if (thread) {
51 rb_erase(&thread->rb_node, &session->threads); 55 rb_erase(&thread->rb_node, &machine->threads);
52 session->last_match = NULL; 56 machine->last_match = NULL;
53 thread__delete(thread); 57 thread__delete(thread);
54 } 58 }
55 59
56 return 0; 60 return 0;
57} 61}
58 62
59struct perf_event_ops build_id__mark_dso_hit_ops = { 63struct perf_tool build_id__mark_dso_hit_ops = {
60 .sample = build_id__mark_dso_hit, 64 .sample = build_id__mark_dso_hit,
61 .mmap = perf_event__process_mmap, 65 .mmap = perf_event__process_mmap,
62 .fork = perf_event__process_task, 66 .fork = perf_event__process_task,
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index 5dafb00eaa06..a993ba87d996 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -3,7 +3,7 @@
3 3
4#include "session.h" 4#include "session.h"
5 5
6extern struct perf_event_ops build_id__mark_dso_hit_ops; 6extern struct perf_tool build_id__mark_dso_hit_ops;
7 7
8char *dso__build_id_filename(struct dso *self, char *bf, size_t size); 8char *dso__build_id_filename(struct dso *self, char *bf, size_t size);
9 9
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 9b4ff16cac96..7f9c0f1ae3a9 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -101,6 +101,9 @@ int callchain_append(struct callchain_root *root,
101int callchain_merge(struct callchain_cursor *cursor, 101int callchain_merge(struct callchain_cursor *cursor,
102 struct callchain_root *dst, struct callchain_root *src); 102 struct callchain_root *dst, struct callchain_root *src);
103 103
104struct ip_callchain;
105union perf_event;
106
104bool ip_callchain__valid(struct ip_callchain *chain, 107bool ip_callchain__valid(struct ip_callchain *chain,
105 const union perf_event *event); 108 const union perf_event *event);
106/* 109/*
diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c
index 96bee5c46008..dbe2f16b1a1a 100644
--- a/tools/perf/util/cgroup.c
+++ b/tools/perf/util/cgroup.c
@@ -3,7 +3,6 @@
3#include "parse-options.h" 3#include "parse-options.h"
4#include "evsel.h" 4#include "evsel.h"
5#include "cgroup.h" 5#include "cgroup.h"
6#include "debugfs.h" /* MAX_PATH, STR() */
7#include "evlist.h" 6#include "evlist.h"
8 7
9int nr_cgroups; 8int nr_cgroups;
@@ -12,7 +11,7 @@ static int
12cgroupfs_find_mountpoint(char *buf, size_t maxlen) 11cgroupfs_find_mountpoint(char *buf, size_t maxlen)
13{ 12{
14 FILE *fp; 13 FILE *fp;
15 char mountpoint[MAX_PATH+1], tokens[MAX_PATH+1], type[MAX_PATH+1]; 14 char mountpoint[PATH_MAX + 1], tokens[PATH_MAX + 1], type[PATH_MAX + 1];
16 char *token, *saved_ptr = NULL; 15 char *token, *saved_ptr = NULL;
17 int found = 0; 16 int found = 0;
18 17
@@ -25,8 +24,8 @@ cgroupfs_find_mountpoint(char *buf, size_t maxlen)
25 * and inspect every cgroupfs mount point to find one that has 24 * and inspect every cgroupfs mount point to find one that has
26 * perf_event subsystem 25 * perf_event subsystem
27 */ 26 */
28 while (fscanf(fp, "%*s %"STR(MAX_PATH)"s %"STR(MAX_PATH)"s %" 27 while (fscanf(fp, "%*s %"STR(PATH_MAX)"s %"STR(PATH_MAX)"s %"
29 STR(MAX_PATH)"s %*d %*d\n", 28 STR(PATH_MAX)"s %*d %*d\n",
30 mountpoint, type, tokens) == 3) { 29 mountpoint, type, tokens) == 3) {
31 30
32 if (!strcmp(type, "cgroup")) { 31 if (!strcmp(type, "cgroup")) {
@@ -57,15 +56,15 @@ cgroupfs_find_mountpoint(char *buf, size_t maxlen)
57 56
58static int open_cgroup(char *name) 57static int open_cgroup(char *name)
59{ 58{
60 char path[MAX_PATH+1]; 59 char path[PATH_MAX + 1];
61 char mnt[MAX_PATH+1]; 60 char mnt[PATH_MAX + 1];
62 int fd; 61 int fd;
63 62
64 63
65 if (cgroupfs_find_mountpoint(mnt, MAX_PATH+1)) 64 if (cgroupfs_find_mountpoint(mnt, PATH_MAX + 1))
66 return -1; 65 return -1;
67 66
68 snprintf(path, MAX_PATH, "%s/%s", mnt, name); 67 snprintf(path, PATH_MAX, "%s/%s", mnt, name);
69 68
70 fd = open(path, O_RDONLY); 69 fd = open(path, O_RDONLY);
71 if (fd == -1) 70 if (fd == -1)
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 80d9598db31a..0deac6a14b65 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -1,5 +1,8 @@
1/* 1/*
2 * GIT - The information manager from hell 2 * config.c
3 *
4 * Helper functions for parsing config items.
5 * Originally copied from GIT source.
3 * 6 *
4 * Copyright (C) Linus Torvalds, 2005 7 * Copyright (C) Linus Torvalds, 2005
5 * Copyright (C) Johannes Schindelin, 2005 8 * Copyright (C) Johannes Schindelin, 2005
diff --git a/tools/perf/util/debugfs.c b/tools/perf/util/debugfs.c
index a88fefc0cc0a..ffc35e748e89 100644
--- a/tools/perf/util/debugfs.c
+++ b/tools/perf/util/debugfs.c
@@ -2,8 +2,12 @@
2#include "debugfs.h" 2#include "debugfs.h"
3#include "cache.h" 3#include "cache.h"
4 4
5#include <linux/kernel.h>
6#include <sys/mount.h>
7
5static int debugfs_premounted; 8static int debugfs_premounted;
6static char debugfs_mountpoint[MAX_PATH+1]; 9char debugfs_mountpoint[PATH_MAX + 1] = "/sys/kernel/debug";
10char tracing_events_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing/events";
7 11
8static const char *debugfs_known_mountpoints[] = { 12static const char *debugfs_known_mountpoints[] = {
9 "/sys/kernel/debug/", 13 "/sys/kernel/debug/",
@@ -62,11 +66,9 @@ const char *debugfs_find_mountpoint(void)
62 /* give up and parse /proc/mounts */ 66 /* give up and parse /proc/mounts */
63 fp = fopen("/proc/mounts", "r"); 67 fp = fopen("/proc/mounts", "r");
64 if (fp == NULL) 68 if (fp == NULL)
65 die("Can't open /proc/mounts for read"); 69 return NULL;
66 70
67 while (fscanf(fp, "%*s %" 71 while (fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
68 STR(MAX_PATH)
69 "s %99s %*s %*d %*d\n",
70 debugfs_mountpoint, type) == 2) { 72 debugfs_mountpoint, type) == 2) {
71 if (strcmp(type, "debugfs") == 0) 73 if (strcmp(type, "debugfs") == 0)
72 break; 74 break;
@@ -106,6 +108,12 @@ int debugfs_valid_entry(const char *path)
106 return 0; 108 return 0;
107} 109}
108 110
111static void debugfs_set_tracing_events_path(const char *mountpoint)
112{
113 snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s",
114 mountpoint, "tracing/events");
115}
116
109/* mount the debugfs somewhere if it's not mounted */ 117/* mount the debugfs somewhere if it's not mounted */
110 118
111char *debugfs_mount(const char *mountpoint) 119char *debugfs_mount(const char *mountpoint)
@@ -113,7 +121,7 @@ char *debugfs_mount(const char *mountpoint)
113 /* see if it's already mounted */ 121 /* see if it's already mounted */
114 if (debugfs_find_mountpoint()) { 122 if (debugfs_find_mountpoint()) {
115 debugfs_premounted = 1; 123 debugfs_premounted = 1;
116 return debugfs_mountpoint; 124 goto out;
117 } 125 }
118 126
119 /* if not mounted and no argument */ 127 /* if not mounted and no argument */
@@ -129,12 +137,19 @@ char *debugfs_mount(const char *mountpoint)
129 return NULL; 137 return NULL;
130 138
131 /* save the mountpoint */ 139 /* save the mountpoint */
132 strncpy(debugfs_mountpoint, mountpoint, sizeof(debugfs_mountpoint));
133 debugfs_found = 1; 140 debugfs_found = 1;
134 141 strncpy(debugfs_mountpoint, mountpoint, sizeof(debugfs_mountpoint));
142out:
143 debugfs_set_tracing_events_path(debugfs_mountpoint);
135 return debugfs_mountpoint; 144 return debugfs_mountpoint;
136} 145}
137 146
147void debugfs_set_path(const char *mountpoint)
148{
149 snprintf(debugfs_mountpoint, sizeof(debugfs_mountpoint), "%s", mountpoint);
150 debugfs_set_tracing_events_path(mountpoint);
151}
152
138/* umount the debugfs */ 153/* umount the debugfs */
139 154
140int debugfs_umount(void) 155int debugfs_umount(void)
@@ -158,7 +173,7 @@ int debugfs_umount(void)
158 173
159int debugfs_write(const char *entry, const char *value) 174int debugfs_write(const char *entry, const char *value)
160{ 175{
161 char path[MAX_PATH+1]; 176 char path[PATH_MAX + 1];
162 int ret, count; 177 int ret, count;
163 int fd; 178 int fd;
164 179
@@ -203,7 +218,7 @@ int debugfs_write(const char *entry, const char *value)
203 */ 218 */
204int debugfs_read(const char *entry, char *buffer, size_t size) 219int debugfs_read(const char *entry, char *buffer, size_t size)
205{ 220{
206 char path[MAX_PATH+1]; 221 char path[PATH_MAX + 1];
207 int ret; 222 int ret;
208 int fd; 223 int fd;
209 224
diff --git a/tools/perf/util/debugfs.h b/tools/perf/util/debugfs.h
index 83a02879745f..4a878f735eb0 100644
--- a/tools/perf/util/debugfs.h
+++ b/tools/perf/util/debugfs.h
@@ -1,25 +1,18 @@
1#ifndef __DEBUGFS_H__ 1#ifndef __DEBUGFS_H__
2#define __DEBUGFS_H__ 2#define __DEBUGFS_H__
3 3
4#include <sys/mount.h> 4const char *debugfs_find_mountpoint(void);
5int debugfs_valid_mountpoint(const char *debugfs);
6int debugfs_valid_entry(const char *path);
7char *debugfs_mount(const char *mountpoint);
8int debugfs_umount(void);
9void debugfs_set_path(const char *mountpoint);
10int debugfs_write(const char *entry, const char *value);
11int debugfs_read(const char *entry, char *buffer, size_t size);
12void debugfs_force_cleanup(void);
13int debugfs_make_path(const char *element, char *buffer, int size);
5 14
6#ifndef MAX_PATH 15extern char debugfs_mountpoint[];
7# define MAX_PATH 256 16extern char tracing_events_path[];
8#endif
9
10#ifndef STR
11# define _STR(x) #x
12# define STR(x) _STR(x)
13#endif
14
15extern const char *debugfs_find_mountpoint(void);
16extern int debugfs_valid_mountpoint(const char *debugfs);
17extern int debugfs_valid_entry(const char *path);
18extern char *debugfs_mount(const char *mountpoint);
19extern int debugfs_umount(void);
20extern int debugfs_write(const char *entry, const char *value);
21extern int debugfs_read(const char *entry, char *buffer, size_t size);
22extern void debugfs_force_cleanup(void);
23extern int debugfs_make_path(const char *element, char *buffer, int size);
24 17
25#endif /* __DEBUGFS_H__ */ 18#endif /* __DEBUGFS_H__ */
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 437f8ca679a0..73ddaf06b8e7 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -1,7 +1,6 @@
1#include <linux/types.h> 1#include <linux/types.h>
2#include "event.h" 2#include "event.h"
3#include "debug.h" 3#include "debug.h"
4#include "session.h"
5#include "sort.h" 4#include "sort.h"
6#include "string.h" 5#include "string.h"
7#include "strlist.h" 6#include "strlist.h"
@@ -44,36 +43,27 @@ static struct perf_sample synth_sample = {
44 .period = 1, 43 .period = 1,
45}; 44};
46 45
47static pid_t perf_event__synthesize_comm(union perf_event *event, pid_t pid, 46static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len)
48 int full, perf_event__handler_t process,
49 struct perf_session *session)
50{ 47{
51 char filename[PATH_MAX]; 48 char filename[PATH_MAX];
52 char bf[BUFSIZ]; 49 char bf[BUFSIZ];
53 FILE *fp; 50 FILE *fp;
54 size_t size = 0; 51 size_t size = 0;
55 DIR *tasks; 52 pid_t tgid = -1;
56 struct dirent dirent, *next;
57 pid_t tgid = 0;
58 53
59 snprintf(filename, sizeof(filename), "/proc/%d/status", pid); 54 snprintf(filename, sizeof(filename), "/proc/%d/status", pid);
60 55
61 fp = fopen(filename, "r"); 56 fp = fopen(filename, "r");
62 if (fp == NULL) { 57 if (fp == NULL) {
63out_race:
64 /*
65 * We raced with a task exiting - just return:
66 */
67 pr_debug("couldn't open %s\n", filename); 58 pr_debug("couldn't open %s\n", filename);
68 return 0; 59 return 0;
69 } 60 }
70 61
71 memset(&event->comm, 0, sizeof(event->comm)); 62 while (!comm[0] || (tgid < 0)) {
72
73 while (!event->comm.comm[0] || !event->comm.pid) {
74 if (fgets(bf, sizeof(bf), fp) == NULL) { 63 if (fgets(bf, sizeof(bf), fp) == NULL) {
75 pr_warning("couldn't get COMM and pgid, malformed %s\n", filename); 64 pr_warning("couldn't get COMM and pgid, malformed %s\n",
76 goto out; 65 filename);
66 break;
77 } 67 }
78 68
79 if (memcmp(bf, "Name:", 5) == 0) { 69 if (memcmp(bf, "Name:", 5) == 0) {
@@ -81,33 +71,65 @@ out_race:
81 while (*name && isspace(*name)) 71 while (*name && isspace(*name))
82 ++name; 72 ++name;
83 size = strlen(name) - 1; 73 size = strlen(name) - 1;
84 memcpy(event->comm.comm, name, size++); 74 if (size >= len)
75 size = len - 1;
76 memcpy(comm, name, size);
77
85 } else if (memcmp(bf, "Tgid:", 5) == 0) { 78 } else if (memcmp(bf, "Tgid:", 5) == 0) {
86 char *tgids = bf + 5; 79 char *tgids = bf + 5;
87 while (*tgids && isspace(*tgids)) 80 while (*tgids && isspace(*tgids))
88 ++tgids; 81 ++tgids;
89 tgid = event->comm.pid = atoi(tgids); 82 tgid = atoi(tgids);
90 } 83 }
91 } 84 }
92 85
86 fclose(fp);
87
88 return tgid;
89}
90
91static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
92 union perf_event *event, pid_t pid,
93 int full,
94 perf_event__handler_t process,
95 struct machine *machine)
96{
97 char filename[PATH_MAX];
98 size_t size;
99 DIR *tasks;
100 struct dirent dirent, *next;
101 pid_t tgid;
102
103 memset(&event->comm, 0, sizeof(event->comm));
104
105 tgid = perf_event__get_comm_tgid(pid, event->comm.comm,
106 sizeof(event->comm.comm));
107 if (tgid < 0)
108 goto out;
109
110 event->comm.pid = tgid;
93 event->comm.header.type = PERF_RECORD_COMM; 111 event->comm.header.type = PERF_RECORD_COMM;
112
113 size = strlen(event->comm.comm) + 1;
94 size = ALIGN(size, sizeof(u64)); 114 size = ALIGN(size, sizeof(u64));
95 memset(event->comm.comm + size, 0, session->id_hdr_size); 115 memset(event->comm.comm + size, 0, machine->id_hdr_size);
96 event->comm.header.size = (sizeof(event->comm) - 116 event->comm.header.size = (sizeof(event->comm) -
97 (sizeof(event->comm.comm) - size) + 117 (sizeof(event->comm.comm) - size) +
98 session->id_hdr_size); 118 machine->id_hdr_size);
99 if (!full) { 119 if (!full) {
100 event->comm.tid = pid; 120 event->comm.tid = pid;
101 121
102 process(event, &synth_sample, session); 122 process(tool, event, &synth_sample, machine);
103 goto out; 123 goto out;
104 } 124 }
105 125
106 snprintf(filename, sizeof(filename), "/proc/%d/task", pid); 126 snprintf(filename, sizeof(filename), "/proc/%d/task", pid);
107 127
108 tasks = opendir(filename); 128 tasks = opendir(filename);
109 if (tasks == NULL) 129 if (tasks == NULL) {
110 goto out_race; 130 pr_debug("couldn't open %s\n", filename);
131 return 0;
132 }
111 133
112 while (!readdir_r(tasks, &dirent, &next) && next) { 134 while (!readdir_r(tasks, &dirent, &next) && next) {
113 char *end; 135 char *end;
@@ -115,22 +137,32 @@ out_race:
115 if (*end) 137 if (*end)
116 continue; 138 continue;
117 139
140 /* already have tgid; jut want to update the comm */
141 (void) perf_event__get_comm_tgid(pid, event->comm.comm,
142 sizeof(event->comm.comm));
143
144 size = strlen(event->comm.comm) + 1;
145 size = ALIGN(size, sizeof(u64));
146 memset(event->comm.comm + size, 0, machine->id_hdr_size);
147 event->comm.header.size = (sizeof(event->comm) -
148 (sizeof(event->comm.comm) - size) +
149 machine->id_hdr_size);
150
118 event->comm.tid = pid; 151 event->comm.tid = pid;
119 152
120 process(event, &synth_sample, session); 153 process(tool, event, &synth_sample, machine);
121 } 154 }
122 155
123 closedir(tasks); 156 closedir(tasks);
124out: 157out:
125 fclose(fp);
126
127 return tgid; 158 return tgid;
128} 159}
129 160
130static int perf_event__synthesize_mmap_events(union perf_event *event, 161static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
162 union perf_event *event,
131 pid_t pid, pid_t tgid, 163 pid_t pid, pid_t tgid,
132 perf_event__handler_t process, 164 perf_event__handler_t process,
133 struct perf_session *session) 165 struct machine *machine)
134{ 166{
135 char filename[PATH_MAX]; 167 char filename[PATH_MAX];
136 FILE *fp; 168 FILE *fp;
@@ -193,12 +225,12 @@ static int perf_event__synthesize_mmap_events(union perf_event *event,
193 event->mmap.len -= event->mmap.start; 225 event->mmap.len -= event->mmap.start;
194 event->mmap.header.size = (sizeof(event->mmap) - 226 event->mmap.header.size = (sizeof(event->mmap) -
195 (sizeof(event->mmap.filename) - size)); 227 (sizeof(event->mmap.filename) - size));
196 memset(event->mmap.filename + size, 0, session->id_hdr_size); 228 memset(event->mmap.filename + size, 0, machine->id_hdr_size);
197 event->mmap.header.size += session->id_hdr_size; 229 event->mmap.header.size += machine->id_hdr_size;
198 event->mmap.pid = tgid; 230 event->mmap.pid = tgid;
199 event->mmap.tid = pid; 231 event->mmap.tid = pid;
200 232
201 process(event, &synth_sample, session); 233 process(tool, event, &synth_sample, machine);
202 } 234 }
203 } 235 }
204 236
@@ -206,14 +238,14 @@ static int perf_event__synthesize_mmap_events(union perf_event *event,
206 return 0; 238 return 0;
207} 239}
208 240
209int perf_event__synthesize_modules(perf_event__handler_t process, 241int perf_event__synthesize_modules(struct perf_tool *tool,
210 struct perf_session *session, 242 perf_event__handler_t process,
211 struct machine *machine) 243 struct machine *machine)
212{ 244{
213 struct rb_node *nd; 245 struct rb_node *nd;
214 struct map_groups *kmaps = &machine->kmaps; 246 struct map_groups *kmaps = &machine->kmaps;
215 union perf_event *event = zalloc((sizeof(event->mmap) + 247 union perf_event *event = zalloc((sizeof(event->mmap) +
216 session->id_hdr_size)); 248 machine->id_hdr_size));
217 if (event == NULL) { 249 if (event == NULL) {
218 pr_debug("Not enough memory synthesizing mmap event " 250 pr_debug("Not enough memory synthesizing mmap event "
219 "for kernel modules\n"); 251 "for kernel modules\n");
@@ -243,15 +275,15 @@ int perf_event__synthesize_modules(perf_event__handler_t process,
243 event->mmap.header.type = PERF_RECORD_MMAP; 275 event->mmap.header.type = PERF_RECORD_MMAP;
244 event->mmap.header.size = (sizeof(event->mmap) - 276 event->mmap.header.size = (sizeof(event->mmap) -
245 (sizeof(event->mmap.filename) - size)); 277 (sizeof(event->mmap.filename) - size));
246 memset(event->mmap.filename + size, 0, session->id_hdr_size); 278 memset(event->mmap.filename + size, 0, machine->id_hdr_size);
247 event->mmap.header.size += session->id_hdr_size; 279 event->mmap.header.size += machine->id_hdr_size;
248 event->mmap.start = pos->start; 280 event->mmap.start = pos->start;
249 event->mmap.len = pos->end - pos->start; 281 event->mmap.len = pos->end - pos->start;
250 event->mmap.pid = machine->pid; 282 event->mmap.pid = machine->pid;
251 283
252 memcpy(event->mmap.filename, pos->dso->long_name, 284 memcpy(event->mmap.filename, pos->dso->long_name,
253 pos->dso->long_name_len + 1); 285 pos->dso->long_name_len + 1);
254 process(event, &synth_sample, session); 286 process(tool, event, &synth_sample, machine);
255 } 287 }
256 288
257 free(event); 289 free(event);
@@ -260,40 +292,69 @@ int perf_event__synthesize_modules(perf_event__handler_t process,
260 292
261static int __event__synthesize_thread(union perf_event *comm_event, 293static int __event__synthesize_thread(union perf_event *comm_event,
262 union perf_event *mmap_event, 294 union perf_event *mmap_event,
263 pid_t pid, perf_event__handler_t process, 295 pid_t pid, int full,
264 struct perf_session *session) 296 perf_event__handler_t process,
297 struct perf_tool *tool,
298 struct machine *machine)
265{ 299{
266 pid_t tgid = perf_event__synthesize_comm(comm_event, pid, 1, process, 300 pid_t tgid = perf_event__synthesize_comm(tool, comm_event, pid, full,
267 session); 301 process, machine);
268 if (tgid == -1) 302 if (tgid == -1)
269 return -1; 303 return -1;
270 return perf_event__synthesize_mmap_events(mmap_event, pid, tgid, 304 return perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
271 process, session); 305 process, machine);
272} 306}
273 307
274int perf_event__synthesize_thread_map(struct thread_map *threads, 308int perf_event__synthesize_thread_map(struct perf_tool *tool,
309 struct thread_map *threads,
275 perf_event__handler_t process, 310 perf_event__handler_t process,
276 struct perf_session *session) 311 struct machine *machine)
277{ 312{
278 union perf_event *comm_event, *mmap_event; 313 union perf_event *comm_event, *mmap_event;
279 int err = -1, thread; 314 int err = -1, thread, j;
280 315
281 comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size); 316 comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
282 if (comm_event == NULL) 317 if (comm_event == NULL)
283 goto out; 318 goto out;
284 319
285 mmap_event = malloc(sizeof(mmap_event->mmap) + session->id_hdr_size); 320 mmap_event = malloc(sizeof(mmap_event->mmap) + machine->id_hdr_size);
286 if (mmap_event == NULL) 321 if (mmap_event == NULL)
287 goto out_free_comm; 322 goto out_free_comm;
288 323
289 err = 0; 324 err = 0;
290 for (thread = 0; thread < threads->nr; ++thread) { 325 for (thread = 0; thread < threads->nr; ++thread) {
291 if (__event__synthesize_thread(comm_event, mmap_event, 326 if (__event__synthesize_thread(comm_event, mmap_event,
292 threads->map[thread], 327 threads->map[thread], 0,
293 process, session)) { 328 process, tool, machine)) {
294 err = -1; 329 err = -1;
295 break; 330 break;
296 } 331 }
332
333 /*
334 * comm.pid is set to thread group id by
335 * perf_event__synthesize_comm
336 */
337 if ((int) comm_event->comm.pid != threads->map[thread]) {
338 bool need_leader = true;
339
340 /* is thread group leader in thread_map? */
341 for (j = 0; j < threads->nr; ++j) {
342 if ((int) comm_event->comm.pid == threads->map[j]) {
343 need_leader = false;
344 break;
345 }
346 }
347
348 /* if not, generate events for it */
349 if (need_leader &&
350 __event__synthesize_thread(comm_event,
351 mmap_event,
352 comm_event->comm.pid, 0,
353 process, tool, machine)) {
354 err = -1;
355 break;
356 }
357 }
297 } 358 }
298 free(mmap_event); 359 free(mmap_event);
299out_free_comm: 360out_free_comm:
@@ -302,19 +363,20 @@ out:
302 return err; 363 return err;
303} 364}
304 365
305int perf_event__synthesize_threads(perf_event__handler_t process, 366int perf_event__synthesize_threads(struct perf_tool *tool,
306 struct perf_session *session) 367 perf_event__handler_t process,
368 struct machine *machine)
307{ 369{
308 DIR *proc; 370 DIR *proc;
309 struct dirent dirent, *next; 371 struct dirent dirent, *next;
310 union perf_event *comm_event, *mmap_event; 372 union perf_event *comm_event, *mmap_event;
311 int err = -1; 373 int err = -1;
312 374
313 comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size); 375 comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
314 if (comm_event == NULL) 376 if (comm_event == NULL)
315 goto out; 377 goto out;
316 378
317 mmap_event = malloc(sizeof(mmap_event->mmap) + session->id_hdr_size); 379 mmap_event = malloc(sizeof(mmap_event->mmap) + machine->id_hdr_size);
318 if (mmap_event == NULL) 380 if (mmap_event == NULL)
319 goto out_free_comm; 381 goto out_free_comm;
320 382
@@ -329,8 +391,8 @@ int perf_event__synthesize_threads(perf_event__handler_t process,
329 if (*end) /* only interested in proper numerical dirents */ 391 if (*end) /* only interested in proper numerical dirents */
330 continue; 392 continue;
331 393
332 __event__synthesize_thread(comm_event, mmap_event, pid, 394 __event__synthesize_thread(comm_event, mmap_event, pid, 1,
333 process, session); 395 process, tool, machine);
334 } 396 }
335 397
336 closedir(proc); 398 closedir(proc);
@@ -365,8 +427,8 @@ static int find_symbol_cb(void *arg, const char *name, char type,
365 return 1; 427 return 1;
366} 428}
367 429
368int perf_event__synthesize_kernel_mmap(perf_event__handler_t process, 430int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
369 struct perf_session *session, 431 perf_event__handler_t process,
370 struct machine *machine, 432 struct machine *machine,
371 const char *symbol_name) 433 const char *symbol_name)
372{ 434{
@@ -383,7 +445,7 @@ int perf_event__synthesize_kernel_mmap(perf_event__handler_t process,
383 */ 445 */
384 struct process_symbol_args args = { .name = symbol_name, }; 446 struct process_symbol_args args = { .name = symbol_name, };
385 union perf_event *event = zalloc((sizeof(event->mmap) + 447 union perf_event *event = zalloc((sizeof(event->mmap) +
386 session->id_hdr_size)); 448 machine->id_hdr_size));
387 if (event == NULL) { 449 if (event == NULL) {
388 pr_debug("Not enough memory synthesizing mmap event " 450 pr_debug("Not enough memory synthesizing mmap event "
389 "for kernel modules\n"); 451 "for kernel modules\n");
@@ -417,25 +479,32 @@ int perf_event__synthesize_kernel_mmap(perf_event__handler_t process,
417 size = ALIGN(size, sizeof(u64)); 479 size = ALIGN(size, sizeof(u64));
418 event->mmap.header.type = PERF_RECORD_MMAP; 480 event->mmap.header.type = PERF_RECORD_MMAP;
419 event->mmap.header.size = (sizeof(event->mmap) - 481 event->mmap.header.size = (sizeof(event->mmap) -
420 (sizeof(event->mmap.filename) - size) + session->id_hdr_size); 482 (sizeof(event->mmap.filename) - size) + machine->id_hdr_size);
421 event->mmap.pgoff = args.start; 483 event->mmap.pgoff = args.start;
422 event->mmap.start = map->start; 484 event->mmap.start = map->start;
423 event->mmap.len = map->end - event->mmap.start; 485 event->mmap.len = map->end - event->mmap.start;
424 event->mmap.pid = machine->pid; 486 event->mmap.pid = machine->pid;
425 487
426 err = process(event, &synth_sample, session); 488 err = process(tool, event, &synth_sample, machine);
427 free(event); 489 free(event);
428 490
429 return err; 491 return err;
430} 492}
431 493
432int perf_event__process_comm(union perf_event *event, 494size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp)
495{
496 return fprintf(fp, ": %s:%d\n", event->comm.comm, event->comm.tid);
497}
498
499int perf_event__process_comm(struct perf_tool *tool __used,
500 union perf_event *event,
433 struct perf_sample *sample __used, 501 struct perf_sample *sample __used,
434 struct perf_session *session) 502 struct machine *machine)
435{ 503{
436 struct thread *thread = perf_session__findnew(session, event->comm.tid); 504 struct thread *thread = machine__findnew_thread(machine, event->comm.tid);
437 505
438 dump_printf(": %s:%d\n", event->comm.comm, event->comm.tid); 506 if (dump_trace)
507 perf_event__fprintf_comm(event, stdout);
439 508
440 if (thread == NULL || thread__set_comm(thread, event->comm.comm)) { 509 if (thread == NULL || thread__set_comm(thread, event->comm.comm)) {
441 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n"); 510 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
@@ -445,13 +514,13 @@ int perf_event__process_comm(union perf_event *event,
445 return 0; 514 return 0;
446} 515}
447 516
448int perf_event__process_lost(union perf_event *event, 517int perf_event__process_lost(struct perf_tool *tool __used,
518 union perf_event *event,
449 struct perf_sample *sample __used, 519 struct perf_sample *sample __used,
450 struct perf_session *session) 520 struct machine *machine __used)
451{ 521{
452 dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n", 522 dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n",
453 event->lost.id, event->lost.lost); 523 event->lost.id, event->lost.lost);
454 session->hists.stats.total_lost += event->lost.lost;
455 return 0; 524 return 0;
456} 525}
457 526
@@ -468,21 +537,15 @@ static void perf_event__set_kernel_mmap_len(union perf_event *event,
468 maps[MAP__FUNCTION]->end = ~0ULL; 537 maps[MAP__FUNCTION]->end = ~0ULL;
469} 538}
470 539
471static int perf_event__process_kernel_mmap(union perf_event *event, 540static int perf_event__process_kernel_mmap(struct perf_tool *tool __used,
472 struct perf_session *session) 541 union perf_event *event,
542 struct machine *machine)
473{ 543{
474 struct map *map; 544 struct map *map;
475 char kmmap_prefix[PATH_MAX]; 545 char kmmap_prefix[PATH_MAX];
476 struct machine *machine;
477 enum dso_kernel_type kernel_type; 546 enum dso_kernel_type kernel_type;
478 bool is_kernel_mmap; 547 bool is_kernel_mmap;
479 548
480 machine = perf_session__findnew_machine(session, event->mmap.pid);
481 if (!machine) {
482 pr_err("Can't find id %d's machine\n", event->mmap.pid);
483 goto out_problem;
484 }
485
486 machine__mmap_name(machine, kmmap_prefix, sizeof(kmmap_prefix)); 549 machine__mmap_name(machine, kmmap_prefix, sizeof(kmmap_prefix));
487 if (machine__is_host(machine)) 550 if (machine__is_host(machine))
488 kernel_type = DSO_TYPE_KERNEL; 551 kernel_type = DSO_TYPE_KERNEL;
@@ -549,9 +612,9 @@ static int perf_event__process_kernel_mmap(union perf_event *event,
549 * time /proc/sys/kernel/kptr_restrict was non zero. 612 * time /proc/sys/kernel/kptr_restrict was non zero.
550 */ 613 */
551 if (event->mmap.pgoff != 0) { 614 if (event->mmap.pgoff != 0) {
552 perf_session__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, 615 maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps,
553 symbol_name, 616 symbol_name,
554 event->mmap.pgoff); 617 event->mmap.pgoff);
555 } 618 }
556 619
557 if (machine__is_default_guest(machine)) { 620 if (machine__is_default_guest(machine)) {
@@ -567,32 +630,35 @@ out_problem:
567 return -1; 630 return -1;
568} 631}
569 632
570int perf_event__process_mmap(union perf_event *event, 633size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
634{
635 return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %s\n",
636 event->mmap.pid, event->mmap.tid, event->mmap.start,
637 event->mmap.len, event->mmap.pgoff, event->mmap.filename);
638}
639
640int perf_event__process_mmap(struct perf_tool *tool,
641 union perf_event *event,
571 struct perf_sample *sample __used, 642 struct perf_sample *sample __used,
572 struct perf_session *session) 643 struct machine *machine)
573{ 644{
574 struct machine *machine;
575 struct thread *thread; 645 struct thread *thread;
576 struct map *map; 646 struct map *map;
577 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 647 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
578 int ret = 0; 648 int ret = 0;
579 649
580 dump_printf(" %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %s\n", 650 if (dump_trace)
581 event->mmap.pid, event->mmap.tid, event->mmap.start, 651 perf_event__fprintf_mmap(event, stdout);
582 event->mmap.len, event->mmap.pgoff, event->mmap.filename);
583 652
584 if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL || 653 if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL ||
585 cpumode == PERF_RECORD_MISC_KERNEL) { 654 cpumode == PERF_RECORD_MISC_KERNEL) {
586 ret = perf_event__process_kernel_mmap(event, session); 655 ret = perf_event__process_kernel_mmap(tool, event, machine);
587 if (ret < 0) 656 if (ret < 0)
588 goto out_problem; 657 goto out_problem;
589 return 0; 658 return 0;
590 } 659 }
591 660
592 machine = perf_session__find_host_machine(session); 661 thread = machine__findnew_thread(machine, event->mmap.pid);
593 if (machine == NULL)
594 goto out_problem;
595 thread = perf_session__findnew(session, event->mmap.pid);
596 if (thread == NULL) 662 if (thread == NULL)
597 goto out_problem; 663 goto out_problem;
598 map = map__new(&machine->user_dsos, event->mmap.start, 664 map = map__new(&machine->user_dsos, event->mmap.start,
@@ -610,18 +676,26 @@ out_problem:
610 return 0; 676 return 0;
611} 677}
612 678
613int perf_event__process_task(union perf_event *event, 679size_t perf_event__fprintf_task(union perf_event *event, FILE *fp)
680{
681 return fprintf(fp, "(%d:%d):(%d:%d)\n",
682 event->fork.pid, event->fork.tid,
683 event->fork.ppid, event->fork.ptid);
684}
685
686int perf_event__process_task(struct perf_tool *tool __used,
687 union perf_event *event,
614 struct perf_sample *sample __used, 688 struct perf_sample *sample __used,
615 struct perf_session *session) 689 struct machine *machine)
616{ 690{
617 struct thread *thread = perf_session__findnew(session, event->fork.tid); 691 struct thread *thread = machine__findnew_thread(machine, event->fork.tid);
618 struct thread *parent = perf_session__findnew(session, event->fork.ptid); 692 struct thread *parent = machine__findnew_thread(machine, event->fork.ptid);
619 693
620 dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid, 694 if (dump_trace)
621 event->fork.ppid, event->fork.ptid); 695 perf_event__fprintf_task(event, stdout);
622 696
623 if (event->header.type == PERF_RECORD_EXIT) { 697 if (event->header.type == PERF_RECORD_EXIT) {
624 perf_session__remove_thread(session, thread); 698 machine__remove_thread(machine, thread);
625 return 0; 699 return 0;
626 } 700 }
627 701
@@ -634,22 +708,45 @@ int perf_event__process_task(union perf_event *event,
634 return 0; 708 return 0;
635} 709}
636 710
637int perf_event__process(union perf_event *event, struct perf_sample *sample, 711size_t perf_event__fprintf(union perf_event *event, FILE *fp)
638 struct perf_session *session) 712{
713 size_t ret = fprintf(fp, "PERF_RECORD_%s",
714 perf_event__name(event->header.type));
715
716 switch (event->header.type) {
717 case PERF_RECORD_COMM:
718 ret += perf_event__fprintf_comm(event, fp);
719 break;
720 case PERF_RECORD_FORK:
721 case PERF_RECORD_EXIT:
722 ret += perf_event__fprintf_task(event, fp);
723 break;
724 case PERF_RECORD_MMAP:
725 ret += perf_event__fprintf_mmap(event, fp);
726 break;
727 default:
728 ret += fprintf(fp, "\n");
729 }
730
731 return ret;
732}
733
734int perf_event__process(struct perf_tool *tool, union perf_event *event,
735 struct perf_sample *sample, struct machine *machine)
639{ 736{
640 switch (event->header.type) { 737 switch (event->header.type) {
641 case PERF_RECORD_COMM: 738 case PERF_RECORD_COMM:
642 perf_event__process_comm(event, sample, session); 739 perf_event__process_comm(tool, event, sample, machine);
643 break; 740 break;
644 case PERF_RECORD_MMAP: 741 case PERF_RECORD_MMAP:
645 perf_event__process_mmap(event, sample, session); 742 perf_event__process_mmap(tool, event, sample, machine);
646 break; 743 break;
647 case PERF_RECORD_FORK: 744 case PERF_RECORD_FORK:
648 case PERF_RECORD_EXIT: 745 case PERF_RECORD_EXIT:
649 perf_event__process_task(event, sample, session); 746 perf_event__process_task(tool, event, sample, machine);
650 break; 747 break;
651 case PERF_RECORD_LOST: 748 case PERF_RECORD_LOST:
652 perf_event__process_lost(event, sample, session); 749 perf_event__process_lost(tool, event, sample, machine);
653 default: 750 default:
654 break; 751 break;
655 } 752 }
@@ -658,36 +755,29 @@ int perf_event__process(union perf_event *event, struct perf_sample *sample,
658} 755}
659 756
660void thread__find_addr_map(struct thread *self, 757void thread__find_addr_map(struct thread *self,
661 struct perf_session *session, u8 cpumode, 758 struct machine *machine, u8 cpumode,
662 enum map_type type, pid_t pid, u64 addr, 759 enum map_type type, u64 addr,
663 struct addr_location *al) 760 struct addr_location *al)
664{ 761{
665 struct map_groups *mg = &self->mg; 762 struct map_groups *mg = &self->mg;
666 struct machine *machine = NULL;
667 763
668 al->thread = self; 764 al->thread = self;
669 al->addr = addr; 765 al->addr = addr;
670 al->cpumode = cpumode; 766 al->cpumode = cpumode;
671 al->filtered = false; 767 al->filtered = false;
672 768
769 if (machine == NULL) {
770 al->map = NULL;
771 return;
772 }
773
673 if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) { 774 if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) {
674 al->level = 'k'; 775 al->level = 'k';
675 machine = perf_session__find_host_machine(session);
676 if (machine == NULL) {
677 al->map = NULL;
678 return;
679 }
680 mg = &machine->kmaps; 776 mg = &machine->kmaps;
681 } else if (cpumode == PERF_RECORD_MISC_USER && perf_host) { 777 } else if (cpumode == PERF_RECORD_MISC_USER && perf_host) {
682 al->level = '.'; 778 al->level = '.';
683 machine = perf_session__find_host_machine(session);
684 } else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) { 779 } else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) {
685 al->level = 'g'; 780 al->level = 'g';
686 machine = perf_session__find_machine(session, pid);
687 if (machine == NULL) {
688 al->map = NULL;
689 return;
690 }
691 mg = &machine->kmaps; 781 mg = &machine->kmaps;
692 } else { 782 } else {
693 /* 783 /*
@@ -733,13 +823,12 @@ try_again:
733 al->addr = al->map->map_ip(al->map, al->addr); 823 al->addr = al->map->map_ip(al->map, al->addr);
734} 824}
735 825
736void thread__find_addr_location(struct thread *self, 826void thread__find_addr_location(struct thread *thread, struct machine *machine,
737 struct perf_session *session, u8 cpumode, 827 u8 cpumode, enum map_type type, u64 addr,
738 enum map_type type, pid_t pid, u64 addr,
739 struct addr_location *al, 828 struct addr_location *al,
740 symbol_filter_t filter) 829 symbol_filter_t filter)
741{ 830{
742 thread__find_addr_map(self, session, cpumode, type, pid, addr, al); 831 thread__find_addr_map(thread, machine, cpumode, type, addr, al);
743 if (al->map != NULL) 832 if (al->map != NULL)
744 al->sym = map__find_symbol(al->map, al->addr, filter); 833 al->sym = map__find_symbol(al->map, al->addr, filter);
745 else 834 else
@@ -747,13 +836,13 @@ void thread__find_addr_location(struct thread *self,
747} 836}
748 837
749int perf_event__preprocess_sample(const union perf_event *event, 838int perf_event__preprocess_sample(const union perf_event *event,
750 struct perf_session *session, 839 struct machine *machine,
751 struct addr_location *al, 840 struct addr_location *al,
752 struct perf_sample *sample, 841 struct perf_sample *sample,
753 symbol_filter_t filter) 842 symbol_filter_t filter)
754{ 843{
755 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 844 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
756 struct thread *thread = perf_session__findnew(session, event->ip.pid); 845 struct thread *thread = machine__findnew_thread(machine, event->ip.pid);
757 846
758 if (thread == NULL) 847 if (thread == NULL)
759 return -1; 848 return -1;
@@ -764,18 +853,18 @@ int perf_event__preprocess_sample(const union perf_event *event,
764 853
765 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); 854 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
766 /* 855 /*
767 * Have we already created the kernel maps for the host machine? 856 * Have we already created the kernel maps for this machine?
768 * 857 *
769 * This should have happened earlier, when we processed the kernel MMAP 858 * This should have happened earlier, when we processed the kernel MMAP
770 * events, but for older perf.data files there was no such thing, so do 859 * events, but for older perf.data files there was no such thing, so do
771 * it now. 860 * it now.
772 */ 861 */
773 if (cpumode == PERF_RECORD_MISC_KERNEL && 862 if (cpumode == PERF_RECORD_MISC_KERNEL &&
774 session->host_machine.vmlinux_maps[MAP__FUNCTION] == NULL) 863 machine->vmlinux_maps[MAP__FUNCTION] == NULL)
775 machine__create_kernel_maps(&session->host_machine); 864 machine__create_kernel_maps(machine);
776 865
777 thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION, 866 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
778 event->ip.pid, event->ip.ip, al); 867 event->ip.ip, al);
779 dump_printf(" ...... dso: %s\n", 868 dump_printf(" ...... dso: %s\n",
780 al->map ? al->map->dso->long_name : 869 al->map ? al->map->dso->long_name :
781 al->level == 'H' ? "[hypervisor]" : "<not found>"); 870 al->level == 'H' ? "[hypervisor]" : "<not found>");
@@ -783,13 +872,14 @@ int perf_event__preprocess_sample(const union perf_event *event,
783 al->cpu = sample->cpu; 872 al->cpu = sample->cpu;
784 873
785 if (al->map) { 874 if (al->map) {
875 struct dso *dso = al->map->dso;
876
786 if (symbol_conf.dso_list && 877 if (symbol_conf.dso_list &&
787 (!al->map || !al->map->dso || 878 (!dso || !(strlist__has_entry(symbol_conf.dso_list,
788 !(strlist__has_entry(symbol_conf.dso_list, 879 dso->short_name) ||
789 al->map->dso->short_name) || 880 (dso->short_name != dso->long_name &&
790 (al->map->dso->short_name != al->map->dso->long_name && 881 strlist__has_entry(symbol_conf.dso_list,
791 strlist__has_entry(symbol_conf.dso_list, 882 dso->long_name)))))
792 al->map->dso->long_name)))))
793 goto out_filtered; 883 goto out_filtered;
794 884
795 al->sym = map__find_symbol(al->map, al->addr, filter); 885 al->sym = map__find_symbol(al->map, al->addr, filter);
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 357a85b85248..cbdeaad9c5e5 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -2,6 +2,7 @@
2#define __PERF_RECORD_H 2#define __PERF_RECORD_H
3 3
4#include <limits.h> 4#include <limits.h>
5#include <stdio.h>
5 6
6#include "../perf.h" 7#include "../perf.h"
7#include "map.h" 8#include "map.h"
@@ -141,43 +142,54 @@ union perf_event {
141 142
142void perf_event__print_totals(void); 143void perf_event__print_totals(void);
143 144
144struct perf_session; 145struct perf_tool;
145struct thread_map; 146struct thread_map;
146 147
147typedef int (*perf_event__handler_synth_t)(union perf_event *event, 148typedef int (*perf_event__handler_t)(struct perf_tool *tool,
148 struct perf_session *session); 149 union perf_event *event,
149typedef int (*perf_event__handler_t)(union perf_event *event,
150 struct perf_sample *sample, 150 struct perf_sample *sample,
151 struct perf_session *session); 151 struct machine *machine);
152 152
153int perf_event__synthesize_thread_map(struct thread_map *threads, 153int perf_event__synthesize_thread_map(struct perf_tool *tool,
154 struct thread_map *threads,
154 perf_event__handler_t process, 155 perf_event__handler_t process,
155 struct perf_session *session); 156 struct machine *machine);
156int perf_event__synthesize_threads(perf_event__handler_t process, 157int perf_event__synthesize_threads(struct perf_tool *tool,
157 struct perf_session *session); 158 perf_event__handler_t process,
158int perf_event__synthesize_kernel_mmap(perf_event__handler_t process, 159 struct machine *machine);
159 struct perf_session *session, 160int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
161 perf_event__handler_t process,
160 struct machine *machine, 162 struct machine *machine,
161 const char *symbol_name); 163 const char *symbol_name);
162 164
163int perf_event__synthesize_modules(perf_event__handler_t process, 165int perf_event__synthesize_modules(struct perf_tool *tool,
164 struct perf_session *session, 166 perf_event__handler_t process,
165 struct machine *machine); 167 struct machine *machine);
166 168
167int perf_event__process_comm(union perf_event *event, struct perf_sample *sample, 169int perf_event__process_comm(struct perf_tool *tool,
168 struct perf_session *session); 170 union perf_event *event,
169int perf_event__process_lost(union perf_event *event, struct perf_sample *sample, 171 struct perf_sample *sample,
170 struct perf_session *session); 172 struct machine *machine);
171int perf_event__process_mmap(union perf_event *event, struct perf_sample *sample, 173int perf_event__process_lost(struct perf_tool *tool,
172 struct perf_session *session); 174 union perf_event *event,
173int perf_event__process_task(union perf_event *event, struct perf_sample *sample, 175 struct perf_sample *sample,
174 struct perf_session *session); 176 struct machine *machine);
175int perf_event__process(union perf_event *event, struct perf_sample *sample, 177int perf_event__process_mmap(struct perf_tool *tool,
176 struct perf_session *session); 178 union perf_event *event,
179 struct perf_sample *sample,
180 struct machine *machine);
181int perf_event__process_task(struct perf_tool *tool,
182 union perf_event *event,
183 struct perf_sample *sample,
184 struct machine *machine);
185int perf_event__process(struct perf_tool *tool,
186 union perf_event *event,
187 struct perf_sample *sample,
188 struct machine *machine);
177 189
178struct addr_location; 190struct addr_location;
179int perf_event__preprocess_sample(const union perf_event *self, 191int perf_event__preprocess_sample(const union perf_event *self,
180 struct perf_session *session, 192 struct machine *machine,
181 struct addr_location *al, 193 struct addr_location *al,
182 struct perf_sample *sample, 194 struct perf_sample *sample,
183 symbol_filter_t filter); 195 symbol_filter_t filter);
@@ -187,5 +199,13 @@ const char *perf_event__name(unsigned int id);
187int perf_event__parse_sample(const union perf_event *event, u64 type, 199int perf_event__parse_sample(const union perf_event *event, u64 type,
188 int sample_size, bool sample_id_all, 200 int sample_size, bool sample_id_all,
189 struct perf_sample *sample, bool swapped); 201 struct perf_sample *sample, bool swapped);
202int perf_event__synthesize_sample(union perf_event *event, u64 type,
203 const struct perf_sample *sample,
204 bool swapped);
205
206size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp);
207size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp);
208size_t perf_event__fprintf_task(union perf_event *event, FILE *fp);
209size_t perf_event__fprintf(union perf_event *event, FILE *fp);
190 210
191#endif /* __PERF_RECORD_H */ 211#endif /* __PERF_RECORD_H */
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index fbb4b4ab9cc6..3f16e08a5c8d 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -6,12 +6,16 @@
6 * 6 *
7 * Released under the GPL v2. (and only v2, not any later version) 7 * Released under the GPL v2. (and only v2, not any later version)
8 */ 8 */
9#include "util.h"
10#include "debugfs.h"
9#include <poll.h> 11#include <poll.h>
10#include "cpumap.h" 12#include "cpumap.h"
11#include "thread_map.h" 13#include "thread_map.h"
12#include "evlist.h" 14#include "evlist.h"
13#include "evsel.h" 15#include "evsel.h"
14#include "util.h" 16#include <unistd.h>
17
18#include "parse-events.h"
15 19
16#include <sys/mman.h> 20#include <sys/mman.h>
17 21
@@ -30,6 +34,7 @@ void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
30 INIT_HLIST_HEAD(&evlist->heads[i]); 34 INIT_HLIST_HEAD(&evlist->heads[i]);
31 INIT_LIST_HEAD(&evlist->entries); 35 INIT_LIST_HEAD(&evlist->entries);
32 perf_evlist__set_maps(evlist, cpus, threads); 36 perf_evlist__set_maps(evlist, cpus, threads);
37 evlist->workload.pid = -1;
33} 38}
34 39
35struct perf_evlist *perf_evlist__new(struct cpu_map *cpus, 40struct perf_evlist *perf_evlist__new(struct cpu_map *cpus,
@@ -43,6 +48,22 @@ struct perf_evlist *perf_evlist__new(struct cpu_map *cpus,
43 return evlist; 48 return evlist;
44} 49}
45 50
51void perf_evlist__config_attrs(struct perf_evlist *evlist,
52 struct perf_record_opts *opts)
53{
54 struct perf_evsel *evsel;
55
56 if (evlist->cpus->map[0] < 0)
57 opts->no_inherit = true;
58
59 list_for_each_entry(evsel, &evlist->entries, node) {
60 perf_evsel__config(evsel, opts);
61
62 if (evlist->nr_entries > 1)
63 evsel->attr.sample_type |= PERF_SAMPLE_ID;
64 }
65}
66
46static void perf_evlist__purge(struct perf_evlist *evlist) 67static void perf_evlist__purge(struct perf_evlist *evlist)
47{ 68{
48 struct perf_evsel *pos, *n; 69 struct perf_evsel *pos, *n;
@@ -76,14 +97,25 @@ void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
76 ++evlist->nr_entries; 97 ++evlist->nr_entries;
77} 98}
78 99
100static void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
101 struct list_head *list,
102 int nr_entries)
103{
104 list_splice_tail(list, &evlist->entries);
105 evlist->nr_entries += nr_entries;
106}
107
79int perf_evlist__add_default(struct perf_evlist *evlist) 108int perf_evlist__add_default(struct perf_evlist *evlist)
80{ 109{
81 struct perf_event_attr attr = { 110 struct perf_event_attr attr = {
82 .type = PERF_TYPE_HARDWARE, 111 .type = PERF_TYPE_HARDWARE,
83 .config = PERF_COUNT_HW_CPU_CYCLES, 112 .config = PERF_COUNT_HW_CPU_CYCLES,
84 }; 113 };
85 struct perf_evsel *evsel = perf_evsel__new(&attr, 0); 114 struct perf_evsel *evsel;
86 115
116 event_attr_init(&attr);
117
118 evsel = perf_evsel__new(&attr, 0);
87 if (evsel == NULL) 119 if (evsel == NULL)
88 goto error; 120 goto error;
89 121
@@ -100,6 +132,126 @@ error:
100 return -ENOMEM; 132 return -ENOMEM;
101} 133}
102 134
135int perf_evlist__add_attrs(struct perf_evlist *evlist,
136 struct perf_event_attr *attrs, size_t nr_attrs)
137{
138 struct perf_evsel *evsel, *n;
139 LIST_HEAD(head);
140 size_t i;
141
142 for (i = 0; i < nr_attrs; i++) {
143 evsel = perf_evsel__new(attrs + i, evlist->nr_entries + i);
144 if (evsel == NULL)
145 goto out_delete_partial_list;
146 list_add_tail(&evsel->node, &head);
147 }
148
149 perf_evlist__splice_list_tail(evlist, &head, nr_attrs);
150
151 return 0;
152
153out_delete_partial_list:
154 list_for_each_entry_safe(evsel, n, &head, node)
155 perf_evsel__delete(evsel);
156 return -1;
157}
158
159static int trace_event__id(const char *evname)
160{
161 char *filename, *colon;
162 int err = -1, fd;
163
164 if (asprintf(&filename, "%s/%s/id", tracing_events_path, evname) < 0)
165 return -1;
166
167 colon = strrchr(filename, ':');
168 if (colon != NULL)
169 *colon = '/';
170
171 fd = open(filename, O_RDONLY);
172 if (fd >= 0) {
173 char id[16];
174 if (read(fd, id, sizeof(id)) > 0)
175 err = atoi(id);
176 close(fd);
177 }
178
179 free(filename);
180 return err;
181}
182
183int perf_evlist__add_tracepoints(struct perf_evlist *evlist,
184 const char *tracepoints[],
185 size_t nr_tracepoints)
186{
187 int err;
188 size_t i;
189 struct perf_event_attr *attrs = zalloc(nr_tracepoints * sizeof(*attrs));
190
191 if (attrs == NULL)
192 return -1;
193
194 for (i = 0; i < nr_tracepoints; i++) {
195 err = trace_event__id(tracepoints[i]);
196
197 if (err < 0)
198 goto out_free_attrs;
199
200 attrs[i].type = PERF_TYPE_TRACEPOINT;
201 attrs[i].config = err;
202 attrs[i].sample_type = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
203 PERF_SAMPLE_CPU);
204 attrs[i].sample_period = 1;
205 }
206
207 err = perf_evlist__add_attrs(evlist, attrs, nr_tracepoints);
208out_free_attrs:
209 free(attrs);
210 return err;
211}
212
213static struct perf_evsel *
214 perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
215{
216 struct perf_evsel *evsel;
217
218 list_for_each_entry(evsel, &evlist->entries, node) {
219 if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
220 (int)evsel->attr.config == id)
221 return evsel;
222 }
223
224 return NULL;
225}
226
227int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist,
228 const struct perf_evsel_str_handler *assocs,
229 size_t nr_assocs)
230{
231 struct perf_evsel *evsel;
232 int err;
233 size_t i;
234
235 for (i = 0; i < nr_assocs; i++) {
236 err = trace_event__id(assocs[i].name);
237 if (err < 0)
238 goto out;
239
240 evsel = perf_evlist__find_tracepoint_by_id(evlist, err);
241 if (evsel == NULL)
242 continue;
243
244 err = -EEXIST;
245 if (evsel->handler.func != NULL)
246 goto out;
247 evsel->handler.func = assocs[i].handler;
248 }
249
250 err = 0;
251out:
252 return err;
253}
254
103void perf_evlist__disable(struct perf_evlist *evlist) 255void perf_evlist__disable(struct perf_evlist *evlist)
104{ 256{
105 int cpu, thread; 257 int cpu, thread;
@@ -126,7 +278,7 @@ void perf_evlist__enable(struct perf_evlist *evlist)
126 } 278 }
127} 279}
128 280
129int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) 281static int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
130{ 282{
131 int nfds = evlist->cpus->nr * evlist->threads->nr * evlist->nr_entries; 283 int nfds = evlist->cpus->nr * evlist->threads->nr * evlist->nr_entries;
132 evlist->pollfd = malloc(sizeof(struct pollfd) * nfds); 284 evlist->pollfd = malloc(sizeof(struct pollfd) * nfds);
@@ -282,7 +434,7 @@ void perf_evlist__munmap(struct perf_evlist *evlist)
282 evlist->mmap = NULL; 434 evlist->mmap = NULL;
283} 435}
284 436
285int perf_evlist__alloc_mmap(struct perf_evlist *evlist) 437static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
286{ 438{
287 evlist->nr_mmaps = evlist->cpus->nr; 439 evlist->nr_mmaps = evlist->cpus->nr;
288 if (evlist->cpus->map[0] == -1) 440 if (evlist->cpus->map[0] == -1)
@@ -298,8 +450,10 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist,
298 evlist->mmap[idx].mask = mask; 450 evlist->mmap[idx].mask = mask;
299 evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, prot, 451 evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, prot,
300 MAP_SHARED, fd, 0); 452 MAP_SHARED, fd, 0);
301 if (evlist->mmap[idx].base == MAP_FAILED) 453 if (evlist->mmap[idx].base == MAP_FAILED) {
454 evlist->mmap[idx].base = NULL;
302 return -1; 455 return -1;
456 }
303 457
304 perf_evlist__add_pollfd(evlist, fd); 458 perf_evlist__add_pollfd(evlist, fd);
305 return 0; 459 return 0;
@@ -400,14 +554,22 @@ out_unmap:
400 * 554 *
401 * Using perf_evlist__read_on_cpu does this automatically. 555 * Using perf_evlist__read_on_cpu does this automatically.
402 */ 556 */
403int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite) 557int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
558 bool overwrite)
404{ 559{
405 unsigned int page_size = sysconf(_SC_PAGE_SIZE); 560 unsigned int page_size = sysconf(_SC_PAGE_SIZE);
406 int mask = pages * page_size - 1;
407 struct perf_evsel *evsel; 561 struct perf_evsel *evsel;
408 const struct cpu_map *cpus = evlist->cpus; 562 const struct cpu_map *cpus = evlist->cpus;
409 const struct thread_map *threads = evlist->threads; 563 const struct thread_map *threads = evlist->threads;
410 int prot = PROT_READ | (overwrite ? 0 : PROT_WRITE); 564 int prot = PROT_READ | (overwrite ? 0 : PROT_WRITE), mask;
565
566 /* 512 kiB: default amount of unprivileged mlocked memory */
567 if (pages == UINT_MAX)
568 pages = (512 * 1024) / page_size;
569 else if (!is_power_of_2(pages))
570 return -EINVAL;
571
572 mask = pages * page_size - 1;
411 573
412 if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0) 574 if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0)
413 return -ENOMEM; 575 return -ENOMEM;
@@ -512,6 +674,38 @@ u64 perf_evlist__sample_type(const struct perf_evlist *evlist)
512 return first->attr.sample_type; 674 return first->attr.sample_type;
513} 675}
514 676
677u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist)
678{
679 struct perf_evsel *first;
680 struct perf_sample *data;
681 u64 sample_type;
682 u16 size = 0;
683
684 first = list_entry(evlist->entries.next, struct perf_evsel, node);
685
686 if (!first->attr.sample_id_all)
687 goto out;
688
689 sample_type = first->attr.sample_type;
690
691 if (sample_type & PERF_SAMPLE_TID)
692 size += sizeof(data->tid) * 2;
693
694 if (sample_type & PERF_SAMPLE_TIME)
695 size += sizeof(data->time);
696
697 if (sample_type & PERF_SAMPLE_ID)
698 size += sizeof(data->id);
699
700 if (sample_type & PERF_SAMPLE_STREAM_ID)
701 size += sizeof(data->stream_id);
702
703 if (sample_type & PERF_SAMPLE_CPU)
704 size += sizeof(data->cpu) * 2;
705out:
706 return size;
707}
708
515bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist) 709bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist)
516{ 710{
517 struct perf_evsel *pos, *first; 711 struct perf_evsel *pos, *first;
@@ -569,3 +763,97 @@ out_err:
569 763
570 return err; 764 return err;
571} 765}
766
767int perf_evlist__prepare_workload(struct perf_evlist *evlist,
768 struct perf_record_opts *opts,
769 const char *argv[])
770{
771 int child_ready_pipe[2], go_pipe[2];
772 char bf;
773
774 if (pipe(child_ready_pipe) < 0) {
775 perror("failed to create 'ready' pipe");
776 return -1;
777 }
778
779 if (pipe(go_pipe) < 0) {
780 perror("failed to create 'go' pipe");
781 goto out_close_ready_pipe;
782 }
783
784 evlist->workload.pid = fork();
785 if (evlist->workload.pid < 0) {
786 perror("failed to fork");
787 goto out_close_pipes;
788 }
789
790 if (!evlist->workload.pid) {
791 if (opts->pipe_output)
792 dup2(2, 1);
793
794 close(child_ready_pipe[0]);
795 close(go_pipe[1]);
796 fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
797
798 /*
799 * Do a dummy execvp to get the PLT entry resolved,
800 * so we avoid the resolver overhead on the real
801 * execvp call.
802 */
803 execvp("", (char **)argv);
804
805 /*
806 * Tell the parent we're ready to go
807 */
808 close(child_ready_pipe[1]);
809
810 /*
811 * Wait until the parent tells us to go.
812 */
813 if (read(go_pipe[0], &bf, 1) == -1)
814 perror("unable to read pipe");
815
816 execvp(argv[0], (char **)argv);
817
818 perror(argv[0]);
819 kill(getppid(), SIGUSR1);
820 exit(-1);
821 }
822
823 if (!opts->system_wide && opts->target_tid == -1 && opts->target_pid == -1)
824 evlist->threads->map[0] = evlist->workload.pid;
825
826 close(child_ready_pipe[1]);
827 close(go_pipe[0]);
828 /*
829 * wait for child to settle
830 */
831 if (read(child_ready_pipe[0], &bf, 1) == -1) {
832 perror("unable to read pipe");
833 goto out_close_pipes;
834 }
835
836 evlist->workload.cork_fd = go_pipe[1];
837 close(child_ready_pipe[0]);
838 return 0;
839
840out_close_pipes:
841 close(go_pipe[0]);
842 close(go_pipe[1]);
843out_close_ready_pipe:
844 close(child_ready_pipe[0]);
845 close(child_ready_pipe[1]);
846 return -1;
847}
848
849int perf_evlist__start_workload(struct perf_evlist *evlist)
850{
851 if (evlist->workload.cork_fd > 0) {
852 /*
853 * Remove the cork, let it rip!
854 */
855 return close(evlist->workload.cork_fd);
856 }
857
858 return 0;
859}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 1779ffef7828..8922aeed0467 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -2,12 +2,16 @@
2#define __PERF_EVLIST_H 1 2#define __PERF_EVLIST_H 1
3 3
4#include <linux/list.h> 4#include <linux/list.h>
5#include <stdio.h>
5#include "../perf.h" 6#include "../perf.h"
6#include "event.h" 7#include "event.h"
8#include "util.h"
9#include <unistd.h>
7 10
8struct pollfd; 11struct pollfd;
9struct thread_map; 12struct thread_map;
10struct cpu_map; 13struct cpu_map;
14struct perf_record_opts;
11 15
12#define PERF_EVLIST__HLIST_BITS 8 16#define PERF_EVLIST__HLIST_BITS 8
13#define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS) 17#define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS)
@@ -19,6 +23,10 @@ struct perf_evlist {
19 int nr_fds; 23 int nr_fds;
20 int nr_mmaps; 24 int nr_mmaps;
21 int mmap_len; 25 int mmap_len;
26 struct {
27 int cork_fd;
28 pid_t pid;
29 } workload;
22 bool overwrite; 30 bool overwrite;
23 union perf_event event_copy; 31 union perf_event event_copy;
24 struct perf_mmap *mmap; 32 struct perf_mmap *mmap;
@@ -28,6 +36,11 @@ struct perf_evlist {
28 struct perf_evsel *selected; 36 struct perf_evsel *selected;
29}; 37};
30 38
39struct perf_evsel_str_handler {
40 const char *name;
41 void *handler;
42};
43
31struct perf_evsel; 44struct perf_evsel;
32 45
33struct perf_evlist *perf_evlist__new(struct cpu_map *cpus, 46struct perf_evlist *perf_evlist__new(struct cpu_map *cpus,
@@ -39,11 +52,26 @@ void perf_evlist__delete(struct perf_evlist *evlist);
39 52
40void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry); 53void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry);
41int perf_evlist__add_default(struct perf_evlist *evlist); 54int perf_evlist__add_default(struct perf_evlist *evlist);
55int perf_evlist__add_attrs(struct perf_evlist *evlist,
56 struct perf_event_attr *attrs, size_t nr_attrs);
57int perf_evlist__add_tracepoints(struct perf_evlist *evlist,
58 const char *tracepoints[], size_t nr_tracepoints);
59int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist,
60 const struct perf_evsel_str_handler *assocs,
61 size_t nr_assocs);
62
63#define perf_evlist__add_attrs_array(evlist, array) \
64 perf_evlist__add_attrs(evlist, array, ARRAY_SIZE(array))
65
66#define perf_evlist__add_tracepoints_array(evlist, array) \
67 perf_evlist__add_tracepoints(evlist, array, ARRAY_SIZE(array))
68
69#define perf_evlist__set_tracepoints_handlers_array(evlist, array) \
70 perf_evlist__set_tracepoints_handlers(evlist, array, ARRAY_SIZE(array))
42 71
43void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel, 72void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
44 int cpu, int thread, u64 id); 73 int cpu, int thread, u64 id);
45 74
46int perf_evlist__alloc_pollfd(struct perf_evlist *evlist);
47void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd); 75void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd);
48 76
49struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id); 77struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id);
@@ -52,8 +80,16 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx);
52 80
53int perf_evlist__open(struct perf_evlist *evlist, bool group); 81int perf_evlist__open(struct perf_evlist *evlist, bool group);
54 82
55int perf_evlist__alloc_mmap(struct perf_evlist *evlist); 83void perf_evlist__config_attrs(struct perf_evlist *evlist,
56int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite); 84 struct perf_record_opts *opts);
85
86int perf_evlist__prepare_workload(struct perf_evlist *evlist,
87 struct perf_record_opts *opts,
88 const char *argv[]);
89int perf_evlist__start_workload(struct perf_evlist *evlist);
90
91int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
92 bool overwrite);
57void perf_evlist__munmap(struct perf_evlist *evlist); 93void perf_evlist__munmap(struct perf_evlist *evlist);
58 94
59void perf_evlist__disable(struct perf_evlist *evlist); 95void perf_evlist__disable(struct perf_evlist *evlist);
@@ -77,6 +113,7 @@ int perf_evlist__set_filters(struct perf_evlist *evlist);
77 113
78u64 perf_evlist__sample_type(const struct perf_evlist *evlist); 114u64 perf_evlist__sample_type(const struct perf_evlist *evlist);
79bool perf_evlist__sample_id_all(const const struct perf_evlist *evlist); 115bool perf_evlist__sample_id_all(const const struct perf_evlist *evlist);
116u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist);
80 117
81bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist); 118bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist);
82bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist); 119bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist);
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index e42626422587..667f3b78bb2c 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -34,6 +34,16 @@ int __perf_evsel__sample_size(u64 sample_type)
34 return size; 34 return size;
35} 35}
36 36
37static void hists__init(struct hists *hists)
38{
39 memset(hists, 0, sizeof(*hists));
40 hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT;
41 hists->entries_in = &hists->entries_in_array[0];
42 hists->entries_collapsed = RB_ROOT;
43 hists->entries = RB_ROOT;
44 pthread_mutex_init(&hists->lock, NULL);
45}
46
37void perf_evsel__init(struct perf_evsel *evsel, 47void perf_evsel__init(struct perf_evsel *evsel,
38 struct perf_event_attr *attr, int idx) 48 struct perf_event_attr *attr, int idx)
39{ 49{
@@ -53,6 +63,79 @@ struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx)
53 return evsel; 63 return evsel;
54} 64}
55 65
66void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts)
67{
68 struct perf_event_attr *attr = &evsel->attr;
69 int track = !evsel->idx; /* only the first counter needs these */
70
71 attr->sample_id_all = opts->sample_id_all_avail ? 1 : 0;
72 attr->inherit = !opts->no_inherit;
73 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
74 PERF_FORMAT_TOTAL_TIME_RUNNING |
75 PERF_FORMAT_ID;
76
77 attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
78
79 /*
80 * We default some events to a 1 default interval. But keep
81 * it a weak assumption overridable by the user.
82 */
83 if (!attr->sample_period || (opts->user_freq != UINT_MAX &&
84 opts->user_interval != ULLONG_MAX)) {
85 if (opts->freq) {
86 attr->sample_type |= PERF_SAMPLE_PERIOD;
87 attr->freq = 1;
88 attr->sample_freq = opts->freq;
89 } else {
90 attr->sample_period = opts->default_interval;
91 }
92 }
93
94 if (opts->no_samples)
95 attr->sample_freq = 0;
96
97 if (opts->inherit_stat)
98 attr->inherit_stat = 1;
99
100 if (opts->sample_address) {
101 attr->sample_type |= PERF_SAMPLE_ADDR;
102 attr->mmap_data = track;
103 }
104
105 if (opts->call_graph)
106 attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
107
108 if (opts->system_wide)
109 attr->sample_type |= PERF_SAMPLE_CPU;
110
111 if (opts->period)
112 attr->sample_type |= PERF_SAMPLE_PERIOD;
113
114 if (opts->sample_id_all_avail &&
115 (opts->sample_time || opts->system_wide ||
116 !opts->no_inherit || opts->cpu_list))
117 attr->sample_type |= PERF_SAMPLE_TIME;
118
119 if (opts->raw_samples) {
120 attr->sample_type |= PERF_SAMPLE_TIME;
121 attr->sample_type |= PERF_SAMPLE_RAW;
122 attr->sample_type |= PERF_SAMPLE_CPU;
123 }
124
125 if (opts->no_delay) {
126 attr->watermark = 0;
127 attr->wakeup_events = 1;
128 }
129
130 attr->mmap = track;
131 attr->comm = track;
132
133 if (opts->target_pid == -1 && opts->target_tid == -1 && !opts->system_wide) {
134 attr->disabled = 1;
135 attr->enable_on_exec = 1;
136 }
137}
138
56int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) 139int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
57{ 140{
58 int cpu, thread; 141 int cpu, thread;
@@ -377,7 +460,7 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
377 u32 val32[2]; 460 u32 val32[2];
378 } u; 461 } u;
379 462
380 463 memset(data, 0, sizeof(*data));
381 data->cpu = data->pid = data->tid = -1; 464 data->cpu = data->pid = data->tid = -1;
382 data->stream_id = data->id = data->time = -1ULL; 465 data->stream_id = data->id = data->time = -1ULL;
383 466
@@ -494,3 +577,82 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
494 577
495 return 0; 578 return 0;
496} 579}
580
581int perf_event__synthesize_sample(union perf_event *event, u64 type,
582 const struct perf_sample *sample,
583 bool swapped)
584{
585 u64 *array;
586
587 /*
588 * used for cross-endian analysis. See git commit 65014ab3
589 * for why this goofiness is needed.
590 */
591 union {
592 u64 val64;
593 u32 val32[2];
594 } u;
595
596 array = event->sample.array;
597
598 if (type & PERF_SAMPLE_IP) {
599 event->ip.ip = sample->ip;
600 array++;
601 }
602
603 if (type & PERF_SAMPLE_TID) {
604 u.val32[0] = sample->pid;
605 u.val32[1] = sample->tid;
606 if (swapped) {
607 /*
608 * Inverse of what is done in perf_event__parse_sample
609 */
610 u.val32[0] = bswap_32(u.val32[0]);
611 u.val32[1] = bswap_32(u.val32[1]);
612 u.val64 = bswap_64(u.val64);
613 }
614
615 *array = u.val64;
616 array++;
617 }
618
619 if (type & PERF_SAMPLE_TIME) {
620 *array = sample->time;
621 array++;
622 }
623
624 if (type & PERF_SAMPLE_ADDR) {
625 *array = sample->addr;
626 array++;
627 }
628
629 if (type & PERF_SAMPLE_ID) {
630 *array = sample->id;
631 array++;
632 }
633
634 if (type & PERF_SAMPLE_STREAM_ID) {
635 *array = sample->stream_id;
636 array++;
637 }
638
639 if (type & PERF_SAMPLE_CPU) {
640 u.val32[0] = sample->cpu;
641 if (swapped) {
642 /*
643 * Inverse of what is done in perf_event__parse_sample
644 */
645 u.val32[0] = bswap_32(u.val32[0]);
646 u.val64 = bswap_64(u.val64);
647 }
648 *array = u.val64;
649 array++;
650 }
651
652 if (type & PERF_SAMPLE_PERIOD) {
653 *array = sample->period;
654 array++;
655 }
656
657 return 0;
658}
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index b1d15e6f7ae3..326b8e4d5035 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -61,12 +61,17 @@ struct perf_evsel {
61 off_t id_offset; 61 off_t id_offset;
62 }; 62 };
63 struct cgroup_sel *cgrp; 63 struct cgroup_sel *cgrp;
64 struct {
65 void *func;
66 void *data;
67 } handler;
64 bool supported; 68 bool supported;
65}; 69};
66 70
67struct cpu_map; 71struct cpu_map;
68struct thread_map; 72struct thread_map;
69struct perf_evlist; 73struct perf_evlist;
74struct perf_record_opts;
70 75
71struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx); 76struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx);
72void perf_evsel__init(struct perf_evsel *evsel, 77void perf_evsel__init(struct perf_evsel *evsel,
@@ -74,6 +79,9 @@ void perf_evsel__init(struct perf_evsel *evsel,
74void perf_evsel__exit(struct perf_evsel *evsel); 79void perf_evsel__exit(struct perf_evsel *evsel);
75void perf_evsel__delete(struct perf_evsel *evsel); 80void perf_evsel__delete(struct perf_evsel *evsel);
76 81
82void perf_evsel__config(struct perf_evsel *evsel,
83 struct perf_record_opts *opts);
84
77int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads); 85int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
78int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads); 86int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads);
79int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus); 87int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus);
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index bcd05d05b4f0..3e7e0b09c12c 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -8,6 +8,7 @@
8#include <stdlib.h> 8#include <stdlib.h>
9#include <linux/list.h> 9#include <linux/list.h>
10#include <linux/kernel.h> 10#include <linux/kernel.h>
11#include <linux/bitops.h>
11#include <sys/utsname.h> 12#include <sys/utsname.h>
12 13
13#include "evlist.h" 14#include "evlist.h"
@@ -28,9 +29,6 @@ static struct perf_trace_event_type *events;
28static u32 header_argc; 29static u32 header_argc;
29static const char **header_argv; 30static const char **header_argv;
30 31
31static int dsos__write_buildid_table(struct perf_header *header, int fd);
32static int perf_session__cache_build_ids(struct perf_session *session);
33
34int perf_header__push_event(u64 id, const char *name) 32int perf_header__push_event(u64 id, const char *name)
35{ 33{
36 if (strlen(name) > MAX_EVENT_NAME) 34 if (strlen(name) > MAX_EVENT_NAME)
@@ -187,6 +185,252 @@ perf_header__set_cmdline(int argc, const char **argv)
187 return 0; 185 return 0;
188} 186}
189 187
188#define dsos__for_each_with_build_id(pos, head) \
189 list_for_each_entry(pos, head, node) \
190 if (!pos->has_build_id) \
191 continue; \
192 else
193
194static int __dsos__write_buildid_table(struct list_head *head, pid_t pid,
195 u16 misc, int fd)
196{
197 struct dso *pos;
198
199 dsos__for_each_with_build_id(pos, head) {
200 int err;
201 struct build_id_event b;
202 size_t len;
203
204 if (!pos->hit)
205 continue;
206 len = pos->long_name_len + 1;
207 len = ALIGN(len, NAME_ALIGN);
208 memset(&b, 0, sizeof(b));
209 memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id));
210 b.pid = pid;
211 b.header.misc = misc;
212 b.header.size = sizeof(b) + len;
213 err = do_write(fd, &b, sizeof(b));
214 if (err < 0)
215 return err;
216 err = write_padded(fd, pos->long_name,
217 pos->long_name_len + 1, len);
218 if (err < 0)
219 return err;
220 }
221
222 return 0;
223}
224
225static int machine__write_buildid_table(struct machine *machine, int fd)
226{
227 int err;
228 u16 kmisc = PERF_RECORD_MISC_KERNEL,
229 umisc = PERF_RECORD_MISC_USER;
230
231 if (!machine__is_host(machine)) {
232 kmisc = PERF_RECORD_MISC_GUEST_KERNEL;
233 umisc = PERF_RECORD_MISC_GUEST_USER;
234 }
235
236 err = __dsos__write_buildid_table(&machine->kernel_dsos, machine->pid,
237 kmisc, fd);
238 if (err == 0)
239 err = __dsos__write_buildid_table(&machine->user_dsos,
240 machine->pid, umisc, fd);
241 return err;
242}
243
244static int dsos__write_buildid_table(struct perf_header *header, int fd)
245{
246 struct perf_session *session = container_of(header,
247 struct perf_session, header);
248 struct rb_node *nd;
249 int err = machine__write_buildid_table(&session->host_machine, fd);
250
251 if (err)
252 return err;
253
254 for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
255 struct machine *pos = rb_entry(nd, struct machine, rb_node);
256 err = machine__write_buildid_table(pos, fd);
257 if (err)
258 break;
259 }
260 return err;
261}
262
263int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
264 const char *name, bool is_kallsyms)
265{
266 const size_t size = PATH_MAX;
267 char *realname, *filename = zalloc(size),
268 *linkname = zalloc(size), *targetname;
269 int len, err = -1;
270
271 if (is_kallsyms) {
272 if (symbol_conf.kptr_restrict) {
273 pr_debug("Not caching a kptr_restrict'ed /proc/kallsyms\n");
274 return 0;
275 }
276 realname = (char *)name;
277 } else
278 realname = realpath(name, NULL);
279
280 if (realname == NULL || filename == NULL || linkname == NULL)
281 goto out_free;
282
283 len = snprintf(filename, size, "%s%s%s",
284 debugdir, is_kallsyms ? "/" : "", realname);
285 if (mkdir_p(filename, 0755))
286 goto out_free;
287
288 snprintf(filename + len, sizeof(filename) - len, "/%s", sbuild_id);
289
290 if (access(filename, F_OK)) {
291 if (is_kallsyms) {
292 if (copyfile("/proc/kallsyms", filename))
293 goto out_free;
294 } else if (link(realname, filename) && copyfile(name, filename))
295 goto out_free;
296 }
297
298 len = snprintf(linkname, size, "%s/.build-id/%.2s",
299 debugdir, sbuild_id);
300
301 if (access(linkname, X_OK) && mkdir_p(linkname, 0755))
302 goto out_free;
303
304 snprintf(linkname + len, size - len, "/%s", sbuild_id + 2);
305 targetname = filename + strlen(debugdir) - 5;
306 memcpy(targetname, "../..", 5);
307
308 if (symlink(targetname, linkname) == 0)
309 err = 0;
310out_free:
311 if (!is_kallsyms)
312 free(realname);
313 free(filename);
314 free(linkname);
315 return err;
316}
317
318static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
319 const char *name, const char *debugdir,
320 bool is_kallsyms)
321{
322 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
323
324 build_id__sprintf(build_id, build_id_size, sbuild_id);
325
326 return build_id_cache__add_s(sbuild_id, debugdir, name, is_kallsyms);
327}
328
329int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
330{
331 const size_t size = PATH_MAX;
332 char *filename = zalloc(size),
333 *linkname = zalloc(size);
334 int err = -1;
335
336 if (filename == NULL || linkname == NULL)
337 goto out_free;
338
339 snprintf(linkname, size, "%s/.build-id/%.2s/%s",
340 debugdir, sbuild_id, sbuild_id + 2);
341
342 if (access(linkname, F_OK))
343 goto out_free;
344
345 if (readlink(linkname, filename, size - 1) < 0)
346 goto out_free;
347
348 if (unlink(linkname))
349 goto out_free;
350
351 /*
352 * Since the link is relative, we must make it absolute:
353 */
354 snprintf(linkname, size, "%s/.build-id/%.2s/%s",
355 debugdir, sbuild_id, filename);
356
357 if (unlink(linkname))
358 goto out_free;
359
360 err = 0;
361out_free:
362 free(filename);
363 free(linkname);
364 return err;
365}
366
367static int dso__cache_build_id(struct dso *dso, const char *debugdir)
368{
369 bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
370
371 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id),
372 dso->long_name, debugdir, is_kallsyms);
373}
374
375static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir)
376{
377 struct dso *pos;
378 int err = 0;
379
380 dsos__for_each_with_build_id(pos, head)
381 if (dso__cache_build_id(pos, debugdir))
382 err = -1;
383
384 return err;
385}
386
387static int machine__cache_build_ids(struct machine *machine, const char *debugdir)
388{
389 int ret = __dsos__cache_build_ids(&machine->kernel_dsos, debugdir);
390 ret |= __dsos__cache_build_ids(&machine->user_dsos, debugdir);
391 return ret;
392}
393
394static int perf_session__cache_build_ids(struct perf_session *session)
395{
396 struct rb_node *nd;
397 int ret;
398 char debugdir[PATH_MAX];
399
400 snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir);
401
402 if (mkdir(debugdir, 0755) != 0 && errno != EEXIST)
403 return -1;
404
405 ret = machine__cache_build_ids(&session->host_machine, debugdir);
406
407 for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
408 struct machine *pos = rb_entry(nd, struct machine, rb_node);
409 ret |= machine__cache_build_ids(pos, debugdir);
410 }
411 return ret ? -1 : 0;
412}
413
414static bool machine__read_build_ids(struct machine *machine, bool with_hits)
415{
416 bool ret = __dsos__read_build_ids(&machine->kernel_dsos, with_hits);
417 ret |= __dsos__read_build_ids(&machine->user_dsos, with_hits);
418 return ret;
419}
420
421static bool perf_session__read_build_ids(struct perf_session *session, bool with_hits)
422{
423 struct rb_node *nd;
424 bool ret = machine__read_build_ids(&session->host_machine, with_hits);
425
426 for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
427 struct machine *pos = rb_entry(nd, struct machine, rb_node);
428 ret |= machine__read_build_ids(pos, with_hits);
429 }
430
431 return ret;
432}
433
190static int write_trace_info(int fd, struct perf_header *h __used, 434static int write_trace_info(int fd, struct perf_header *h __used,
191 struct perf_evlist *evlist) 435 struct perf_evlist *evlist)
192{ 436{
@@ -202,6 +446,9 @@ static int write_build_id(int fd, struct perf_header *h,
202 446
203 session = container_of(h, struct perf_session, header); 447 session = container_of(h, struct perf_session, header);
204 448
449 if (!perf_session__read_build_ids(session, true))
450 return -1;
451
205 err = dsos__write_buildid_table(h, fd); 452 err = dsos__write_buildid_table(h, fd);
206 if (err < 0) { 453 if (err < 0) {
207 pr_debug("failed to write buildid table\n"); 454 pr_debug("failed to write buildid table\n");
@@ -388,7 +635,7 @@ static int write_event_desc(int fd, struct perf_header *h __used,
388 /* 635 /*
389 * write event string as passed on cmdline 636 * write event string as passed on cmdline
390 */ 637 */
391 ret = do_write_string(fd, attr->name); 638 ret = do_write_string(fd, event_name(attr));
392 if (ret < 0) 639 if (ret < 0)
393 return ret; 640 return ret;
394 /* 641 /*
@@ -1065,26 +1312,30 @@ struct feature_ops {
1065 bool full_only; 1312 bool full_only;
1066}; 1313};
1067 1314
1068#define FEAT_OPA(n, w, p) \ 1315#define FEAT_OPA(n, func) \
1069 [n] = { .name = #n, .write = w, .print = p } 1316 [n] = { .name = #n, .write = write_##func, .print = print_##func }
1070#define FEAT_OPF(n, w, p) \ 1317#define FEAT_OPF(n, func) \
1071 [n] = { .name = #n, .write = w, .print = p, .full_only = true } 1318 [n] = { .name = #n, .write = write_##func, .print = print_##func, .full_only = true }
1319
1320/* feature_ops not implemented: */
1321#define print_trace_info NULL
1322#define print_build_id NULL
1072 1323
1073static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = { 1324static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
1074 FEAT_OPA(HEADER_TRACE_INFO, write_trace_info, NULL), 1325 FEAT_OPA(HEADER_TRACE_INFO, trace_info),
1075 FEAT_OPA(HEADER_BUILD_ID, write_build_id, NULL), 1326 FEAT_OPA(HEADER_BUILD_ID, build_id),
1076 FEAT_OPA(HEADER_HOSTNAME, write_hostname, print_hostname), 1327 FEAT_OPA(HEADER_HOSTNAME, hostname),
1077 FEAT_OPA(HEADER_OSRELEASE, write_osrelease, print_osrelease), 1328 FEAT_OPA(HEADER_OSRELEASE, osrelease),
1078 FEAT_OPA(HEADER_VERSION, write_version, print_version), 1329 FEAT_OPA(HEADER_VERSION, version),
1079 FEAT_OPA(HEADER_ARCH, write_arch, print_arch), 1330 FEAT_OPA(HEADER_ARCH, arch),
1080 FEAT_OPA(HEADER_NRCPUS, write_nrcpus, print_nrcpus), 1331 FEAT_OPA(HEADER_NRCPUS, nrcpus),
1081 FEAT_OPA(HEADER_CPUDESC, write_cpudesc, print_cpudesc), 1332 FEAT_OPA(HEADER_CPUDESC, cpudesc),
1082 FEAT_OPA(HEADER_CPUID, write_cpuid, print_cpuid), 1333 FEAT_OPA(HEADER_CPUID, cpuid),
1083 FEAT_OPA(HEADER_TOTAL_MEM, write_total_mem, print_total_mem), 1334 FEAT_OPA(HEADER_TOTAL_MEM, total_mem),
1084 FEAT_OPA(HEADER_EVENT_DESC, write_event_desc, print_event_desc), 1335 FEAT_OPA(HEADER_EVENT_DESC, event_desc),
1085 FEAT_OPA(HEADER_CMDLINE, write_cmdline, print_cmdline), 1336 FEAT_OPA(HEADER_CMDLINE, cmdline),
1086 FEAT_OPF(HEADER_CPU_TOPOLOGY, write_cpu_topology, print_cpu_topology), 1337 FEAT_OPF(HEADER_CPU_TOPOLOGY, cpu_topology),
1087 FEAT_OPF(HEADER_NUMA_TOPOLOGY, write_numa_topology, print_numa_topology), 1338 FEAT_OPF(HEADER_NUMA_TOPOLOGY, numa_topology),
1088}; 1339};
1089 1340
1090struct header_print_data { 1341struct header_print_data {
@@ -1103,9 +1354,9 @@ static int perf_file_section__fprintf_info(struct perf_file_section *section,
1103 "%d, continuing...\n", section->offset, feat); 1354 "%d, continuing...\n", section->offset, feat);
1104 return 0; 1355 return 0;
1105 } 1356 }
1106 if (feat < HEADER_TRACE_INFO || feat >= HEADER_LAST_FEATURE) { 1357 if (feat >= HEADER_LAST_FEATURE) {
1107 pr_warning("unknown feature %d\n", feat); 1358 pr_warning("unknown feature %d\n", feat);
1108 return -1; 1359 return 0;
1109 } 1360 }
1110 if (!feat_ops[feat].print) 1361 if (!feat_ops[feat].print)
1111 return 0; 1362 return 0;
@@ -1132,252 +1383,6 @@ int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full)
1132 return 0; 1383 return 0;
1133} 1384}
1134 1385
1135#define dsos__for_each_with_build_id(pos, head) \
1136 list_for_each_entry(pos, head, node) \
1137 if (!pos->has_build_id) \
1138 continue; \
1139 else
1140
1141static int __dsos__write_buildid_table(struct list_head *head, pid_t pid,
1142 u16 misc, int fd)
1143{
1144 struct dso *pos;
1145
1146 dsos__for_each_with_build_id(pos, head) {
1147 int err;
1148 struct build_id_event b;
1149 size_t len;
1150
1151 if (!pos->hit)
1152 continue;
1153 len = pos->long_name_len + 1;
1154 len = ALIGN(len, NAME_ALIGN);
1155 memset(&b, 0, sizeof(b));
1156 memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id));
1157 b.pid = pid;
1158 b.header.misc = misc;
1159 b.header.size = sizeof(b) + len;
1160 err = do_write(fd, &b, sizeof(b));
1161 if (err < 0)
1162 return err;
1163 err = write_padded(fd, pos->long_name,
1164 pos->long_name_len + 1, len);
1165 if (err < 0)
1166 return err;
1167 }
1168
1169 return 0;
1170}
1171
1172static int machine__write_buildid_table(struct machine *machine, int fd)
1173{
1174 int err;
1175 u16 kmisc = PERF_RECORD_MISC_KERNEL,
1176 umisc = PERF_RECORD_MISC_USER;
1177
1178 if (!machine__is_host(machine)) {
1179 kmisc = PERF_RECORD_MISC_GUEST_KERNEL;
1180 umisc = PERF_RECORD_MISC_GUEST_USER;
1181 }
1182
1183 err = __dsos__write_buildid_table(&machine->kernel_dsos, machine->pid,
1184 kmisc, fd);
1185 if (err == 0)
1186 err = __dsos__write_buildid_table(&machine->user_dsos,
1187 machine->pid, umisc, fd);
1188 return err;
1189}
1190
1191static int dsos__write_buildid_table(struct perf_header *header, int fd)
1192{
1193 struct perf_session *session = container_of(header,
1194 struct perf_session, header);
1195 struct rb_node *nd;
1196 int err = machine__write_buildid_table(&session->host_machine, fd);
1197
1198 if (err)
1199 return err;
1200
1201 for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
1202 struct machine *pos = rb_entry(nd, struct machine, rb_node);
1203 err = machine__write_buildid_table(pos, fd);
1204 if (err)
1205 break;
1206 }
1207 return err;
1208}
1209
1210int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
1211 const char *name, bool is_kallsyms)
1212{
1213 const size_t size = PATH_MAX;
1214 char *realname, *filename = zalloc(size),
1215 *linkname = zalloc(size), *targetname;
1216 int len, err = -1;
1217
1218 if (is_kallsyms) {
1219 if (symbol_conf.kptr_restrict) {
1220 pr_debug("Not caching a kptr_restrict'ed /proc/kallsyms\n");
1221 return 0;
1222 }
1223 realname = (char *)name;
1224 } else
1225 realname = realpath(name, NULL);
1226
1227 if (realname == NULL || filename == NULL || linkname == NULL)
1228 goto out_free;
1229
1230 len = snprintf(filename, size, "%s%s%s",
1231 debugdir, is_kallsyms ? "/" : "", realname);
1232 if (mkdir_p(filename, 0755))
1233 goto out_free;
1234
1235 snprintf(filename + len, sizeof(filename) - len, "/%s", sbuild_id);
1236
1237 if (access(filename, F_OK)) {
1238 if (is_kallsyms) {
1239 if (copyfile("/proc/kallsyms", filename))
1240 goto out_free;
1241 } else if (link(realname, filename) && copyfile(name, filename))
1242 goto out_free;
1243 }
1244
1245 len = snprintf(linkname, size, "%s/.build-id/%.2s",
1246 debugdir, sbuild_id);
1247
1248 if (access(linkname, X_OK) && mkdir_p(linkname, 0755))
1249 goto out_free;
1250
1251 snprintf(linkname + len, size - len, "/%s", sbuild_id + 2);
1252 targetname = filename + strlen(debugdir) - 5;
1253 memcpy(targetname, "../..", 5);
1254
1255 if (symlink(targetname, linkname) == 0)
1256 err = 0;
1257out_free:
1258 if (!is_kallsyms)
1259 free(realname);
1260 free(filename);
1261 free(linkname);
1262 return err;
1263}
1264
1265static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
1266 const char *name, const char *debugdir,
1267 bool is_kallsyms)
1268{
1269 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
1270
1271 build_id__sprintf(build_id, build_id_size, sbuild_id);
1272
1273 return build_id_cache__add_s(sbuild_id, debugdir, name, is_kallsyms);
1274}
1275
1276int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
1277{
1278 const size_t size = PATH_MAX;
1279 char *filename = zalloc(size),
1280 *linkname = zalloc(size);
1281 int err = -1;
1282
1283 if (filename == NULL || linkname == NULL)
1284 goto out_free;
1285
1286 snprintf(linkname, size, "%s/.build-id/%.2s/%s",
1287 debugdir, sbuild_id, sbuild_id + 2);
1288
1289 if (access(linkname, F_OK))
1290 goto out_free;
1291
1292 if (readlink(linkname, filename, size - 1) < 0)
1293 goto out_free;
1294
1295 if (unlink(linkname))
1296 goto out_free;
1297
1298 /*
1299 * Since the link is relative, we must make it absolute:
1300 */
1301 snprintf(linkname, size, "%s/.build-id/%.2s/%s",
1302 debugdir, sbuild_id, filename);
1303
1304 if (unlink(linkname))
1305 goto out_free;
1306
1307 err = 0;
1308out_free:
1309 free(filename);
1310 free(linkname);
1311 return err;
1312}
1313
1314static int dso__cache_build_id(struct dso *dso, const char *debugdir)
1315{
1316 bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
1317
1318 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id),
1319 dso->long_name, debugdir, is_kallsyms);
1320}
1321
1322static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir)
1323{
1324 struct dso *pos;
1325 int err = 0;
1326
1327 dsos__for_each_with_build_id(pos, head)
1328 if (dso__cache_build_id(pos, debugdir))
1329 err = -1;
1330
1331 return err;
1332}
1333
1334static int machine__cache_build_ids(struct machine *machine, const char *debugdir)
1335{
1336 int ret = __dsos__cache_build_ids(&machine->kernel_dsos, debugdir);
1337 ret |= __dsos__cache_build_ids(&machine->user_dsos, debugdir);
1338 return ret;
1339}
1340
1341static int perf_session__cache_build_ids(struct perf_session *session)
1342{
1343 struct rb_node *nd;
1344 int ret;
1345 char debugdir[PATH_MAX];
1346
1347 snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir);
1348
1349 if (mkdir(debugdir, 0755) != 0 && errno != EEXIST)
1350 return -1;
1351
1352 ret = machine__cache_build_ids(&session->host_machine, debugdir);
1353
1354 for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
1355 struct machine *pos = rb_entry(nd, struct machine, rb_node);
1356 ret |= machine__cache_build_ids(pos, debugdir);
1357 }
1358 return ret ? -1 : 0;
1359}
1360
1361static bool machine__read_build_ids(struct machine *machine, bool with_hits)
1362{
1363 bool ret = __dsos__read_build_ids(&machine->kernel_dsos, with_hits);
1364 ret |= __dsos__read_build_ids(&machine->user_dsos, with_hits);
1365 return ret;
1366}
1367
1368static bool perf_session__read_build_ids(struct perf_session *session, bool with_hits)
1369{
1370 struct rb_node *nd;
1371 bool ret = machine__read_build_ids(&session->host_machine, with_hits);
1372
1373 for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
1374 struct machine *pos = rb_entry(nd, struct machine, rb_node);
1375 ret |= machine__read_build_ids(pos, with_hits);
1376 }
1377
1378 return ret;
1379}
1380
1381static int do_write_feat(int fd, struct perf_header *h, int type, 1386static int do_write_feat(int fd, struct perf_header *h, int type,
1382 struct perf_file_section **p, 1387 struct perf_file_section **p,
1383 struct perf_evlist *evlist) 1388 struct perf_evlist *evlist)
@@ -1386,6 +1391,8 @@ static int do_write_feat(int fd, struct perf_header *h, int type,
1386 int ret = 0; 1391 int ret = 0;
1387 1392
1388 if (perf_header__has_feat(h, type)) { 1393 if (perf_header__has_feat(h, type)) {
1394 if (!feat_ops[type].write)
1395 return -1;
1389 1396
1390 (*p)->offset = lseek(fd, 0, SEEK_CUR); 1397 (*p)->offset = lseek(fd, 0, SEEK_CUR);
1391 1398
@@ -1408,18 +1415,12 @@ static int perf_header__adds_write(struct perf_header *header,
1408 struct perf_evlist *evlist, int fd) 1415 struct perf_evlist *evlist, int fd)
1409{ 1416{
1410 int nr_sections; 1417 int nr_sections;
1411 struct perf_session *session;
1412 struct perf_file_section *feat_sec, *p; 1418 struct perf_file_section *feat_sec, *p;
1413 int sec_size; 1419 int sec_size;
1414 u64 sec_start; 1420 u64 sec_start;
1421 int feat;
1415 int err; 1422 int err;
1416 1423
1417 session = container_of(header, struct perf_session, header);
1418
1419 if (perf_header__has_feat(header, HEADER_BUILD_ID &&
1420 !perf_session__read_build_ids(session, true)))
1421 perf_header__clear_feat(header, HEADER_BUILD_ID);
1422
1423 nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS); 1424 nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS);
1424 if (!nr_sections) 1425 if (!nr_sections)
1425 return 0; 1426 return 0;
@@ -1433,64 +1434,11 @@ static int perf_header__adds_write(struct perf_header *header,
1433 sec_start = header->data_offset + header->data_size; 1434 sec_start = header->data_offset + header->data_size;
1434 lseek(fd, sec_start + sec_size, SEEK_SET); 1435 lseek(fd, sec_start + sec_size, SEEK_SET);
1435 1436
1436 err = do_write_feat(fd, header, HEADER_TRACE_INFO, &p, evlist); 1437 for_each_set_bit(feat, header->adds_features, HEADER_FEAT_BITS) {
1437 if (err) 1438 if (do_write_feat(fd, header, feat, &p, evlist))
1438 goto out_free; 1439 perf_header__clear_feat(header, feat);
1439
1440 err = do_write_feat(fd, header, HEADER_BUILD_ID, &p, evlist);
1441 if (err) {
1442 perf_header__clear_feat(header, HEADER_BUILD_ID);
1443 goto out_free;
1444 } 1440 }
1445 1441
1446 err = do_write_feat(fd, header, HEADER_HOSTNAME, &p, evlist);
1447 if (err)
1448 perf_header__clear_feat(header, HEADER_HOSTNAME);
1449
1450 err = do_write_feat(fd, header, HEADER_OSRELEASE, &p, evlist);
1451 if (err)
1452 perf_header__clear_feat(header, HEADER_OSRELEASE);
1453
1454 err = do_write_feat(fd, header, HEADER_VERSION, &p, evlist);
1455 if (err)
1456 perf_header__clear_feat(header, HEADER_VERSION);
1457
1458 err = do_write_feat(fd, header, HEADER_ARCH, &p, evlist);
1459 if (err)
1460 perf_header__clear_feat(header, HEADER_ARCH);
1461
1462 err = do_write_feat(fd, header, HEADER_NRCPUS, &p, evlist);
1463 if (err)
1464 perf_header__clear_feat(header, HEADER_NRCPUS);
1465
1466 err = do_write_feat(fd, header, HEADER_CPUDESC, &p, evlist);
1467 if (err)
1468 perf_header__clear_feat(header, HEADER_CPUDESC);
1469
1470 err = do_write_feat(fd, header, HEADER_CPUID, &p, evlist);
1471 if (err)
1472 perf_header__clear_feat(header, HEADER_CPUID);
1473
1474 err = do_write_feat(fd, header, HEADER_TOTAL_MEM, &p, evlist);
1475 if (err)
1476 perf_header__clear_feat(header, HEADER_TOTAL_MEM);
1477
1478 err = do_write_feat(fd, header, HEADER_CMDLINE, &p, evlist);
1479 if (err)
1480 perf_header__clear_feat(header, HEADER_CMDLINE);
1481
1482 err = do_write_feat(fd, header, HEADER_EVENT_DESC, &p, evlist);
1483 if (err)
1484 perf_header__clear_feat(header, HEADER_EVENT_DESC);
1485
1486 err = do_write_feat(fd, header, HEADER_CPU_TOPOLOGY, &p, evlist);
1487 if (err)
1488 perf_header__clear_feat(header, HEADER_CPU_TOPOLOGY);
1489
1490 err = do_write_feat(fd, header, HEADER_NUMA_TOPOLOGY, &p, evlist);
1491 if (err)
1492 perf_header__clear_feat(header, HEADER_NUMA_TOPOLOGY);
1493
1494 lseek(fd, sec_start, SEEK_SET); 1442 lseek(fd, sec_start, SEEK_SET);
1495 /* 1443 /*
1496 * may write more than needed due to dropped feature, but 1444 * may write more than needed due to dropped feature, but
@@ -1499,7 +1447,6 @@ static int perf_header__adds_write(struct perf_header *header,
1499 err = do_write(fd, feat_sec, sec_size); 1447 err = do_write(fd, feat_sec, sec_size);
1500 if (err < 0) 1448 if (err < 0)
1501 pr_debug("failed to write feature section\n"); 1449 pr_debug("failed to write feature section\n");
1502out_free:
1503 free(feat_sec); 1450 free(feat_sec);
1504 return err; 1451 return err;
1505} 1452}
@@ -1637,20 +1584,20 @@ static int perf_header__getbuffer64(struct perf_header *header,
1637int perf_header__process_sections(struct perf_header *header, int fd, 1584int perf_header__process_sections(struct perf_header *header, int fd,
1638 void *data, 1585 void *data,
1639 int (*process)(struct perf_file_section *section, 1586 int (*process)(struct perf_file_section *section,
1640 struct perf_header *ph, 1587 struct perf_header *ph,
1641 int feat, int fd, void *data)) 1588 int feat, int fd, void *data))
1642{ 1589{
1643 struct perf_file_section *feat_sec; 1590 struct perf_file_section *feat_sec, *sec;
1644 int nr_sections; 1591 int nr_sections;
1645 int sec_size; 1592 int sec_size;
1646 int idx = 0; 1593 int feat;
1647 int err = -1, feat = 1; 1594 int err;
1648 1595
1649 nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS); 1596 nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS);
1650 if (!nr_sections) 1597 if (!nr_sections)
1651 return 0; 1598 return 0;
1652 1599
1653 feat_sec = calloc(sizeof(*feat_sec), nr_sections); 1600 feat_sec = sec = calloc(sizeof(*feat_sec), nr_sections);
1654 if (!feat_sec) 1601 if (!feat_sec)
1655 return -1; 1602 return -1;
1656 1603
@@ -1658,20 +1605,16 @@ int perf_header__process_sections(struct perf_header *header, int fd,
1658 1605
1659 lseek(fd, header->data_offset + header->data_size, SEEK_SET); 1606 lseek(fd, header->data_offset + header->data_size, SEEK_SET);
1660 1607
1661 if (perf_header__getbuffer64(header, fd, feat_sec, sec_size)) 1608 err = perf_header__getbuffer64(header, fd, feat_sec, sec_size);
1609 if (err < 0)
1662 goto out_free; 1610 goto out_free;
1663 1611
1664 err = 0; 1612 for_each_set_bit(feat, header->adds_features, HEADER_LAST_FEATURE) {
1665 while (idx < nr_sections && feat < HEADER_LAST_FEATURE) { 1613 err = process(sec++, header, feat, fd, data);
1666 if (perf_header__has_feat(header, feat)) { 1614 if (err < 0)
1667 struct perf_file_section *sec = &feat_sec[idx++]; 1615 goto out_free;
1668
1669 err = process(sec, header, feat, fd, data);
1670 if (err < 0)
1671 break;
1672 }
1673 ++feat;
1674 } 1616 }
1617 err = 0;
1675out_free: 1618out_free:
1676 free(feat_sec); 1619 free(feat_sec);
1677 return err; 1620 return err;
@@ -1906,32 +1849,21 @@ static int perf_file_section__process(struct perf_file_section *section,
1906 return 0; 1849 return 0;
1907 } 1850 }
1908 1851
1852 if (feat >= HEADER_LAST_FEATURE) {
1853 pr_debug("unknown feature %d, continuing...\n", feat);
1854 return 0;
1855 }
1856
1909 switch (feat) { 1857 switch (feat) {
1910 case HEADER_TRACE_INFO: 1858 case HEADER_TRACE_INFO:
1911 trace_report(fd, false); 1859 trace_report(fd, false);
1912 break; 1860 break;
1913
1914 case HEADER_BUILD_ID: 1861 case HEADER_BUILD_ID:
1915 if (perf_header__read_build_ids(ph, fd, section->offset, section->size)) 1862 if (perf_header__read_build_ids(ph, fd, section->offset, section->size))
1916 pr_debug("Failed to read buildids, continuing...\n"); 1863 pr_debug("Failed to read buildids, continuing...\n");
1917 break; 1864 break;
1918
1919 case HEADER_HOSTNAME:
1920 case HEADER_OSRELEASE:
1921 case HEADER_VERSION:
1922 case HEADER_ARCH:
1923 case HEADER_NRCPUS:
1924 case HEADER_CPUDESC:
1925 case HEADER_CPUID:
1926 case HEADER_TOTAL_MEM:
1927 case HEADER_CMDLINE:
1928 case HEADER_EVENT_DESC:
1929 case HEADER_CPU_TOPOLOGY:
1930 case HEADER_NUMA_TOPOLOGY:
1931 break;
1932
1933 default: 1865 default:
1934 pr_debug("unknown feature %d, continuing...\n", feat); 1866 break;
1935 } 1867 }
1936 1868
1937 return 0; 1869 return 0;
@@ -2041,6 +1973,8 @@ int perf_session__read_header(struct perf_session *session, int fd)
2041 lseek(fd, tmp, SEEK_SET); 1973 lseek(fd, tmp, SEEK_SET);
2042 } 1974 }
2043 1975
1976 symbol_conf.nr_events = nr_attrs;
1977
2044 if (f_header.event_types.size) { 1978 if (f_header.event_types.size) {
2045 lseek(fd, f_header.event_types.offset, SEEK_SET); 1979 lseek(fd, f_header.event_types.offset, SEEK_SET);
2046 events = malloc(f_header.event_types.size); 1980 events = malloc(f_header.event_types.size);
@@ -2068,9 +2002,9 @@ out_delete_evlist:
2068 return -ENOMEM; 2002 return -ENOMEM;
2069} 2003}
2070 2004
2071int perf_event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id, 2005int perf_event__synthesize_attr(struct perf_tool *tool,
2072 perf_event__handler_t process, 2006 struct perf_event_attr *attr, u16 ids, u64 *id,
2073 struct perf_session *session) 2007 perf_event__handler_t process)
2074{ 2008{
2075 union perf_event *ev; 2009 union perf_event *ev;
2076 size_t size; 2010 size_t size;
@@ -2092,22 +2026,23 @@ int perf_event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id,
2092 ev->attr.header.type = PERF_RECORD_HEADER_ATTR; 2026 ev->attr.header.type = PERF_RECORD_HEADER_ATTR;
2093 ev->attr.header.size = size; 2027 ev->attr.header.size = size;
2094 2028
2095 err = process(ev, NULL, session); 2029 err = process(tool, ev, NULL, NULL);
2096 2030
2097 free(ev); 2031 free(ev);
2098 2032
2099 return err; 2033 return err;
2100} 2034}
2101 2035
2102int perf_session__synthesize_attrs(struct perf_session *session, 2036int perf_event__synthesize_attrs(struct perf_tool *tool,
2037 struct perf_session *session,
2103 perf_event__handler_t process) 2038 perf_event__handler_t process)
2104{ 2039{
2105 struct perf_evsel *attr; 2040 struct perf_evsel *attr;
2106 int err = 0; 2041 int err = 0;
2107 2042
2108 list_for_each_entry(attr, &session->evlist->entries, node) { 2043 list_for_each_entry(attr, &session->evlist->entries, node) {
2109 err = perf_event__synthesize_attr(&attr->attr, attr->ids, 2044 err = perf_event__synthesize_attr(tool, &attr->attr, attr->ids,
2110 attr->id, process, session); 2045 attr->id, process);
2111 if (err) { 2046 if (err) {
2112 pr_debug("failed to create perf header attribute\n"); 2047 pr_debug("failed to create perf header attribute\n");
2113 return err; 2048 return err;
@@ -2118,23 +2053,23 @@ int perf_session__synthesize_attrs(struct perf_session *session,
2118} 2053}
2119 2054
2120int perf_event__process_attr(union perf_event *event, 2055int perf_event__process_attr(union perf_event *event,
2121 struct perf_session *session) 2056 struct perf_evlist **pevlist)
2122{ 2057{
2123 unsigned int i, ids, n_ids; 2058 unsigned int i, ids, n_ids;
2124 struct perf_evsel *evsel; 2059 struct perf_evsel *evsel;
2060 struct perf_evlist *evlist = *pevlist;
2125 2061
2126 if (session->evlist == NULL) { 2062 if (evlist == NULL) {
2127 session->evlist = perf_evlist__new(NULL, NULL); 2063 *pevlist = evlist = perf_evlist__new(NULL, NULL);
2128 if (session->evlist == NULL) 2064 if (evlist == NULL)
2129 return -ENOMEM; 2065 return -ENOMEM;
2130 } 2066 }
2131 2067
2132 evsel = perf_evsel__new(&event->attr.attr, 2068 evsel = perf_evsel__new(&event->attr.attr, evlist->nr_entries);
2133 session->evlist->nr_entries);
2134 if (evsel == NULL) 2069 if (evsel == NULL)
2135 return -ENOMEM; 2070 return -ENOMEM;
2136 2071
2137 perf_evlist__add(session->evlist, evsel); 2072 perf_evlist__add(evlist, evsel);
2138 2073
2139 ids = event->header.size; 2074 ids = event->header.size;
2140 ids -= (void *)&event->attr.id - (void *)event; 2075 ids -= (void *)&event->attr.id - (void *)event;
@@ -2148,18 +2083,16 @@ int perf_event__process_attr(union perf_event *event,
2148 return -ENOMEM; 2083 return -ENOMEM;
2149 2084
2150 for (i = 0; i < n_ids; i++) { 2085 for (i = 0; i < n_ids; i++) {
2151 perf_evlist__id_add(session->evlist, evsel, 0, i, 2086 perf_evlist__id_add(evlist, evsel, 0, i, event->attr.id[i]);
2152 event->attr.id[i]);
2153 } 2087 }
2154 2088
2155 perf_session__update_sample_type(session);
2156
2157 return 0; 2089 return 0;
2158} 2090}
2159 2091
2160int perf_event__synthesize_event_type(u64 event_id, char *name, 2092int perf_event__synthesize_event_type(struct perf_tool *tool,
2093 u64 event_id, char *name,
2161 perf_event__handler_t process, 2094 perf_event__handler_t process,
2162 struct perf_session *session) 2095 struct machine *machine)
2163{ 2096{
2164 union perf_event ev; 2097 union perf_event ev;
2165 size_t size = 0; 2098 size_t size = 0;
@@ -2177,13 +2110,14 @@ int perf_event__synthesize_event_type(u64 event_id, char *name,
2177 ev.event_type.header.size = sizeof(ev.event_type) - 2110 ev.event_type.header.size = sizeof(ev.event_type) -
2178 (sizeof(ev.event_type.event_type.name) - size); 2111 (sizeof(ev.event_type.event_type.name) - size);
2179 2112
2180 err = process(&ev, NULL, session); 2113 err = process(tool, &ev, NULL, machine);
2181 2114
2182 return err; 2115 return err;
2183} 2116}
2184 2117
2185int perf_event__synthesize_event_types(perf_event__handler_t process, 2118int perf_event__synthesize_event_types(struct perf_tool *tool,
2186 struct perf_session *session) 2119 perf_event__handler_t process,
2120 struct machine *machine)
2187{ 2121{
2188 struct perf_trace_event_type *type; 2122 struct perf_trace_event_type *type;
2189 int i, err = 0; 2123 int i, err = 0;
@@ -2191,9 +2125,9 @@ int perf_event__synthesize_event_types(perf_event__handler_t process,
2191 for (i = 0; i < event_count; i++) { 2125 for (i = 0; i < event_count; i++) {
2192 type = &events[i]; 2126 type = &events[i];
2193 2127
2194 err = perf_event__synthesize_event_type(type->event_id, 2128 err = perf_event__synthesize_event_type(tool, type->event_id,
2195 type->name, process, 2129 type->name, process,
2196 session); 2130 machine);
2197 if (err) { 2131 if (err) {
2198 pr_debug("failed to create perf header event type\n"); 2132 pr_debug("failed to create perf header event type\n");
2199 return err; 2133 return err;
@@ -2203,8 +2137,8 @@ int perf_event__synthesize_event_types(perf_event__handler_t process,
2203 return err; 2137 return err;
2204} 2138}
2205 2139
2206int perf_event__process_event_type(union perf_event *event, 2140int perf_event__process_event_type(struct perf_tool *tool __unused,
2207 struct perf_session *session __unused) 2141 union perf_event *event)
2208{ 2142{
2209 if (perf_header__push_event(event->event_type.event_type.event_id, 2143 if (perf_header__push_event(event->event_type.event_type.event_id,
2210 event->event_type.event_type.name) < 0) 2144 event->event_type.event_type.name) < 0)
@@ -2213,9 +2147,9 @@ int perf_event__process_event_type(union perf_event *event,
2213 return 0; 2147 return 0;
2214} 2148}
2215 2149
2216int perf_event__synthesize_tracing_data(int fd, struct perf_evlist *evlist, 2150int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,
2217 perf_event__handler_t process, 2151 struct perf_evlist *evlist,
2218 struct perf_session *session __unused) 2152 perf_event__handler_t process)
2219{ 2153{
2220 union perf_event ev; 2154 union perf_event ev;
2221 struct tracing_data *tdata; 2155 struct tracing_data *tdata;
@@ -2246,7 +2180,7 @@ int perf_event__synthesize_tracing_data(int fd, struct perf_evlist *evlist,
2246 ev.tracing_data.header.size = sizeof(ev.tracing_data); 2180 ev.tracing_data.header.size = sizeof(ev.tracing_data);
2247 ev.tracing_data.size = aligned_size; 2181 ev.tracing_data.size = aligned_size;
2248 2182
2249 process(&ev, NULL, session); 2183 process(tool, &ev, NULL, NULL);
2250 2184
2251 /* 2185 /*
2252 * The put function will copy all the tracing data 2186 * The put function will copy all the tracing data
@@ -2288,10 +2222,10 @@ int perf_event__process_tracing_data(union perf_event *event,
2288 return size_read + padding; 2222 return size_read + padding;
2289} 2223}
2290 2224
2291int perf_event__synthesize_build_id(struct dso *pos, u16 misc, 2225int perf_event__synthesize_build_id(struct perf_tool *tool,
2226 struct dso *pos, u16 misc,
2292 perf_event__handler_t process, 2227 perf_event__handler_t process,
2293 struct machine *machine, 2228 struct machine *machine)
2294 struct perf_session *session)
2295{ 2229{
2296 union perf_event ev; 2230 union perf_event ev;
2297 size_t len; 2231 size_t len;
@@ -2311,12 +2245,13 @@ int perf_event__synthesize_build_id(struct dso *pos, u16 misc,
2311 ev.build_id.header.size = sizeof(ev.build_id) + len; 2245 ev.build_id.header.size = sizeof(ev.build_id) + len;
2312 memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len); 2246 memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len);
2313 2247
2314 err = process(&ev, NULL, session); 2248 err = process(tool, &ev, NULL, machine);
2315 2249
2316 return err; 2250 return err;
2317} 2251}
2318 2252
2319int perf_event__process_build_id(union perf_event *event, 2253int perf_event__process_build_id(struct perf_tool *tool __used,
2254 union perf_event *event,
2320 struct perf_session *session) 2255 struct perf_session *session)
2321{ 2256{
2322 __event_process_build_id(&event->build_id, 2257 __event_process_build_id(&event->build_id,
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 3d5a742f4a2a..ac4ec956024e 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -10,7 +10,8 @@
10#include <linux/bitmap.h> 10#include <linux/bitmap.h>
11 11
12enum { 12enum {
13 HEADER_TRACE_INFO = 1, 13 HEADER_RESERVED = 0, /* always cleared */
14 HEADER_TRACE_INFO = 1,
14 HEADER_BUILD_ID, 15 HEADER_BUILD_ID,
15 16
16 HEADER_HOSTNAME, 17 HEADER_HOSTNAME,
@@ -27,10 +28,9 @@ enum {
27 HEADER_NUMA_TOPOLOGY, 28 HEADER_NUMA_TOPOLOGY,
28 29
29 HEADER_LAST_FEATURE, 30 HEADER_LAST_FEATURE,
31 HEADER_FEAT_BITS = 256,
30}; 32};
31 33
32#define HEADER_FEAT_BITS 256
33
34struct perf_file_section { 34struct perf_file_section {
35 u64 offset; 35 u64 offset;
36 u64 size; 36 u64 size;
@@ -68,6 +68,7 @@ struct perf_header {
68}; 68};
69 69
70struct perf_evlist; 70struct perf_evlist;
71struct perf_session;
71 72
72int perf_session__read_header(struct perf_session *session, int fd); 73int perf_session__read_header(struct perf_session *session, int fd);
73int perf_session__write_header(struct perf_session *session, 74int perf_session__write_header(struct perf_session *session,
@@ -96,32 +97,36 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
96 const char *name, bool is_kallsyms); 97 const char *name, bool is_kallsyms);
97int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir); 98int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir);
98 99
99int perf_event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id, 100int perf_event__synthesize_attr(struct perf_tool *tool,
100 perf_event__handler_t process, 101 struct perf_event_attr *attr, u16 ids, u64 *id,
101 struct perf_session *session); 102 perf_event__handler_t process);
102int perf_session__synthesize_attrs(struct perf_session *session, 103int perf_event__synthesize_attrs(struct perf_tool *tool,
103 perf_event__handler_t process); 104 struct perf_session *session,
104int perf_event__process_attr(union perf_event *event, struct perf_session *session); 105 perf_event__handler_t process);
106int perf_event__process_attr(union perf_event *event, struct perf_evlist **pevlist);
105 107
106int perf_event__synthesize_event_type(u64 event_id, char *name, 108int perf_event__synthesize_event_type(struct perf_tool *tool,
109 u64 event_id, char *name,
107 perf_event__handler_t process, 110 perf_event__handler_t process,
108 struct perf_session *session); 111 struct machine *machine);
109int perf_event__synthesize_event_types(perf_event__handler_t process, 112int perf_event__synthesize_event_types(struct perf_tool *tool,
110 struct perf_session *session); 113 perf_event__handler_t process,
111int perf_event__process_event_type(union perf_event *event, 114 struct machine *machine);
112 struct perf_session *session); 115int perf_event__process_event_type(struct perf_tool *tool,
113 116 union perf_event *event);
114int perf_event__synthesize_tracing_data(int fd, struct perf_evlist *evlist, 117
115 perf_event__handler_t process, 118int perf_event__synthesize_tracing_data(struct perf_tool *tool,
116 struct perf_session *session); 119 int fd, struct perf_evlist *evlist,
120 perf_event__handler_t process);
117int perf_event__process_tracing_data(union perf_event *event, 121int perf_event__process_tracing_data(union perf_event *event,
118 struct perf_session *session); 122 struct perf_session *session);
119 123
120int perf_event__synthesize_build_id(struct dso *pos, u16 misc, 124int perf_event__synthesize_build_id(struct perf_tool *tool,
125 struct dso *pos, u16 misc,
121 perf_event__handler_t process, 126 perf_event__handler_t process,
122 struct machine *machine, 127 struct machine *machine);
123 struct perf_session *session); 128int perf_event__process_build_id(struct perf_tool *tool,
124int perf_event__process_build_id(union perf_event *event, 129 union perf_event *event,
125 struct perf_session *session); 130 struct perf_session *session);
126 131
127/* 132/*
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index a36a3fa81ffb..6f505d1abac7 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -76,21 +76,21 @@ static void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
76 } 76 }
77} 77}
78 78
79static void hist_entry__add_cpumode_period(struct hist_entry *self, 79static void hist_entry__add_cpumode_period(struct hist_entry *he,
80 unsigned int cpumode, u64 period) 80 unsigned int cpumode, u64 period)
81{ 81{
82 switch (cpumode) { 82 switch (cpumode) {
83 case PERF_RECORD_MISC_KERNEL: 83 case PERF_RECORD_MISC_KERNEL:
84 self->period_sys += period; 84 he->period_sys += period;
85 break; 85 break;
86 case PERF_RECORD_MISC_USER: 86 case PERF_RECORD_MISC_USER:
87 self->period_us += period; 87 he->period_us += period;
88 break; 88 break;
89 case PERF_RECORD_MISC_GUEST_KERNEL: 89 case PERF_RECORD_MISC_GUEST_KERNEL:
90 self->period_guest_sys += period; 90 he->period_guest_sys += period;
91 break; 91 break;
92 case PERF_RECORD_MISC_GUEST_USER: 92 case PERF_RECORD_MISC_GUEST_USER:
93 self->period_guest_us += period; 93 he->period_guest_us += period;
94 break; 94 break;
95 default: 95 default:
96 break; 96 break;
@@ -165,18 +165,18 @@ void hists__decay_entries_threaded(struct hists *hists,
165static struct hist_entry *hist_entry__new(struct hist_entry *template) 165static struct hist_entry *hist_entry__new(struct hist_entry *template)
166{ 166{
167 size_t callchain_size = symbol_conf.use_callchain ? sizeof(struct callchain_root) : 0; 167 size_t callchain_size = symbol_conf.use_callchain ? sizeof(struct callchain_root) : 0;
168 struct hist_entry *self = malloc(sizeof(*self) + callchain_size); 168 struct hist_entry *he = malloc(sizeof(*he) + callchain_size);
169 169
170 if (self != NULL) { 170 if (he != NULL) {
171 *self = *template; 171 *he = *template;
172 self->nr_events = 1; 172 he->nr_events = 1;
173 if (self->ms.map) 173 if (he->ms.map)
174 self->ms.map->referenced = true; 174 he->ms.map->referenced = true;
175 if (symbol_conf.use_callchain) 175 if (symbol_conf.use_callchain)
176 callchain_init(self->callchain); 176 callchain_init(he->callchain);
177 } 177 }
178 178
179 return self; 179 return he;
180} 180}
181 181
182static void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h) 182static void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h)
@@ -677,15 +677,16 @@ static size_t callchain__fprintf_flat(FILE *fp, struct callchain_node *self,
677 return ret; 677 return ret;
678} 678}
679 679
680static size_t hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self, 680static size_t hist_entry_callchain__fprintf(struct hist_entry *he,
681 u64 total_samples, int left_margin) 681 u64 total_samples, int left_margin,
682 FILE *fp)
682{ 683{
683 struct rb_node *rb_node; 684 struct rb_node *rb_node;
684 struct callchain_node *chain; 685 struct callchain_node *chain;
685 size_t ret = 0; 686 size_t ret = 0;
686 u32 entries_printed = 0; 687 u32 entries_printed = 0;
687 688
688 rb_node = rb_first(&self->sorted_chain); 689 rb_node = rb_first(&he->sorted_chain);
689 while (rb_node) { 690 while (rb_node) {
690 double percent; 691 double percent;
691 692
@@ -730,35 +731,35 @@ void hists__output_recalc_col_len(struct hists *hists, int max_rows)
730 } 731 }
731} 732}
732 733
733static int hist_entry__pcnt_snprintf(struct hist_entry *self, char *s, 734static int hist_entry__pcnt_snprintf(struct hist_entry *he, char *s,
734 size_t size, struct hists *pair_hists, 735 size_t size, struct hists *pair_hists,
735 bool show_displacement, long displacement, 736 bool show_displacement, long displacement,
736 bool color, u64 session_total) 737 bool color, u64 total_period)
737{ 738{
738 u64 period, total, period_sys, period_us, period_guest_sys, period_guest_us; 739 u64 period, total, period_sys, period_us, period_guest_sys, period_guest_us;
739 u64 nr_events; 740 u64 nr_events;
740 const char *sep = symbol_conf.field_sep; 741 const char *sep = symbol_conf.field_sep;
741 int ret; 742 int ret;
742 743
743 if (symbol_conf.exclude_other && !self->parent) 744 if (symbol_conf.exclude_other && !he->parent)
744 return 0; 745 return 0;
745 746
746 if (pair_hists) { 747 if (pair_hists) {
747 period = self->pair ? self->pair->period : 0; 748 period = he->pair ? he->pair->period : 0;
748 nr_events = self->pair ? self->pair->nr_events : 0; 749 nr_events = he->pair ? he->pair->nr_events : 0;
749 total = pair_hists->stats.total_period; 750 total = pair_hists->stats.total_period;
750 period_sys = self->pair ? self->pair->period_sys : 0; 751 period_sys = he->pair ? he->pair->period_sys : 0;
751 period_us = self->pair ? self->pair->period_us : 0; 752 period_us = he->pair ? he->pair->period_us : 0;
752 period_guest_sys = self->pair ? self->pair->period_guest_sys : 0; 753 period_guest_sys = he->pair ? he->pair->period_guest_sys : 0;
753 period_guest_us = self->pair ? self->pair->period_guest_us : 0; 754 period_guest_us = he->pair ? he->pair->period_guest_us : 0;
754 } else { 755 } else {
755 period = self->period; 756 period = he->period;
756 nr_events = self->nr_events; 757 nr_events = he->nr_events;
757 total = session_total; 758 total = total_period;
758 period_sys = self->period_sys; 759 period_sys = he->period_sys;
759 period_us = self->period_us; 760 period_us = he->period_us;
760 period_guest_sys = self->period_guest_sys; 761 period_guest_sys = he->period_guest_sys;
761 period_guest_us = self->period_guest_us; 762 period_guest_us = he->period_guest_us;
762 } 763 }
763 764
764 if (total) { 765 if (total) {
@@ -812,8 +813,8 @@ static int hist_entry__pcnt_snprintf(struct hist_entry *self, char *s,
812 813
813 if (total > 0) 814 if (total > 0)
814 old_percent = (period * 100.0) / total; 815 old_percent = (period * 100.0) / total;
815 if (session_total > 0) 816 if (total_period > 0)
816 new_percent = (self->period * 100.0) / session_total; 817 new_percent = (he->period * 100.0) / total_period;
817 818
818 diff = new_percent - old_percent; 819 diff = new_percent - old_percent;
819 820
@@ -862,9 +863,10 @@ int hist_entry__snprintf(struct hist_entry *he, char *s, size_t size,
862 return ret; 863 return ret;
863} 864}
864 865
865int hist_entry__fprintf(struct hist_entry *he, size_t size, struct hists *hists, 866static int hist_entry__fprintf(struct hist_entry *he, size_t size,
866 struct hists *pair_hists, bool show_displacement, 867 struct hists *hists, struct hists *pair_hists,
867 long displacement, FILE *fp, u64 session_total) 868 bool show_displacement, long displacement,
869 u64 total_period, FILE *fp)
868{ 870{
869 char bf[512]; 871 char bf[512];
870 int ret; 872 int ret;
@@ -874,14 +876,14 @@ int hist_entry__fprintf(struct hist_entry *he, size_t size, struct hists *hists,
874 876
875 ret = hist_entry__pcnt_snprintf(he, bf, size, pair_hists, 877 ret = hist_entry__pcnt_snprintf(he, bf, size, pair_hists,
876 show_displacement, displacement, 878 show_displacement, displacement,
877 true, session_total); 879 true, total_period);
878 hist_entry__snprintf(he, bf + ret, size - ret, hists); 880 hist_entry__snprintf(he, bf + ret, size - ret, hists);
879 return fprintf(fp, "%s\n", bf); 881 return fprintf(fp, "%s\n", bf);
880} 882}
881 883
882static size_t hist_entry__fprintf_callchain(struct hist_entry *self, 884static size_t hist_entry__fprintf_callchain(struct hist_entry *he,
883 struct hists *hists, FILE *fp, 885 struct hists *hists,
884 u64 session_total) 886 u64 total_period, FILE *fp)
885{ 887{
886 int left_margin = 0; 888 int left_margin = 0;
887 889
@@ -889,11 +891,10 @@ static size_t hist_entry__fprintf_callchain(struct hist_entry *self,
889 struct sort_entry *se = list_first_entry(&hist_entry__sort_list, 891 struct sort_entry *se = list_first_entry(&hist_entry__sort_list,
890 typeof(*se), list); 892 typeof(*se), list);
891 left_margin = hists__col_len(hists, se->se_width_idx); 893 left_margin = hists__col_len(hists, se->se_width_idx);
892 left_margin -= thread__comm_len(self->thread); 894 left_margin -= thread__comm_len(he->thread);
893 } 895 }
894 896
895 return hist_entry_callchain__fprintf(fp, self, session_total, 897 return hist_entry_callchain__fprintf(he, total_period, left_margin, fp);
896 left_margin);
897} 898}
898 899
899size_t hists__fprintf(struct hists *hists, struct hists *pair, 900size_t hists__fprintf(struct hists *hists, struct hists *pair,
@@ -903,6 +904,7 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
903 struct sort_entry *se; 904 struct sort_entry *se;
904 struct rb_node *nd; 905 struct rb_node *nd;
905 size_t ret = 0; 906 size_t ret = 0;
907 u64 total_period;
906 unsigned long position = 1; 908 unsigned long position = 1;
907 long displacement = 0; 909 long displacement = 0;
908 unsigned int width; 910 unsigned int width;
@@ -917,20 +919,6 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
917 919
918 fprintf(fp, "# %s", pair ? "Baseline" : "Overhead"); 920 fprintf(fp, "# %s", pair ? "Baseline" : "Overhead");
919 921
920 if (symbol_conf.show_nr_samples) {
921 if (sep)
922 fprintf(fp, "%cSamples", *sep);
923 else
924 fputs(" Samples ", fp);
925 }
926
927 if (symbol_conf.show_total_period) {
928 if (sep)
929 ret += fprintf(fp, "%cPeriod", *sep);
930 else
931 ret += fprintf(fp, " Period ");
932 }
933
934 if (symbol_conf.show_cpu_utilization) { 922 if (symbol_conf.show_cpu_utilization) {
935 if (sep) { 923 if (sep) {
936 ret += fprintf(fp, "%csys", *sep); 924 ret += fprintf(fp, "%csys", *sep);
@@ -940,8 +928,8 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
940 ret += fprintf(fp, "%cguest us", *sep); 928 ret += fprintf(fp, "%cguest us", *sep);
941 } 929 }
942 } else { 930 } else {
943 ret += fprintf(fp, " sys "); 931 ret += fprintf(fp, " sys ");
944 ret += fprintf(fp, " us "); 932 ret += fprintf(fp, " us ");
945 if (perf_guest) { 933 if (perf_guest) {
946 ret += fprintf(fp, " guest sys "); 934 ret += fprintf(fp, " guest sys ");
947 ret += fprintf(fp, " guest us "); 935 ret += fprintf(fp, " guest us ");
@@ -949,6 +937,20 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
949 } 937 }
950 } 938 }
951 939
940 if (symbol_conf.show_nr_samples) {
941 if (sep)
942 fprintf(fp, "%cSamples", *sep);
943 else
944 fputs(" Samples ", fp);
945 }
946
947 if (symbol_conf.show_total_period) {
948 if (sep)
949 ret += fprintf(fp, "%cPeriod", *sep);
950 else
951 ret += fprintf(fp, " Period ");
952 }
953
952 if (pair) { 954 if (pair) {
953 if (sep) 955 if (sep)
954 ret += fprintf(fp, "%cDelta", *sep); 956 ret += fprintf(fp, "%cDelta", *sep);
@@ -993,6 +995,8 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
993 goto print_entries; 995 goto print_entries;
994 996
995 fprintf(fp, "# ........"); 997 fprintf(fp, "# ........");
998 if (symbol_conf.show_cpu_utilization)
999 fprintf(fp, " ....... .......");
996 if (symbol_conf.show_nr_samples) 1000 if (symbol_conf.show_nr_samples)
997 fprintf(fp, " .........."); 1001 fprintf(fp, " ..........");
998 if (symbol_conf.show_total_period) 1002 if (symbol_conf.show_total_period)
@@ -1025,6 +1029,8 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
1025 goto out; 1029 goto out;
1026 1030
1027print_entries: 1031print_entries:
1032 total_period = hists->stats.total_period;
1033
1028 for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { 1034 for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
1029 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); 1035 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
1030 1036
@@ -1040,11 +1046,10 @@ print_entries:
1040 ++position; 1046 ++position;
1041 } 1047 }
1042 ret += hist_entry__fprintf(h, max_cols, hists, pair, show_displacement, 1048 ret += hist_entry__fprintf(h, max_cols, hists, pair, show_displacement,
1043 displacement, fp, hists->stats.total_period); 1049 displacement, total_period, fp);
1044 1050
1045 if (symbol_conf.use_callchain) 1051 if (symbol_conf.use_callchain)
1046 ret += hist_entry__fprintf_callchain(h, hists, fp, 1052 ret += hist_entry__fprintf_callchain(h, hists, total_period, fp);
1047 hists->stats.total_period);
1048 if (max_rows && ++nr_rows >= max_rows) 1053 if (max_rows && ++nr_rows >= max_rows)
1049 goto out; 1054 goto out;
1050 1055
@@ -1211,13 +1216,3 @@ size_t hists__fprintf_nr_events(struct hists *hists, FILE *fp)
1211 1216
1212 return ret; 1217 return ret;
1213} 1218}
1214
1215void hists__init(struct hists *hists)
1216{
1217 memset(hists, 0, sizeof(*hists));
1218 hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT;
1219 hists->entries_in = &hists->entries_in_array[0];
1220 hists->entries_collapsed = RB_ROOT;
1221 hists->entries = RB_ROOT;
1222 pthread_mutex_init(&hists->lock, NULL);
1223}
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index c86c1d27bd1e..f55f0a8d1f81 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -63,16 +63,11 @@ struct hists {
63 struct callchain_cursor callchain_cursor; 63 struct callchain_cursor callchain_cursor;
64}; 64};
65 65
66void hists__init(struct hists *hists);
67
68struct hist_entry *__hists__add_entry(struct hists *self, 66struct hist_entry *__hists__add_entry(struct hists *self,
69 struct addr_location *al, 67 struct addr_location *al,
70 struct symbol *parent, u64 period); 68 struct symbol *parent, u64 period);
71extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *); 69int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right);
72extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *); 70int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right);
73int hist_entry__fprintf(struct hist_entry *he, size_t size, struct hists *hists,
74 struct hists *pair_hists, bool show_displacement,
75 long displacement, FILE *fp, u64 session_total);
76int hist_entry__snprintf(struct hist_entry *self, char *bf, size_t size, 71int hist_entry__snprintf(struct hist_entry *self, char *bf, size_t size,
77 struct hists *hists); 72 struct hists *hists);
78void hist_entry__free(struct hist_entry *); 73void hist_entry__free(struct hist_entry *);
@@ -119,7 +114,6 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __used,
119 114
120static inline int hist_entry__tui_annotate(struct hist_entry *self __used, 115static inline int hist_entry__tui_annotate(struct hist_entry *self __used,
121 int evidx __used, 116 int evidx __used,
122 int nr_events __used,
123 void(*timer)(void *arg) __used, 117 void(*timer)(void *arg) __used,
124 void *arg __used, 118 void *arg __used,
125 int delay_secs __used) 119 int delay_secs __used)
@@ -130,7 +124,7 @@ static inline int hist_entry__tui_annotate(struct hist_entry *self __used,
130#define K_RIGHT -2 124#define K_RIGHT -2
131#else 125#else
132#include "ui/keysyms.h" 126#include "ui/keysyms.h"
133int hist_entry__tui_annotate(struct hist_entry *he, int evidx, int nr_events, 127int hist_entry__tui_annotate(struct hist_entry *he, int evidx,
134 void(*timer)(void *arg), void *arg, int delay_secs); 128 void(*timer)(void *arg), void *arg, int delay_secs);
135 129
136int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, 130int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
diff --git a/tools/perf/util/include/linux/bitops.h b/tools/perf/util/include/linux/bitops.h
index 305c8484f200..62cdee78db7b 100644
--- a/tools/perf/util/include/linux/bitops.h
+++ b/tools/perf/util/include/linux/bitops.h
@@ -9,6 +9,17 @@
9#define BITS_PER_BYTE 8 9#define BITS_PER_BYTE 8
10#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) 10#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
11 11
12#define for_each_set_bit(bit, addr, size) \
13 for ((bit) = find_first_bit((addr), (size)); \
14 (bit) < (size); \
15 (bit) = find_next_bit((addr), (size), (bit) + 1))
16
17/* same as for_each_set_bit() but use bit as value to start with */
18#define for_each_set_bit_cont(bit, addr, size) \
19 for ((bit) = find_next_bit((addr), (size), (bit)); \
20 (bit) < (size); \
21 (bit) = find_next_bit((addr), (size), (bit) + 1))
22
12static inline void set_bit(int nr, unsigned long *addr) 23static inline void set_bit(int nr, unsigned long *addr)
13{ 24{
14 addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG); 25 addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG);
@@ -30,4 +41,111 @@ static inline unsigned long hweight_long(unsigned long w)
30 return sizeof(w) == 4 ? hweight32(w) : hweight64(w); 41 return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
31} 42}
32 43
44#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
45
46/**
47 * __ffs - find first bit in word.
48 * @word: The word to search
49 *
50 * Undefined if no bit exists, so code should check against 0 first.
51 */
52static __always_inline unsigned long __ffs(unsigned long word)
53{
54 int num = 0;
55
56#if BITS_PER_LONG == 64
57 if ((word & 0xffffffff) == 0) {
58 num += 32;
59 word >>= 32;
60 }
61#endif
62 if ((word & 0xffff) == 0) {
63 num += 16;
64 word >>= 16;
65 }
66 if ((word & 0xff) == 0) {
67 num += 8;
68 word >>= 8;
69 }
70 if ((word & 0xf) == 0) {
71 num += 4;
72 word >>= 4;
73 }
74 if ((word & 0x3) == 0) {
75 num += 2;
76 word >>= 2;
77 }
78 if ((word & 0x1) == 0)
79 num += 1;
80 return num;
81}
82
83/*
84 * Find the first set bit in a memory region.
85 */
86static inline unsigned long
87find_first_bit(const unsigned long *addr, unsigned long size)
88{
89 const unsigned long *p = addr;
90 unsigned long result = 0;
91 unsigned long tmp;
92
93 while (size & ~(BITS_PER_LONG-1)) {
94 if ((tmp = *(p++)))
95 goto found;
96 result += BITS_PER_LONG;
97 size -= BITS_PER_LONG;
98 }
99 if (!size)
100 return result;
101
102 tmp = (*p) & (~0UL >> (BITS_PER_LONG - size));
103 if (tmp == 0UL) /* Are any bits set? */
104 return result + size; /* Nope. */
105found:
106 return result + __ffs(tmp);
107}
108
109/*
110 * Find the next set bit in a memory region.
111 */
112static inline unsigned long
113find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset)
114{
115 const unsigned long *p = addr + BITOP_WORD(offset);
116 unsigned long result = offset & ~(BITS_PER_LONG-1);
117 unsigned long tmp;
118
119 if (offset >= size)
120 return size;
121 size -= result;
122 offset %= BITS_PER_LONG;
123 if (offset) {
124 tmp = *(p++);
125 tmp &= (~0UL << offset);
126 if (size < BITS_PER_LONG)
127 goto found_first;
128 if (tmp)
129 goto found_middle;
130 size -= BITS_PER_LONG;
131 result += BITS_PER_LONG;
132 }
133 while (size & ~(BITS_PER_LONG-1)) {
134 if ((tmp = *(p++)))
135 goto found_middle;
136 result += BITS_PER_LONG;
137 size -= BITS_PER_LONG;
138 }
139 if (!size)
140 return result;
141 tmp = *p;
142
143found_first:
144 tmp &= (~0UL >> (BITS_PER_LONG - size));
145 if (tmp == 0UL) /* Are any bits set? */
146 return result + size; /* Nope. */
147found_middle:
148 return result + __ffs(tmp);
149}
150
33#endif 151#endif
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 78284b13e808..316aa0ab7122 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -562,6 +562,10 @@ int machine__init(struct machine *self, const char *root_dir, pid_t pid)
562 INIT_LIST_HEAD(&self->user_dsos); 562 INIT_LIST_HEAD(&self->user_dsos);
563 INIT_LIST_HEAD(&self->kernel_dsos); 563 INIT_LIST_HEAD(&self->kernel_dsos);
564 564
565 self->threads = RB_ROOT;
566 INIT_LIST_HEAD(&self->dead_threads);
567 self->last_match = NULL;
568
565 self->kmaps.machine = self; 569 self->kmaps.machine = self;
566 self->pid = pid; 570 self->pid = pid;
567 self->root_dir = strdup(root_dir); 571 self->root_dir = strdup(root_dir);
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 890d85545d0f..2b8017f8a930 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -18,9 +18,11 @@ enum map_type {
18extern const char *map_type__name[MAP__NR_TYPES]; 18extern const char *map_type__name[MAP__NR_TYPES];
19 19
20struct dso; 20struct dso;
21struct ip_callchain;
21struct ref_reloc_sym; 22struct ref_reloc_sym;
22struct map_groups; 23struct map_groups;
23struct machine; 24struct machine;
25struct perf_evsel;
24 26
25struct map { 27struct map {
26 union { 28 union {
@@ -61,7 +63,11 @@ struct map_groups {
61struct machine { 63struct machine {
62 struct rb_node rb_node; 64 struct rb_node rb_node;
63 pid_t pid; 65 pid_t pid;
66 u16 id_hdr_size;
64 char *root_dir; 67 char *root_dir;
68 struct rb_root threads;
69 struct list_head dead_threads;
70 struct thread *last_match;
65 struct list_head user_dsos; 71 struct list_head user_dsos;
66 struct list_head kernel_dsos; 72 struct list_head kernel_dsos;
67 struct map_groups kmaps; 73 struct map_groups kmaps;
@@ -148,6 +154,13 @@ int machine__init(struct machine *self, const char *root_dir, pid_t pid);
148void machine__exit(struct machine *self); 154void machine__exit(struct machine *self);
149void machine__delete(struct machine *self); 155void machine__delete(struct machine *self);
150 156
157int machine__resolve_callchain(struct machine *machine,
158 struct perf_evsel *evsel, struct thread *thread,
159 struct ip_callchain *chain,
160 struct symbol **parent);
161int maps__set_kallsyms_ref_reloc_sym(struct map **maps, const char *symbol_name,
162 u64 addr);
163
151/* 164/*
152 * Default guest kernel is defined by parameter --guestkallsyms 165 * Default guest kernel is defined by parameter --guestkallsyms
153 * and --guestmodules 166 * and --guestmodules
@@ -190,6 +203,12 @@ struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg,
190 struct map **mapp, 203 struct map **mapp,
191 symbol_filter_t filter); 204 symbol_filter_t filter);
192 205
206
207struct thread *machine__findnew_thread(struct machine *machine, pid_t pid);
208void machine__remove_thread(struct machine *machine, struct thread *th);
209
210size_t machine__fprintf(struct machine *machine, FILE *fp);
211
193static inline 212static inline
194struct symbol *machine__find_kernel_symbol(struct machine *self, 213struct symbol *machine__find_kernel_symbol(struct machine *self,
195 enum map_type type, u64 addr, 214 enum map_type type, u64 addr,
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 928918b796b2..b029296d20d9 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -25,8 +25,6 @@ enum event_result {
25 EVT_HANDLED_ALL 25 EVT_HANDLED_ALL
26}; 26};
27 27
28char debugfs_path[MAXPATHLEN];
29
30#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x 28#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
31#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x 29#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
32 30
@@ -40,6 +38,7 @@ static struct event_symbol event_symbols[] = {
40 { CHW(BRANCH_INSTRUCTIONS), "branch-instructions", "branches" }, 38 { CHW(BRANCH_INSTRUCTIONS), "branch-instructions", "branches" },
41 { CHW(BRANCH_MISSES), "branch-misses", "" }, 39 { CHW(BRANCH_MISSES), "branch-misses", "" },
42 { CHW(BUS_CYCLES), "bus-cycles", "" }, 40 { CHW(BUS_CYCLES), "bus-cycles", "" },
41 { CHW(REF_CPU_CYCLES), "ref-cycles", "" },
43 42
44 { CSW(CPU_CLOCK), "cpu-clock", "" }, 43 { CSW(CPU_CLOCK), "cpu-clock", "" },
45 { CSW(TASK_CLOCK), "task-clock", "" }, 44 { CSW(TASK_CLOCK), "task-clock", "" },
@@ -70,6 +69,7 @@ static const char *hw_event_names[PERF_COUNT_HW_MAX] = {
70 "bus-cycles", 69 "bus-cycles",
71 "stalled-cycles-frontend", 70 "stalled-cycles-frontend",
72 "stalled-cycles-backend", 71 "stalled-cycles-backend",
72 "ref-cycles",
73}; 73};
74 74
75static const char *sw_event_names[PERF_COUNT_SW_MAX] = { 75static const char *sw_event_names[PERF_COUNT_SW_MAX] = {
@@ -140,7 +140,7 @@ static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir)
140 char evt_path[MAXPATHLEN]; 140 char evt_path[MAXPATHLEN];
141 int fd; 141 int fd;
142 142
143 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path, 143 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", tracing_events_path,
144 sys_dir->d_name, evt_dir->d_name); 144 sys_dir->d_name, evt_dir->d_name);
145 fd = open(evt_path, O_RDONLY); 145 fd = open(evt_path, O_RDONLY);
146 if (fd < 0) 146 if (fd < 0)
@@ -171,16 +171,16 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
171 char evt_path[MAXPATHLEN]; 171 char evt_path[MAXPATHLEN];
172 char dir_path[MAXPATHLEN]; 172 char dir_path[MAXPATHLEN];
173 173
174 if (debugfs_valid_mountpoint(debugfs_path)) 174 if (debugfs_valid_mountpoint(tracing_events_path))
175 return NULL; 175 return NULL;
176 176
177 sys_dir = opendir(debugfs_path); 177 sys_dir = opendir(tracing_events_path);
178 if (!sys_dir) 178 if (!sys_dir)
179 return NULL; 179 return NULL;
180 180
181 for_each_subsystem(sys_dir, sys_dirent, sys_next) { 181 for_each_subsystem(sys_dir, sys_dirent, sys_next) {
182 182
183 snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path, 183 snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
184 sys_dirent.d_name); 184 sys_dirent.d_name);
185 evt_dir = opendir(dir_path); 185 evt_dir = opendir(dir_path);
186 if (!evt_dir) 186 if (!evt_dir)
@@ -447,7 +447,7 @@ parse_single_tracepoint_event(char *sys_name,
447 u64 id; 447 u64 id;
448 int fd; 448 int fd;
449 449
450 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path, 450 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", tracing_events_path,
451 sys_name, evt_name); 451 sys_name, evt_name);
452 452
453 fd = open(evt_path, O_RDONLY); 453 fd = open(evt_path, O_RDONLY);
@@ -485,7 +485,7 @@ parse_multiple_tracepoint_event(struct perf_evlist *evlist, char *sys_name,
485 struct dirent *evt_ent; 485 struct dirent *evt_ent;
486 DIR *evt_dir; 486 DIR *evt_dir;
487 487
488 snprintf(evt_path, MAXPATHLEN, "%s/%s", debugfs_path, sys_name); 488 snprintf(evt_path, MAXPATHLEN, "%s/%s", tracing_events_path, sys_name);
489 evt_dir = opendir(evt_path); 489 evt_dir = opendir(evt_path);
490 490
491 if (!evt_dir) { 491 if (!evt_dir) {
@@ -528,7 +528,7 @@ parse_tracepoint_event(struct perf_evlist *evlist, const char **strp,
528 char sys_name[MAX_EVENT_LENGTH]; 528 char sys_name[MAX_EVENT_LENGTH];
529 unsigned int sys_length, evt_length; 529 unsigned int sys_length, evt_length;
530 530
531 if (debugfs_valid_mountpoint(debugfs_path)) 531 if (debugfs_valid_mountpoint(tracing_events_path))
532 return 0; 532 return 0;
533 533
534 evt_name = strchr(*strp, ':'); 534 evt_name = strchr(*strp, ':');
@@ -735,8 +735,8 @@ static int
735parse_event_modifier(const char **strp, struct perf_event_attr *attr) 735parse_event_modifier(const char **strp, struct perf_event_attr *attr)
736{ 736{
737 const char *str = *strp; 737 const char *str = *strp;
738 int exclude = 0; 738 int exclude = 0, exclude_GH = 0;
739 int eu = 0, ek = 0, eh = 0, precise = 0; 739 int eu = 0, ek = 0, eh = 0, eH = 0, eG = 0, precise = 0;
740 740
741 if (!*str) 741 if (!*str)
742 return 0; 742 return 0;
@@ -760,6 +760,14 @@ parse_event_modifier(const char **strp, struct perf_event_attr *attr)
760 if (!exclude) 760 if (!exclude)
761 exclude = eu = ek = eh = 1; 761 exclude = eu = ek = eh = 1;
762 eh = 0; 762 eh = 0;
763 } else if (*str == 'G') {
764 if (!exclude_GH)
765 exclude_GH = eG = eH = 1;
766 eG = 0;
767 } else if (*str == 'H') {
768 if (!exclude_GH)
769 exclude_GH = eG = eH = 1;
770 eH = 0;
763 } else if (*str == 'p') { 771 } else if (*str == 'p') {
764 precise++; 772 precise++;
765 } else 773 } else
@@ -776,6 +784,8 @@ parse_event_modifier(const char **strp, struct perf_event_attr *attr)
776 attr->exclude_kernel = ek; 784 attr->exclude_kernel = ek;
777 attr->exclude_hv = eh; 785 attr->exclude_hv = eh;
778 attr->precise_ip = precise; 786 attr->precise_ip = precise;
787 attr->exclude_host = eH;
788 attr->exclude_guest = eG;
779 789
780 return 0; 790 return 0;
781} 791}
@@ -838,6 +848,7 @@ int parse_events(struct perf_evlist *evlist , const char *str, int unset __used)
838 for (;;) { 848 for (;;) {
839 ostr = str; 849 ostr = str;
840 memset(&attr, 0, sizeof(attr)); 850 memset(&attr, 0, sizeof(attr));
851 event_attr_init(&attr);
841 ret = parse_event_symbols(evlist, &str, &attr); 852 ret = parse_event_symbols(evlist, &str, &attr);
842 if (ret == EVT_FAILED) 853 if (ret == EVT_FAILED)
843 return -1; 854 return -1;
@@ -920,10 +931,10 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob)
920 char evt_path[MAXPATHLEN]; 931 char evt_path[MAXPATHLEN];
921 char dir_path[MAXPATHLEN]; 932 char dir_path[MAXPATHLEN];
922 933
923 if (debugfs_valid_mountpoint(debugfs_path)) 934 if (debugfs_valid_mountpoint(tracing_events_path))
924 return; 935 return;
925 936
926 sys_dir = opendir(debugfs_path); 937 sys_dir = opendir(tracing_events_path);
927 if (!sys_dir) 938 if (!sys_dir)
928 return; 939 return;
929 940
@@ -932,7 +943,7 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob)
932 !strglobmatch(sys_dirent.d_name, subsys_glob)) 943 !strglobmatch(sys_dirent.d_name, subsys_glob))
933 continue; 944 continue;
934 945
935 snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path, 946 snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
936 sys_dirent.d_name); 947 sys_dirent.d_name);
937 evt_dir = opendir(dir_path); 948 evt_dir = opendir(dir_path);
938 if (!evt_dir) 949 if (!evt_dir)
@@ -964,16 +975,16 @@ int is_valid_tracepoint(const char *event_string)
964 char evt_path[MAXPATHLEN]; 975 char evt_path[MAXPATHLEN];
965 char dir_path[MAXPATHLEN]; 976 char dir_path[MAXPATHLEN];
966 977
967 if (debugfs_valid_mountpoint(debugfs_path)) 978 if (debugfs_valid_mountpoint(tracing_events_path))
968 return 0; 979 return 0;
969 980
970 sys_dir = opendir(debugfs_path); 981 sys_dir = opendir(tracing_events_path);
971 if (!sys_dir) 982 if (!sys_dir)
972 return 0; 983 return 0;
973 984
974 for_each_subsystem(sys_dir, sys_dirent, sys_next) { 985 for_each_subsystem(sys_dir, sys_dirent, sys_next) {
975 986
976 snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path, 987 snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
977 sys_dirent.d_name); 988 sys_dirent.d_name);
978 evt_dir = opendir(dir_path); 989 evt_dir = opendir(dir_path);
979 if (!evt_dir) 990 if (!evt_dir)
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 2f8e375e038d..7e0cbe75d5f1 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -39,7 +39,6 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob);
39int print_hwcache_events(const char *event_glob); 39int print_hwcache_events(const char *event_glob);
40extern int is_valid_tracepoint(const char *event_string); 40extern int is_valid_tracepoint(const char *event_string);
41 41
42extern char debugfs_path[];
43extern int valid_debugfs_mount(const char *debugfs); 42extern int valid_debugfs_mount(const char *debugfs);
44 43
45#endif /* __PERF_PARSE_EVENTS_H */ 44#endif /* __PERF_PARSE_EVENTS_H */
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index 1132c8f0ce89..17e94d0c36f9 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -5,7 +5,6 @@
5#include "util.h" 5#include "util.h"
6#include "probe-event.h" 6#include "probe-event.h"
7 7
8#define MAX_PATH_LEN 256
9#define MAX_PROBE_BUFFER 1024 8#define MAX_PROBE_BUFFER 1024
10#define MAX_PROBES 128 9#define MAX_PROBES 128
11 10
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index 74350ffb57fe..e30749e38a9b 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -27,7 +27,10 @@
27 27
28#include "../../perf.h" 28#include "../../perf.h"
29#include "../util.h" 29#include "../util.h"
30#include "../thread.h"
31#include "../event.h"
30#include "../trace-event.h" 32#include "../trace-event.h"
33#include "../evsel.h"
31 34
32#include <EXTERN.h> 35#include <EXTERN.h>
33#include <perl.h> 36#include <perl.h>
@@ -245,11 +248,11 @@ static inline struct event *find_cache_event(int type)
245 return event; 248 return event;
246} 249}
247 250
248static void perl_process_event(union perf_event *pevent __unused, 251static void perl_process_tracepoint(union perf_event *pevent __unused,
249 struct perf_sample *sample, 252 struct perf_sample *sample,
250 struct perf_evsel *evsel, 253 struct perf_evsel *evsel,
251 struct perf_session *session __unused, 254 struct machine *machine __unused,
252 struct thread *thread) 255 struct thread *thread)
253{ 256{
254 struct format_field *field; 257 struct format_field *field;
255 static char handler[256]; 258 static char handler[256];
@@ -265,6 +268,9 @@ static void perl_process_event(union perf_event *pevent __unused,
265 268
266 dSP; 269 dSP;
267 270
271 if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
272 return;
273
268 type = trace_parse_common_type(data); 274 type = trace_parse_common_type(data);
269 275
270 event = find_cache_event(type); 276 event = find_cache_event(type);
@@ -332,6 +338,42 @@ static void perl_process_event(union perf_event *pevent __unused,
332 LEAVE; 338 LEAVE;
333} 339}
334 340
341static void perl_process_event_generic(union perf_event *pevent __unused,
342 struct perf_sample *sample,
343 struct perf_evsel *evsel __unused,
344 struct machine *machine __unused,
345 struct thread *thread __unused)
346{
347 dSP;
348
349 if (!get_cv("process_event", 0))
350 return;
351
352 ENTER;
353 SAVETMPS;
354 PUSHMARK(SP);
355 XPUSHs(sv_2mortal(newSVpvn((const char *)pevent, pevent->header.size)));
356 XPUSHs(sv_2mortal(newSVpvn((const char *)&evsel->attr, sizeof(evsel->attr))));
357 XPUSHs(sv_2mortal(newSVpvn((const char *)sample, sizeof(*sample))));
358 XPUSHs(sv_2mortal(newSVpvn((const char *)sample->raw_data, sample->raw_size)));
359 PUTBACK;
360 call_pv("process_event", G_SCALAR);
361 SPAGAIN;
362 PUTBACK;
363 FREETMPS;
364 LEAVE;
365}
366
367static void perl_process_event(union perf_event *pevent,
368 struct perf_sample *sample,
369 struct perf_evsel *evsel,
370 struct machine *machine,
371 struct thread *thread)
372{
373 perl_process_tracepoint(pevent, sample, evsel, machine, thread);
374 perl_process_event_generic(pevent, sample, evsel, machine, thread);
375}
376
335static void run_start_sub(void) 377static void run_start_sub(void)
336{ 378{
337 dSP; /* access to Perl stack */ 379 dSP; /* access to Perl stack */
@@ -553,7 +595,28 @@ static int perl_generate_script(const char *outfile)
553 fprintf(ofp, "sub print_header\n{\n" 595 fprintf(ofp, "sub print_header\n{\n"
554 "\tmy ($event_name, $cpu, $secs, $nsecs, $pid, $comm) = @_;\n\n" 596 "\tmy ($event_name, $cpu, $secs, $nsecs, $pid, $comm) = @_;\n\n"
555 "\tprintf(\"%%-20s %%5u %%05u.%%09u %%8u %%-20s \",\n\t " 597 "\tprintf(\"%%-20s %%5u %%05u.%%09u %%8u %%-20s \",\n\t "
556 "$event_name, $cpu, $secs, $nsecs, $pid, $comm);\n}"); 598 "$event_name, $cpu, $secs, $nsecs, $pid, $comm);\n}\n");
599
600 fprintf(ofp,
601 "\n# Packed byte string args of process_event():\n"
602 "#\n"
603 "# $event:\tunion perf_event\tutil/event.h\n"
604 "# $attr:\tstruct perf_event_attr\tlinux/perf_event.h\n"
605 "# $sample:\tstruct perf_sample\tutil/event.h\n"
606 "# $raw_data:\tperf_sample->raw_data\tutil/event.h\n"
607 "\n"
608 "sub process_event\n"
609 "{\n"
610 "\tmy ($event, $attr, $sample, $raw_data) = @_;\n"
611 "\n"
612 "\tmy @event\t= unpack(\"LSS\", $event);\n"
613 "\tmy @attr\t= unpack(\"LLQQQQQLLQQ\", $attr);\n"
614 "\tmy @sample\t= unpack(\"QLLQQQQQLL\", $sample);\n"
615 "\tmy @raw_data\t= unpack(\"C*\", $raw_data);\n"
616 "\n"
617 "\tuse Data::Dumper;\n"
618 "\tprint Dumper \\@event, \\@attr, \\@sample, \\@raw_data;\n"
619 "}\n");
557 620
558 fclose(ofp); 621 fclose(ofp);
559 622
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 6ccf70e8d8f2..0b2a48783172 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -29,6 +29,8 @@
29 29
30#include "../../perf.h" 30#include "../../perf.h"
31#include "../util.h" 31#include "../util.h"
32#include "../event.h"
33#include "../thread.h"
32#include "../trace-event.h" 34#include "../trace-event.h"
33 35
34PyMODINIT_FUNC initperf_trace_context(void); 36PyMODINIT_FUNC initperf_trace_context(void);
@@ -207,7 +209,7 @@ static inline struct event *find_cache_event(int type)
207static void python_process_event(union perf_event *pevent __unused, 209static void python_process_event(union perf_event *pevent __unused,
208 struct perf_sample *sample, 210 struct perf_sample *sample,
209 struct perf_evsel *evsel __unused, 211 struct perf_evsel *evsel __unused,
210 struct perf_session *session __unused, 212 struct machine *machine __unused,
211 struct thread *thread) 213 struct thread *thread)
212{ 214{
213 PyObject *handler, *retval, *context, *t, *obj, *dict = NULL; 215 PyObject *handler, *retval, *context, *t, *obj, *dict = NULL;
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 85c1e6b76f0a..b5ca2558c7bb 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -10,6 +10,7 @@
10#include "evlist.h" 10#include "evlist.h"
11#include "evsel.h" 11#include "evsel.h"
12#include "session.h" 12#include "session.h"
13#include "tool.h"
13#include "sort.h" 14#include "sort.h"
14#include "util.h" 15#include "util.h"
15#include "cpumap.h" 16#include "cpumap.h"
@@ -78,39 +79,13 @@ out_close:
78 return -1; 79 return -1;
79} 80}
80 81
81static void perf_session__id_header_size(struct perf_session *session)
82{
83 struct perf_sample *data;
84 u64 sample_type = session->sample_type;
85 u16 size = 0;
86
87 if (!session->sample_id_all)
88 goto out;
89
90 if (sample_type & PERF_SAMPLE_TID)
91 size += sizeof(data->tid) * 2;
92
93 if (sample_type & PERF_SAMPLE_TIME)
94 size += sizeof(data->time);
95
96 if (sample_type & PERF_SAMPLE_ID)
97 size += sizeof(data->id);
98
99 if (sample_type & PERF_SAMPLE_STREAM_ID)
100 size += sizeof(data->stream_id);
101
102 if (sample_type & PERF_SAMPLE_CPU)
103 size += sizeof(data->cpu) * 2;
104out:
105 session->id_hdr_size = size;
106}
107
108void perf_session__update_sample_type(struct perf_session *self) 82void perf_session__update_sample_type(struct perf_session *self)
109{ 83{
110 self->sample_type = perf_evlist__sample_type(self->evlist); 84 self->sample_type = perf_evlist__sample_type(self->evlist);
111 self->sample_size = __perf_evsel__sample_size(self->sample_type); 85 self->sample_size = __perf_evsel__sample_size(self->sample_type);
112 self->sample_id_all = perf_evlist__sample_id_all(self->evlist); 86 self->sample_id_all = perf_evlist__sample_id_all(self->evlist);
113 perf_session__id_header_size(self); 87 self->id_hdr_size = perf_evlist__id_hdr_size(self->evlist);
88 self->host_machine.id_hdr_size = self->id_hdr_size;
114} 89}
115 90
116int perf_session__create_kernel_maps(struct perf_session *self) 91int perf_session__create_kernel_maps(struct perf_session *self)
@@ -130,18 +105,26 @@ static void perf_session__destroy_kernel_maps(struct perf_session *self)
130 105
131struct perf_session *perf_session__new(const char *filename, int mode, 106struct perf_session *perf_session__new(const char *filename, int mode,
132 bool force, bool repipe, 107 bool force, bool repipe,
133 struct perf_event_ops *ops) 108 struct perf_tool *tool)
134{ 109{
135 size_t len = filename ? strlen(filename) + 1 : 0; 110 struct perf_session *self;
136 struct perf_session *self = zalloc(sizeof(*self) + len); 111 struct stat st;
112 size_t len;
113
114 if (!filename || !strlen(filename)) {
115 if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
116 filename = "-";
117 else
118 filename = "perf.data";
119 }
120
121 len = strlen(filename);
122 self = zalloc(sizeof(*self) + len);
137 123
138 if (self == NULL) 124 if (self == NULL)
139 goto out; 125 goto out;
140 126
141 memcpy(self->filename, filename, len); 127 memcpy(self->filename, filename, len);
142 self->threads = RB_ROOT;
143 INIT_LIST_HEAD(&self->dead_threads);
144 self->last_match = NULL;
145 /* 128 /*
146 * On 64bit we can mmap the data file in one go. No need for tiny mmap 129 * On 64bit we can mmap the data file in one go. No need for tiny mmap
147 * slices. On 32bit we use 32MB. 130 * slices. On 32bit we use 32MB.
@@ -171,10 +154,10 @@ struct perf_session *perf_session__new(const char *filename, int mode,
171 goto out_delete; 154 goto out_delete;
172 } 155 }
173 156
174 if (ops && ops->ordering_requires_timestamps && 157 if (tool && tool->ordering_requires_timestamps &&
175 ops->ordered_samples && !self->sample_id_all) { 158 tool->ordered_samples && !self->sample_id_all) {
176 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); 159 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
177 ops->ordered_samples = false; 160 tool->ordered_samples = false;
178 } 161 }
179 162
180out: 163out:
@@ -184,17 +167,22 @@ out_delete:
184 return NULL; 167 return NULL;
185} 168}
186 169
187static void perf_session__delete_dead_threads(struct perf_session *self) 170static void machine__delete_dead_threads(struct machine *machine)
188{ 171{
189 struct thread *n, *t; 172 struct thread *n, *t;
190 173
191 list_for_each_entry_safe(t, n, &self->dead_threads, node) { 174 list_for_each_entry_safe(t, n, &machine->dead_threads, node) {
192 list_del(&t->node); 175 list_del(&t->node);
193 thread__delete(t); 176 thread__delete(t);
194 } 177 }
195} 178}
196 179
197static void perf_session__delete_threads(struct perf_session *self) 180static void perf_session__delete_dead_threads(struct perf_session *session)
181{
182 machine__delete_dead_threads(&session->host_machine);
183}
184
185static void machine__delete_threads(struct machine *self)
198{ 186{
199 struct rb_node *nd = rb_first(&self->threads); 187 struct rb_node *nd = rb_first(&self->threads);
200 188
@@ -207,6 +195,11 @@ static void perf_session__delete_threads(struct perf_session *self)
207 } 195 }
208} 196}
209 197
198static void perf_session__delete_threads(struct perf_session *session)
199{
200 machine__delete_threads(&session->host_machine);
201}
202
210void perf_session__delete(struct perf_session *self) 203void perf_session__delete(struct perf_session *self)
211{ 204{
212 perf_session__destroy_kernel_maps(self); 205 perf_session__destroy_kernel_maps(self);
@@ -217,7 +210,7 @@ void perf_session__delete(struct perf_session *self)
217 free(self); 210 free(self);
218} 211}
219 212
220void perf_session__remove_thread(struct perf_session *self, struct thread *th) 213void machine__remove_thread(struct machine *self, struct thread *th)
221{ 214{
222 self->last_match = NULL; 215 self->last_match = NULL;
223 rb_erase(&th->rb_node, &self->threads); 216 rb_erase(&th->rb_node, &self->threads);
@@ -236,16 +229,16 @@ static bool symbol__match_parent_regex(struct symbol *sym)
236 return 0; 229 return 0;
237} 230}
238 231
239int perf_session__resolve_callchain(struct perf_session *self, 232int machine__resolve_callchain(struct machine *self, struct perf_evsel *evsel,
240 struct thread *thread, 233 struct thread *thread,
241 struct ip_callchain *chain, 234 struct ip_callchain *chain,
242 struct symbol **parent) 235 struct symbol **parent)
243{ 236{
244 u8 cpumode = PERF_RECORD_MISC_USER; 237 u8 cpumode = PERF_RECORD_MISC_USER;
245 unsigned int i; 238 unsigned int i;
246 int err; 239 int err;
247 240
248 callchain_cursor_reset(&self->callchain_cursor); 241 callchain_cursor_reset(&evsel->hists.callchain_cursor);
249 242
250 for (i = 0; i < chain->nr; i++) { 243 for (i = 0; i < chain->nr; i++) {
251 u64 ip; 244 u64 ip;
@@ -272,7 +265,7 @@ int perf_session__resolve_callchain(struct perf_session *self,
272 265
273 al.filtered = false; 266 al.filtered = false;
274 thread__find_addr_location(thread, self, cpumode, 267 thread__find_addr_location(thread, self, cpumode,
275 MAP__FUNCTION, thread->pid, ip, &al, NULL); 268 MAP__FUNCTION, ip, &al, NULL);
276 if (al.sym != NULL) { 269 if (al.sym != NULL) {
277 if (sort__has_parent && !*parent && 270 if (sort__has_parent && !*parent &&
278 symbol__match_parent_regex(al.sym)) 271 symbol__match_parent_regex(al.sym))
@@ -281,7 +274,7 @@ int perf_session__resolve_callchain(struct perf_session *self,
281 break; 274 break;
282 } 275 }
283 276
284 err = callchain_cursor_append(&self->callchain_cursor, 277 err = callchain_cursor_append(&evsel->hists.callchain_cursor,
285 ip, al.map, al.sym); 278 ip, al.map, al.sym);
286 if (err) 279 if (err)
287 return err; 280 return err;
@@ -290,75 +283,91 @@ int perf_session__resolve_callchain(struct perf_session *self,
290 return 0; 283 return 0;
291} 284}
292 285
293static int process_event_synth_stub(union perf_event *event __used, 286static int process_event_synth_tracing_data_stub(union perf_event *event __used,
294 struct perf_session *session __used) 287 struct perf_session *session __used)
295{ 288{
296 dump_printf(": unhandled!\n"); 289 dump_printf(": unhandled!\n");
297 return 0; 290 return 0;
298} 291}
299 292
300static int process_event_sample_stub(union perf_event *event __used, 293static int process_event_synth_attr_stub(union perf_event *event __used,
294 struct perf_evlist **pevlist __used)
295{
296 dump_printf(": unhandled!\n");
297 return 0;
298}
299
300static int process_event_sample_stub(struct perf_tool *tool __used,
301 union perf_event *event __used,
301 struct perf_sample *sample __used, 302 struct perf_sample *sample __used,
302 struct perf_evsel *evsel __used, 303 struct perf_evsel *evsel __used,
303 struct perf_session *session __used) 304 struct machine *machine __used)
304{ 305{
305 dump_printf(": unhandled!\n"); 306 dump_printf(": unhandled!\n");
306 return 0; 307 return 0;
307} 308}
308 309
309static int process_event_stub(union perf_event *event __used, 310static int process_event_stub(struct perf_tool *tool __used,
311 union perf_event *event __used,
310 struct perf_sample *sample __used, 312 struct perf_sample *sample __used,
311 struct perf_session *session __used) 313 struct machine *machine __used)
314{
315 dump_printf(": unhandled!\n");
316 return 0;
317}
318
319static int process_finished_round_stub(struct perf_tool *tool __used,
320 union perf_event *event __used,
321 struct perf_session *perf_session __used)
312{ 322{
313 dump_printf(": unhandled!\n"); 323 dump_printf(": unhandled!\n");
314 return 0; 324 return 0;
315} 325}
316 326
317static int process_finished_round_stub(union perf_event *event __used, 327static int process_event_type_stub(struct perf_tool *tool __used,
318 struct perf_session *session __used, 328 union perf_event *event __used)
319 struct perf_event_ops *ops __used)
320{ 329{
321 dump_printf(": unhandled!\n"); 330 dump_printf(": unhandled!\n");
322 return 0; 331 return 0;
323} 332}
324 333
325static int process_finished_round(union perf_event *event, 334static int process_finished_round(struct perf_tool *tool,
326 struct perf_session *session, 335 union perf_event *event,
327 struct perf_event_ops *ops); 336 struct perf_session *session);
328 337
329static void perf_event_ops__fill_defaults(struct perf_event_ops *handler) 338static void perf_tool__fill_defaults(struct perf_tool *tool)
330{ 339{
331 if (handler->sample == NULL) 340 if (tool->sample == NULL)
332 handler->sample = process_event_sample_stub; 341 tool->sample = process_event_sample_stub;
333 if (handler->mmap == NULL) 342 if (tool->mmap == NULL)
334 handler->mmap = process_event_stub; 343 tool->mmap = process_event_stub;
335 if (handler->comm == NULL) 344 if (tool->comm == NULL)
336 handler->comm = process_event_stub; 345 tool->comm = process_event_stub;
337 if (handler->fork == NULL) 346 if (tool->fork == NULL)
338 handler->fork = process_event_stub; 347 tool->fork = process_event_stub;
339 if (handler->exit == NULL) 348 if (tool->exit == NULL)
340 handler->exit = process_event_stub; 349 tool->exit = process_event_stub;
341 if (handler->lost == NULL) 350 if (tool->lost == NULL)
342 handler->lost = perf_event__process_lost; 351 tool->lost = perf_event__process_lost;
343 if (handler->read == NULL) 352 if (tool->read == NULL)
344 handler->read = process_event_stub; 353 tool->read = process_event_sample_stub;
345 if (handler->throttle == NULL) 354 if (tool->throttle == NULL)
346 handler->throttle = process_event_stub; 355 tool->throttle = process_event_stub;
347 if (handler->unthrottle == NULL) 356 if (tool->unthrottle == NULL)
348 handler->unthrottle = process_event_stub; 357 tool->unthrottle = process_event_stub;
349 if (handler->attr == NULL) 358 if (tool->attr == NULL)
350 handler->attr = process_event_synth_stub; 359 tool->attr = process_event_synth_attr_stub;
351 if (handler->event_type == NULL) 360 if (tool->event_type == NULL)
352 handler->event_type = process_event_synth_stub; 361 tool->event_type = process_event_type_stub;
353 if (handler->tracing_data == NULL) 362 if (tool->tracing_data == NULL)
354 handler->tracing_data = process_event_synth_stub; 363 tool->tracing_data = process_event_synth_tracing_data_stub;
355 if (handler->build_id == NULL) 364 if (tool->build_id == NULL)
356 handler->build_id = process_event_synth_stub; 365 tool->build_id = process_finished_round_stub;
357 if (handler->finished_round == NULL) { 366 if (tool->finished_round == NULL) {
358 if (handler->ordered_samples) 367 if (tool->ordered_samples)
359 handler->finished_round = process_finished_round; 368 tool->finished_round = process_finished_round;
360 else 369 else
361 handler->finished_round = process_finished_round_stub; 370 tool->finished_round = process_finished_round_stub;
362 } 371 }
363} 372}
364 373
@@ -490,11 +499,11 @@ static void perf_session_free_sample_buffers(struct perf_session *session)
490static int perf_session_deliver_event(struct perf_session *session, 499static int perf_session_deliver_event(struct perf_session *session,
491 union perf_event *event, 500 union perf_event *event,
492 struct perf_sample *sample, 501 struct perf_sample *sample,
493 struct perf_event_ops *ops, 502 struct perf_tool *tool,
494 u64 file_offset); 503 u64 file_offset);
495 504
496static void flush_sample_queue(struct perf_session *s, 505static void flush_sample_queue(struct perf_session *s,
497 struct perf_event_ops *ops) 506 struct perf_tool *tool)
498{ 507{
499 struct ordered_samples *os = &s->ordered_samples; 508 struct ordered_samples *os = &s->ordered_samples;
500 struct list_head *head = &os->samples; 509 struct list_head *head = &os->samples;
@@ -505,7 +514,7 @@ static void flush_sample_queue(struct perf_session *s,
505 unsigned idx = 0, progress_next = os->nr_samples / 16; 514 unsigned idx = 0, progress_next = os->nr_samples / 16;
506 int ret; 515 int ret;
507 516
508 if (!ops->ordered_samples || !limit) 517 if (!tool->ordered_samples || !limit)
509 return; 518 return;
510 519
511 list_for_each_entry_safe(iter, tmp, head, list) { 520 list_for_each_entry_safe(iter, tmp, head, list) {
@@ -516,7 +525,7 @@ static void flush_sample_queue(struct perf_session *s,
516 if (ret) 525 if (ret)
517 pr_err("Can't parse sample, err = %d\n", ret); 526 pr_err("Can't parse sample, err = %d\n", ret);
518 else 527 else
519 perf_session_deliver_event(s, iter->event, &sample, ops, 528 perf_session_deliver_event(s, iter->event, &sample, tool,
520 iter->file_offset); 529 iter->file_offset);
521 530
522 os->last_flush = iter->timestamp; 531 os->last_flush = iter->timestamp;
@@ -578,11 +587,11 @@ static void flush_sample_queue(struct perf_session *s,
578 * Flush every events below timestamp 7 587 * Flush every events below timestamp 7
579 * etc... 588 * etc...
580 */ 589 */
581static int process_finished_round(union perf_event *event __used, 590static int process_finished_round(struct perf_tool *tool,
582 struct perf_session *session, 591 union perf_event *event __used,
583 struct perf_event_ops *ops) 592 struct perf_session *session)
584{ 593{
585 flush_sample_queue(session, ops); 594 flush_sample_queue(session, tool);
586 session->ordered_samples.next_flush = session->ordered_samples.max_timestamp; 595 session->ordered_samples.next_flush = session->ordered_samples.max_timestamp;
587 596
588 return 0; 597 return 0;
@@ -737,13 +746,26 @@ static void dump_sample(struct perf_session *session, union perf_event *event,
737 callchain__printf(sample); 746 callchain__printf(sample);
738} 747}
739 748
749static struct machine *
750 perf_session__find_machine_for_cpumode(struct perf_session *session,
751 union perf_event *event)
752{
753 const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
754
755 if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest)
756 return perf_session__find_machine(session, event->ip.pid);
757
758 return perf_session__find_host_machine(session);
759}
760
740static int perf_session_deliver_event(struct perf_session *session, 761static int perf_session_deliver_event(struct perf_session *session,
741 union perf_event *event, 762 union perf_event *event,
742 struct perf_sample *sample, 763 struct perf_sample *sample,
743 struct perf_event_ops *ops, 764 struct perf_tool *tool,
744 u64 file_offset) 765 u64 file_offset)
745{ 766{
746 struct perf_evsel *evsel; 767 struct perf_evsel *evsel;
768 struct machine *machine;
747 769
748 dump_event(session, event, file_offset, sample); 770 dump_event(session, event, file_offset, sample);
749 771
@@ -765,6 +787,8 @@ static int perf_session_deliver_event(struct perf_session *session,
765 hists__inc_nr_events(&evsel->hists, event->header.type); 787 hists__inc_nr_events(&evsel->hists, event->header.type);
766 } 788 }
767 789
790 machine = perf_session__find_machine_for_cpumode(session, event);
791
768 switch (event->header.type) { 792 switch (event->header.type) {
769 case PERF_RECORD_SAMPLE: 793 case PERF_RECORD_SAMPLE:
770 dump_sample(session, event, sample); 794 dump_sample(session, event, sample);
@@ -772,23 +796,25 @@ static int perf_session_deliver_event(struct perf_session *session,
772 ++session->hists.stats.nr_unknown_id; 796 ++session->hists.stats.nr_unknown_id;
773 return -1; 797 return -1;
774 } 798 }
775 return ops->sample(event, sample, evsel, session); 799 return tool->sample(tool, event, sample, evsel, machine);
776 case PERF_RECORD_MMAP: 800 case PERF_RECORD_MMAP:
777 return ops->mmap(event, sample, session); 801 return tool->mmap(tool, event, sample, machine);
778 case PERF_RECORD_COMM: 802 case PERF_RECORD_COMM:
779 return ops->comm(event, sample, session); 803 return tool->comm(tool, event, sample, machine);
780 case PERF_RECORD_FORK: 804 case PERF_RECORD_FORK:
781 return ops->fork(event, sample, session); 805 return tool->fork(tool, event, sample, machine);
782 case PERF_RECORD_EXIT: 806 case PERF_RECORD_EXIT:
783 return ops->exit(event, sample, session); 807 return tool->exit(tool, event, sample, machine);
784 case PERF_RECORD_LOST: 808 case PERF_RECORD_LOST:
785 return ops->lost(event, sample, session); 809 if (tool->lost == perf_event__process_lost)
810 session->hists.stats.total_lost += event->lost.lost;
811 return tool->lost(tool, event, sample, machine);
786 case PERF_RECORD_READ: 812 case PERF_RECORD_READ:
787 return ops->read(event, sample, session); 813 return tool->read(tool, event, sample, evsel, machine);
788 case PERF_RECORD_THROTTLE: 814 case PERF_RECORD_THROTTLE:
789 return ops->throttle(event, sample, session); 815 return tool->throttle(tool, event, sample, machine);
790 case PERF_RECORD_UNTHROTTLE: 816 case PERF_RECORD_UNTHROTTLE:
791 return ops->unthrottle(event, sample, session); 817 return tool->unthrottle(tool, event, sample, machine);
792 default: 818 default:
793 ++session->hists.stats.nr_unknown_events; 819 ++session->hists.stats.nr_unknown_events;
794 return -1; 820 return -1;
@@ -812,24 +838,29 @@ static int perf_session__preprocess_sample(struct perf_session *session,
812} 838}
813 839
814static int perf_session__process_user_event(struct perf_session *session, union perf_event *event, 840static int perf_session__process_user_event(struct perf_session *session, union perf_event *event,
815 struct perf_event_ops *ops, u64 file_offset) 841 struct perf_tool *tool, u64 file_offset)
816{ 842{
843 int err;
844
817 dump_event(session, event, file_offset, NULL); 845 dump_event(session, event, file_offset, NULL);
818 846
819 /* These events are processed right away */ 847 /* These events are processed right away */
820 switch (event->header.type) { 848 switch (event->header.type) {
821 case PERF_RECORD_HEADER_ATTR: 849 case PERF_RECORD_HEADER_ATTR:
822 return ops->attr(event, session); 850 err = tool->attr(event, &session->evlist);
851 if (err == 0)
852 perf_session__update_sample_type(session);
853 return err;
823 case PERF_RECORD_HEADER_EVENT_TYPE: 854 case PERF_RECORD_HEADER_EVENT_TYPE:
824 return ops->event_type(event, session); 855 return tool->event_type(tool, event);
825 case PERF_RECORD_HEADER_TRACING_DATA: 856 case PERF_RECORD_HEADER_TRACING_DATA:
826 /* setup for reading amidst mmap */ 857 /* setup for reading amidst mmap */
827 lseek(session->fd, file_offset, SEEK_SET); 858 lseek(session->fd, file_offset, SEEK_SET);
828 return ops->tracing_data(event, session); 859 return tool->tracing_data(event, session);
829 case PERF_RECORD_HEADER_BUILD_ID: 860 case PERF_RECORD_HEADER_BUILD_ID:
830 return ops->build_id(event, session); 861 return tool->build_id(tool, event, session);
831 case PERF_RECORD_FINISHED_ROUND: 862 case PERF_RECORD_FINISHED_ROUND:
832 return ops->finished_round(event, session, ops); 863 return tool->finished_round(tool, event, session);
833 default: 864 default:
834 return -EINVAL; 865 return -EINVAL;
835 } 866 }
@@ -837,7 +868,7 @@ static int perf_session__process_user_event(struct perf_session *session, union
837 868
838static int perf_session__process_event(struct perf_session *session, 869static int perf_session__process_event(struct perf_session *session,
839 union perf_event *event, 870 union perf_event *event,
840 struct perf_event_ops *ops, 871 struct perf_tool *tool,
841 u64 file_offset) 872 u64 file_offset)
842{ 873{
843 struct perf_sample sample; 874 struct perf_sample sample;
@@ -853,7 +884,7 @@ static int perf_session__process_event(struct perf_session *session,
853 hists__inc_nr_events(&session->hists, event->header.type); 884 hists__inc_nr_events(&session->hists, event->header.type);
854 885
855 if (event->header.type >= PERF_RECORD_USER_TYPE_START) 886 if (event->header.type >= PERF_RECORD_USER_TYPE_START)
856 return perf_session__process_user_event(session, event, ops, file_offset); 887 return perf_session__process_user_event(session, event, tool, file_offset);
857 888
858 /* 889 /*
859 * For all kernel events we get the sample data 890 * For all kernel events we get the sample data
@@ -866,14 +897,14 @@ static int perf_session__process_event(struct perf_session *session,
866 if (perf_session__preprocess_sample(session, event, &sample)) 897 if (perf_session__preprocess_sample(session, event, &sample))
867 return 0; 898 return 0;
868 899
869 if (ops->ordered_samples) { 900 if (tool->ordered_samples) {
870 ret = perf_session_queue_event(session, event, &sample, 901 ret = perf_session_queue_event(session, event, &sample,
871 file_offset); 902 file_offset);
872 if (ret != -ETIME) 903 if (ret != -ETIME)
873 return ret; 904 return ret;
874 } 905 }
875 906
876 return perf_session_deliver_event(session, event, &sample, ops, 907 return perf_session_deliver_event(session, event, &sample, tool,
877 file_offset); 908 file_offset);
878} 909}
879 910
@@ -884,6 +915,11 @@ void perf_event_header__bswap(struct perf_event_header *self)
884 self->size = bswap_16(self->size); 915 self->size = bswap_16(self->size);
885} 916}
886 917
918struct thread *perf_session__findnew(struct perf_session *session, pid_t pid)
919{
920 return machine__findnew_thread(&session->host_machine, pid);
921}
922
887static struct thread *perf_session__register_idle_thread(struct perf_session *self) 923static struct thread *perf_session__register_idle_thread(struct perf_session *self)
888{ 924{
889 struct thread *thread = perf_session__findnew(self, 0); 925 struct thread *thread = perf_session__findnew(self, 0);
@@ -897,9 +933,9 @@ static struct thread *perf_session__register_idle_thread(struct perf_session *se
897} 933}
898 934
899static void perf_session__warn_about_errors(const struct perf_session *session, 935static void perf_session__warn_about_errors(const struct perf_session *session,
900 const struct perf_event_ops *ops) 936 const struct perf_tool *tool)
901{ 937{
902 if (ops->lost == perf_event__process_lost && 938 if (tool->lost == perf_event__process_lost &&
903 session->hists.stats.nr_events[PERF_RECORD_LOST] != 0) { 939 session->hists.stats.nr_events[PERF_RECORD_LOST] != 0) {
904 ui__warning("Processed %d events and lost %d chunks!\n\n" 940 ui__warning("Processed %d events and lost %d chunks!\n\n"
905 "Check IO/CPU overload!\n\n", 941 "Check IO/CPU overload!\n\n",
@@ -934,7 +970,7 @@ static void perf_session__warn_about_errors(const struct perf_session *session,
934volatile int session_done; 970volatile int session_done;
935 971
936static int __perf_session__process_pipe_events(struct perf_session *self, 972static int __perf_session__process_pipe_events(struct perf_session *self,
937 struct perf_event_ops *ops) 973 struct perf_tool *tool)
938{ 974{
939 union perf_event event; 975 union perf_event event;
940 uint32_t size; 976 uint32_t size;
@@ -943,7 +979,7 @@ static int __perf_session__process_pipe_events(struct perf_session *self,
943 int err; 979 int err;
944 void *p; 980 void *p;
945 981
946 perf_event_ops__fill_defaults(ops); 982 perf_tool__fill_defaults(tool);
947 983
948 head = 0; 984 head = 0;
949more: 985more:
@@ -979,8 +1015,7 @@ more:
979 } 1015 }
980 } 1016 }
981 1017
982 if (size == 0 || 1018 if ((skip = perf_session__process_event(self, &event, tool, head)) < 0) {
983 (skip = perf_session__process_event(self, &event, ops, head)) < 0) {
984 dump_printf("%#" PRIx64 " [%#x]: skipping unknown header type: %d\n", 1019 dump_printf("%#" PRIx64 " [%#x]: skipping unknown header type: %d\n",
985 head, event.header.size, event.header.type); 1020 head, event.header.size, event.header.type);
986 /* 1021 /*
@@ -1003,7 +1038,7 @@ more:
1003done: 1038done:
1004 err = 0; 1039 err = 0;
1005out_err: 1040out_err:
1006 perf_session__warn_about_errors(self, ops); 1041 perf_session__warn_about_errors(self, tool);
1007 perf_session_free_sample_buffers(self); 1042 perf_session_free_sample_buffers(self);
1008 return err; 1043 return err;
1009} 1044}
@@ -1034,7 +1069,7 @@ fetch_mmaped_event(struct perf_session *session,
1034 1069
1035int __perf_session__process_events(struct perf_session *session, 1070int __perf_session__process_events(struct perf_session *session,
1036 u64 data_offset, u64 data_size, 1071 u64 data_offset, u64 data_size,
1037 u64 file_size, struct perf_event_ops *ops) 1072 u64 file_size, struct perf_tool *tool)
1038{ 1073{
1039 u64 head, page_offset, file_offset, file_pos, progress_next; 1074 u64 head, page_offset, file_offset, file_pos, progress_next;
1040 int err, mmap_prot, mmap_flags, map_idx = 0; 1075 int err, mmap_prot, mmap_flags, map_idx = 0;
@@ -1043,7 +1078,7 @@ int __perf_session__process_events(struct perf_session *session,
1043 union perf_event *event; 1078 union perf_event *event;
1044 uint32_t size; 1079 uint32_t size;
1045 1080
1046 perf_event_ops__fill_defaults(ops); 1081 perf_tool__fill_defaults(tool);
1047 1082
1048 page_size = sysconf(_SC_PAGESIZE); 1083 page_size = sysconf(_SC_PAGESIZE);
1049 1084
@@ -1098,7 +1133,7 @@ more:
1098 size = event->header.size; 1133 size = event->header.size;
1099 1134
1100 if (size == 0 || 1135 if (size == 0 ||
1101 perf_session__process_event(session, event, ops, file_pos) < 0) { 1136 perf_session__process_event(session, event, tool, file_pos) < 0) {
1102 dump_printf("%#" PRIx64 " [%#x]: skipping unknown header type: %d\n", 1137 dump_printf("%#" PRIx64 " [%#x]: skipping unknown header type: %d\n",
1103 file_offset + head, event->header.size, 1138 file_offset + head, event->header.size,
1104 event->header.type); 1139 event->header.type);
@@ -1127,15 +1162,15 @@ more:
1127 err = 0; 1162 err = 0;
1128 /* do the final flush for ordered samples */ 1163 /* do the final flush for ordered samples */
1129 session->ordered_samples.next_flush = ULLONG_MAX; 1164 session->ordered_samples.next_flush = ULLONG_MAX;
1130 flush_sample_queue(session, ops); 1165 flush_sample_queue(session, tool);
1131out_err: 1166out_err:
1132 perf_session__warn_about_errors(session, ops); 1167 perf_session__warn_about_errors(session, tool);
1133 perf_session_free_sample_buffers(session); 1168 perf_session_free_sample_buffers(session);
1134 return err; 1169 return err;
1135} 1170}
1136 1171
1137int perf_session__process_events(struct perf_session *self, 1172int perf_session__process_events(struct perf_session *self,
1138 struct perf_event_ops *ops) 1173 struct perf_tool *tool)
1139{ 1174{
1140 int err; 1175 int err;
1141 1176
@@ -1146,9 +1181,9 @@ int perf_session__process_events(struct perf_session *self,
1146 err = __perf_session__process_events(self, 1181 err = __perf_session__process_events(self,
1147 self->header.data_offset, 1182 self->header.data_offset,
1148 self->header.data_size, 1183 self->header.data_size,
1149 self->size, ops); 1184 self->size, tool);
1150 else 1185 else
1151 err = __perf_session__process_pipe_events(self, ops); 1186 err = __perf_session__process_pipe_events(self, tool);
1152 1187
1153 return err; 1188 return err;
1154} 1189}
@@ -1163,9 +1198,8 @@ bool perf_session__has_traces(struct perf_session *self, const char *msg)
1163 return true; 1198 return true;
1164} 1199}
1165 1200
1166int perf_session__set_kallsyms_ref_reloc_sym(struct map **maps, 1201int maps__set_kallsyms_ref_reloc_sym(struct map **maps,
1167 const char *symbol_name, 1202 const char *symbol_name, u64 addr)
1168 u64 addr)
1169{ 1203{
1170 char *bracket; 1204 char *bracket;
1171 enum map_type i; 1205 enum map_type i;
@@ -1224,6 +1258,27 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
1224 return ret; 1258 return ret;
1225} 1259}
1226 1260
1261size_t perf_session__fprintf(struct perf_session *session, FILE *fp)
1262{
1263 /*
1264 * FIXME: Here we have to actually print all the machines in this
1265 * session, not just the host...
1266 */
1267 return machine__fprintf(&session->host_machine, fp);
1268}
1269
1270void perf_session__remove_thread(struct perf_session *session,
1271 struct thread *th)
1272{
1273 /*
1274 * FIXME: This one makes no sense, we need to remove the thread from
1275 * the machine it belongs to, perf_session can have many machines, so
1276 * doing it always on ->host_machine is wrong. Fix when auditing all
1277 * the 'perf kvm' code.
1278 */
1279 machine__remove_thread(&session->host_machine, th);
1280}
1281
1227struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, 1282struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
1228 unsigned int type) 1283 unsigned int type)
1229{ 1284{
@@ -1236,17 +1291,16 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
1236 return NULL; 1291 return NULL;
1237} 1292}
1238 1293
1239void perf_session__print_ip(union perf_event *event, 1294void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
1240 struct perf_sample *sample, 1295 struct machine *machine, struct perf_evsel *evsel,
1241 struct perf_session *session, 1296 int print_sym, int print_dso)
1242 int print_sym, int print_dso)
1243{ 1297{
1244 struct addr_location al; 1298 struct addr_location al;
1245 const char *symname, *dsoname; 1299 const char *symname, *dsoname;
1246 struct callchain_cursor *cursor = &session->callchain_cursor; 1300 struct callchain_cursor *cursor = &evsel->hists.callchain_cursor;
1247 struct callchain_cursor_node *node; 1301 struct callchain_cursor_node *node;
1248 1302
1249 if (perf_event__preprocess_sample(event, session, &al, sample, 1303 if (perf_event__preprocess_sample(event, machine, &al, sample,
1250 NULL) < 0) { 1304 NULL) < 0) {
1251 error("problem processing %d event, skipping it.\n", 1305 error("problem processing %d event, skipping it.\n",
1252 event->header.type); 1306 event->header.type);
@@ -1255,7 +1309,7 @@ void perf_session__print_ip(union perf_event *event,
1255 1309
1256 if (symbol_conf.use_callchain && sample->callchain) { 1310 if (symbol_conf.use_callchain && sample->callchain) {
1257 1311
1258 if (perf_session__resolve_callchain(session, al.thread, 1312 if (machine__resolve_callchain(machine, evsel, al.thread,
1259 sample->callchain, NULL) != 0) { 1313 sample->callchain, NULL) != 0) {
1260 if (verbose) 1314 if (verbose)
1261 error("Failed to resolve callchain. Skipping\n"); 1315 error("Failed to resolve callchain. Skipping\n");
@@ -1333,6 +1387,10 @@ int perf_session__cpu_bitmap(struct perf_session *session,
1333 } 1387 }
1334 1388
1335 map = cpu_map__new(cpu_list); 1389 map = cpu_map__new(cpu_list);
1390 if (map == NULL) {
1391 pr_err("Invalid cpu_list\n");
1392 return -1;
1393 }
1336 1394
1337 for (i = 0; i < map->nr; i++) { 1395 for (i = 0; i < map->nr; i++) {
1338 int cpu = map->map[i]; 1396 int cpu = map->map[i];
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 6e393c98eb34..37bc38381fb6 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -30,9 +30,6 @@ struct perf_session {
30 struct perf_header header; 30 struct perf_header header;
31 unsigned long size; 31 unsigned long size;
32 unsigned long mmap_window; 32 unsigned long mmap_window;
33 struct rb_root threads;
34 struct list_head dead_threads;
35 struct thread *last_match;
36 struct machine host_machine; 33 struct machine host_machine;
37 struct rb_root machines; 34 struct rb_root machines;
38 struct perf_evlist *evlist; 35 struct perf_evlist *evlist;
@@ -53,65 +50,31 @@ struct perf_session {
53 int cwdlen; 50 int cwdlen;
54 char *cwd; 51 char *cwd;
55 struct ordered_samples ordered_samples; 52 struct ordered_samples ordered_samples;
56 struct callchain_cursor callchain_cursor; 53 char filename[1];
57 char filename[0];
58}; 54};
59 55
60struct perf_evsel; 56struct perf_tool;
61struct perf_event_ops;
62
63typedef int (*event_sample)(union perf_event *event, struct perf_sample *sample,
64 struct perf_evsel *evsel, struct perf_session *session);
65typedef int (*event_op)(union perf_event *self, struct perf_sample *sample,
66 struct perf_session *session);
67typedef int (*event_synth_op)(union perf_event *self,
68 struct perf_session *session);
69typedef int (*event_op2)(union perf_event *self, struct perf_session *session,
70 struct perf_event_ops *ops);
71
72struct perf_event_ops {
73 event_sample sample;
74 event_op mmap,
75 comm,
76 fork,
77 exit,
78 lost,
79 read,
80 throttle,
81 unthrottle;
82 event_synth_op attr,
83 event_type,
84 tracing_data,
85 build_id;
86 event_op2 finished_round;
87 bool ordered_samples;
88 bool ordering_requires_timestamps;
89};
90 57
91struct perf_session *perf_session__new(const char *filename, int mode, 58struct perf_session *perf_session__new(const char *filename, int mode,
92 bool force, bool repipe, 59 bool force, bool repipe,
93 struct perf_event_ops *ops); 60 struct perf_tool *tool);
94void perf_session__delete(struct perf_session *self); 61void perf_session__delete(struct perf_session *self);
95 62
96void perf_event_header__bswap(struct perf_event_header *self); 63void perf_event_header__bswap(struct perf_event_header *self);
97 64
98int __perf_session__process_events(struct perf_session *self, 65int __perf_session__process_events(struct perf_session *self,
99 u64 data_offset, u64 data_size, u64 size, 66 u64 data_offset, u64 data_size, u64 size,
100 struct perf_event_ops *ops); 67 struct perf_tool *tool);
101int perf_session__process_events(struct perf_session *self, 68int perf_session__process_events(struct perf_session *self,
102 struct perf_event_ops *event_ops); 69 struct perf_tool *tool);
103 70
104int perf_session__resolve_callchain(struct perf_session *self, 71int perf_session__resolve_callchain(struct perf_session *self, struct perf_evsel *evsel,
105 struct thread *thread, 72 struct thread *thread,
106 struct ip_callchain *chain, 73 struct ip_callchain *chain,
107 struct symbol **parent); 74 struct symbol **parent);
108 75
109bool perf_session__has_traces(struct perf_session *self, const char *msg); 76bool perf_session__has_traces(struct perf_session *self, const char *msg);
110 77
111int perf_session__set_kallsyms_ref_reloc_sym(struct map **maps,
112 const char *symbol_name,
113 u64 addr);
114
115void mem_bswap_64(void *src, int byte_size); 78void mem_bswap_64(void *src, int byte_size);
116void perf_event__attr_swap(struct perf_event_attr *attr); 79void perf_event__attr_swap(struct perf_event_attr *attr);
117 80
@@ -144,12 +107,16 @@ struct machine *perf_session__findnew_machine(struct perf_session *self, pid_t p
144 107
145static inline 108static inline
146void perf_session__process_machines(struct perf_session *self, 109void perf_session__process_machines(struct perf_session *self,
110 struct perf_tool *tool,
147 machine__process_t process) 111 machine__process_t process)
148{ 112{
149 process(&self->host_machine, self); 113 process(&self->host_machine, tool);
150 return machines__process(&self->machines, process, self); 114 return machines__process(&self->machines, process, tool);
151} 115}
152 116
117struct thread *perf_session__findnew(struct perf_session *self, pid_t pid);
118size_t perf_session__fprintf(struct perf_session *self, FILE *fp);
119
153size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp); 120size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp);
154 121
155size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, 122size_t perf_session__fprintf_dsos_buildid(struct perf_session *self,
@@ -167,13 +134,20 @@ static inline int perf_session__parse_sample(struct perf_session *session,
167 session->header.needs_swap); 134 session->header.needs_swap);
168} 135}
169 136
137static inline int perf_session__synthesize_sample(struct perf_session *session,
138 union perf_event *event,
139 const struct perf_sample *sample)
140{
141 return perf_event__synthesize_sample(event, session->sample_type,
142 sample, session->header.needs_swap);
143}
144
170struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, 145struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
171 unsigned int type); 146 unsigned int type);
172 147
173void perf_session__print_ip(union perf_event *event, 148void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
174 struct perf_sample *sample, 149 struct machine *machine, struct perf_evsel *evsel,
175 struct perf_session *session, 150 int print_sym, int print_dso);
176 int print_sym, int print_dso);
177 151
178int perf_session__cpu_bitmap(struct perf_session *session, 152int perf_session__cpu_bitmap(struct perf_session *session,
179 const char *cpu_list, unsigned long *cpu_bitmap); 153 const char *cpu_list, unsigned long *cpu_bitmap);
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py
index 95d370074928..36d4c5619575 100644
--- a/tools/perf/util/setup.py
+++ b/tools/perf/util/setup.py
@@ -27,7 +27,8 @@ build_tmp = getenv('PYTHON_EXTBUILD_TMP')
27perf = Extension('perf', 27perf = Extension('perf',
28 sources = ['util/python.c', 'util/ctype.c', 'util/evlist.c', 28 sources = ['util/python.c', 'util/ctype.c', 'util/evlist.c',
29 'util/evsel.c', 'util/cpumap.c', 'util/thread_map.c', 29 'util/evsel.c', 'util/cpumap.c', 'util/thread_map.c',
30 'util/util.c', 'util/xyarray.c', 'util/cgroup.c'], 30 'util/util.c', 'util/xyarray.c', 'util/cgroup.c',
31 'util/debugfs.c'],
31 include_dirs = ['util/include'], 32 include_dirs = ['util/include'],
32 extra_compile_args = cflags, 33 extra_compile_args = cflags,
33 ) 34 )
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 632b50c7bc26..215d50f2042e 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1757,7 +1757,7 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg,
1757 struct stat st; 1757 struct stat st;
1758 1758
1759 /*sshfs might return bad dent->d_type, so we have to stat*/ 1759 /*sshfs might return bad dent->d_type, so we have to stat*/
1760 sprintf(path, "%s/%s", dir_name, dent->d_name); 1760 snprintf(path, sizeof(path), "%s/%s", dir_name, dent->d_name);
1761 if (stat(path, &st)) 1761 if (stat(path, &st))
1762 continue; 1762 continue;
1763 1763
@@ -1766,8 +1766,6 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg,
1766 !strcmp(dent->d_name, "..")) 1766 !strcmp(dent->d_name, ".."))
1767 continue; 1767 continue;
1768 1768
1769 snprintf(path, sizeof(path), "%s/%s",
1770 dir_name, dent->d_name);
1771 ret = map_groups__set_modules_path_dir(mg, path); 1769 ret = map_groups__set_modules_path_dir(mg, path);
1772 if (ret < 0) 1770 if (ret < 0)
1773 goto out; 1771 goto out;
@@ -1788,9 +1786,6 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg,
1788 if (map == NULL) 1786 if (map == NULL)
1789 continue; 1787 continue;
1790 1788
1791 snprintf(path, sizeof(path), "%s/%s",
1792 dir_name, dent->d_name);
1793
1794 long_name = strdup(path); 1789 long_name = strdup(path);
1795 if (long_name == NULL) { 1790 if (long_name == NULL) {
1796 ret = -1; 1791 ret = -1;
@@ -2609,10 +2604,10 @@ int symbol__init(void)
2609 symbol_conf.initialized = true; 2604 symbol_conf.initialized = true;
2610 return 0; 2605 return 0;
2611 2606
2612out_free_dso_list:
2613 strlist__delete(symbol_conf.dso_list);
2614out_free_comm_list: 2607out_free_comm_list:
2615 strlist__delete(symbol_conf.comm_list); 2608 strlist__delete(symbol_conf.comm_list);
2609out_free_dso_list:
2610 strlist__delete(symbol_conf.dso_list);
2616 return -1; 2611 return -1;
2617} 2612}
2618 2613
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 29f8d742e92f..123c2e14353e 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -68,6 +68,7 @@ struct strlist;
68 68
69struct symbol_conf { 69struct symbol_conf {
70 unsigned short priv_size; 70 unsigned short priv_size;
71 unsigned short nr_events;
71 bool try_vmlinux_path, 72 bool try_vmlinux_path,
72 use_modules, 73 use_modules,
73 sort_by_name, 74 sort_by_name,
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index d5d3b22250f3..fb4b7ea6752f 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -61,7 +61,7 @@ static size_t thread__fprintf(struct thread *self, FILE *fp)
61 map_groups__fprintf(&self->mg, verbose, fp); 61 map_groups__fprintf(&self->mg, verbose, fp);
62} 62}
63 63
64struct thread *perf_session__findnew(struct perf_session *self, pid_t pid) 64struct thread *machine__findnew_thread(struct machine *self, pid_t pid)
65{ 65{
66 struct rb_node **p = &self->threads.rb_node; 66 struct rb_node **p = &self->threads.rb_node;
67 struct rb_node *parent = NULL; 67 struct rb_node *parent = NULL;
@@ -125,12 +125,12 @@ int thread__fork(struct thread *self, struct thread *parent)
125 return 0; 125 return 0;
126} 126}
127 127
128size_t perf_session__fprintf(struct perf_session *self, FILE *fp) 128size_t machine__fprintf(struct machine *machine, FILE *fp)
129{ 129{
130 size_t ret = 0; 130 size_t ret = 0;
131 struct rb_node *nd; 131 struct rb_node *nd;
132 132
133 for (nd = rb_first(&self->threads); nd; nd = rb_next(nd)) { 133 for (nd = rb_first(&machine->threads); nd; nd = rb_next(nd)) {
134 struct thread *pos = rb_entry(nd, struct thread, rb_node); 134 struct thread *pos = rb_entry(nd, struct thread, rb_node);
135 135
136 ret += thread__fprintf(pos, fp); 136 ret += thread__fprintf(pos, fp);
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index e5f2401c1b5e..70c2c13ff679 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -18,16 +18,14 @@ struct thread {
18 int comm_len; 18 int comm_len;
19}; 19};
20 20
21struct perf_session; 21struct machine;
22 22
23void thread__delete(struct thread *self); 23void thread__delete(struct thread *self);
24 24
25int thread__set_comm(struct thread *self, const char *comm); 25int thread__set_comm(struct thread *self, const char *comm);
26int thread__comm_len(struct thread *self); 26int thread__comm_len(struct thread *self);
27struct thread *perf_session__findnew(struct perf_session *self, pid_t pid);
28void thread__insert_map(struct thread *self, struct map *map); 27void thread__insert_map(struct thread *self, struct map *map);
29int thread__fork(struct thread *self, struct thread *parent); 28int thread__fork(struct thread *self, struct thread *parent);
30size_t perf_session__fprintf(struct perf_session *self, FILE *fp);
31 29
32static inline struct map *thread__find_map(struct thread *self, 30static inline struct map *thread__find_map(struct thread *self,
33 enum map_type type, u64 addr) 31 enum map_type type, u64 addr)
@@ -35,14 +33,12 @@ static inline struct map *thread__find_map(struct thread *self,
35 return self ? map_groups__find(&self->mg, type, addr) : NULL; 33 return self ? map_groups__find(&self->mg, type, addr) : NULL;
36} 34}
37 35
38void thread__find_addr_map(struct thread *self, 36void thread__find_addr_map(struct thread *thread, struct machine *machine,
39 struct perf_session *session, u8 cpumode, 37 u8 cpumode, enum map_type type, u64 addr,
40 enum map_type type, pid_t pid, u64 addr,
41 struct addr_location *al); 38 struct addr_location *al);
42 39
43void thread__find_addr_location(struct thread *self, 40void thread__find_addr_location(struct thread *thread, struct machine *machine,
44 struct perf_session *session, u8 cpumode, 41 u8 cpumode, enum map_type type, u64 addr,
45 enum map_type type, pid_t pid, u64 addr,
46 struct addr_location *al, 42 struct addr_location *al,
47 symbol_filter_t filter); 43 symbol_filter_t filter);
48#endif /* __PERF_THREAD_H */ 44#endif /* __PERF_THREAD_H */
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
new file mode 100644
index 000000000000..b0e1aadba8d5
--- /dev/null
+++ b/tools/perf/util/tool.h
@@ -0,0 +1,50 @@
1#ifndef __PERF_TOOL_H
2#define __PERF_TOOL_H
3
4#include <stdbool.h>
5
6struct perf_session;
7union perf_event;
8struct perf_evlist;
9struct perf_evsel;
10struct perf_sample;
11struct perf_tool;
12struct machine;
13
14typedef int (*event_sample)(struct perf_tool *tool, union perf_event *event,
15 struct perf_sample *sample,
16 struct perf_evsel *evsel, struct machine *machine);
17
18typedef int (*event_op)(struct perf_tool *tool, union perf_event *event,
19 struct perf_sample *sample, struct machine *machine);
20
21typedef int (*event_attr_op)(union perf_event *event,
22 struct perf_evlist **pevlist);
23typedef int (*event_simple_op)(struct perf_tool *tool, union perf_event *event);
24
25typedef int (*event_synth_op)(union perf_event *event,
26 struct perf_session *session);
27
28typedef int (*event_op2)(struct perf_tool *tool, union perf_event *event,
29 struct perf_session *session);
30
31struct perf_tool {
32 event_sample sample,
33 read;
34 event_op mmap,
35 comm,
36 fork,
37 exit,
38 lost,
39 throttle,
40 unthrottle;
41 event_attr_op attr;
42 event_synth_op tracing_data;
43 event_simple_op event_type;
44 event_op2 finished_round,
45 build_id;
46 bool ordered_samples;
47 bool ordering_requires_timestamps;
48};
49
50#endif /* __PERF_TOOL_H */
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index 399650967958..a248f3c2c60d 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -1,15 +1,17 @@
1#ifndef __PERF_TOP_H 1#ifndef __PERF_TOP_H
2#define __PERF_TOP_H 1 2#define __PERF_TOP_H 1
3 3
4#include "tool.h"
4#include "types.h" 5#include "types.h"
5#include "../perf.h"
6#include <stddef.h> 6#include <stddef.h>
7#include <stdbool.h>
7 8
8struct perf_evlist; 9struct perf_evlist;
9struct perf_evsel; 10struct perf_evsel;
10struct perf_session; 11struct perf_session;
11 12
12struct perf_top { 13struct perf_top {
14 struct perf_tool tool;
13 struct perf_evlist *evlist; 15 struct perf_evlist *evlist;
14 /* 16 /*
15 * Symbols will be added here in perf_event__process_sample and will 17 * Symbols will be added here in perf_event__process_sample and will
@@ -23,10 +25,26 @@ struct perf_top {
23 int freq; 25 int freq;
24 pid_t target_pid, target_tid; 26 pid_t target_pid, target_tid;
25 bool hide_kernel_symbols, hide_user_symbols, zero; 27 bool hide_kernel_symbols, hide_user_symbols, zero;
28 bool system_wide;
29 bool use_tui, use_stdio;
30 bool sort_has_symbols;
31 bool dont_use_callchains;
32 bool kptr_restrict_warned;
33 bool vmlinux_warned;
34 bool inherit;
35 bool group;
36 bool sample_id_all_avail;
37 bool dump_symtab;
26 const char *cpu_list; 38 const char *cpu_list;
27 struct hist_entry *sym_filter_entry; 39 struct hist_entry *sym_filter_entry;
28 struct perf_evsel *sym_evsel; 40 struct perf_evsel *sym_evsel;
29 struct perf_session *session; 41 struct perf_session *session;
42 struct winsize winsize;
43 unsigned int mmap_pages;
44 int default_interval;
45 int realtime_prio;
46 int sym_pcnt_filter;
47 const char *sym_filter;
30}; 48};
31 49
32size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size); 50size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size);
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index d2655f08bcc0..fc22cf5c605f 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -18,7 +18,7 @@
18 * 18 *
19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20 */ 20 */
21#define _GNU_SOURCE 21#include "util.h"
22#include <dirent.h> 22#include <dirent.h>
23#include <mntent.h> 23#include <mntent.h>
24#include <stdio.h> 24#include <stdio.h>
@@ -31,7 +31,6 @@
31#include <pthread.h> 31#include <pthread.h>
32#include <fcntl.h> 32#include <fcntl.h>
33#include <unistd.h> 33#include <unistd.h>
34#include <ctype.h>
35#include <errno.h> 34#include <errno.h>
36#include <stdbool.h> 35#include <stdbool.h>
37#include <linux/list.h> 36#include <linux/list.h>
@@ -44,10 +43,6 @@
44 43
45#define VERSION "0.5" 44#define VERSION "0.5"
46 45
47#define _STR(x) #x
48#define STR(x) _STR(x)
49#define MAX_PATH 256
50
51#define TRACE_CTRL "tracing_on" 46#define TRACE_CTRL "tracing_on"
52#define TRACE "trace" 47#define TRACE "trace"
53#define AVAILABLE "available_tracers" 48#define AVAILABLE "available_tracers"
@@ -73,26 +68,6 @@ struct events {
73}; 68};
74 69
75 70
76
77static void die(const char *fmt, ...)
78{
79 va_list ap;
80 int ret = errno;
81
82 if (errno)
83 perror("perf");
84 else
85 ret = -1;
86
87 va_start(ap, fmt);
88 fprintf(stderr, " ");
89 vfprintf(stderr, fmt, ap);
90 va_end(ap);
91
92 fprintf(stderr, "\n");
93 exit(ret);
94}
95
96void *malloc_or_die(unsigned int size) 71void *malloc_or_die(unsigned int size)
97{ 72{
98 void *data; 73 void *data;
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index 0a7ed5b5e281..6c164dc9ee95 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -1537,6 +1537,8 @@ process_flags(struct event *event, struct print_arg *arg, char **tok)
1537 field = malloc_or_die(sizeof(*field)); 1537 field = malloc_or_die(sizeof(*field));
1538 1538
1539 type = process_arg(event, field, &token); 1539 type = process_arg(event, field, &token);
1540 while (type == EVENT_OP)
1541 type = process_op(event, field, &token);
1540 if (test_type_token(type, token, EVENT_DELIM, ",")) 1542 if (test_type_token(type, token, EVENT_DELIM, ","))
1541 goto out_free; 1543 goto out_free;
1542 1544
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
index c9dcbec7d800..a3fdf55f317b 100644
--- a/tools/perf/util/trace-event-scripting.c
+++ b/tools/perf/util/trace-event-scripting.c
@@ -39,7 +39,7 @@ static int stop_script_unsupported(void)
39static void process_event_unsupported(union perf_event *event __unused, 39static void process_event_unsupported(union perf_event *event __unused,
40 struct perf_sample *sample __unused, 40 struct perf_sample *sample __unused,
41 struct perf_evsel *evsel __unused, 41 struct perf_evsel *evsel __unused,
42 struct perf_session *session __unused, 42 struct machine *machine __unused,
43 struct thread *thread __unused) 43 struct thread *thread __unused)
44{ 44{
45} 45}
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index a84100817649..58ae14c5baac 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -3,7 +3,11 @@
3 3
4#include <stdbool.h> 4#include <stdbool.h>
5#include "parse-events.h" 5#include "parse-events.h"
6#include "session.h" 6
7struct machine;
8struct perf_sample;
9union perf_event;
10struct thread;
7 11
8#define __unused __attribute__((unused)) 12#define __unused __attribute__((unused))
9 13
@@ -292,7 +296,7 @@ struct scripting_ops {
292 void (*process_event) (union perf_event *event, 296 void (*process_event) (union perf_event *event,
293 struct perf_sample *sample, 297 struct perf_sample *sample,
294 struct perf_evsel *evsel, 298 struct perf_evsel *evsel,
295 struct perf_session *session, 299 struct machine *machine,
296 struct thread *thread); 300 struct thread *thread);
297 int (*generate_script) (const char *outfile); 301 int (*generate_script) (const char *outfile);
298}; 302};
diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c
index 0575905d1205..295a9c93f945 100644
--- a/tools/perf/util/ui/browsers/annotate.c
+++ b/tools/perf/util/ui/browsers/annotate.c
@@ -224,7 +224,7 @@ static bool annotate_browser__toggle_source(struct annotate_browser *browser)
224} 224}
225 225
226static int annotate_browser__run(struct annotate_browser *self, int evidx, 226static int annotate_browser__run(struct annotate_browser *self, int evidx,
227 int nr_events, void(*timer)(void *arg), 227 void(*timer)(void *arg),
228 void *arg, int delay_secs) 228 void *arg, int delay_secs)
229{ 229{
230 struct rb_node *nd = NULL; 230 struct rb_node *nd = NULL;
@@ -328,8 +328,7 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,
328 notes = symbol__annotation(target); 328 notes = symbol__annotation(target);
329 pthread_mutex_lock(&notes->lock); 329 pthread_mutex_lock(&notes->lock);
330 330
331 if (notes->src == NULL && 331 if (notes->src == NULL && symbol__alloc_hist(target) < 0) {
332 symbol__alloc_hist(target, nr_events) < 0) {
333 pthread_mutex_unlock(&notes->lock); 332 pthread_mutex_unlock(&notes->lock);
334 ui__warning("Not enough memory for annotating '%s' symbol!\n", 333 ui__warning("Not enough memory for annotating '%s' symbol!\n",
335 target->name); 334 target->name);
@@ -337,7 +336,7 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,
337 } 336 }
338 337
339 pthread_mutex_unlock(&notes->lock); 338 pthread_mutex_unlock(&notes->lock);
340 symbol__tui_annotate(target, ms->map, evidx, nr_events, 339 symbol__tui_annotate(target, ms->map, evidx,
341 timer, arg, delay_secs); 340 timer, arg, delay_secs);
342 } 341 }
343 continue; 342 continue;
@@ -358,15 +357,15 @@ out:
358 return key; 357 return key;
359} 358}
360 359
361int hist_entry__tui_annotate(struct hist_entry *he, int evidx, int nr_events, 360int hist_entry__tui_annotate(struct hist_entry *he, int evidx,
362 void(*timer)(void *arg), void *arg, int delay_secs) 361 void(*timer)(void *arg), void *arg, int delay_secs)
363{ 362{
364 return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx, nr_events, 363 return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx,
365 timer, arg, delay_secs); 364 timer, arg, delay_secs);
366} 365}
367 366
368int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, 367int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
369 int nr_events, void(*timer)(void *arg), void *arg, 368 void(*timer)(void *arg), void *arg,
370 int delay_secs) 369 int delay_secs)
371{ 370{
372 struct objdump_line *pos, *n; 371 struct objdump_line *pos, *n;
@@ -419,8 +418,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
419 browser.b.nr_entries = browser.nr_entries; 418 browser.b.nr_entries = browser.nr_entries;
420 browser.b.entries = &notes->src->source, 419 browser.b.entries = &notes->src->source,
421 browser.b.width += 18; /* Percentage */ 420 browser.b.width += 18; /* Percentage */
422 ret = annotate_browser__run(&browser, evidx, nr_events, 421 ret = annotate_browser__run(&browser, evidx, timer, arg, delay_secs);
423 timer, arg, delay_secs);
424 list_for_each_entry_safe(pos, n, &notes->src->source, node) { 422 list_for_each_entry_safe(pos, n, &notes->src->source, node) {
425 list_del(&pos->node); 423 list_del(&pos->node);
426 objdump_line__free(pos); 424 objdump_line__free(pos);
diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c
index d0c94b459685..1212a386a033 100644
--- a/tools/perf/util/ui/browsers/hists.c
+++ b/tools/perf/util/ui/browsers/hists.c
@@ -1020,7 +1020,7 @@ do_annotate:
1020 * Don't let this be freed, say, by hists__decay_entry. 1020 * Don't let this be freed, say, by hists__decay_entry.
1021 */ 1021 */
1022 he->used = true; 1022 he->used = true;
1023 err = hist_entry__tui_annotate(he, evsel->idx, nr_events, 1023 err = hist_entry__tui_annotate(he, evsel->idx,
1024 timer, arg, delay_secs); 1024 timer, arg, delay_secs);
1025 he->used = false; 1025 he->used = false;
1026 ui_browser__update_nr_entries(&browser->b, browser->hists->nr_entries); 1026 ui_browser__update_nr_entries(&browser->b, browser->hists->nr_entries);
diff --git a/tools/perf/util/ui/progress.c b/tools/perf/util/ui/progress.c
index 295e366b6311..13aa64e50e11 100644
--- a/tools/perf/util/ui/progress.c
+++ b/tools/perf/util/ui/progress.c
@@ -14,6 +14,9 @@ void ui_progress__update(u64 curr, u64 total, const char *title)
14 if (use_browser <= 0) 14 if (use_browser <= 0)
15 return; 15 return;
16 16
17 if (total == 0)
18 return;
19
17 ui__refresh_dimensions(true); 20 ui__refresh_dimensions(true);
18 pthread_mutex_lock(&ui__lock); 21 pthread_mutex_lock(&ui__lock);
19 y = SLtt_Screen_Rows / 2 - 2; 22 y = SLtt_Screen_Rows / 2 - 2;
diff --git a/tools/perf/util/usage.c b/tools/perf/util/usage.c
index e16bf9a707e8..d76d1c0ff98f 100644
--- a/tools/perf/util/usage.c
+++ b/tools/perf/util/usage.c
@@ -1,5 +1,8 @@
1/* 1/*
2 * GIT - The information manager from hell 2 * usage.c
3 *
4 * Various reporting routines.
5 * Originally copied from GIT source.
3 * 6 *
4 * Copyright (C) Linus Torvalds, 2005 7 * Copyright (C) Linus Torvalds, 2005
5 */ 8 */
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 5b3ea49aa63e..813141047fc2 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -1,6 +1,21 @@
1#include "../perf.h"
1#include "util.h" 2#include "util.h"
2#include <sys/mman.h> 3#include <sys/mman.h>
3 4
5/*
6 * XXX We need to find a better place for these things...
7 */
8bool perf_host = true;
9bool perf_guest = true;
10
11void event_attr_init(struct perf_event_attr *attr)
12{
13 if (!perf_host)
14 attr->exclude_host = 1;
15 if (!perf_guest)
16 attr->exclude_guest = 1;
17}
18
4int mkdir_p(char *path, mode_t mode) 19int mkdir_p(char *path, mode_t mode)
5{ 20{
6 struct stat st; 21 struct stat st;
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 0128906bac88..b9c530cce79a 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -242,7 +242,22 @@ int strtailcmp(const char *s1, const char *s2);
242unsigned long convert_unit(unsigned long value, char *unit); 242unsigned long convert_unit(unsigned long value, char *unit);
243int readn(int fd, void *buf, size_t size); 243int readn(int fd, void *buf, size_t size);
244 244
245struct perf_event_attr;
246
247void event_attr_init(struct perf_event_attr *attr);
248
245#define _STR(x) #x 249#define _STR(x) #x
246#define STR(x) _STR(x) 250#define STR(x) _STR(x)
247 251
252/*
253 * Determine whether some value is a power of two, where zero is
254 * *not* considered a power of two.
255 */
256
257static inline __attribute__((const))
258bool is_power_of_2(unsigned long n)
259{
260 return (n != 0 && ((n & (n - 1)) == 0));
261}
262
248#endif 263#endif
diff --git a/tools/perf/util/values.c b/tools/perf/util/values.c
index bdd33470b235..697c8b4e59cc 100644
--- a/tools/perf/util/values.c
+++ b/tools/perf/util/values.c
@@ -32,6 +32,7 @@ void perf_read_values_destroy(struct perf_read_values *values)
32 32
33 for (i = 0; i < values->threads; i++) 33 for (i = 0; i < values->threads; i++)
34 free(values->value[i]); 34 free(values->value[i]);
35 free(values->value);
35 free(values->pid); 36 free(values->pid);
36 free(values->tid); 37 free(values->tid);
37 free(values->counterrawid); 38 free(values->counterrawid);