aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/annotate.c6
-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/debugfs.c35
-rw-r--r--tools/perf/util/debugfs.h31
-rw-r--r--tools/perf/util/event.c243
-rw-r--r--tools/perf/util/event.h68
-rw-r--r--tools/perf/util/evlist.c293
-rw-r--r--tools/perf/util/evlist.h43
-rw-r--r--tools/perf/util/evsel.c149
-rw-r--r--tools/perf/util/evsel.h8
-rw-r--r--tools/perf/util/header.c75
-rw-r--r--tools/perf/util/header.h45
-rw-r--r--tools/perf/util/hist.h3
-rw-r--r--tools/perf/util/map.c4
-rw-r--r--tools/perf/util/map.h19
-rw-r--r--tools/perf/util/parse-events.c28
-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.c4
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c4
-rw-r--r--tools/perf/util/session.c326
-rw-r--r--tools/perf/util/session.h70
-rw-r--r--tools/perf/util/setup.py3
-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.c28
-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
38 files changed, 1147 insertions, 513 deletions
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 119e996035c8..376e643f7066 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}
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/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..97c479bcb0dc 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,9 +43,10 @@ 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__synthesize_comm(struct perf_tool *tool,
47 union perf_event *event, pid_t pid,
48 int full, perf_event__handler_t process, 48 int full, perf_event__handler_t process,
49 struct perf_session *session) 49 struct machine *machine)
50{ 50{
51 char filename[PATH_MAX]; 51 char filename[PATH_MAX];
52 char bf[BUFSIZ]; 52 char bf[BUFSIZ];
@@ -92,14 +92,14 @@ out_race:
92 92
93 event->comm.header.type = PERF_RECORD_COMM; 93 event->comm.header.type = PERF_RECORD_COMM;
94 size = ALIGN(size, sizeof(u64)); 94 size = ALIGN(size, sizeof(u64));
95 memset(event->comm.comm + size, 0, session->id_hdr_size); 95 memset(event->comm.comm + size, 0, machine->id_hdr_size);
96 event->comm.header.size = (sizeof(event->comm) - 96 event->comm.header.size = (sizeof(event->comm) -
97 (sizeof(event->comm.comm) - size) + 97 (sizeof(event->comm.comm) - size) +
98 session->id_hdr_size); 98 machine->id_hdr_size);
99 if (!full) { 99 if (!full) {
100 event->comm.tid = pid; 100 event->comm.tid = pid;
101 101
102 process(event, &synth_sample, session); 102 process(tool, event, &synth_sample, machine);
103 goto out; 103 goto out;
104 } 104 }
105 105
@@ -117,7 +117,7 @@ out_race:
117 117
118 event->comm.tid = pid; 118 event->comm.tid = pid;
119 119
120 process(event, &synth_sample, session); 120 process(tool, event, &synth_sample, machine);
121 } 121 }
122 122
123 closedir(tasks); 123 closedir(tasks);
@@ -127,10 +127,11 @@ out:
127 return tgid; 127 return tgid;
128} 128}
129 129
130static int perf_event__synthesize_mmap_events(union perf_event *event, 130static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
131 union perf_event *event,
131 pid_t pid, pid_t tgid, 132 pid_t pid, pid_t tgid,
132 perf_event__handler_t process, 133 perf_event__handler_t process,
133 struct perf_session *session) 134 struct machine *machine)
134{ 135{
135 char filename[PATH_MAX]; 136 char filename[PATH_MAX];
136 FILE *fp; 137 FILE *fp;
@@ -193,12 +194,12 @@ static int perf_event__synthesize_mmap_events(union perf_event *event,
193 event->mmap.len -= event->mmap.start; 194 event->mmap.len -= event->mmap.start;
194 event->mmap.header.size = (sizeof(event->mmap) - 195 event->mmap.header.size = (sizeof(event->mmap) -
195 (sizeof(event->mmap.filename) - size)); 196 (sizeof(event->mmap.filename) - size));
196 memset(event->mmap.filename + size, 0, session->id_hdr_size); 197 memset(event->mmap.filename + size, 0, machine->id_hdr_size);
197 event->mmap.header.size += session->id_hdr_size; 198 event->mmap.header.size += machine->id_hdr_size;
198 event->mmap.pid = tgid; 199 event->mmap.pid = tgid;
199 event->mmap.tid = pid; 200 event->mmap.tid = pid;
200 201
201 process(event, &synth_sample, session); 202 process(tool, event, &synth_sample, machine);
202 } 203 }
203 } 204 }
204 205
@@ -206,14 +207,14 @@ static int perf_event__synthesize_mmap_events(union perf_event *event,
206 return 0; 207 return 0;
207} 208}
208 209
209int perf_event__synthesize_modules(perf_event__handler_t process, 210int perf_event__synthesize_modules(struct perf_tool *tool,
210 struct perf_session *session, 211 perf_event__handler_t process,
211 struct machine *machine) 212 struct machine *machine)
212{ 213{
213 struct rb_node *nd; 214 struct rb_node *nd;
214 struct map_groups *kmaps = &machine->kmaps; 215 struct map_groups *kmaps = &machine->kmaps;
215 union perf_event *event = zalloc((sizeof(event->mmap) + 216 union perf_event *event = zalloc((sizeof(event->mmap) +
216 session->id_hdr_size)); 217 machine->id_hdr_size));
217 if (event == NULL) { 218 if (event == NULL) {
218 pr_debug("Not enough memory synthesizing mmap event " 219 pr_debug("Not enough memory synthesizing mmap event "
219 "for kernel modules\n"); 220 "for kernel modules\n");
@@ -243,15 +244,15 @@ int perf_event__synthesize_modules(perf_event__handler_t process,
243 event->mmap.header.type = PERF_RECORD_MMAP; 244 event->mmap.header.type = PERF_RECORD_MMAP;
244 event->mmap.header.size = (sizeof(event->mmap) - 245 event->mmap.header.size = (sizeof(event->mmap) -
245 (sizeof(event->mmap.filename) - size)); 246 (sizeof(event->mmap.filename) - size));
246 memset(event->mmap.filename + size, 0, session->id_hdr_size); 247 memset(event->mmap.filename + size, 0, machine->id_hdr_size);
247 event->mmap.header.size += session->id_hdr_size; 248 event->mmap.header.size += machine->id_hdr_size;
248 event->mmap.start = pos->start; 249 event->mmap.start = pos->start;
249 event->mmap.len = pos->end - pos->start; 250 event->mmap.len = pos->end - pos->start;
250 event->mmap.pid = machine->pid; 251 event->mmap.pid = machine->pid;
251 252
252 memcpy(event->mmap.filename, pos->dso->long_name, 253 memcpy(event->mmap.filename, pos->dso->long_name,
253 pos->dso->long_name_len + 1); 254 pos->dso->long_name_len + 1);
254 process(event, &synth_sample, session); 255 process(tool, event, &synth_sample, machine);
255 } 256 }
256 257
257 free(event); 258 free(event);
@@ -261,28 +262,30 @@ int perf_event__synthesize_modules(perf_event__handler_t process,
261static int __event__synthesize_thread(union perf_event *comm_event, 262static int __event__synthesize_thread(union perf_event *comm_event,
262 union perf_event *mmap_event, 263 union perf_event *mmap_event,
263 pid_t pid, perf_event__handler_t process, 264 pid_t pid, perf_event__handler_t process,
264 struct perf_session *session) 265 struct perf_tool *tool,
266 struct machine *machine)
265{ 267{
266 pid_t tgid = perf_event__synthesize_comm(comm_event, pid, 1, process, 268 pid_t tgid = perf_event__synthesize_comm(tool, comm_event, pid, 1,
267 session); 269 process, machine);
268 if (tgid == -1) 270 if (tgid == -1)
269 return -1; 271 return -1;
270 return perf_event__synthesize_mmap_events(mmap_event, pid, tgid, 272 return perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
271 process, session); 273 process, machine);
272} 274}
273 275
274int perf_event__synthesize_thread_map(struct thread_map *threads, 276int perf_event__synthesize_thread_map(struct perf_tool *tool,
277 struct thread_map *threads,
275 perf_event__handler_t process, 278 perf_event__handler_t process,
276 struct perf_session *session) 279 struct machine *machine)
277{ 280{
278 union perf_event *comm_event, *mmap_event; 281 union perf_event *comm_event, *mmap_event;
279 int err = -1, thread; 282 int err = -1, thread;
280 283
281 comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size); 284 comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
282 if (comm_event == NULL) 285 if (comm_event == NULL)
283 goto out; 286 goto out;
284 287
285 mmap_event = malloc(sizeof(mmap_event->mmap) + session->id_hdr_size); 288 mmap_event = malloc(sizeof(mmap_event->mmap) + machine->id_hdr_size);
286 if (mmap_event == NULL) 289 if (mmap_event == NULL)
287 goto out_free_comm; 290 goto out_free_comm;
288 291
@@ -290,7 +293,7 @@ int perf_event__synthesize_thread_map(struct thread_map *threads,
290 for (thread = 0; thread < threads->nr; ++thread) { 293 for (thread = 0; thread < threads->nr; ++thread) {
291 if (__event__synthesize_thread(comm_event, mmap_event, 294 if (__event__synthesize_thread(comm_event, mmap_event,
292 threads->map[thread], 295 threads->map[thread],
293 process, session)) { 296 process, tool, machine)) {
294 err = -1; 297 err = -1;
295 break; 298 break;
296 } 299 }
@@ -302,19 +305,20 @@ out:
302 return err; 305 return err;
303} 306}
304 307
305int perf_event__synthesize_threads(perf_event__handler_t process, 308int perf_event__synthesize_threads(struct perf_tool *tool,
306 struct perf_session *session) 309 perf_event__handler_t process,
310 struct machine *machine)
307{ 311{
308 DIR *proc; 312 DIR *proc;
309 struct dirent dirent, *next; 313 struct dirent dirent, *next;
310 union perf_event *comm_event, *mmap_event; 314 union perf_event *comm_event, *mmap_event;
311 int err = -1; 315 int err = -1;
312 316
313 comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size); 317 comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
314 if (comm_event == NULL) 318 if (comm_event == NULL)
315 goto out; 319 goto out;
316 320
317 mmap_event = malloc(sizeof(mmap_event->mmap) + session->id_hdr_size); 321 mmap_event = malloc(sizeof(mmap_event->mmap) + machine->id_hdr_size);
318 if (mmap_event == NULL) 322 if (mmap_event == NULL)
319 goto out_free_comm; 323 goto out_free_comm;
320 324
@@ -330,7 +334,7 @@ int perf_event__synthesize_threads(perf_event__handler_t process,
330 continue; 334 continue;
331 335
332 __event__synthesize_thread(comm_event, mmap_event, pid, 336 __event__synthesize_thread(comm_event, mmap_event, pid,
333 process, session); 337 process, tool, machine);
334 } 338 }
335 339
336 closedir(proc); 340 closedir(proc);
@@ -365,8 +369,8 @@ static int find_symbol_cb(void *arg, const char *name, char type,
365 return 1; 369 return 1;
366} 370}
367 371
368int perf_event__synthesize_kernel_mmap(perf_event__handler_t process, 372int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
369 struct perf_session *session, 373 perf_event__handler_t process,
370 struct machine *machine, 374 struct machine *machine,
371 const char *symbol_name) 375 const char *symbol_name)
372{ 376{
@@ -383,7 +387,7 @@ int perf_event__synthesize_kernel_mmap(perf_event__handler_t process,
383 */ 387 */
384 struct process_symbol_args args = { .name = symbol_name, }; 388 struct process_symbol_args args = { .name = symbol_name, };
385 union perf_event *event = zalloc((sizeof(event->mmap) + 389 union perf_event *event = zalloc((sizeof(event->mmap) +
386 session->id_hdr_size)); 390 machine->id_hdr_size));
387 if (event == NULL) { 391 if (event == NULL) {
388 pr_debug("Not enough memory synthesizing mmap event " 392 pr_debug("Not enough memory synthesizing mmap event "
389 "for kernel modules\n"); 393 "for kernel modules\n");
@@ -417,25 +421,32 @@ int perf_event__synthesize_kernel_mmap(perf_event__handler_t process,
417 size = ALIGN(size, sizeof(u64)); 421 size = ALIGN(size, sizeof(u64));
418 event->mmap.header.type = PERF_RECORD_MMAP; 422 event->mmap.header.type = PERF_RECORD_MMAP;
419 event->mmap.header.size = (sizeof(event->mmap) - 423 event->mmap.header.size = (sizeof(event->mmap) -
420 (sizeof(event->mmap.filename) - size) + session->id_hdr_size); 424 (sizeof(event->mmap.filename) - size) + machine->id_hdr_size);
421 event->mmap.pgoff = args.start; 425 event->mmap.pgoff = args.start;
422 event->mmap.start = map->start; 426 event->mmap.start = map->start;
423 event->mmap.len = map->end - event->mmap.start; 427 event->mmap.len = map->end - event->mmap.start;
424 event->mmap.pid = machine->pid; 428 event->mmap.pid = machine->pid;
425 429
426 err = process(event, &synth_sample, session); 430 err = process(tool, event, &synth_sample, machine);
427 free(event); 431 free(event);
428 432
429 return err; 433 return err;
430} 434}
431 435
432int perf_event__process_comm(union perf_event *event, 436size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp)
437{
438 return fprintf(fp, ": %s:%d\n", event->comm.comm, event->comm.tid);
439}
440
441int perf_event__process_comm(struct perf_tool *tool __used,
442 union perf_event *event,
433 struct perf_sample *sample __used, 443 struct perf_sample *sample __used,
434 struct perf_session *session) 444 struct machine *machine)
435{ 445{
436 struct thread *thread = perf_session__findnew(session, event->comm.tid); 446 struct thread *thread = machine__findnew_thread(machine, event->comm.tid);
437 447
438 dump_printf(": %s:%d\n", event->comm.comm, event->comm.tid); 448 if (dump_trace)
449 perf_event__fprintf_comm(event, stdout);
439 450
440 if (thread == NULL || thread__set_comm(thread, event->comm.comm)) { 451 if (thread == NULL || thread__set_comm(thread, event->comm.comm)) {
441 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n"); 452 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
@@ -445,13 +456,13 @@ int perf_event__process_comm(union perf_event *event,
445 return 0; 456 return 0;
446} 457}
447 458
448int perf_event__process_lost(union perf_event *event, 459int perf_event__process_lost(struct perf_tool *tool __used,
460 union perf_event *event,
449 struct perf_sample *sample __used, 461 struct perf_sample *sample __used,
450 struct perf_session *session) 462 struct machine *machine __used)
451{ 463{
452 dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n", 464 dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n",
453 event->lost.id, event->lost.lost); 465 event->lost.id, event->lost.lost);
454 session->hists.stats.total_lost += event->lost.lost;
455 return 0; 466 return 0;
456} 467}
457 468
@@ -468,21 +479,15 @@ static void perf_event__set_kernel_mmap_len(union perf_event *event,
468 maps[MAP__FUNCTION]->end = ~0ULL; 479 maps[MAP__FUNCTION]->end = ~0ULL;
469} 480}
470 481
471static int perf_event__process_kernel_mmap(union perf_event *event, 482static int perf_event__process_kernel_mmap(struct perf_tool *tool __used,
472 struct perf_session *session) 483 union perf_event *event,
484 struct machine *machine)
473{ 485{
474 struct map *map; 486 struct map *map;
475 char kmmap_prefix[PATH_MAX]; 487 char kmmap_prefix[PATH_MAX];
476 struct machine *machine;
477 enum dso_kernel_type kernel_type; 488 enum dso_kernel_type kernel_type;
478 bool is_kernel_mmap; 489 bool is_kernel_mmap;
479 490
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)); 491 machine__mmap_name(machine, kmmap_prefix, sizeof(kmmap_prefix));
487 if (machine__is_host(machine)) 492 if (machine__is_host(machine))
488 kernel_type = DSO_TYPE_KERNEL; 493 kernel_type = DSO_TYPE_KERNEL;
@@ -549,9 +554,9 @@ static int perf_event__process_kernel_mmap(union perf_event *event,
549 * time /proc/sys/kernel/kptr_restrict was non zero. 554 * time /proc/sys/kernel/kptr_restrict was non zero.
550 */ 555 */
551 if (event->mmap.pgoff != 0) { 556 if (event->mmap.pgoff != 0) {
552 perf_session__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, 557 maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps,
553 symbol_name, 558 symbol_name,
554 event->mmap.pgoff); 559 event->mmap.pgoff);
555 } 560 }
556 561
557 if (machine__is_default_guest(machine)) { 562 if (machine__is_default_guest(machine)) {
@@ -567,32 +572,35 @@ out_problem:
567 return -1; 572 return -1;
568} 573}
569 574
570int perf_event__process_mmap(union perf_event *event, 575size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
576{
577 return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %s\n",
578 event->mmap.pid, event->mmap.tid, event->mmap.start,
579 event->mmap.len, event->mmap.pgoff, event->mmap.filename);
580}
581
582int perf_event__process_mmap(struct perf_tool *tool,
583 union perf_event *event,
571 struct perf_sample *sample __used, 584 struct perf_sample *sample __used,
572 struct perf_session *session) 585 struct machine *machine)
573{ 586{
574 struct machine *machine;
575 struct thread *thread; 587 struct thread *thread;
576 struct map *map; 588 struct map *map;
577 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 589 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
578 int ret = 0; 590 int ret = 0;
579 591
580 dump_printf(" %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %s\n", 592 if (dump_trace)
581 event->mmap.pid, event->mmap.tid, event->mmap.start, 593 perf_event__fprintf_mmap(event, stdout);
582 event->mmap.len, event->mmap.pgoff, event->mmap.filename);
583 594
584 if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL || 595 if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL ||
585 cpumode == PERF_RECORD_MISC_KERNEL) { 596 cpumode == PERF_RECORD_MISC_KERNEL) {
586 ret = perf_event__process_kernel_mmap(event, session); 597 ret = perf_event__process_kernel_mmap(tool, event, machine);
587 if (ret < 0) 598 if (ret < 0)
588 goto out_problem; 599 goto out_problem;
589 return 0; 600 return 0;
590 } 601 }
591 602
592 machine = perf_session__find_host_machine(session); 603 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) 604 if (thread == NULL)
597 goto out_problem; 605 goto out_problem;
598 map = map__new(&machine->user_dsos, event->mmap.start, 606 map = map__new(&machine->user_dsos, event->mmap.start,
@@ -610,18 +618,26 @@ out_problem:
610 return 0; 618 return 0;
611} 619}
612 620
613int perf_event__process_task(union perf_event *event, 621size_t perf_event__fprintf_task(union perf_event *event, FILE *fp)
622{
623 return fprintf(fp, "(%d:%d):(%d:%d)\n",
624 event->fork.pid, event->fork.tid,
625 event->fork.ppid, event->fork.ptid);
626}
627
628int perf_event__process_task(struct perf_tool *tool __used,
629 union perf_event *event,
614 struct perf_sample *sample __used, 630 struct perf_sample *sample __used,
615 struct perf_session *session) 631 struct machine *machine)
616{ 632{
617 struct thread *thread = perf_session__findnew(session, event->fork.tid); 633 struct thread *thread = machine__findnew_thread(machine, event->fork.tid);
618 struct thread *parent = perf_session__findnew(session, event->fork.ptid); 634 struct thread *parent = machine__findnew_thread(machine, event->fork.ptid);
619 635
620 dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid, 636 if (dump_trace)
621 event->fork.ppid, event->fork.ptid); 637 perf_event__fprintf_task(event, stdout);
622 638
623 if (event->header.type == PERF_RECORD_EXIT) { 639 if (event->header.type == PERF_RECORD_EXIT) {
624 perf_session__remove_thread(session, thread); 640 machine__remove_thread(machine, thread);
625 return 0; 641 return 0;
626 } 642 }
627 643
@@ -634,22 +650,45 @@ int perf_event__process_task(union perf_event *event,
634 return 0; 650 return 0;
635} 651}
636 652
637int perf_event__process(union perf_event *event, struct perf_sample *sample, 653size_t perf_event__fprintf(union perf_event *event, FILE *fp)
638 struct perf_session *session)
639{ 654{
655 size_t ret = fprintf(fp, "PERF_RECORD_%s",
656 perf_event__name(event->header.type));
657
640 switch (event->header.type) { 658 switch (event->header.type) {
641 case PERF_RECORD_COMM: 659 case PERF_RECORD_COMM:
642 perf_event__process_comm(event, sample, session); 660 ret += perf_event__fprintf_comm(event, fp);
661 break;
662 case PERF_RECORD_FORK:
663 case PERF_RECORD_EXIT:
664 ret += perf_event__fprintf_task(event, fp);
643 break; 665 break;
644 case PERF_RECORD_MMAP: 666 case PERF_RECORD_MMAP:
645 perf_event__process_mmap(event, sample, session); 667 ret += perf_event__fprintf_mmap(event, fp);
668 break;
669 default:
670 ret += fprintf(fp, "\n");
671 }
672
673 return ret;
674}
675
676int perf_event__process(struct perf_tool *tool, union perf_event *event,
677 struct perf_sample *sample, struct machine *machine)
678{
679 switch (event->header.type) {
680 case PERF_RECORD_COMM:
681 perf_event__process_comm(tool, event, sample, machine);
682 break;
683 case PERF_RECORD_MMAP:
684 perf_event__process_mmap(tool, event, sample, machine);
646 break; 685 break;
647 case PERF_RECORD_FORK: 686 case PERF_RECORD_FORK:
648 case PERF_RECORD_EXIT: 687 case PERF_RECORD_EXIT:
649 perf_event__process_task(event, sample, session); 688 perf_event__process_task(tool, event, sample, machine);
650 break; 689 break;
651 case PERF_RECORD_LOST: 690 case PERF_RECORD_LOST:
652 perf_event__process_lost(event, sample, session); 691 perf_event__process_lost(tool, event, sample, machine);
653 default: 692 default:
654 break; 693 break;
655 } 694 }
@@ -658,36 +697,29 @@ int perf_event__process(union perf_event *event, struct perf_sample *sample,
658} 697}
659 698
660void thread__find_addr_map(struct thread *self, 699void thread__find_addr_map(struct thread *self,
661 struct perf_session *session, u8 cpumode, 700 struct machine *machine, u8 cpumode,
662 enum map_type type, pid_t pid, u64 addr, 701 enum map_type type, u64 addr,
663 struct addr_location *al) 702 struct addr_location *al)
664{ 703{
665 struct map_groups *mg = &self->mg; 704 struct map_groups *mg = &self->mg;
666 struct machine *machine = NULL;
667 705
668 al->thread = self; 706 al->thread = self;
669 al->addr = addr; 707 al->addr = addr;
670 al->cpumode = cpumode; 708 al->cpumode = cpumode;
671 al->filtered = false; 709 al->filtered = false;
672 710
711 if (machine == NULL) {
712 al->map = NULL;
713 return;
714 }
715
673 if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) { 716 if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) {
674 al->level = 'k'; 717 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; 718 mg = &machine->kmaps;
681 } else if (cpumode == PERF_RECORD_MISC_USER && perf_host) { 719 } else if (cpumode == PERF_RECORD_MISC_USER && perf_host) {
682 al->level = '.'; 720 al->level = '.';
683 machine = perf_session__find_host_machine(session);
684 } else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) { 721 } else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) {
685 al->level = 'g'; 722 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; 723 mg = &machine->kmaps;
692 } else { 724 } else {
693 /* 725 /*
@@ -733,13 +765,12 @@ try_again:
733 al->addr = al->map->map_ip(al->map, al->addr); 765 al->addr = al->map->map_ip(al->map, al->addr);
734} 766}
735 767
736void thread__find_addr_location(struct thread *self, 768void thread__find_addr_location(struct thread *thread, struct machine *machine,
737 struct perf_session *session, u8 cpumode, 769 u8 cpumode, enum map_type type, u64 addr,
738 enum map_type type, pid_t pid, u64 addr,
739 struct addr_location *al, 770 struct addr_location *al,
740 symbol_filter_t filter) 771 symbol_filter_t filter)
741{ 772{
742 thread__find_addr_map(self, session, cpumode, type, pid, addr, al); 773 thread__find_addr_map(thread, machine, cpumode, type, addr, al);
743 if (al->map != NULL) 774 if (al->map != NULL)
744 al->sym = map__find_symbol(al->map, al->addr, filter); 775 al->sym = map__find_symbol(al->map, al->addr, filter);
745 else 776 else
@@ -747,13 +778,13 @@ void thread__find_addr_location(struct thread *self,
747} 778}
748 779
749int perf_event__preprocess_sample(const union perf_event *event, 780int perf_event__preprocess_sample(const union perf_event *event,
750 struct perf_session *session, 781 struct machine *machine,
751 struct addr_location *al, 782 struct addr_location *al,
752 struct perf_sample *sample, 783 struct perf_sample *sample,
753 symbol_filter_t filter) 784 symbol_filter_t filter)
754{ 785{
755 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 786 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
756 struct thread *thread = perf_session__findnew(session, event->ip.pid); 787 struct thread *thread = machine__findnew_thread(machine, event->ip.pid);
757 788
758 if (thread == NULL) 789 if (thread == NULL)
759 return -1; 790 return -1;
@@ -764,18 +795,18 @@ int perf_event__preprocess_sample(const union perf_event *event,
764 795
765 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); 796 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
766 /* 797 /*
767 * Have we already created the kernel maps for the host machine? 798 * Have we already created the kernel maps for this machine?
768 * 799 *
769 * This should have happened earlier, when we processed the kernel MMAP 800 * 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 801 * events, but for older perf.data files there was no such thing, so do
771 * it now. 802 * it now.
772 */ 803 */
773 if (cpumode == PERF_RECORD_MISC_KERNEL && 804 if (cpumode == PERF_RECORD_MISC_KERNEL &&
774 session->host_machine.vmlinux_maps[MAP__FUNCTION] == NULL) 805 machine->vmlinux_maps[MAP__FUNCTION] == NULL)
775 machine__create_kernel_maps(&session->host_machine); 806 machine__create_kernel_maps(machine);
776 807
777 thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION, 808 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
778 event->ip.pid, event->ip.ip, al); 809 event->ip.ip, al);
779 dump_printf(" ...... dso: %s\n", 810 dump_printf(" ...... dso: %s\n",
780 al->map ? al->map->dso->long_name : 811 al->map ? al->map->dso->long_name :
781 al->level == 'H' ? "[hypervisor]" : "<not found>"); 812 al->level == 'H' ? "[hypervisor]" : "<not found>");
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..8b19e7a1e881 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,6 +97,14 @@ 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 = {
@@ -100,6 +129,126 @@ error:
100 return -ENOMEM; 129 return -ENOMEM;
101} 130}
102 131
132int perf_evlist__add_attrs(struct perf_evlist *evlist,
133 struct perf_event_attr *attrs, size_t nr_attrs)
134{
135 struct perf_evsel *evsel, *n;
136 LIST_HEAD(head);
137 size_t i;
138
139 for (i = 0; i < nr_attrs; i++) {
140 evsel = perf_evsel__new(attrs + i, evlist->nr_entries + i);
141 if (evsel == NULL)
142 goto out_delete_partial_list;
143 list_add_tail(&evsel->node, &head);
144 }
145
146 perf_evlist__splice_list_tail(evlist, &head, nr_attrs);
147
148 return 0;
149
150out_delete_partial_list:
151 list_for_each_entry_safe(evsel, n, &head, node)
152 perf_evsel__delete(evsel);
153 return -1;
154}
155
156static int trace_event__id(const char *evname)
157{
158 char *filename, *colon;
159 int err = -1, fd;
160
161 if (asprintf(&filename, "%s/%s/id", tracing_events_path, evname) < 0)
162 return -1;
163
164 colon = strrchr(filename, ':');
165 if (colon != NULL)
166 *colon = '/';
167
168 fd = open(filename, O_RDONLY);
169 if (fd >= 0) {
170 char id[16];
171 if (read(fd, id, sizeof(id)) > 0)
172 err = atoi(id);
173 close(fd);
174 }
175
176 free(filename);
177 return err;
178}
179
180int perf_evlist__add_tracepoints(struct perf_evlist *evlist,
181 const char *tracepoints[],
182 size_t nr_tracepoints)
183{
184 int err;
185 size_t i;
186 struct perf_event_attr *attrs = zalloc(nr_tracepoints * sizeof(*attrs));
187
188 if (attrs == NULL)
189 return -1;
190
191 for (i = 0; i < nr_tracepoints; i++) {
192 err = trace_event__id(tracepoints[i]);
193
194 if (err < 0)
195 goto out_free_attrs;
196
197 attrs[i].type = PERF_TYPE_TRACEPOINT;
198 attrs[i].config = err;
199 attrs[i].sample_type = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
200 PERF_SAMPLE_CPU);
201 attrs[i].sample_period = 1;
202 }
203
204 err = perf_evlist__add_attrs(evlist, attrs, nr_tracepoints);
205out_free_attrs:
206 free(attrs);
207 return err;
208}
209
210static struct perf_evsel *
211 perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
212{
213 struct perf_evsel *evsel;
214
215 list_for_each_entry(evsel, &evlist->entries, node) {
216 if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
217 (int)evsel->attr.config == id)
218 return evsel;
219 }
220
221 return NULL;
222}
223
224int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist,
225 const struct perf_evsel_str_handler *assocs,
226 size_t nr_assocs)
227{
228 struct perf_evsel *evsel;
229 int err;
230 size_t i;
231
232 for (i = 0; i < nr_assocs; i++) {
233 err = trace_event__id(assocs[i].name);
234 if (err < 0)
235 goto out;
236
237 evsel = perf_evlist__find_tracepoint_by_id(evlist, err);
238 if (evsel == NULL)
239 continue;
240
241 err = -EEXIST;
242 if (evsel->handler.func != NULL)
243 goto out;
244 evsel->handler.func = assocs[i].handler;
245 }
246
247 err = 0;
248out:
249 return err;
250}
251
103void perf_evlist__disable(struct perf_evlist *evlist) 252void perf_evlist__disable(struct perf_evlist *evlist)
104{ 253{
105 int cpu, thread; 254 int cpu, thread;
@@ -126,7 +275,7 @@ void perf_evlist__enable(struct perf_evlist *evlist)
126 } 275 }
127} 276}
128 277
129int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) 278static int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
130{ 279{
131 int nfds = evlist->cpus->nr * evlist->threads->nr * evlist->nr_entries; 280 int nfds = evlist->cpus->nr * evlist->threads->nr * evlist->nr_entries;
132 evlist->pollfd = malloc(sizeof(struct pollfd) * nfds); 281 evlist->pollfd = malloc(sizeof(struct pollfd) * nfds);
@@ -282,7 +431,7 @@ void perf_evlist__munmap(struct perf_evlist *evlist)
282 evlist->mmap = NULL; 431 evlist->mmap = NULL;
283} 432}
284 433
285int perf_evlist__alloc_mmap(struct perf_evlist *evlist) 434static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
286{ 435{
287 evlist->nr_mmaps = evlist->cpus->nr; 436 evlist->nr_mmaps = evlist->cpus->nr;
288 if (evlist->cpus->map[0] == -1) 437 if (evlist->cpus->map[0] == -1)
@@ -400,14 +549,20 @@ out_unmap:
400 * 549 *
401 * Using perf_evlist__read_on_cpu does this automatically. 550 * Using perf_evlist__read_on_cpu does this automatically.
402 */ 551 */
403int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite) 552int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
553 bool overwrite)
404{ 554{
405 unsigned int page_size = sysconf(_SC_PAGE_SIZE); 555 unsigned int page_size = sysconf(_SC_PAGE_SIZE);
406 int mask = pages * page_size - 1;
407 struct perf_evsel *evsel; 556 struct perf_evsel *evsel;
408 const struct cpu_map *cpus = evlist->cpus; 557 const struct cpu_map *cpus = evlist->cpus;
409 const struct thread_map *threads = evlist->threads; 558 const struct thread_map *threads = evlist->threads;
410 int prot = PROT_READ | (overwrite ? 0 : PROT_WRITE); 559 int prot = PROT_READ | (overwrite ? 0 : PROT_WRITE), mask;
560
561 /* 512 kiB: default amount of unprivileged mlocked memory */
562 if (pages == UINT_MAX)
563 pages = (512 * 1024) / page_size;
564
565 mask = pages * page_size - 1;
411 566
412 if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0) 567 if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0)
413 return -ENOMEM; 568 return -ENOMEM;
@@ -512,6 +667,38 @@ u64 perf_evlist__sample_type(const struct perf_evlist *evlist)
512 return first->attr.sample_type; 667 return first->attr.sample_type;
513} 668}
514 669
670u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist)
671{
672 struct perf_evsel *first;
673 struct perf_sample *data;
674 u64 sample_type;
675 u16 size = 0;
676
677 first = list_entry(evlist->entries.next, struct perf_evsel, node);
678
679 if (!first->attr.sample_id_all)
680 goto out;
681
682 sample_type = first->attr.sample_type;
683
684 if (sample_type & PERF_SAMPLE_TID)
685 size += sizeof(data->tid) * 2;
686
687 if (sample_type & PERF_SAMPLE_TIME)
688 size += sizeof(data->time);
689
690 if (sample_type & PERF_SAMPLE_ID)
691 size += sizeof(data->id);
692
693 if (sample_type & PERF_SAMPLE_STREAM_ID)
694 size += sizeof(data->stream_id);
695
696 if (sample_type & PERF_SAMPLE_CPU)
697 size += sizeof(data->cpu) * 2;
698out:
699 return size;
700}
701
515bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist) 702bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist)
516{ 703{
517 struct perf_evsel *pos, *first; 704 struct perf_evsel *pos, *first;
@@ -569,3 +756,97 @@ out_err:
569 756
570 return err; 757 return err;
571} 758}
759
760int perf_evlist__prepare_workload(struct perf_evlist *evlist,
761 struct perf_record_opts *opts,
762 const char *argv[])
763{
764 int child_ready_pipe[2], go_pipe[2];
765 char bf;
766
767 if (pipe(child_ready_pipe) < 0) {
768 perror("failed to create 'ready' pipe");
769 return -1;
770 }
771
772 if (pipe(go_pipe) < 0) {
773 perror("failed to create 'go' pipe");
774 goto out_close_ready_pipe;
775 }
776
777 evlist->workload.pid = fork();
778 if (evlist->workload.pid < 0) {
779 perror("failed to fork");
780 goto out_close_pipes;
781 }
782
783 if (!evlist->workload.pid) {
784 if (opts->pipe_output)
785 dup2(2, 1);
786
787 close(child_ready_pipe[0]);
788 close(go_pipe[1]);
789 fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
790
791 /*
792 * Do a dummy execvp to get the PLT entry resolved,
793 * so we avoid the resolver overhead on the real
794 * execvp call.
795 */
796 execvp("", (char **)argv);
797
798 /*
799 * Tell the parent we're ready to go
800 */
801 close(child_ready_pipe[1]);
802
803 /*
804 * Wait until the parent tells us to go.
805 */
806 if (read(go_pipe[0], &bf, 1) == -1)
807 perror("unable to read pipe");
808
809 execvp(argv[0], (char **)argv);
810
811 perror(argv[0]);
812 kill(getppid(), SIGUSR1);
813 exit(-1);
814 }
815
816 if (!opts->system_wide && opts->target_tid == -1 && opts->target_pid == -1)
817 evlist->threads->map[0] = evlist->workload.pid;
818
819 close(child_ready_pipe[1]);
820 close(go_pipe[0]);
821 /*
822 * wait for child to settle
823 */
824 if (read(child_ready_pipe[0], &bf, 1) == -1) {
825 perror("unable to read pipe");
826 goto out_close_pipes;
827 }
828
829 evlist->workload.cork_fd = go_pipe[1];
830 close(child_ready_pipe[0]);
831 return 0;
832
833out_close_pipes:
834 close(go_pipe[0]);
835 close(go_pipe[1]);
836out_close_ready_pipe:
837 close(child_ready_pipe[0]);
838 close(child_ready_pipe[1]);
839 return -1;
840}
841
842int perf_evlist__start_workload(struct perf_evlist *evlist)
843{
844 if (evlist->workload.cork_fd > 0) {
845 /*
846 * Remove the cork, let it rip!
847 */
848 return close(evlist->workload.cork_fd);
849 }
850
851 return 0;
852}
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 d7915d4e77cb..4a8c8b02e9cc 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -63,6 +63,76 @@ struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx)
63 return evsel; 63 return evsel;
64} 64}
65 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->sample_id_all_avail &&
112 (opts->sample_time || opts->system_wide ||
113 !opts->no_inherit || opts->cpu_list))
114 attr->sample_type |= PERF_SAMPLE_TIME;
115
116 if (opts->raw_samples) {
117 attr->sample_type |= PERF_SAMPLE_TIME;
118 attr->sample_type |= PERF_SAMPLE_RAW;
119 attr->sample_type |= PERF_SAMPLE_CPU;
120 }
121
122 if (opts->no_delay) {
123 attr->watermark = 0;
124 attr->wakeup_events = 1;
125 }
126
127 attr->mmap = track;
128 attr->comm = track;
129
130 if (opts->target_pid == -1 && opts->target_tid == -1 && !opts->system_wide) {
131 attr->disabled = 1;
132 attr->enable_on_exec = 1;
133 }
134}
135
66int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) 136int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
67{ 137{
68 int cpu, thread; 138 int cpu, thread;
@@ -504,3 +574,82 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
504 574
505 return 0; 575 return 0;
506} 576}
577
578int perf_event__synthesize_sample(union perf_event *event, u64 type,
579 const struct perf_sample *sample,
580 bool swapped)
581{
582 u64 *array;
583
584 /*
585 * used for cross-endian analysis. See git commit 65014ab3
586 * for why this goofiness is needed.
587 */
588 union {
589 u64 val64;
590 u32 val32[2];
591 } u;
592
593 array = event->sample.array;
594
595 if (type & PERF_SAMPLE_IP) {
596 event->ip.ip = sample->ip;
597 array++;
598 }
599
600 if (type & PERF_SAMPLE_TID) {
601 u.val32[0] = sample->pid;
602 u.val32[1] = sample->tid;
603 if (swapped) {
604 /*
605 * Inverse of what is done in perf_event__parse_sample
606 */
607 u.val32[0] = bswap_32(u.val32[0]);
608 u.val32[1] = bswap_32(u.val32[1]);
609 u.val64 = bswap_64(u.val64);
610 }
611
612 *array = u.val64;
613 array++;
614 }
615
616 if (type & PERF_SAMPLE_TIME) {
617 *array = sample->time;
618 array++;
619 }
620
621 if (type & PERF_SAMPLE_ADDR) {
622 *array = sample->addr;
623 array++;
624 }
625
626 if (type & PERF_SAMPLE_ID) {
627 *array = sample->id;
628 array++;
629 }
630
631 if (type & PERF_SAMPLE_STREAM_ID) {
632 *array = sample->stream_id;
633 array++;
634 }
635
636 if (type & PERF_SAMPLE_CPU) {
637 u.val32[0] = sample->cpu;
638 if (swapped) {
639 /*
640 * Inverse of what is done in perf_event__parse_sample
641 */
642 u.val32[0] = bswap_32(u.val32[0]);
643 u.val64 = bswap_64(u.val64);
644 }
645 *array = u.val64;
646 array++;
647 }
648
649 if (type & PERF_SAMPLE_PERIOD) {
650 *array = sample->period;
651 array++;
652 }
653
654 return 0;
655}
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 33c17a2b2a81..5b01449152ef 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2041,6 +2041,8 @@ int perf_session__read_header(struct perf_session *session, int fd)
2041 lseek(fd, tmp, SEEK_SET); 2041 lseek(fd, tmp, SEEK_SET);
2042 } 2042 }
2043 2043
2044 symbol_conf.nr_events = nr_attrs;
2045
2044 if (f_header.event_types.size) { 2046 if (f_header.event_types.size) {
2045 lseek(fd, f_header.event_types.offset, SEEK_SET); 2047 lseek(fd, f_header.event_types.offset, SEEK_SET);
2046 events = malloc(f_header.event_types.size); 2048 events = malloc(f_header.event_types.size);
@@ -2068,9 +2070,9 @@ out_delete_evlist:
2068 return -ENOMEM; 2070 return -ENOMEM;
2069} 2071}
2070 2072
2071int perf_event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id, 2073int perf_event__synthesize_attr(struct perf_tool *tool,
2072 perf_event__handler_t process, 2074 struct perf_event_attr *attr, u16 ids, u64 *id,
2073 struct perf_session *session) 2075 perf_event__handler_t process)
2074{ 2076{
2075 union perf_event *ev; 2077 union perf_event *ev;
2076 size_t size; 2078 size_t size;
@@ -2092,22 +2094,23 @@ int perf_event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id,
2092 ev->attr.header.type = PERF_RECORD_HEADER_ATTR; 2094 ev->attr.header.type = PERF_RECORD_HEADER_ATTR;
2093 ev->attr.header.size = size; 2095 ev->attr.header.size = size;
2094 2096
2095 err = process(ev, NULL, session); 2097 err = process(tool, ev, NULL, NULL);
2096 2098
2097 free(ev); 2099 free(ev);
2098 2100
2099 return err; 2101 return err;
2100} 2102}
2101 2103
2102int perf_session__synthesize_attrs(struct perf_session *session, 2104int perf_event__synthesize_attrs(struct perf_tool *tool,
2105 struct perf_session *session,
2103 perf_event__handler_t process) 2106 perf_event__handler_t process)
2104{ 2107{
2105 struct perf_evsel *attr; 2108 struct perf_evsel *attr;
2106 int err = 0; 2109 int err = 0;
2107 2110
2108 list_for_each_entry(attr, &session->evlist->entries, node) { 2111 list_for_each_entry(attr, &session->evlist->entries, node) {
2109 err = perf_event__synthesize_attr(&attr->attr, attr->ids, 2112 err = perf_event__synthesize_attr(tool, &attr->attr, attr->ids,
2110 attr->id, process, session); 2113 attr->id, process);
2111 if (err) { 2114 if (err) {
2112 pr_debug("failed to create perf header attribute\n"); 2115 pr_debug("failed to create perf header attribute\n");
2113 return err; 2116 return err;
@@ -2118,23 +2121,23 @@ int perf_session__synthesize_attrs(struct perf_session *session,
2118} 2121}
2119 2122
2120int perf_event__process_attr(union perf_event *event, 2123int perf_event__process_attr(union perf_event *event,
2121 struct perf_session *session) 2124 struct perf_evlist **pevlist)
2122{ 2125{
2123 unsigned int i, ids, n_ids; 2126 unsigned int i, ids, n_ids;
2124 struct perf_evsel *evsel; 2127 struct perf_evsel *evsel;
2128 struct perf_evlist *evlist = *pevlist;
2125 2129
2126 if (session->evlist == NULL) { 2130 if (evlist == NULL) {
2127 session->evlist = perf_evlist__new(NULL, NULL); 2131 *pevlist = evlist = perf_evlist__new(NULL, NULL);
2128 if (session->evlist == NULL) 2132 if (evlist == NULL)
2129 return -ENOMEM; 2133 return -ENOMEM;
2130 } 2134 }
2131 2135
2132 evsel = perf_evsel__new(&event->attr.attr, 2136 evsel = perf_evsel__new(&event->attr.attr, evlist->nr_entries);
2133 session->evlist->nr_entries);
2134 if (evsel == NULL) 2137 if (evsel == NULL)
2135 return -ENOMEM; 2138 return -ENOMEM;
2136 2139
2137 perf_evlist__add(session->evlist, evsel); 2140 perf_evlist__add(evlist, evsel);
2138 2141
2139 ids = event->header.size; 2142 ids = event->header.size;
2140 ids -= (void *)&event->attr.id - (void *)event; 2143 ids -= (void *)&event->attr.id - (void *)event;
@@ -2148,18 +2151,16 @@ int perf_event__process_attr(union perf_event *event,
2148 return -ENOMEM; 2151 return -ENOMEM;
2149 2152
2150 for (i = 0; i < n_ids; i++) { 2153 for (i = 0; i < n_ids; i++) {
2151 perf_evlist__id_add(session->evlist, evsel, 0, i, 2154 perf_evlist__id_add(evlist, evsel, 0, i, event->attr.id[i]);
2152 event->attr.id[i]);
2153 } 2155 }
2154 2156
2155 perf_session__update_sample_type(session);
2156
2157 return 0; 2157 return 0;
2158} 2158}
2159 2159
2160int perf_event__synthesize_event_type(u64 event_id, char *name, 2160int perf_event__synthesize_event_type(struct perf_tool *tool,
2161 u64 event_id, char *name,
2161 perf_event__handler_t process, 2162 perf_event__handler_t process,
2162 struct perf_session *session) 2163 struct machine *machine)
2163{ 2164{
2164 union perf_event ev; 2165 union perf_event ev;
2165 size_t size = 0; 2166 size_t size = 0;
@@ -2177,13 +2178,14 @@ int perf_event__synthesize_event_type(u64 event_id, char *name,
2177 ev.event_type.header.size = sizeof(ev.event_type) - 2178 ev.event_type.header.size = sizeof(ev.event_type) -
2178 (sizeof(ev.event_type.event_type.name) - size); 2179 (sizeof(ev.event_type.event_type.name) - size);
2179 2180
2180 err = process(&ev, NULL, session); 2181 err = process(tool, &ev, NULL, machine);
2181 2182
2182 return err; 2183 return err;
2183} 2184}
2184 2185
2185int perf_event__synthesize_event_types(perf_event__handler_t process, 2186int perf_event__synthesize_event_types(struct perf_tool *tool,
2186 struct perf_session *session) 2187 perf_event__handler_t process,
2188 struct machine *machine)
2187{ 2189{
2188 struct perf_trace_event_type *type; 2190 struct perf_trace_event_type *type;
2189 int i, err = 0; 2191 int i, err = 0;
@@ -2191,9 +2193,9 @@ int perf_event__synthesize_event_types(perf_event__handler_t process,
2191 for (i = 0; i < event_count; i++) { 2193 for (i = 0; i < event_count; i++) {
2192 type = &events[i]; 2194 type = &events[i];
2193 2195
2194 err = perf_event__synthesize_event_type(type->event_id, 2196 err = perf_event__synthesize_event_type(tool, type->event_id,
2195 type->name, process, 2197 type->name, process,
2196 session); 2198 machine);
2197 if (err) { 2199 if (err) {
2198 pr_debug("failed to create perf header event type\n"); 2200 pr_debug("failed to create perf header event type\n");
2199 return err; 2201 return err;
@@ -2203,8 +2205,8 @@ int perf_event__synthesize_event_types(perf_event__handler_t process,
2203 return err; 2205 return err;
2204} 2206}
2205 2207
2206int perf_event__process_event_type(union perf_event *event, 2208int perf_event__process_event_type(struct perf_tool *tool __unused,
2207 struct perf_session *session __unused) 2209 union perf_event *event)
2208{ 2210{
2209 if (perf_header__push_event(event->event_type.event_type.event_id, 2211 if (perf_header__push_event(event->event_type.event_type.event_id,
2210 event->event_type.event_type.name) < 0) 2212 event->event_type.event_type.name) < 0)
@@ -2213,9 +2215,9 @@ int perf_event__process_event_type(union perf_event *event,
2213 return 0; 2215 return 0;
2214} 2216}
2215 2217
2216int perf_event__synthesize_tracing_data(int fd, struct perf_evlist *evlist, 2218int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,
2217 perf_event__handler_t process, 2219 struct perf_evlist *evlist,
2218 struct perf_session *session __unused) 2220 perf_event__handler_t process)
2219{ 2221{
2220 union perf_event ev; 2222 union perf_event ev;
2221 struct tracing_data *tdata; 2223 struct tracing_data *tdata;
@@ -2246,7 +2248,7 @@ int perf_event__synthesize_tracing_data(int fd, struct perf_evlist *evlist,
2246 ev.tracing_data.header.size = sizeof(ev.tracing_data); 2248 ev.tracing_data.header.size = sizeof(ev.tracing_data);
2247 ev.tracing_data.size = aligned_size; 2249 ev.tracing_data.size = aligned_size;
2248 2250
2249 process(&ev, NULL, session); 2251 process(tool, &ev, NULL, NULL);
2250 2252
2251 /* 2253 /*
2252 * The put function will copy all the tracing data 2254 * The put function will copy all the tracing data
@@ -2288,10 +2290,10 @@ int perf_event__process_tracing_data(union perf_event *event,
2288 return size_read + padding; 2290 return size_read + padding;
2289} 2291}
2290 2292
2291int perf_event__synthesize_build_id(struct dso *pos, u16 misc, 2293int perf_event__synthesize_build_id(struct perf_tool *tool,
2294 struct dso *pos, u16 misc,
2292 perf_event__handler_t process, 2295 perf_event__handler_t process,
2293 struct machine *machine, 2296 struct machine *machine)
2294 struct perf_session *session)
2295{ 2297{
2296 union perf_event ev; 2298 union perf_event ev;
2297 size_t len; 2299 size_t len;
@@ -2311,12 +2313,13 @@ int perf_event__synthesize_build_id(struct dso *pos, u16 misc,
2311 ev.build_id.header.size = sizeof(ev.build_id) + len; 2313 ev.build_id.header.size = sizeof(ev.build_id) + len;
2312 memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len); 2314 memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len);
2313 2315
2314 err = process(&ev, NULL, session); 2316 err = process(tool, &ev, NULL, machine);
2315 2317
2316 return err; 2318 return err;
2317} 2319}
2318 2320
2319int perf_event__process_build_id(union perf_event *event, 2321int perf_event__process_build_id(struct perf_tool *tool __used,
2322 union perf_event *event,
2320 struct perf_session *session) 2323 struct perf_session *session)
2321{ 2324{
2322 __event_process_build_id(&event->build_id, 2325 __event_process_build_id(&event->build_id,
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 3d5a742f4a2a..09365b32098e 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -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.h b/tools/perf/util/hist.h
index 89289c8e935e..ff6f9d56ea41 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -117,7 +117,6 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __used,
117 117
118static inline int hist_entry__tui_annotate(struct hist_entry *self __used, 118static inline int hist_entry__tui_annotate(struct hist_entry *self __used,
119 int evidx __used, 119 int evidx __used,
120 int nr_events __used,
121 void(*timer)(void *arg) __used, 120 void(*timer)(void *arg) __used,
122 void *arg __used, 121 void *arg __used,
123 int delay_secs __used) 122 int delay_secs __used)
@@ -128,7 +127,7 @@ static inline int hist_entry__tui_annotate(struct hist_entry *self __used,
128#define K_RIGHT -2 127#define K_RIGHT -2
129#else 128#else
130#include "ui/keysyms.h" 129#include "ui/keysyms.h"
131int hist_entry__tui_annotate(struct hist_entry *he, int evidx, int nr_events, 130int hist_entry__tui_annotate(struct hist_entry *he, int evidx,
132 void(*timer)(void *arg), void *arg, int delay_secs); 131 void(*timer)(void *arg), void *arg, int delay_secs);
133 132
134int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, 133int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
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..586ab3fe60f8 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
@@ -140,7 +138,7 @@ static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir)
140 char evt_path[MAXPATHLEN]; 138 char evt_path[MAXPATHLEN];
141 int fd; 139 int fd;
142 140
143 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path, 141 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", tracing_events_path,
144 sys_dir->d_name, evt_dir->d_name); 142 sys_dir->d_name, evt_dir->d_name);
145 fd = open(evt_path, O_RDONLY); 143 fd = open(evt_path, O_RDONLY);
146 if (fd < 0) 144 if (fd < 0)
@@ -171,16 +169,16 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
171 char evt_path[MAXPATHLEN]; 169 char evt_path[MAXPATHLEN];
172 char dir_path[MAXPATHLEN]; 170 char dir_path[MAXPATHLEN];
173 171
174 if (debugfs_valid_mountpoint(debugfs_path)) 172 if (debugfs_valid_mountpoint(tracing_events_path))
175 return NULL; 173 return NULL;
176 174
177 sys_dir = opendir(debugfs_path); 175 sys_dir = opendir(tracing_events_path);
178 if (!sys_dir) 176 if (!sys_dir)
179 return NULL; 177 return NULL;
180 178
181 for_each_subsystem(sys_dir, sys_dirent, sys_next) { 179 for_each_subsystem(sys_dir, sys_dirent, sys_next) {
182 180
183 snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path, 181 snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
184 sys_dirent.d_name); 182 sys_dirent.d_name);
185 evt_dir = opendir(dir_path); 183 evt_dir = opendir(dir_path);
186 if (!evt_dir) 184 if (!evt_dir)
@@ -447,7 +445,7 @@ parse_single_tracepoint_event(char *sys_name,
447 u64 id; 445 u64 id;
448 int fd; 446 int fd;
449 447
450 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path, 448 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", tracing_events_path,
451 sys_name, evt_name); 449 sys_name, evt_name);
452 450
453 fd = open(evt_path, O_RDONLY); 451 fd = open(evt_path, O_RDONLY);
@@ -485,7 +483,7 @@ parse_multiple_tracepoint_event(struct perf_evlist *evlist, char *sys_name,
485 struct dirent *evt_ent; 483 struct dirent *evt_ent;
486 DIR *evt_dir; 484 DIR *evt_dir;
487 485
488 snprintf(evt_path, MAXPATHLEN, "%s/%s", debugfs_path, sys_name); 486 snprintf(evt_path, MAXPATHLEN, "%s/%s", tracing_events_path, sys_name);
489 evt_dir = opendir(evt_path); 487 evt_dir = opendir(evt_path);
490 488
491 if (!evt_dir) { 489 if (!evt_dir) {
@@ -528,7 +526,7 @@ parse_tracepoint_event(struct perf_evlist *evlist, const char **strp,
528 char sys_name[MAX_EVENT_LENGTH]; 526 char sys_name[MAX_EVENT_LENGTH];
529 unsigned int sys_length, evt_length; 527 unsigned int sys_length, evt_length;
530 528
531 if (debugfs_valid_mountpoint(debugfs_path)) 529 if (debugfs_valid_mountpoint(tracing_events_path))
532 return 0; 530 return 0;
533 531
534 evt_name = strchr(*strp, ':'); 532 evt_name = strchr(*strp, ':');
@@ -920,10 +918,10 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob)
920 char evt_path[MAXPATHLEN]; 918 char evt_path[MAXPATHLEN];
921 char dir_path[MAXPATHLEN]; 919 char dir_path[MAXPATHLEN];
922 920
923 if (debugfs_valid_mountpoint(debugfs_path)) 921 if (debugfs_valid_mountpoint(tracing_events_path))
924 return; 922 return;
925 923
926 sys_dir = opendir(debugfs_path); 924 sys_dir = opendir(tracing_events_path);
927 if (!sys_dir) 925 if (!sys_dir)
928 return; 926 return;
929 927
@@ -932,7 +930,7 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob)
932 !strglobmatch(sys_dirent.d_name, subsys_glob)) 930 !strglobmatch(sys_dirent.d_name, subsys_glob))
933 continue; 931 continue;
934 932
935 snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path, 933 snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
936 sys_dirent.d_name); 934 sys_dirent.d_name);
937 evt_dir = opendir(dir_path); 935 evt_dir = opendir(dir_path);
938 if (!evt_dir) 936 if (!evt_dir)
@@ -964,16 +962,16 @@ int is_valid_tracepoint(const char *event_string)
964 char evt_path[MAXPATHLEN]; 962 char evt_path[MAXPATHLEN];
965 char dir_path[MAXPATHLEN]; 963 char dir_path[MAXPATHLEN];
966 964
967 if (debugfs_valid_mountpoint(debugfs_path)) 965 if (debugfs_valid_mountpoint(tracing_events_path))
968 return 0; 966 return 0;
969 967
970 sys_dir = opendir(debugfs_path); 968 sys_dir = opendir(tracing_events_path);
971 if (!sys_dir) 969 if (!sys_dir)
972 return 0; 970 return 0;
973 971
974 for_each_subsystem(sys_dir, sys_dirent, sys_next) { 972 for_each_subsystem(sys_dir, sys_dirent, sys_next) {
975 973
976 snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path, 974 snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
977 sys_dirent.d_name); 975 sys_dirent.d_name);
978 evt_dir = opendir(dir_path); 976 evt_dir = opendir(dir_path);
979 if (!evt_dir) 977 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..a82ce4303ff5 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -27,6 +27,8 @@
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"
31 33
32#include <EXTERN.h> 34#include <EXTERN.h>
@@ -248,7 +250,7 @@ static inline struct event *find_cache_event(int type)
248static void perl_process_event(union perf_event *pevent __unused, 250static void perl_process_event(union perf_event *pevent __unused,
249 struct perf_sample *sample, 251 struct perf_sample *sample,
250 struct perf_evsel *evsel, 252 struct perf_evsel *evsel,
251 struct perf_session *session __unused, 253 struct machine *machine __unused,
252 struct thread *thread) 254 struct thread *thread)
253{ 255{
254 struct format_field *field; 256 struct format_field *field;
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 0f4555ce9063..d9318d8a9ba1 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,7 +105,7 @@ 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 size_t len = filename ? strlen(filename) + 1 : 0;
136 struct perf_session *self = zalloc(sizeof(*self) + len); 111 struct perf_session *self = zalloc(sizeof(*self) + len);
@@ -139,9 +114,6 @@ struct perf_session *perf_session__new(const char *filename, int mode,
139 goto out; 114 goto out;
140 115
141 memcpy(self->filename, filename, len); 116 memcpy(self->filename, filename, len);
142 self->threads = RB_ROOT;
143 INIT_LIST_HEAD(&self->dead_threads);
144 self->last_match = NULL;
145 /* 117 /*
146 * On 64bit we can mmap the data file in one go. No need for tiny mmap 118 * On 64bit we can mmap the data file in one go. No need for tiny mmap
147 * slices. On 32bit we use 32MB. 119 * slices. On 32bit we use 32MB.
@@ -171,10 +143,10 @@ struct perf_session *perf_session__new(const char *filename, int mode,
171 goto out_delete; 143 goto out_delete;
172 } 144 }
173 145
174 if (ops && ops->ordering_requires_timestamps && 146 if (tool && tool->ordering_requires_timestamps &&
175 ops->ordered_samples && !self->sample_id_all) { 147 tool->ordered_samples && !self->sample_id_all) {
176 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); 148 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
177 ops->ordered_samples = false; 149 tool->ordered_samples = false;
178 } 150 }
179 151
180out: 152out:
@@ -184,17 +156,22 @@ out_delete:
184 return NULL; 156 return NULL;
185} 157}
186 158
187static void perf_session__delete_dead_threads(struct perf_session *self) 159static void machine__delete_dead_threads(struct machine *machine)
188{ 160{
189 struct thread *n, *t; 161 struct thread *n, *t;
190 162
191 list_for_each_entry_safe(t, n, &self->dead_threads, node) { 163 list_for_each_entry_safe(t, n, &machine->dead_threads, node) {
192 list_del(&t->node); 164 list_del(&t->node);
193 thread__delete(t); 165 thread__delete(t);
194 } 166 }
195} 167}
196 168
197static void perf_session__delete_threads(struct perf_session *self) 169static void perf_session__delete_dead_threads(struct perf_session *session)
170{
171 machine__delete_dead_threads(&session->host_machine);
172}
173
174static void machine__delete_threads(struct machine *self)
198{ 175{
199 struct rb_node *nd = rb_first(&self->threads); 176 struct rb_node *nd = rb_first(&self->threads);
200 177
@@ -207,6 +184,11 @@ static void perf_session__delete_threads(struct perf_session *self)
207 } 184 }
208} 185}
209 186
187static void perf_session__delete_threads(struct perf_session *session)
188{
189 machine__delete_threads(&session->host_machine);
190}
191
210void perf_session__delete(struct perf_session *self) 192void perf_session__delete(struct perf_session *self)
211{ 193{
212 perf_session__destroy_kernel_maps(self); 194 perf_session__destroy_kernel_maps(self);
@@ -217,7 +199,7 @@ void perf_session__delete(struct perf_session *self)
217 free(self); 199 free(self);
218} 200}
219 201
220void perf_session__remove_thread(struct perf_session *self, struct thread *th) 202void machine__remove_thread(struct machine *self, struct thread *th)
221{ 203{
222 self->last_match = NULL; 204 self->last_match = NULL;
223 rb_erase(&th->rb_node, &self->threads); 205 rb_erase(&th->rb_node, &self->threads);
@@ -236,16 +218,16 @@ static bool symbol__match_parent_regex(struct symbol *sym)
236 return 0; 218 return 0;
237} 219}
238 220
239int perf_session__resolve_callchain(struct perf_session *self, 221int machine__resolve_callchain(struct machine *self, struct perf_evsel *evsel,
240 struct thread *thread, 222 struct thread *thread,
241 struct ip_callchain *chain, 223 struct ip_callchain *chain,
242 struct symbol **parent) 224 struct symbol **parent)
243{ 225{
244 u8 cpumode = PERF_RECORD_MISC_USER; 226 u8 cpumode = PERF_RECORD_MISC_USER;
245 unsigned int i; 227 unsigned int i;
246 int err; 228 int err;
247 229
248 callchain_cursor_reset(&self->callchain_cursor); 230 callchain_cursor_reset(&evsel->hists.callchain_cursor);
249 231
250 for (i = 0; i < chain->nr; i++) { 232 for (i = 0; i < chain->nr; i++) {
251 u64 ip; 233 u64 ip;
@@ -272,7 +254,7 @@ int perf_session__resolve_callchain(struct perf_session *self,
272 254
273 al.filtered = false; 255 al.filtered = false;
274 thread__find_addr_location(thread, self, cpumode, 256 thread__find_addr_location(thread, self, cpumode,
275 MAP__FUNCTION, thread->pid, ip, &al, NULL); 257 MAP__FUNCTION, ip, &al, NULL);
276 if (al.sym != NULL) { 258 if (al.sym != NULL) {
277 if (sort__has_parent && !*parent && 259 if (sort__has_parent && !*parent &&
278 symbol__match_parent_regex(al.sym)) 260 symbol__match_parent_regex(al.sym))
@@ -281,7 +263,7 @@ int perf_session__resolve_callchain(struct perf_session *self,
281 break; 263 break;
282 } 264 }
283 265
284 err = callchain_cursor_append(&self->callchain_cursor, 266 err = callchain_cursor_append(&evsel->hists.callchain_cursor,
285 ip, al.map, al.sym); 267 ip, al.map, al.sym);
286 if (err) 268 if (err)
287 return err; 269 return err;
@@ -290,75 +272,91 @@ int perf_session__resolve_callchain(struct perf_session *self,
290 return 0; 272 return 0;
291} 273}
292 274
293static int process_event_synth_stub(union perf_event *event __used, 275static int process_event_synth_tracing_data_stub(union perf_event *event __used,
294 struct perf_session *session __used) 276 struct perf_session *session __used)
277{
278 dump_printf(": unhandled!\n");
279 return 0;
280}
281
282static int process_event_synth_attr_stub(union perf_event *event __used,
283 struct perf_evlist **pevlist __used)
295{ 284{
296 dump_printf(": unhandled!\n"); 285 dump_printf(": unhandled!\n");
297 return 0; 286 return 0;
298} 287}
299 288
300static int process_event_sample_stub(union perf_event *event __used, 289static int process_event_sample_stub(struct perf_tool *tool __used,
290 union perf_event *event __used,
301 struct perf_sample *sample __used, 291 struct perf_sample *sample __used,
302 struct perf_evsel *evsel __used, 292 struct perf_evsel *evsel __used,
303 struct perf_session *session __used) 293 struct machine *machine __used)
304{ 294{
305 dump_printf(": unhandled!\n"); 295 dump_printf(": unhandled!\n");
306 return 0; 296 return 0;
307} 297}
308 298
309static int process_event_stub(union perf_event *event __used, 299static int process_event_stub(struct perf_tool *tool __used,
300 union perf_event *event __used,
310 struct perf_sample *sample __used, 301 struct perf_sample *sample __used,
311 struct perf_session *session __used) 302 struct machine *machine __used)
303{
304 dump_printf(": unhandled!\n");
305 return 0;
306}
307
308static int process_finished_round_stub(struct perf_tool *tool __used,
309 union perf_event *event __used,
310 struct perf_session *perf_session __used)
312{ 311{
313 dump_printf(": unhandled!\n"); 312 dump_printf(": unhandled!\n");
314 return 0; 313 return 0;
315} 314}
316 315
317static int process_finished_round_stub(union perf_event *event __used, 316static int process_event_type_stub(struct perf_tool *tool __used,
318 struct perf_session *session __used, 317 union perf_event *event __used)
319 struct perf_event_ops *ops __used)
320{ 318{
321 dump_printf(": unhandled!\n"); 319 dump_printf(": unhandled!\n");
322 return 0; 320 return 0;
323} 321}
324 322
325static int process_finished_round(union perf_event *event, 323static int process_finished_round(struct perf_tool *tool,
326 struct perf_session *session, 324 union perf_event *event,
327 struct perf_event_ops *ops); 325 struct perf_session *session);
328 326
329static void perf_event_ops__fill_defaults(struct perf_event_ops *handler) 327static void perf_tool__fill_defaults(struct perf_tool *tool)
330{ 328{
331 if (handler->sample == NULL) 329 if (tool->sample == NULL)
332 handler->sample = process_event_sample_stub; 330 tool->sample = process_event_sample_stub;
333 if (handler->mmap == NULL) 331 if (tool->mmap == NULL)
334 handler->mmap = process_event_stub; 332 tool->mmap = process_event_stub;
335 if (handler->comm == NULL) 333 if (tool->comm == NULL)
336 handler->comm = process_event_stub; 334 tool->comm = process_event_stub;
337 if (handler->fork == NULL) 335 if (tool->fork == NULL)
338 handler->fork = process_event_stub; 336 tool->fork = process_event_stub;
339 if (handler->exit == NULL) 337 if (tool->exit == NULL)
340 handler->exit = process_event_stub; 338 tool->exit = process_event_stub;
341 if (handler->lost == NULL) 339 if (tool->lost == NULL)
342 handler->lost = perf_event__process_lost; 340 tool->lost = perf_event__process_lost;
343 if (handler->read == NULL) 341 if (tool->read == NULL)
344 handler->read = process_event_stub; 342 tool->read = process_event_sample_stub;
345 if (handler->throttle == NULL) 343 if (tool->throttle == NULL)
346 handler->throttle = process_event_stub; 344 tool->throttle = process_event_stub;
347 if (handler->unthrottle == NULL) 345 if (tool->unthrottle == NULL)
348 handler->unthrottle = process_event_stub; 346 tool->unthrottle = process_event_stub;
349 if (handler->attr == NULL) 347 if (tool->attr == NULL)
350 handler->attr = process_event_synth_stub; 348 tool->attr = process_event_synth_attr_stub;
351 if (handler->event_type == NULL) 349 if (tool->event_type == NULL)
352 handler->event_type = process_event_synth_stub; 350 tool->event_type = process_event_type_stub;
353 if (handler->tracing_data == NULL) 351 if (tool->tracing_data == NULL)
354 handler->tracing_data = process_event_synth_stub; 352 tool->tracing_data = process_event_synth_tracing_data_stub;
355 if (handler->build_id == NULL) 353 if (tool->build_id == NULL)
356 handler->build_id = process_event_synth_stub; 354 tool->build_id = process_finished_round_stub;
357 if (handler->finished_round == NULL) { 355 if (tool->finished_round == NULL) {
358 if (handler->ordered_samples) 356 if (tool->ordered_samples)
359 handler->finished_round = process_finished_round; 357 tool->finished_round = process_finished_round;
360 else 358 else
361 handler->finished_round = process_finished_round_stub; 359 tool->finished_round = process_finished_round_stub;
362 } 360 }
363} 361}
364 362
@@ -490,11 +488,11 @@ static void perf_session_free_sample_buffers(struct perf_session *session)
490static int perf_session_deliver_event(struct perf_session *session, 488static int perf_session_deliver_event(struct perf_session *session,
491 union perf_event *event, 489 union perf_event *event,
492 struct perf_sample *sample, 490 struct perf_sample *sample,
493 struct perf_event_ops *ops, 491 struct perf_tool *tool,
494 u64 file_offset); 492 u64 file_offset);
495 493
496static void flush_sample_queue(struct perf_session *s, 494static void flush_sample_queue(struct perf_session *s,
497 struct perf_event_ops *ops) 495 struct perf_tool *tool)
498{ 496{
499 struct ordered_samples *os = &s->ordered_samples; 497 struct ordered_samples *os = &s->ordered_samples;
500 struct list_head *head = &os->samples; 498 struct list_head *head = &os->samples;
@@ -505,7 +503,7 @@ static void flush_sample_queue(struct perf_session *s,
505 unsigned idx = 0, progress_next = os->nr_samples / 16; 503 unsigned idx = 0, progress_next = os->nr_samples / 16;
506 int ret; 504 int ret;
507 505
508 if (!ops->ordered_samples || !limit) 506 if (!tool->ordered_samples || !limit)
509 return; 507 return;
510 508
511 list_for_each_entry_safe(iter, tmp, head, list) { 509 list_for_each_entry_safe(iter, tmp, head, list) {
@@ -516,7 +514,7 @@ static void flush_sample_queue(struct perf_session *s,
516 if (ret) 514 if (ret)
517 pr_err("Can't parse sample, err = %d\n", ret); 515 pr_err("Can't parse sample, err = %d\n", ret);
518 else 516 else
519 perf_session_deliver_event(s, iter->event, &sample, ops, 517 perf_session_deliver_event(s, iter->event, &sample, tool,
520 iter->file_offset); 518 iter->file_offset);
521 519
522 os->last_flush = iter->timestamp; 520 os->last_flush = iter->timestamp;
@@ -578,11 +576,11 @@ static void flush_sample_queue(struct perf_session *s,
578 * Flush every events below timestamp 7 576 * Flush every events below timestamp 7
579 * etc... 577 * etc...
580 */ 578 */
581static int process_finished_round(union perf_event *event __used, 579static int process_finished_round(struct perf_tool *tool,
582 struct perf_session *session, 580 union perf_event *event __used,
583 struct perf_event_ops *ops) 581 struct perf_session *session)
584{ 582{
585 flush_sample_queue(session, ops); 583 flush_sample_queue(session, tool);
586 session->ordered_samples.next_flush = session->ordered_samples.max_timestamp; 584 session->ordered_samples.next_flush = session->ordered_samples.max_timestamp;
587 585
588 return 0; 586 return 0;
@@ -737,13 +735,26 @@ static void dump_sample(struct perf_session *session, union perf_event *event,
737 callchain__printf(sample); 735 callchain__printf(sample);
738} 736}
739 737
738static struct machine *
739 perf_session__find_machine_for_cpumode(struct perf_session *session,
740 union perf_event *event)
741{
742 const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
743
744 if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest)
745 return perf_session__find_machine(session, event->ip.pid);
746
747 return perf_session__find_host_machine(session);
748}
749
740static int perf_session_deliver_event(struct perf_session *session, 750static int perf_session_deliver_event(struct perf_session *session,
741 union perf_event *event, 751 union perf_event *event,
742 struct perf_sample *sample, 752 struct perf_sample *sample,
743 struct perf_event_ops *ops, 753 struct perf_tool *tool,
744 u64 file_offset) 754 u64 file_offset)
745{ 755{
746 struct perf_evsel *evsel; 756 struct perf_evsel *evsel;
757 struct machine *machine;
747 758
748 dump_event(session, event, file_offset, sample); 759 dump_event(session, event, file_offset, sample);
749 760
@@ -765,6 +776,8 @@ static int perf_session_deliver_event(struct perf_session *session,
765 hists__inc_nr_events(&evsel->hists, event->header.type); 776 hists__inc_nr_events(&evsel->hists, event->header.type);
766 } 777 }
767 778
779 machine = perf_session__find_machine_for_cpumode(session, event);
780
768 switch (event->header.type) { 781 switch (event->header.type) {
769 case PERF_RECORD_SAMPLE: 782 case PERF_RECORD_SAMPLE:
770 dump_sample(session, event, sample); 783 dump_sample(session, event, sample);
@@ -772,23 +785,25 @@ static int perf_session_deliver_event(struct perf_session *session,
772 ++session->hists.stats.nr_unknown_id; 785 ++session->hists.stats.nr_unknown_id;
773 return -1; 786 return -1;
774 } 787 }
775 return ops->sample(event, sample, evsel, session); 788 return tool->sample(tool, event, sample, evsel, machine);
776 case PERF_RECORD_MMAP: 789 case PERF_RECORD_MMAP:
777 return ops->mmap(event, sample, session); 790 return tool->mmap(tool, event, sample, machine);
778 case PERF_RECORD_COMM: 791 case PERF_RECORD_COMM:
779 return ops->comm(event, sample, session); 792 return tool->comm(tool, event, sample, machine);
780 case PERF_RECORD_FORK: 793 case PERF_RECORD_FORK:
781 return ops->fork(event, sample, session); 794 return tool->fork(tool, event, sample, machine);
782 case PERF_RECORD_EXIT: 795 case PERF_RECORD_EXIT:
783 return ops->exit(event, sample, session); 796 return tool->exit(tool, event, sample, machine);
784 case PERF_RECORD_LOST: 797 case PERF_RECORD_LOST:
785 return ops->lost(event, sample, session); 798 if (tool->lost == perf_event__process_lost)
799 session->hists.stats.total_lost += event->lost.lost;
800 return tool->lost(tool, event, sample, machine);
786 case PERF_RECORD_READ: 801 case PERF_RECORD_READ:
787 return ops->read(event, sample, session); 802 return tool->read(tool, event, sample, evsel, machine);
788 case PERF_RECORD_THROTTLE: 803 case PERF_RECORD_THROTTLE:
789 return ops->throttle(event, sample, session); 804 return tool->throttle(tool, event, sample, machine);
790 case PERF_RECORD_UNTHROTTLE: 805 case PERF_RECORD_UNTHROTTLE:
791 return ops->unthrottle(event, sample, session); 806 return tool->unthrottle(tool, event, sample, machine);
792 default: 807 default:
793 ++session->hists.stats.nr_unknown_events; 808 ++session->hists.stats.nr_unknown_events;
794 return -1; 809 return -1;
@@ -812,24 +827,29 @@ static int perf_session__preprocess_sample(struct perf_session *session,
812} 827}
813 828
814static int perf_session__process_user_event(struct perf_session *session, union perf_event *event, 829static int perf_session__process_user_event(struct perf_session *session, union perf_event *event,
815 struct perf_event_ops *ops, u64 file_offset) 830 struct perf_tool *tool, u64 file_offset)
816{ 831{
832 int err;
833
817 dump_event(session, event, file_offset, NULL); 834 dump_event(session, event, file_offset, NULL);
818 835
819 /* These events are processed right away */ 836 /* These events are processed right away */
820 switch (event->header.type) { 837 switch (event->header.type) {
821 case PERF_RECORD_HEADER_ATTR: 838 case PERF_RECORD_HEADER_ATTR:
822 return ops->attr(event, session); 839 err = tool->attr(event, &session->evlist);
840 if (err == 0)
841 perf_session__update_sample_type(session);
842 return err;
823 case PERF_RECORD_HEADER_EVENT_TYPE: 843 case PERF_RECORD_HEADER_EVENT_TYPE:
824 return ops->event_type(event, session); 844 return tool->event_type(tool, event);
825 case PERF_RECORD_HEADER_TRACING_DATA: 845 case PERF_RECORD_HEADER_TRACING_DATA:
826 /* setup for reading amidst mmap */ 846 /* setup for reading amidst mmap */
827 lseek(session->fd, file_offset, SEEK_SET); 847 lseek(session->fd, file_offset, SEEK_SET);
828 return ops->tracing_data(event, session); 848 return tool->tracing_data(event, session);
829 case PERF_RECORD_HEADER_BUILD_ID: 849 case PERF_RECORD_HEADER_BUILD_ID:
830 return ops->build_id(event, session); 850 return tool->build_id(tool, event, session);
831 case PERF_RECORD_FINISHED_ROUND: 851 case PERF_RECORD_FINISHED_ROUND:
832 return ops->finished_round(event, session, ops); 852 return tool->finished_round(tool, event, session);
833 default: 853 default:
834 return -EINVAL; 854 return -EINVAL;
835 } 855 }
@@ -837,7 +857,7 @@ static int perf_session__process_user_event(struct perf_session *session, union
837 857
838static int perf_session__process_event(struct perf_session *session, 858static int perf_session__process_event(struct perf_session *session,
839 union perf_event *event, 859 union perf_event *event,
840 struct perf_event_ops *ops, 860 struct perf_tool *tool,
841 u64 file_offset) 861 u64 file_offset)
842{ 862{
843 struct perf_sample sample; 863 struct perf_sample sample;
@@ -853,7 +873,7 @@ static int perf_session__process_event(struct perf_session *session,
853 hists__inc_nr_events(&session->hists, event->header.type); 873 hists__inc_nr_events(&session->hists, event->header.type);
854 874
855 if (event->header.type >= PERF_RECORD_USER_TYPE_START) 875 if (event->header.type >= PERF_RECORD_USER_TYPE_START)
856 return perf_session__process_user_event(session, event, ops, file_offset); 876 return perf_session__process_user_event(session, event, tool, file_offset);
857 877
858 /* 878 /*
859 * For all kernel events we get the sample data 879 * For all kernel events we get the sample data
@@ -866,14 +886,14 @@ static int perf_session__process_event(struct perf_session *session,
866 if (perf_session__preprocess_sample(session, event, &sample)) 886 if (perf_session__preprocess_sample(session, event, &sample))
867 return 0; 887 return 0;
868 888
869 if (ops->ordered_samples) { 889 if (tool->ordered_samples) {
870 ret = perf_session_queue_event(session, event, &sample, 890 ret = perf_session_queue_event(session, event, &sample,
871 file_offset); 891 file_offset);
872 if (ret != -ETIME) 892 if (ret != -ETIME)
873 return ret; 893 return ret;
874 } 894 }
875 895
876 return perf_session_deliver_event(session, event, &sample, ops, 896 return perf_session_deliver_event(session, event, &sample, tool,
877 file_offset); 897 file_offset);
878} 898}
879 899
@@ -884,6 +904,11 @@ void perf_event_header__bswap(struct perf_event_header *self)
884 self->size = bswap_16(self->size); 904 self->size = bswap_16(self->size);
885} 905}
886 906
907struct thread *perf_session__findnew(struct perf_session *session, pid_t pid)
908{
909 return machine__findnew_thread(&session->host_machine, pid);
910}
911
887static struct thread *perf_session__register_idle_thread(struct perf_session *self) 912static struct thread *perf_session__register_idle_thread(struct perf_session *self)
888{ 913{
889 struct thread *thread = perf_session__findnew(self, 0); 914 struct thread *thread = perf_session__findnew(self, 0);
@@ -897,9 +922,9 @@ static struct thread *perf_session__register_idle_thread(struct perf_session *se
897} 922}
898 923
899static void perf_session__warn_about_errors(const struct perf_session *session, 924static void perf_session__warn_about_errors(const struct perf_session *session,
900 const struct perf_event_ops *ops) 925 const struct perf_tool *tool)
901{ 926{
902 if (ops->lost == perf_event__process_lost && 927 if (tool->lost == perf_event__process_lost &&
903 session->hists.stats.nr_events[PERF_RECORD_LOST] != 0) { 928 session->hists.stats.nr_events[PERF_RECORD_LOST] != 0) {
904 ui__warning("Processed %d events and lost %d chunks!\n\n" 929 ui__warning("Processed %d events and lost %d chunks!\n\n"
905 "Check IO/CPU overload!\n\n", 930 "Check IO/CPU overload!\n\n",
@@ -934,7 +959,7 @@ static void perf_session__warn_about_errors(const struct perf_session *session,
934volatile int session_done; 959volatile int session_done;
935 960
936static int __perf_session__process_pipe_events(struct perf_session *self, 961static int __perf_session__process_pipe_events(struct perf_session *self,
937 struct perf_event_ops *ops) 962 struct perf_tool *tool)
938{ 963{
939 union perf_event event; 964 union perf_event event;
940 uint32_t size; 965 uint32_t size;
@@ -943,7 +968,7 @@ static int __perf_session__process_pipe_events(struct perf_session *self,
943 int err; 968 int err;
944 void *p; 969 void *p;
945 970
946 perf_event_ops__fill_defaults(ops); 971 perf_tool__fill_defaults(tool);
947 972
948 head = 0; 973 head = 0;
949more: 974more:
@@ -980,7 +1005,7 @@ more:
980 } 1005 }
981 1006
982 if (size == 0 || 1007 if (size == 0 ||
983 (skip = perf_session__process_event(self, &event, ops, head)) < 0) { 1008 (skip = perf_session__process_event(self, &event, tool, head)) < 0) {
984 dump_printf("%#" PRIx64 " [%#x]: skipping unknown header type: %d\n", 1009 dump_printf("%#" PRIx64 " [%#x]: skipping unknown header type: %d\n",
985 head, event.header.size, event.header.type); 1010 head, event.header.size, event.header.type);
986 /* 1011 /*
@@ -1003,7 +1028,7 @@ more:
1003done: 1028done:
1004 err = 0; 1029 err = 0;
1005out_err: 1030out_err:
1006 perf_session__warn_about_errors(self, ops); 1031 perf_session__warn_about_errors(self, tool);
1007 perf_session_free_sample_buffers(self); 1032 perf_session_free_sample_buffers(self);
1008 return err; 1033 return err;
1009} 1034}
@@ -1034,7 +1059,7 @@ fetch_mmaped_event(struct perf_session *session,
1034 1059
1035int __perf_session__process_events(struct perf_session *session, 1060int __perf_session__process_events(struct perf_session *session,
1036 u64 data_offset, u64 data_size, 1061 u64 data_offset, u64 data_size,
1037 u64 file_size, struct perf_event_ops *ops) 1062 u64 file_size, struct perf_tool *tool)
1038{ 1063{
1039 u64 head, page_offset, file_offset, file_pos, progress_next; 1064 u64 head, page_offset, file_offset, file_pos, progress_next;
1040 int err, mmap_prot, mmap_flags, map_idx = 0; 1065 int err, mmap_prot, mmap_flags, map_idx = 0;
@@ -1043,7 +1068,7 @@ int __perf_session__process_events(struct perf_session *session,
1043 union perf_event *event; 1068 union perf_event *event;
1044 uint32_t size; 1069 uint32_t size;
1045 1070
1046 perf_event_ops__fill_defaults(ops); 1071 perf_tool__fill_defaults(tool);
1047 1072
1048 page_size = sysconf(_SC_PAGESIZE); 1073 page_size = sysconf(_SC_PAGESIZE);
1049 1074
@@ -1098,7 +1123,7 @@ more:
1098 size = event->header.size; 1123 size = event->header.size;
1099 1124
1100 if (size == 0 || 1125 if (size == 0 ||
1101 perf_session__process_event(session, event, ops, file_pos) < 0) { 1126 perf_session__process_event(session, event, tool, file_pos) < 0) {
1102 dump_printf("%#" PRIx64 " [%#x]: skipping unknown header type: %d\n", 1127 dump_printf("%#" PRIx64 " [%#x]: skipping unknown header type: %d\n",
1103 file_offset + head, event->header.size, 1128 file_offset + head, event->header.size,
1104 event->header.type); 1129 event->header.type);
@@ -1127,15 +1152,15 @@ more:
1127 err = 0; 1152 err = 0;
1128 /* do the final flush for ordered samples */ 1153 /* do the final flush for ordered samples */
1129 session->ordered_samples.next_flush = ULLONG_MAX; 1154 session->ordered_samples.next_flush = ULLONG_MAX;
1130 flush_sample_queue(session, ops); 1155 flush_sample_queue(session, tool);
1131out_err: 1156out_err:
1132 perf_session__warn_about_errors(session, ops); 1157 perf_session__warn_about_errors(session, tool);
1133 perf_session_free_sample_buffers(session); 1158 perf_session_free_sample_buffers(session);
1134 return err; 1159 return err;
1135} 1160}
1136 1161
1137int perf_session__process_events(struct perf_session *self, 1162int perf_session__process_events(struct perf_session *self,
1138 struct perf_event_ops *ops) 1163 struct perf_tool *tool)
1139{ 1164{
1140 int err; 1165 int err;
1141 1166
@@ -1146,9 +1171,9 @@ int perf_session__process_events(struct perf_session *self,
1146 err = __perf_session__process_events(self, 1171 err = __perf_session__process_events(self,
1147 self->header.data_offset, 1172 self->header.data_offset,
1148 self->header.data_size, 1173 self->header.data_size,
1149 self->size, ops); 1174 self->size, tool);
1150 else 1175 else
1151 err = __perf_session__process_pipe_events(self, ops); 1176 err = __perf_session__process_pipe_events(self, tool);
1152 1177
1153 return err; 1178 return err;
1154} 1179}
@@ -1163,9 +1188,8 @@ bool perf_session__has_traces(struct perf_session *self, const char *msg)
1163 return true; 1188 return true;
1164} 1189}
1165 1190
1166int perf_session__set_kallsyms_ref_reloc_sym(struct map **maps, 1191int maps__set_kallsyms_ref_reloc_sym(struct map **maps,
1167 const char *symbol_name, 1192 const char *symbol_name, u64 addr)
1168 u64 addr)
1169{ 1193{
1170 char *bracket; 1194 char *bracket;
1171 enum map_type i; 1195 enum map_type i;
@@ -1224,6 +1248,27 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
1224 return ret; 1248 return ret;
1225} 1249}
1226 1250
1251size_t perf_session__fprintf(struct perf_session *session, FILE *fp)
1252{
1253 /*
1254 * FIXME: Here we have to actually print all the machines in this
1255 * session, not just the host...
1256 */
1257 return machine__fprintf(&session->host_machine, fp);
1258}
1259
1260void perf_session__remove_thread(struct perf_session *session,
1261 struct thread *th)
1262{
1263 /*
1264 * FIXME: This one makes no sense, we need to remove the thread from
1265 * the machine it belongs to, perf_session can have many machines, so
1266 * doing it always on ->host_machine is wrong. Fix when auditing all
1267 * the 'perf kvm' code.
1268 */
1269 machine__remove_thread(&session->host_machine, th);
1270}
1271
1227struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, 1272struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
1228 unsigned int type) 1273 unsigned int type)
1229{ 1274{
@@ -1236,17 +1281,16 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
1236 return NULL; 1281 return NULL;
1237} 1282}
1238 1283
1239void perf_session__print_ip(union perf_event *event, 1284void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
1240 struct perf_sample *sample, 1285 struct machine *machine, struct perf_evsel *evsel,
1241 struct perf_session *session, 1286 int print_sym, int print_dso)
1242 int print_sym, int print_dso)
1243{ 1287{
1244 struct addr_location al; 1288 struct addr_location al;
1245 const char *symname, *dsoname; 1289 const char *symname, *dsoname;
1246 struct callchain_cursor *cursor = &session->callchain_cursor; 1290 struct callchain_cursor *cursor = &evsel->hists.callchain_cursor;
1247 struct callchain_cursor_node *node; 1291 struct callchain_cursor_node *node;
1248 1292
1249 if (perf_event__preprocess_sample(event, session, &al, sample, 1293 if (perf_event__preprocess_sample(event, machine, &al, sample,
1250 NULL) < 0) { 1294 NULL) < 0) {
1251 error("problem processing %d event, skipping it.\n", 1295 error("problem processing %d event, skipping it.\n",
1252 event->header.type); 1296 event->header.type);
@@ -1255,7 +1299,7 @@ void perf_session__print_ip(union perf_event *event,
1255 1299
1256 if (symbol_conf.use_callchain && sample->callchain) { 1300 if (symbol_conf.use_callchain && sample->callchain) {
1257 1301
1258 if (perf_session__resolve_callchain(session, al.thread, 1302 if (machine__resolve_callchain(machine, evsel, al.thread,
1259 sample->callchain, NULL) != 0) { 1303 sample->callchain, NULL) != 0) {
1260 if (verbose) 1304 if (verbose)
1261 error("Failed to resolve callchain. Skipping\n"); 1305 error("Failed to resolve callchain. Skipping\n");
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 6e393c98eb34..fb696124ad61 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;
57 char filename[0]; 53 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.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..ac6830d8292b 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -18,7 +18,8 @@
18 * 18 *
19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20 */ 20 */
21#define _GNU_SOURCE 21#include <ctype.h>
22#include "util.h"
22#include <dirent.h> 23#include <dirent.h>
23#include <mntent.h> 24#include <mntent.h>
24#include <stdio.h> 25#include <stdio.h>
@@ -31,7 +32,6 @@
31#include <pthread.h> 32#include <pthread.h>
32#include <fcntl.h> 33#include <fcntl.h>
33#include <unistd.h> 34#include <unistd.h>
34#include <ctype.h>
35#include <errno.h> 35#include <errno.h>
36#include <stdbool.h> 36#include <stdbool.h>
37#include <linux/list.h> 37#include <linux/list.h>
@@ -44,10 +44,6 @@
44 44
45#define VERSION "0.5" 45#define VERSION "0.5"
46 46
47#define _STR(x) #x
48#define STR(x) _STR(x)
49#define MAX_PATH 256
50
51#define TRACE_CTRL "tracing_on" 47#define TRACE_CTRL "tracing_on"
52#define TRACE "trace" 48#define TRACE "trace"
53#define AVAILABLE "available_tracers" 49#define AVAILABLE "available_tracers"
@@ -73,26 +69,6 @@ struct events {
73}; 69};
74 70
75 71
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) 72void *malloc_or_die(unsigned int size)
97{ 73{
98 void *data; 74 void *data;
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;