aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/Documentation/perf-record.txt5
-rw-r--r--tools/perf/builtin-record.c16
-rw-r--r--tools/perf/builtin-top.c14
-rw-r--r--tools/perf/util/event.c285
-rw-r--r--tools/perf/util/event.h7
-rw-r--r--tools/perf/util/header.c18
-rw-r--r--tools/perf/util/header.h1
-rw-r--r--tools/perf/util/session.c66
-rw-r--r--tools/perf/util/session.h3
9 files changed, 315 insertions, 100 deletions
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 0ad1bc75ab49..52462ae26455 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -108,6 +108,11 @@ OPTIONS
108--data:: 108--data::
109 Sample addresses. 109 Sample addresses.
110 110
111-T::
112--timestamp::
113 Sample timestamps. Use it with 'perf report -D' to see the timestamps,
114 for instance.
115
111-n:: 116-n::
112--no-samples:: 117--no-samples::
113 Don't sample. 118 Don't sample.
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index b34de9291c27..699dd2149c4b 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -49,6 +49,7 @@ static const char *output_name = "perf.data";
49static int group = 0; 49static int group = 0;
50static int realtime_prio = 0; 50static int realtime_prio = 0;
51static bool raw_samples = false; 51static bool raw_samples = false;
52static bool sample_id_all_avail = true;
52static bool system_wide = false; 53static bool system_wide = false;
53static pid_t target_pid = -1; 54static pid_t target_pid = -1;
54static pid_t target_tid = -1; 55static pid_t target_tid = -1;
@@ -61,6 +62,7 @@ static bool call_graph = false;
61static bool inherit_stat = false; 62static bool inherit_stat = false;
62static bool no_samples = false; 63static bool no_samples = false;
63static bool sample_address = false; 64static bool sample_address = false;
65static bool sample_time = false;
64static bool no_buildid = false; 66static bool no_buildid = false;
65static bool no_buildid_cache = false; 67static bool no_buildid_cache = false;
66 68
@@ -283,6 +285,9 @@ static void create_counter(int counter, int cpu)
283 if (system_wide) 285 if (system_wide)
284 attr->sample_type |= PERF_SAMPLE_CPU; 286 attr->sample_type |= PERF_SAMPLE_CPU;
285 287
288 if (sample_time)
289 attr->sample_type |= PERF_SAMPLE_TIME;
290
286 if (raw_samples) { 291 if (raw_samples) {
287 attr->sample_type |= PERF_SAMPLE_TIME; 292 attr->sample_type |= PERF_SAMPLE_TIME;
288 attr->sample_type |= PERF_SAMPLE_RAW; 293 attr->sample_type |= PERF_SAMPLE_RAW;
@@ -299,6 +304,8 @@ static void create_counter(int counter, int cpu)
299 attr->disabled = 1; 304 attr->disabled = 1;
300 attr->enable_on_exec = 1; 305 attr->enable_on_exec = 1;
301 } 306 }
307retry_sample_id:
308 attr->sample_id_all = sample_id_all_avail ? 1 : 0;
302 309
303 for (thread_index = 0; thread_index < thread_num; thread_index++) { 310 for (thread_index = 0; thread_index < thread_num; thread_index++) {
304try_again: 311try_again:
@@ -315,6 +322,12 @@ try_again:
315 else if (err == ENODEV && cpu_list) { 322 else if (err == ENODEV && cpu_list) {
316 die("No such device - did you specify" 323 die("No such device - did you specify"
317 " an out-of-range profile CPU?\n"); 324 " an out-of-range profile CPU?\n");
325 } else if (err == EINVAL && sample_id_all_avail) {
326 /*
327 * Old kernel, no attr->sample_id_type_all field
328 */
329 sample_id_all_avail = false;
330 goto retry_sample_id;
318 } 331 }
319 332
320 /* 333 /*
@@ -661,6 +674,8 @@ static int __cmd_record(int argc, const char **argv)
661 674
662 post_processing_offset = lseek(output, 0, SEEK_CUR); 675 post_processing_offset = lseek(output, 0, SEEK_CUR);
663 676
677 perf_session__set_sample_id_all(session, sample_id_all_avail);
678
664 if (pipe_output) { 679 if (pipe_output) {
665 err = event__synthesize_attrs(&session->header, 680 err = event__synthesize_attrs(&session->header,
666 process_synthesized_event, 681 process_synthesized_event,
@@ -841,6 +856,7 @@ const struct option record_options[] = {
841 "per thread counts"), 856 "per thread counts"),
842 OPT_BOOLEAN('d', "data", &sample_address, 857 OPT_BOOLEAN('d', "data", &sample_address,
843 "Sample addresses"), 858 "Sample addresses"),
859 OPT_BOOLEAN('T', "timestamp", &sample_time, "Sample timestamps"),
844 OPT_BOOLEAN('n', "no-samples", &no_samples, 860 OPT_BOOLEAN('n', "no-samples", &no_samples,
845 "don't sample"), 861 "don't sample"),
846 OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid_cache, 862 OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid_cache,
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 5aa29e1e855a..0515ce9d3d3e 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -977,12 +977,12 @@ static int symbol_filter(struct map *map, struct symbol *sym)
977} 977}
978 978
979static void event__process_sample(const event_t *self, 979static void event__process_sample(const event_t *self,
980 struct perf_session *session, int counter) 980 struct sample_data *sample,
981 struct perf_session *session, int counter)
981{ 982{
982 u64 ip = self->ip.ip; 983 u64 ip = self->ip.ip;
983 struct sym_entry *syme; 984 struct sym_entry *syme;
984 struct addr_location al; 985 struct addr_location al;
985 struct sample_data data;
986 struct machine *machine; 986 struct machine *machine;
987 u8 origin = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 987 u8 origin = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
988 988
@@ -1025,9 +1025,7 @@ static void event__process_sample(const event_t *self,
1025 if (self->header.misc & PERF_RECORD_MISC_EXACT_IP) 1025 if (self->header.misc & PERF_RECORD_MISC_EXACT_IP)
1026 exact_samples++; 1026 exact_samples++;
1027 1027
1028 event__parse_sample(self, session->sample_type, &data); 1028 if (event__preprocess_sample(self, session, &al, sample,
1029
1030 if (event__preprocess_sample(self, session, &al, &data,
1031 symbol_filter) < 0 || 1029 symbol_filter) < 0 ||
1032 al.filtered) 1030 al.filtered)
1033 return; 1031 return;
@@ -1107,6 +1105,7 @@ static void perf_session__mmap_read_counter(struct perf_session *self,
1107 unsigned int head = mmap_read_head(md); 1105 unsigned int head = mmap_read_head(md);
1108 unsigned int old = md->prev; 1106 unsigned int old = md->prev;
1109 unsigned char *data = md->base + page_size; 1107 unsigned char *data = md->base + page_size;
1108 struct sample_data sample;
1110 int diff; 1109 int diff;
1111 1110
1112 /* 1111 /*
@@ -1154,10 +1153,11 @@ static void perf_session__mmap_read_counter(struct perf_session *self,
1154 event = &event_copy; 1153 event = &event_copy;
1155 } 1154 }
1156 1155
1156 event__parse_sample(event, self, &sample);
1157 if (event->header.type == PERF_RECORD_SAMPLE) 1157 if (event->header.type == PERF_RECORD_SAMPLE)
1158 event__process_sample(event, self, md->counter); 1158 event__process_sample(event, &sample, self, md->counter);
1159 else 1159 else
1160 event__process(event, NULL, self); 1160 event__process(event, &sample, self);
1161 old += size; 1161 old += size;
1162 } 1162 }
1163 1163
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 34510f441975..e4cdc1ebe0fb 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -33,11 +33,10 @@ static struct sample_data synth_sample = {
33 .period = 1, 33 .period = 1,
34}; 34};
35 35
36static pid_t event__synthesize_comm(pid_t pid, int full, 36static pid_t event__synthesize_comm(event_t *event, pid_t pid, int full,
37 event__handler_t process, 37 event__handler_t process,
38 struct perf_session *session) 38 struct perf_session *session)
39{ 39{
40 event_t ev;
41 char filename[PATH_MAX]; 40 char filename[PATH_MAX];
42 char bf[BUFSIZ]; 41 char bf[BUFSIZ];
43 FILE *fp; 42 FILE *fp;
@@ -58,34 +57,39 @@ out_race:
58 return 0; 57 return 0;
59 } 58 }
60 59
61 memset(&ev.comm, 0, sizeof(ev.comm)); 60 memset(&event->comm, 0, sizeof(event->comm));
62 while (!ev.comm.comm[0] || !ev.comm.pid) { 61
63 if (fgets(bf, sizeof(bf), fp) == NULL) 62 while (!event->comm.comm[0] || !event->comm.pid) {
64 goto out_failure; 63 if (fgets(bf, sizeof(bf), fp) == NULL) {
64 pr_warning("couldn't get COMM and pgid, malformed %s\n", filename);
65 goto out;
66 }
65 67
66 if (memcmp(bf, "Name:", 5) == 0) { 68 if (memcmp(bf, "Name:", 5) == 0) {
67 char *name = bf + 5; 69 char *name = bf + 5;
68 while (*name && isspace(*name)) 70 while (*name && isspace(*name))
69 ++name; 71 ++name;
70 size = strlen(name) - 1; 72 size = strlen(name) - 1;
71 memcpy(ev.comm.comm, name, size++); 73 memcpy(event->comm.comm, name, size++);
72 } else if (memcmp(bf, "Tgid:", 5) == 0) { 74 } else if (memcmp(bf, "Tgid:", 5) == 0) {
73 char *tgids = bf + 5; 75 char *tgids = bf + 5;
74 while (*tgids && isspace(*tgids)) 76 while (*tgids && isspace(*tgids))
75 ++tgids; 77 ++tgids;
76 tgid = ev.comm.pid = atoi(tgids); 78 tgid = event->comm.pid = atoi(tgids);
77 } 79 }
78 } 80 }
79 81
80 ev.comm.header.type = PERF_RECORD_COMM; 82 event->comm.header.type = PERF_RECORD_COMM;
81 size = ALIGN(size, sizeof(u64)); 83 size = ALIGN(size, sizeof(u64));
82 ev.comm.header.size = sizeof(ev.comm) - (sizeof(ev.comm.comm) - size); 84 memset(event->comm.comm + size, 0, session->id_hdr_size);
83 85 event->comm.header.size = (sizeof(event->comm) -
86 (sizeof(event->comm.comm) - size) +
87 session->id_hdr_size);
84 if (!full) { 88 if (!full) {
85 ev.comm.tid = pid; 89 event->comm.tid = pid;
86 90
87 process(&ev, &synth_sample, session); 91 process(event, &synth_sample, session);
88 goto out_fclose; 92 goto out;
89 } 93 }
90 94
91 snprintf(filename, sizeof(filename), "/proc/%d/task", pid); 95 snprintf(filename, sizeof(filename), "/proc/%d/task", pid);
@@ -100,22 +104,19 @@ out_race:
100 if (*end) 104 if (*end)
101 continue; 105 continue;
102 106
103 ev.comm.tid = pid; 107 event->comm.tid = pid;
104 108
105 process(&ev, &synth_sample, session); 109 process(event, &synth_sample, session);
106 } 110 }
107 closedir(tasks);
108 111
109out_fclose: 112 closedir(tasks);
113out:
110 fclose(fp); 114 fclose(fp);
111 return tgid;
112 115
113out_failure: 116 return tgid;
114 pr_warning("couldn't get COMM and pgid, malformed %s\n", filename);
115 return -1;
116} 117}
117 118
118static int event__synthesize_mmap_events(pid_t pid, pid_t tgid, 119static int event__synthesize_mmap_events(event_t *event, pid_t pid, pid_t tgid,
119 event__handler_t process, 120 event__handler_t process,
120 struct perf_session *session) 121 struct perf_session *session)
121{ 122{
@@ -133,29 +134,25 @@ static int event__synthesize_mmap_events(pid_t pid, pid_t tgid,
133 return -1; 134 return -1;
134 } 135 }
135 136
137 event->header.type = PERF_RECORD_MMAP;
138 /*
139 * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
140 */
141 event->header.misc = PERF_RECORD_MISC_USER;
142
136 while (1) { 143 while (1) {
137 char bf[BUFSIZ], *pbf = bf; 144 char bf[BUFSIZ], *pbf = bf;
138 event_t ev = {
139 .header = {
140 .type = PERF_RECORD_MMAP,
141 /*
142 * Just like the kernel, see __perf_event_mmap
143 * in kernel/perf_event.c
144 */
145 .misc = PERF_RECORD_MISC_USER,
146 },
147 };
148 int n; 145 int n;
149 size_t size; 146 size_t size;
150 if (fgets(bf, sizeof(bf), fp) == NULL) 147 if (fgets(bf, sizeof(bf), fp) == NULL)
151 break; 148 break;
152 149
153 /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */ 150 /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */
154 n = hex2u64(pbf, &ev.mmap.start); 151 n = hex2u64(pbf, &event->mmap.start);
155 if (n < 0) 152 if (n < 0)
156 continue; 153 continue;
157 pbf += n + 1; 154 pbf += n + 1;
158 n = hex2u64(pbf, &ev.mmap.len); 155 n = hex2u64(pbf, &event->mmap.len);
159 if (n < 0) 156 if (n < 0)
160 continue; 157 continue;
161 pbf += n + 3; 158 pbf += n + 3;
@@ -170,19 +167,21 @@ static int event__synthesize_mmap_events(pid_t pid, pid_t tgid,
170 continue; 167 continue;
171 168
172 pbf += 3; 169 pbf += 3;
173 n = hex2u64(pbf, &ev.mmap.pgoff); 170 n = hex2u64(pbf, &event->mmap.pgoff);
174 171
175 size = strlen(execname); 172 size = strlen(execname);
176 execname[size - 1] = '\0'; /* Remove \n */ 173 execname[size - 1] = '\0'; /* Remove \n */
177 memcpy(ev.mmap.filename, execname, size); 174 memcpy(event->mmap.filename, execname, size);
178 size = ALIGN(size, sizeof(u64)); 175 size = ALIGN(size, sizeof(u64));
179 ev.mmap.len -= ev.mmap.start; 176 event->mmap.len -= event->mmap.start;
180 ev.mmap.header.size = (sizeof(ev.mmap) - 177 event->mmap.header.size = (sizeof(event->mmap) -
181 (sizeof(ev.mmap.filename) - size)); 178 (sizeof(event->mmap.filename) - size));
182 ev.mmap.pid = tgid; 179 memset(event->mmap.filename + size, 0, session->id_hdr_size);
183 ev.mmap.tid = pid; 180 event->mmap.header.size += session->id_hdr_size;
184 181 event->mmap.pid = tgid;
185 process(&ev, &synth_sample, session); 182 event->mmap.tid = pid;
183
184 process(event, &synth_sample, session);
186 } 185 }
187 } 186 }
188 187
@@ -196,20 +195,27 @@ int event__synthesize_modules(event__handler_t process,
196{ 195{
197 struct rb_node *nd; 196 struct rb_node *nd;
198 struct map_groups *kmaps = &machine->kmaps; 197 struct map_groups *kmaps = &machine->kmaps;
199 u16 misc; 198 event_t *event = zalloc(sizeof(event->mmap) + session->id_hdr_size);
199
200 if (event == NULL) {
201 pr_debug("Not enough memory synthesizing mmap event "
202 "for kernel modules\n");
203 return -1;
204 }
205
206 event->header.type = PERF_RECORD_MMAP;
200 207
201 /* 208 /*
202 * kernel uses 0 for user space maps, see kernel/perf_event.c 209 * kernel uses 0 for user space maps, see kernel/perf_event.c
203 * __perf_event_mmap 210 * __perf_event_mmap
204 */ 211 */
205 if (machine__is_host(machine)) 212 if (machine__is_host(machine))
206 misc = PERF_RECORD_MISC_KERNEL; 213 event->header.misc = PERF_RECORD_MISC_KERNEL;
207 else 214 else
208 misc = PERF_RECORD_MISC_GUEST_KERNEL; 215 event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
209 216
210 for (nd = rb_first(&kmaps->maps[MAP__FUNCTION]); 217 for (nd = rb_first(&kmaps->maps[MAP__FUNCTION]);
211 nd; nd = rb_next(nd)) { 218 nd; nd = rb_next(nd)) {
212 event_t ev;
213 size_t size; 219 size_t size;
214 struct map *pos = rb_entry(nd, struct map, rb_node); 220 struct map *pos = rb_entry(nd, struct map, rb_node);
215 221
@@ -217,39 +223,78 @@ int event__synthesize_modules(event__handler_t process,
217 continue; 223 continue;
218 224
219 size = ALIGN(pos->dso->long_name_len + 1, sizeof(u64)); 225 size = ALIGN(pos->dso->long_name_len + 1, sizeof(u64));
220 memset(&ev, 0, sizeof(ev)); 226 event->mmap.header.type = PERF_RECORD_MMAP;
221 ev.mmap.header.misc = misc; 227 event->mmap.header.size = (sizeof(event->mmap) -
222 ev.mmap.header.type = PERF_RECORD_MMAP; 228 (sizeof(event->mmap.filename) - size));
223 ev.mmap.header.size = (sizeof(ev.mmap) - 229 memset(event->mmap.filename + size, 0, session->id_hdr_size);
224 (sizeof(ev.mmap.filename) - size)); 230 event->mmap.header.size += session->id_hdr_size;
225 ev.mmap.start = pos->start; 231 event->mmap.start = pos->start;
226 ev.mmap.len = pos->end - pos->start; 232 event->mmap.len = pos->end - pos->start;
227 ev.mmap.pid = machine->pid; 233 event->mmap.pid = machine->pid;
228 234
229 memcpy(ev.mmap.filename, pos->dso->long_name, 235 memcpy(event->mmap.filename, pos->dso->long_name,
230 pos->dso->long_name_len + 1); 236 pos->dso->long_name_len + 1);
231 process(&ev, &synth_sample, session); 237 process(event, &synth_sample, session);
232 } 238 }
233 239
240 free(event);
234 return 0; 241 return 0;
235} 242}
236 243
237int event__synthesize_thread(pid_t pid, event__handler_t process, 244static int __event__synthesize_thread(event_t *comm_event, event_t *mmap_event,
238 struct perf_session *session) 245 pid_t pid, event__handler_t process,
246 struct perf_session *session)
239{ 247{
240 pid_t tgid = event__synthesize_comm(pid, 1, process, session); 248 pid_t tgid = event__synthesize_comm(comm_event, pid, 1, process,
249 session);
241 if (tgid == -1) 250 if (tgid == -1)
242 return -1; 251 return -1;
243 return event__synthesize_mmap_events(pid, tgid, process, session); 252 return event__synthesize_mmap_events(mmap_event, pid, tgid,
253 process, session);
244} 254}
245 255
246void event__synthesize_threads(event__handler_t process, 256int event__synthesize_thread(pid_t pid, event__handler_t process,
247 struct perf_session *session) 257 struct perf_session *session)
258{
259 event_t *comm_event, *mmap_event;
260 int err = -1;
261
262 comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size);
263 if (comm_event == NULL)
264 goto out;
265
266 mmap_event = malloc(sizeof(mmap_event->mmap) + session->id_hdr_size);
267 if (mmap_event == NULL)
268 goto out_free_comm;
269
270 err = __event__synthesize_thread(comm_event, mmap_event, pid,
271 process, session);
272 free(mmap_event);
273out_free_comm:
274 free(comm_event);
275out:
276 return err;
277}
278
279int event__synthesize_threads(event__handler_t process,
280 struct perf_session *session)
248{ 281{
249 DIR *proc; 282 DIR *proc;
250 struct dirent dirent, *next; 283 struct dirent dirent, *next;
284 event_t *comm_event, *mmap_event;
285 int err = -1;
286
287 comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size);
288 if (comm_event == NULL)
289 goto out;
290
291 mmap_event = malloc(sizeof(mmap_event->mmap) + session->id_hdr_size);
292 if (mmap_event == NULL)
293 goto out_free_comm;
251 294
252 proc = opendir("/proc"); 295 proc = opendir("/proc");
296 if (proc == NULL)
297 goto out_free_mmap;
253 298
254 while (!readdir_r(proc, &dirent, &next) && next) { 299 while (!readdir_r(proc, &dirent, &next) && next) {
255 char *end; 300 char *end;
@@ -258,10 +303,18 @@ void event__synthesize_threads(event__handler_t process,
258 if (*end) /* only interested in proper numerical dirents */ 303 if (*end) /* only interested in proper numerical dirents */
259 continue; 304 continue;
260 305
261 event__synthesize_thread(pid, process, session); 306 __event__synthesize_thread(comm_event, mmap_event, pid,
307 process, session);
262 } 308 }
263 309
264 closedir(proc); 310 closedir(proc);
311 err = 0;
312out_free_mmap:
313 free(mmap_event);
314out_free_comm:
315 free(comm_event);
316out:
317 return err;
265} 318}
266 319
267struct process_symbol_args { 320struct process_symbol_args {
@@ -295,18 +348,20 @@ int event__synthesize_kernel_mmap(event__handler_t process,
295 char path[PATH_MAX]; 348 char path[PATH_MAX];
296 char name_buff[PATH_MAX]; 349 char name_buff[PATH_MAX];
297 struct map *map; 350 struct map *map;
298 351 int err;
299 event_t ev = {
300 .header = {
301 .type = PERF_RECORD_MMAP,
302 },
303 };
304 /* 352 /*
305 * We should get this from /sys/kernel/sections/.text, but till that is 353 * We should get this from /sys/kernel/sections/.text, but till that is
306 * available use this, and after it is use this as a fallback for older 354 * available use this, and after it is use this as a fallback for older
307 * kernels. 355 * kernels.
308 */ 356 */
309 struct process_symbol_args args = { .name = symbol_name, }; 357 struct process_symbol_args args = { .name = symbol_name, };
358 event_t *event = zalloc(sizeof(event->mmap) + session->id_hdr_size);
359
360 if (event == NULL) {
361 pr_debug("Not enough memory synthesizing mmap event "
362 "for kernel modules\n");
363 return -1;
364 }
310 365
311 mmap_name = machine__mmap_name(machine, name_buff, sizeof(name_buff)); 366 mmap_name = machine__mmap_name(machine, name_buff, sizeof(name_buff));
312 if (machine__is_host(machine)) { 367 if (machine__is_host(machine)) {
@@ -314,10 +369,10 @@ int event__synthesize_kernel_mmap(event__handler_t process,
314 * kernel uses PERF_RECORD_MISC_USER for user space maps, 369 * kernel uses PERF_RECORD_MISC_USER for user space maps,
315 * see kernel/perf_event.c __perf_event_mmap 370 * see kernel/perf_event.c __perf_event_mmap
316 */ 371 */
317 ev.header.misc = PERF_RECORD_MISC_KERNEL; 372 event->header.misc = PERF_RECORD_MISC_KERNEL;
318 filename = "/proc/kallsyms"; 373 filename = "/proc/kallsyms";
319 } else { 374 } else {
320 ev.header.misc = PERF_RECORD_MISC_GUEST_KERNEL; 375 event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
321 if (machine__is_default_guest(machine)) 376 if (machine__is_default_guest(machine))
322 filename = (char *) symbol_conf.default_guest_kallsyms; 377 filename = (char *) symbol_conf.default_guest_kallsyms;
323 else { 378 else {
@@ -330,17 +385,21 @@ int event__synthesize_kernel_mmap(event__handler_t process,
330 return -ENOENT; 385 return -ENOENT;
331 386
332 map = machine->vmlinux_maps[MAP__FUNCTION]; 387 map = machine->vmlinux_maps[MAP__FUNCTION];
333 size = snprintf(ev.mmap.filename, sizeof(ev.mmap.filename), 388 size = snprintf(event->mmap.filename, sizeof(event->mmap.filename),
334 "%s%s", mmap_name, symbol_name) + 1; 389 "%s%s", mmap_name, symbol_name) + 1;
335 size = ALIGN(size, sizeof(u64)); 390 size = ALIGN(size, sizeof(u64));
336 ev.mmap.header.size = (sizeof(ev.mmap) - 391 event->mmap.header.type = PERF_RECORD_MMAP;
337 (sizeof(ev.mmap.filename) - size)); 392 event->mmap.header.size = (sizeof(event->mmap) -
338 ev.mmap.pgoff = args.start; 393 (sizeof(event->mmap.filename) - size) + session->id_hdr_size);
339 ev.mmap.start = map->start; 394 event->mmap.pgoff = args.start;
340 ev.mmap.len = map->end - ev.mmap.start; 395 event->mmap.start = map->start;
341 ev.mmap.pid = machine->pid; 396 event->mmap.len = map->end - event->mmap.start;
342 397 event->mmap.pid = machine->pid;
343 return process(&ev, &synth_sample, session); 398
399 err = process(event, &synth_sample, session);
400 free(event);
401
402 return err;
344} 403}
345 404
346static void thread__comm_adjust(struct thread *self, struct hists *hists) 405static void thread__comm_adjust(struct thread *self, struct hists *hists)
@@ -756,9 +815,65 @@ out_filtered:
756 return 0; 815 return 0;
757} 816}
758 817
759int event__parse_sample(const event_t *event, u64 type, struct sample_data *data) 818static int event__parse_id_sample(const event_t *event,
819 struct perf_session *session,
820 struct sample_data *sample)
760{ 821{
761 const u64 *array = event->sample.array; 822 const u64 *array;
823 u64 type;
824
825 sample->cpu = sample->pid = sample->tid = -1;
826 sample->stream_id = sample->id = sample->time = -1ULL;
827
828 if (!session->sample_id_all)
829 return 0;
830
831 array = event->sample.array;
832 array += ((event->header.size -
833 sizeof(event->header)) / sizeof(u64)) - 1;
834 type = session->sample_type;
835
836 if (type & PERF_SAMPLE_CPU) {
837 u32 *p = (u32 *)array;
838 sample->cpu = *p;
839 array--;
840 }
841
842 if (type & PERF_SAMPLE_STREAM_ID) {
843 sample->stream_id = *array;
844 array--;
845 }
846
847 if (type & PERF_SAMPLE_ID) {
848 sample->id = *array;
849 array--;
850 }
851
852 if (type & PERF_SAMPLE_TIME) {
853 sample->time = *array;
854 array--;
855 }
856
857 if (type & PERF_SAMPLE_TID) {
858 u32 *p = (u32 *)array;
859 sample->pid = p[0];
860 sample->tid = p[1];
861 }
862
863 return 0;
864}
865
866int event__parse_sample(const event_t *event, struct perf_session *session,
867 struct sample_data *data)
868{
869 const u64 *array;
870 u64 type;
871
872 if (event->header.type != PERF_RECORD_SAMPLE)
873 return event__parse_id_sample(event, session, data);
874
875 array = event->sample.array;
876 type = session->sample_type;
762 877
763 if (type & PERF_SAMPLE_IP) { 878 if (type & PERF_SAMPLE_IP) {
764 data->ip = event->ip.ip; 879 data->ip = event->ip.ip;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 08c400b83d57..a95ab18575ce 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -142,8 +142,8 @@ typedef int (*event__handler_t)(event_t *event, struct sample_data *sample,
142 142
143int event__synthesize_thread(pid_t pid, event__handler_t process, 143int event__synthesize_thread(pid_t pid, event__handler_t process,
144 struct perf_session *session); 144 struct perf_session *session);
145void event__synthesize_threads(event__handler_t process, 145int event__synthesize_threads(event__handler_t process,
146 struct perf_session *session); 146 struct perf_session *session);
147int event__synthesize_kernel_mmap(event__handler_t process, 147int event__synthesize_kernel_mmap(event__handler_t process,
148 struct perf_session *session, 148 struct perf_session *session,
149 struct machine *machine, 149 struct machine *machine,
@@ -168,7 +168,8 @@ struct addr_location;
168int event__preprocess_sample(const event_t *self, struct perf_session *session, 168int event__preprocess_sample(const event_t *self, struct perf_session *session,
169 struct addr_location *al, struct sample_data *data, 169 struct addr_location *al, struct sample_data *data,
170 symbol_filter_t filter); 170 symbol_filter_t filter);
171int event__parse_sample(const event_t *event, u64 type, struct sample_data *data); 171int event__parse_sample(const event_t *event, struct perf_session *session,
172 struct sample_data *sample);
172 173
173extern const char *event__name[]; 174extern const char *event__name[];
174 175
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index fe652f3b0aa7..073f0e1c7123 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -946,6 +946,24 @@ u64 perf_header__sample_type(struct perf_header *header)
946 return type; 946 return type;
947} 947}
948 948
949bool perf_header__sample_id_all(const struct perf_header *header)
950{
951 bool value = false, first = true;
952 int i;
953
954 for (i = 0; i < header->attrs; i++) {
955 struct perf_header_attr *attr = header->attr[i];
956
957 if (first) {
958 value = attr->attr.sample_id_all;
959 first = false;
960 } else if (value != attr->attr.sample_id_all)
961 die("non matching sample_id_all");
962 }
963
964 return value;
965}
966
949struct perf_event_attr * 967struct perf_event_attr *
950perf_header__find_attr(u64 id, struct perf_header *header) 968perf_header__find_attr(u64 id, struct perf_header *header)
951{ 969{
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index ed550bffd655..6335965e1f93 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -81,6 +81,7 @@ void perf_header_attr__delete(struct perf_header_attr *self);
81int perf_header_attr__add_id(struct perf_header_attr *self, u64 id); 81int perf_header_attr__add_id(struct perf_header_attr *self, u64 id);
82 82
83u64 perf_header__sample_type(struct perf_header *header); 83u64 perf_header__sample_type(struct perf_header *header);
84bool perf_header__sample_id_all(const struct perf_header *header);
84struct perf_event_attr * 85struct perf_event_attr *
85perf_header__find_attr(u64 id, struct perf_header *header); 86perf_header__find_attr(u64 id, struct perf_header *header);
86void perf_header__set_feat(struct perf_header *self, int feat); 87void perf_header__set_feat(struct perf_header *self, int feat);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 08ec018966a8..5c756609104e 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -65,9 +65,37 @@ out_close:
65 return -1; 65 return -1;
66} 66}
67 67
68void perf_session__update_sample_type(struct perf_session *self) 68static void perf_session__id_header_size(struct perf_session *session)
69{ 69{
70 self->sample_type = perf_header__sample_type(&self->header); 70 struct sample_data *data;
71 u64 sample_type = session->sample_type;
72 u16 size = 0;
73
74 if (!session->sample_id_all)
75 goto out;
76
77 if (sample_type & PERF_SAMPLE_TID)
78 size += sizeof(data->tid) * 2;
79
80 if (sample_type & PERF_SAMPLE_TIME)
81 size += sizeof(data->time);
82
83 if (sample_type & PERF_SAMPLE_ID)
84 size += sizeof(data->id);
85
86 if (sample_type & PERF_SAMPLE_STREAM_ID)
87 size += sizeof(data->stream_id);
88
89 if (sample_type & PERF_SAMPLE_CPU)
90 size += sizeof(data->cpu) * 2;
91out:
92 session->id_hdr_size = size;
93}
94
95void perf_session__set_sample_id_all(struct perf_session *session, bool value)
96{
97 session->sample_id_all = value;
98 perf_session__id_header_size(session);
71} 99}
72 100
73void perf_session__set_sample_type(struct perf_session *session, u64 type) 101void perf_session__set_sample_type(struct perf_session *session, u64 type)
@@ -75,6 +103,13 @@ void perf_session__set_sample_type(struct perf_session *session, u64 type)
75 session->sample_type = type; 103 session->sample_type = type;
76} 104}
77 105
106void perf_session__update_sample_type(struct perf_session *self)
107{
108 self->sample_type = perf_header__sample_type(&self->header);
109 self->sample_id_all = perf_header__sample_id_all(&self->header);
110 perf_session__id_header_size(self);
111}
112
78int perf_session__create_kernel_maps(struct perf_session *self) 113int perf_session__create_kernel_maps(struct perf_session *self)
79{ 114{
80 int ret = machine__create_kernel_maps(&self->host_machine); 115 int ret = machine__create_kernel_maps(&self->host_machine);
@@ -443,7 +478,7 @@ static void flush_sample_queue(struct perf_session *s,
443 if (iter->timestamp > limit) 478 if (iter->timestamp > limit)
444 break; 479 break;
445 480
446 event__parse_sample(iter->event, s->sample_type, &sample); 481 event__parse_sample(iter->event, s, &sample);
447 ops->sample(iter->event, &sample, s); 482 ops->sample(iter->event, &sample, s);
448 483
449 os->last_flush = iter->timestamp; 484 os->last_flush = iter->timestamp;
@@ -618,6 +653,23 @@ static void callchain__dump(struct sample_data *sample)
618 printf("..... %2d: %016Lx\n", i, sample->callchain->ips[i]); 653 printf("..... %2d: %016Lx\n", i, sample->callchain->ips[i]);
619} 654}
620 655
656static void perf_session__print_tstamp(struct perf_session *session,
657 event_t *event,
658 struct sample_data *sample)
659{
660 if (event->header.type != PERF_RECORD_SAMPLE &&
661 !session->sample_id_all) {
662 fputs("-1 -1 ", stdout);
663 return;
664 }
665
666 if ((session->sample_type & PERF_SAMPLE_CPU))
667 printf("%u ", sample->cpu);
668
669 if (session->sample_type & PERF_SAMPLE_TIME)
670 printf("%Lu ", sample->time);
671}
672
621static int perf_session__process_event(struct perf_session *self, 673static int perf_session__process_event(struct perf_session *self,
622 event_t *event, 674 event_t *event,
623 struct perf_event_ops *ops, 675 struct perf_event_ops *ops,
@@ -630,8 +682,12 @@ static int perf_session__process_event(struct perf_session *self,
630 if (self->header.needs_swap && event__swap_ops[event->header.type]) 682 if (self->header.needs_swap && event__swap_ops[event->header.type])
631 event__swap_ops[event->header.type](event); 683 event__swap_ops[event->header.type](event);
632 684
633 if (event->header.type == PERF_RECORD_SAMPLE) 685 if (event->header.type >= PERF_RECORD_MMAP &&
634 event__parse_sample(event, self->sample_type, &sample); 686 event->header.type <= PERF_RECORD_SAMPLE) {
687 event__parse_sample(event, self, &sample);
688 if (dump_trace)
689 perf_session__print_tstamp(self, event, &sample);
690 }
635 691
636 if (event->header.type < PERF_RECORD_HEADER_MAX) { 692 if (event->header.type < PERF_RECORD_HEADER_MAX) {
637 dump_printf("%#Lx [%#x]: PERF_RECORD_%s", 693 dump_printf("%#Lx [%#x]: PERF_RECORD_%s",
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 4578f86a6209..ac36f99f14af 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -46,6 +46,8 @@ struct perf_session {
46 int fd; 46 int fd;
47 bool fd_pipe; 47 bool fd_pipe;
48 bool repipe; 48 bool repipe;
49 bool sample_id_all;
50 u16 id_hdr_size;
49 int cwdlen; 51 int cwdlen;
50 char *cwd; 52 char *cwd;
51 struct ordered_samples ordered_samples; 53 struct ordered_samples ordered_samples;
@@ -106,6 +108,7 @@ int perf_session__create_kernel_maps(struct perf_session *self);
106 108
107int do_read(int fd, void *buf, size_t size); 109int do_read(int fd, void *buf, size_t size);
108void perf_session__update_sample_type(struct perf_session *self); 110void perf_session__update_sample_type(struct perf_session *self);
111void perf_session__set_sample_id_all(struct perf_session *session, bool value);
109void perf_session__set_sample_type(struct perf_session *session, u64 type); 112void perf_session__set_sample_type(struct perf_session *session, u64 type);
110void perf_session__remove_thread(struct perf_session *self, struct thread *th); 113void perf_session__remove_thread(struct perf_session *self, struct thread *th);
111 114