blob: 26f5b2fe5dc89832c44eb8c20b5deb6db1c72d3e [file] [log] [blame]
Arnaldo Carvalho de Meloa9072bc2011-10-26 12:41:38 -02001#include "util.h"
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002#include <sys/types.h>
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -02003#include <byteswap.h>
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02004#include <unistd.h>
5#include <stdio.h>
6#include <stdlib.h>
Frederic Weisbecker8671dab2009-11-11 04:51:03 +01007#include <linux/list.h>
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -02008#include <linux/kernel.h>
Robert Richterb1e5a9b2011-12-07 10:02:57 +01009#include <linux/bitops.h>
Stephane Eranianfbe96f22011-09-30 15:40:40 +020010#include <sys/utsname.h>
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020011
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -020012#include "evlist.h"
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -030013#include "evsel.h"
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020014#include "header.h"
Frederic Weisbecker03456a12009-10-06 23:36:47 +020015#include "../perf.h"
16#include "trace-event.h"
Arnaldo Carvalho de Melo301a0b02009-12-13 19:50:25 -020017#include "session.h"
Frederic Weisbecker8671dab2009-11-11 04:51:03 +010018#include "symbol.h"
Frederic Weisbecker4778d2e2009-11-11 04:51:05 +010019#include "debug.h"
Stephane Eranianfbe96f22011-09-30 15:40:40 +020020#include "cpumap.h"
Robert Richter50a96672012-08-16 21:10:24 +020021#include "pmu.h"
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +020022#include "vdso.h"
Namhyung Kima1ae5652012-09-24 17:14:59 +090023#include "strbuf.h"
Jiri Olsaebb296c2012-10-27 23:18:28 +020024#include "build-id.h"
Jiri Olsacc9784bd2013-10-15 16:27:34 +020025#include "data.h"
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020026
Stephane Eraniana1ac1d32010-06-17 11:39:01 +020027static bool no_buildid_cache = false;
28
Stephane Eranianfbe96f22011-09-30 15:40:40 +020029static u32 header_argc;
30static const char **header_argv;
31
Stephane Eranian73323f52012-02-02 13:54:44 +010032/*
33 * magic2 = "PERFILE2"
34 * must be a numerical value to let the endianness
35 * determine the memory layout. That way we are able
36 * to detect endianness when reading the perf.data file
37 * back.
38 *
39 * we check for legacy (PERFFILE) format.
40 */
41static const char *__perf_magic1 = "PERFFILE";
42static const u64 __perf_magic2 = 0x32454c4946524550ULL;
43static const u64 __perf_magic2_sw = 0x50455246494c4532ULL;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020044
Stephane Eranian73323f52012-02-02 13:54:44 +010045#define PERF_MAGIC __perf_magic2
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020046
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020047struct perf_file_attr {
Ingo Molnarcdd6c482009-09-21 12:02:48 +020048 struct perf_event_attr attr;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020049 struct perf_file_section ids;
50};
51
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -030052void perf_header__set_feat(struct perf_header *header, int feat)
Arnaldo Carvalho de Melo8d063672009-11-04 18:50:43 -020053{
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -030054 set_bit(feat, header->adds_features);
Arnaldo Carvalho de Melo8d063672009-11-04 18:50:43 -020055}
56
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -030057void perf_header__clear_feat(struct perf_header *header, int feat)
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -020058{
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -030059 clear_bit(feat, header->adds_features);
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -020060}
61
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -030062bool perf_header__has_feat(const struct perf_header *header, int feat)
Arnaldo Carvalho de Melo8d063672009-11-04 18:50:43 -020063{
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -030064 return test_bit(feat, header->adds_features);
Arnaldo Carvalho de Melo8d063672009-11-04 18:50:43 -020065}
66
Arnaldo Carvalho de Melo3726cc72009-11-17 01:18:12 -020067static int do_write(int fd, const void *buf, size_t size)
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020068{
69 while (size) {
70 int ret = write(fd, buf, size);
71
72 if (ret < 0)
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -020073 return -errno;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020074
75 size -= ret;
76 buf += ret;
77 }
Arnaldo Carvalho de Melo3726cc72009-11-17 01:18:12 -020078
79 return 0;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020080}
81
Arnaldo Carvalho de Melof92cb242010-01-04 16:19:28 -020082#define NAME_ALIGN 64
83
84static int write_padded(int fd, const void *bf, size_t count,
85 size_t count_aligned)
86{
87 static const char zero_buf[NAME_ALIGN];
88 int err = do_write(fd, bf, count);
89
90 if (!err)
91 err = do_write(fd, zero_buf, count_aligned - count);
92
93 return err;
94}
95
Stephane Eranianfbe96f22011-09-30 15:40:40 +020096static int do_write_string(int fd, const char *str)
97{
98 u32 len, olen;
99 int ret;
100
101 olen = strlen(str) + 1;
Irina Tirdea9ac3e482012-09-11 01:15:01 +0300102 len = PERF_ALIGN(olen, NAME_ALIGN);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200103
104 /* write len, incl. \0 */
105 ret = do_write(fd, &len, sizeof(len));
106 if (ret < 0)
107 return ret;
108
109 return write_padded(fd, str, olen, len);
110}
111
112static char *do_read_string(int fd, struct perf_header *ph)
113{
114 ssize_t sz, ret;
115 u32 len;
116 char *buf;
117
Namhyung Kim5323f602012-12-17 15:38:54 +0900118 sz = readn(fd, &len, sizeof(len));
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200119 if (sz < (ssize_t)sizeof(len))
120 return NULL;
121
122 if (ph->needs_swap)
123 len = bswap_32(len);
124
125 buf = malloc(len);
126 if (!buf)
127 return NULL;
128
Namhyung Kim5323f602012-12-17 15:38:54 +0900129 ret = readn(fd, buf, len);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200130 if (ret == (ssize_t)len) {
131 /*
132 * strings are padded by zeroes
133 * thus the actual strlen of buf
134 * may be less than len
135 */
136 return buf;
137 }
138
139 free(buf);
140 return NULL;
141}
142
143int
144perf_header__set_cmdline(int argc, const char **argv)
145{
146 int i;
147
David Ahern56e6f602012-07-29 20:53:51 -0600148 /*
149 * If header_argv has already been set, do not override it.
150 * This allows a command to set the cmdline, parse args and
151 * then call another builtin function that implements a
152 * command -- e.g, cmd_kvm calling cmd_record.
153 */
154 if (header_argv)
155 return 0;
156
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200157 header_argc = (u32)argc;
158
159 /* do not include NULL termination */
160 header_argv = calloc(argc, sizeof(char *));
161 if (!header_argv)
162 return -ENOMEM;
163
164 /*
165 * must copy argv contents because it gets moved
166 * around during option parsing
167 */
168 for (i = 0; i < argc ; i++)
169 header_argv[i] = argv[i];
170
171 return 0;
172}
173
Robert Richter1b549502011-12-07 10:02:53 +0100174#define dsos__for_each_with_build_id(pos, head) \
175 list_for_each_entry(pos, head, node) \
176 if (!pos->has_build_id) \
177 continue; \
178 else
179
Arnaldo Carvalho de Melobf4414a2013-12-10 15:19:23 -0300180static int write_buildid(const char *name, size_t name_len, u8 *build_id,
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +0200181 pid_t pid, u16 misc, int fd)
182{
183 int err;
184 struct build_id_event b;
185 size_t len;
186
187 len = name_len + 1;
188 len = PERF_ALIGN(len, NAME_ALIGN);
189
190 memset(&b, 0, sizeof(b));
191 memcpy(&b.build_id, build_id, BUILD_ID_SIZE);
192 b.pid = pid;
193 b.header.misc = misc;
194 b.header.size = sizeof(b) + len;
195
196 err = do_write(fd, &b, sizeof(b));
197 if (err < 0)
198 return err;
199
200 return write_padded(fd, name, name_len + 1, len);
201}
202
Adrian Hunter1f625b02014-07-22 16:17:23 +0300203static int __dsos__hit_all(struct list_head *head)
204{
205 struct dso *pos;
206
207 list_for_each_entry(pos, head, node)
208 pos->hit = true;
209
210 return 0;
211}
212
213static int machine__hit_all_dsos(struct machine *machine)
214{
215 int err;
216
Waiman Long8fa7d872014-09-29 16:07:28 -0400217 err = __dsos__hit_all(&machine->kernel_dsos.head);
Adrian Hunter1f625b02014-07-22 16:17:23 +0300218 if (err)
219 return err;
220
Waiman Long8fa7d872014-09-29 16:07:28 -0400221 return __dsos__hit_all(&machine->user_dsos.head);
Adrian Hunter1f625b02014-07-22 16:17:23 +0300222}
223
224int dsos__hit_all(struct perf_session *session)
225{
226 struct rb_node *nd;
227 int err;
228
229 err = machine__hit_all_dsos(&session->machines.host);
230 if (err)
231 return err;
232
233 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
234 struct machine *pos = rb_entry(nd, struct machine, rb_node);
235
236 err = machine__hit_all_dsos(pos);
237 if (err)
238 return err;
239 }
240
241 return 0;
242}
243
Adrian Hunter5b6a42f2013-09-12 21:19:19 +0300244static int __dsos__write_buildid_table(struct list_head *head,
245 struct machine *machine,
246 pid_t pid, u16 misc, int fd)
Robert Richter1b549502011-12-07 10:02:53 +0100247{
Adrian Hunter5b6a42f2013-09-12 21:19:19 +0300248 char nm[PATH_MAX];
Robert Richter1b549502011-12-07 10:02:53 +0100249 struct dso *pos;
250
251 dsos__for_each_with_build_id(pos, head) {
252 int err;
Arnaldo Carvalho de Melobf4414a2013-12-10 15:19:23 -0300253 const char *name;
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +0200254 size_t name_len;
Robert Richter1b549502011-12-07 10:02:53 +0100255
256 if (!pos->hit)
257 continue;
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +0200258
Adrian Hunter51682dc2014-07-22 16:17:57 +0300259 if (dso__is_vdso(pos)) {
260 name = pos->short_name;
261 name_len = pos->short_name_len + 1;
Adrian Hunter5b6a42f2013-09-12 21:19:19 +0300262 } else if (dso__is_kcore(pos)) {
263 machine__mmap_name(machine, nm, sizeof(nm));
264 name = nm;
265 name_len = strlen(nm) + 1;
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +0200266 } else {
267 name = pos->long_name;
268 name_len = pos->long_name_len + 1;
269 }
270
271 err = write_buildid(name, name_len, pos->build_id,
272 pid, misc, fd);
273 if (err)
Robert Richter1b549502011-12-07 10:02:53 +0100274 return err;
275 }
276
277 return 0;
278}
279
280static int machine__write_buildid_table(struct machine *machine, int fd)
281{
282 int err;
283 u16 kmisc = PERF_RECORD_MISC_KERNEL,
284 umisc = PERF_RECORD_MISC_USER;
285
286 if (!machine__is_host(machine)) {
287 kmisc = PERF_RECORD_MISC_GUEST_KERNEL;
288 umisc = PERF_RECORD_MISC_GUEST_USER;
289 }
290
Waiman Long8fa7d872014-09-29 16:07:28 -0400291 err = __dsos__write_buildid_table(&machine->kernel_dsos.head, machine,
Adrian Hunter5b6a42f2013-09-12 21:19:19 +0300292 machine->pid, kmisc, fd);
Robert Richter1b549502011-12-07 10:02:53 +0100293 if (err == 0)
Waiman Long8fa7d872014-09-29 16:07:28 -0400294 err = __dsos__write_buildid_table(&machine->user_dsos.head,
295 machine, machine->pid, umisc,
296 fd);
Robert Richter1b549502011-12-07 10:02:53 +0100297 return err;
298}
299
300static int dsos__write_buildid_table(struct perf_header *header, int fd)
301{
302 struct perf_session *session = container_of(header,
303 struct perf_session, header);
304 struct rb_node *nd;
Arnaldo Carvalho de Melo876650e2012-12-18 19:15:48 -0300305 int err = machine__write_buildid_table(&session->machines.host, fd);
Robert Richter1b549502011-12-07 10:02:53 +0100306
307 if (err)
308 return err;
309
Arnaldo Carvalho de Melo876650e2012-12-18 19:15:48 -0300310 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
Robert Richter1b549502011-12-07 10:02:53 +0100311 struct machine *pos = rb_entry(nd, struct machine, rb_node);
312 err = machine__write_buildid_table(pos, fd);
313 if (err)
314 break;
315 }
316 return err;
317}
318
319int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +0200320 const char *name, bool is_kallsyms, bool is_vdso)
Robert Richter1b549502011-12-07 10:02:53 +0100321{
322 const size_t size = PATH_MAX;
323 char *realname, *filename = zalloc(size),
324 *linkname = zalloc(size), *targetname;
325 int len, err = -1;
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +0200326 bool slash = is_kallsyms || is_vdso;
Robert Richter1b549502011-12-07 10:02:53 +0100327
328 if (is_kallsyms) {
329 if (symbol_conf.kptr_restrict) {
330 pr_debug("Not caching a kptr_restrict'ed /proc/kallsyms\n");
Thomas Jaroschfdae6372013-01-25 11:21:39 +0100331 err = 0;
332 goto out_free;
Robert Richter1b549502011-12-07 10:02:53 +0100333 }
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +0200334 realname = (char *) name;
Robert Richter1b549502011-12-07 10:02:53 +0100335 } else
336 realname = realpath(name, NULL);
337
338 if (realname == NULL || filename == NULL || linkname == NULL)
339 goto out_free;
340
Arnaldo Carvalho de Meloe7f01d12012-03-14 12:29:29 -0300341 len = scnprintf(filename, size, "%s%s%s",
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +0200342 debugdir, slash ? "/" : "",
Adrian Hunter51682dc2014-07-22 16:17:57 +0300343 is_vdso ? DSO__NAME_VDSO : realname);
Robert Richter1b549502011-12-07 10:02:53 +0100344 if (mkdir_p(filename, 0755))
345 goto out_free;
346
Namhyung Kimafda0f92012-05-01 23:19:36 +0900347 snprintf(filename + len, size - len, "/%s", sbuild_id);
Robert Richter1b549502011-12-07 10:02:53 +0100348
349 if (access(filename, F_OK)) {
350 if (is_kallsyms) {
351 if (copyfile("/proc/kallsyms", filename))
352 goto out_free;
353 } else if (link(realname, filename) && copyfile(name, filename))
354 goto out_free;
355 }
356
Arnaldo Carvalho de Meloe7f01d12012-03-14 12:29:29 -0300357 len = scnprintf(linkname, size, "%s/.build-id/%.2s",
Robert Richter1b549502011-12-07 10:02:53 +0100358 debugdir, sbuild_id);
359
360 if (access(linkname, X_OK) && mkdir_p(linkname, 0755))
361 goto out_free;
362
363 snprintf(linkname + len, size - len, "/%s", sbuild_id + 2);
364 targetname = filename + strlen(debugdir) - 5;
365 memcpy(targetname, "../..", 5);
366
367 if (symlink(targetname, linkname) == 0)
368 err = 0;
369out_free:
370 if (!is_kallsyms)
371 free(realname);
372 free(filename);
373 free(linkname);
374 return err;
375}
376
377static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
378 const char *name, const char *debugdir,
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +0200379 bool is_kallsyms, bool is_vdso)
Robert Richter1b549502011-12-07 10:02:53 +0100380{
381 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
382
383 build_id__sprintf(build_id, build_id_size, sbuild_id);
384
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +0200385 return build_id_cache__add_s(sbuild_id, debugdir, name,
386 is_kallsyms, is_vdso);
Robert Richter1b549502011-12-07 10:02:53 +0100387}
388
389int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
390{
391 const size_t size = PATH_MAX;
392 char *filename = zalloc(size),
393 *linkname = zalloc(size);
394 int err = -1;
395
396 if (filename == NULL || linkname == NULL)
397 goto out_free;
398
399 snprintf(linkname, size, "%s/.build-id/%.2s/%s",
400 debugdir, sbuild_id, sbuild_id + 2);
401
402 if (access(linkname, F_OK))
403 goto out_free;
404
405 if (readlink(linkname, filename, size - 1) < 0)
406 goto out_free;
407
408 if (unlink(linkname))
409 goto out_free;
410
411 /*
412 * Since the link is relative, we must make it absolute:
413 */
414 snprintf(linkname, size, "%s/.build-id/%.2s/%s",
415 debugdir, sbuild_id, filename);
416
417 if (unlink(linkname))
418 goto out_free;
419
420 err = 0;
421out_free:
422 free(filename);
423 free(linkname);
424 return err;
425}
426
Adrian Hunter5b6a42f2013-09-12 21:19:19 +0300427static int dso__cache_build_id(struct dso *dso, struct machine *machine,
428 const char *debugdir)
Robert Richter1b549502011-12-07 10:02:53 +0100429{
430 bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
Adrian Hunter51682dc2014-07-22 16:17:57 +0300431 bool is_vdso = dso__is_vdso(dso);
Arnaldo Carvalho de Melobf4414a2013-12-10 15:19:23 -0300432 const char *name = dso->long_name;
Adrian Hunter5b6a42f2013-09-12 21:19:19 +0300433 char nm[PATH_MAX];
Robert Richter1b549502011-12-07 10:02:53 +0100434
Adrian Hunter5b6a42f2013-09-12 21:19:19 +0300435 if (dso__is_kcore(dso)) {
436 is_kallsyms = true;
437 machine__mmap_name(machine, nm, sizeof(nm));
438 name = nm;
439 }
440 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name,
441 debugdir, is_kallsyms, is_vdso);
Robert Richter1b549502011-12-07 10:02:53 +0100442}
443
Adrian Hunter5b6a42f2013-09-12 21:19:19 +0300444static int __dsos__cache_build_ids(struct list_head *head,
445 struct machine *machine, const char *debugdir)
Robert Richter1b549502011-12-07 10:02:53 +0100446{
447 struct dso *pos;
448 int err = 0;
449
450 dsos__for_each_with_build_id(pos, head)
Adrian Hunter5b6a42f2013-09-12 21:19:19 +0300451 if (dso__cache_build_id(pos, machine, debugdir))
Robert Richter1b549502011-12-07 10:02:53 +0100452 err = -1;
453
454 return err;
455}
456
457static int machine__cache_build_ids(struct machine *machine, const char *debugdir)
458{
Waiman Long8fa7d872014-09-29 16:07:28 -0400459 int ret = __dsos__cache_build_ids(&machine->kernel_dsos.head, machine,
Adrian Hunter5b6a42f2013-09-12 21:19:19 +0300460 debugdir);
Waiman Long8fa7d872014-09-29 16:07:28 -0400461 ret |= __dsos__cache_build_ids(&machine->user_dsos.head, machine,
462 debugdir);
Robert Richter1b549502011-12-07 10:02:53 +0100463 return ret;
464}
465
466static int perf_session__cache_build_ids(struct perf_session *session)
467{
468 struct rb_node *nd;
469 int ret;
470 char debugdir[PATH_MAX];
471
472 snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir);
473
474 if (mkdir(debugdir, 0755) != 0 && errno != EEXIST)
475 return -1;
476
Arnaldo Carvalho de Melo876650e2012-12-18 19:15:48 -0300477 ret = machine__cache_build_ids(&session->machines.host, debugdir);
Robert Richter1b549502011-12-07 10:02:53 +0100478
Arnaldo Carvalho de Melo876650e2012-12-18 19:15:48 -0300479 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
Robert Richter1b549502011-12-07 10:02:53 +0100480 struct machine *pos = rb_entry(nd, struct machine, rb_node);
481 ret |= machine__cache_build_ids(pos, debugdir);
482 }
483 return ret ? -1 : 0;
484}
485
486static bool machine__read_build_ids(struct machine *machine, bool with_hits)
487{
Waiman Long8fa7d872014-09-29 16:07:28 -0400488 bool ret;
489
490 ret = __dsos__read_build_ids(&machine->kernel_dsos.head, with_hits);
491 ret |= __dsos__read_build_ids(&machine->user_dsos.head, with_hits);
Robert Richter1b549502011-12-07 10:02:53 +0100492 return ret;
493}
494
495static bool perf_session__read_build_ids(struct perf_session *session, bool with_hits)
496{
497 struct rb_node *nd;
Arnaldo Carvalho de Melo876650e2012-12-18 19:15:48 -0300498 bool ret = machine__read_build_ids(&session->machines.host, with_hits);
Robert Richter1b549502011-12-07 10:02:53 +0100499
Arnaldo Carvalho de Melo876650e2012-12-18 19:15:48 -0300500 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
Robert Richter1b549502011-12-07 10:02:53 +0100501 struct machine *pos = rb_entry(nd, struct machine, rb_node);
502 ret |= machine__read_build_ids(pos, with_hits);
503 }
504
505 return ret;
506}
507
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300508static int write_tracing_data(int fd, struct perf_header *h __maybe_unused,
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200509 struct perf_evlist *evlist)
510{
511 return read_tracing_data(fd, &evlist->entries);
512}
513
514
515static int write_build_id(int fd, struct perf_header *h,
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300516 struct perf_evlist *evlist __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200517{
518 struct perf_session *session;
519 int err;
520
521 session = container_of(h, struct perf_session, header);
522
Robert Richtere20960c2011-12-07 10:02:55 +0100523 if (!perf_session__read_build_ids(session, true))
524 return -1;
525
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200526 err = dsos__write_buildid_table(h, fd);
527 if (err < 0) {
528 pr_debug("failed to write buildid table\n");
529 return err;
530 }
531 if (!no_buildid_cache)
532 perf_session__cache_build_ids(session);
533
534 return 0;
535}
536
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300537static int write_hostname(int fd, struct perf_header *h __maybe_unused,
538 struct perf_evlist *evlist __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200539{
540 struct utsname uts;
541 int ret;
542
543 ret = uname(&uts);
544 if (ret < 0)
545 return -1;
546
547 return do_write_string(fd, uts.nodename);
548}
549
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300550static int write_osrelease(int fd, struct perf_header *h __maybe_unused,
551 struct perf_evlist *evlist __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200552{
553 struct utsname uts;
554 int ret;
555
556 ret = uname(&uts);
557 if (ret < 0)
558 return -1;
559
560 return do_write_string(fd, uts.release);
561}
562
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300563static int write_arch(int fd, struct perf_header *h __maybe_unused,
564 struct perf_evlist *evlist __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200565{
566 struct utsname uts;
567 int ret;
568
569 ret = uname(&uts);
570 if (ret < 0)
571 return -1;
572
573 return do_write_string(fd, uts.machine);
574}
575
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300576static int write_version(int fd, struct perf_header *h __maybe_unused,
577 struct perf_evlist *evlist __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200578{
579 return do_write_string(fd, perf_version_string);
580}
581
Wang Nan493c3032014-10-24 09:45:26 +0800582static int __write_cpudesc(int fd, const char *cpuinfo_proc)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200583{
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200584 FILE *file;
585 char *buf = NULL;
586 char *s, *p;
Wang Nan493c3032014-10-24 09:45:26 +0800587 const char *search = cpuinfo_proc;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200588 size_t len = 0;
589 int ret = -1;
590
591 if (!search)
592 return -1;
593
594 file = fopen("/proc/cpuinfo", "r");
595 if (!file)
596 return -1;
597
598 while (getline(&buf, &len, file) > 0) {
599 ret = strncmp(buf, search, strlen(search));
600 if (!ret)
601 break;
602 }
603
604 if (ret)
605 goto done;
606
607 s = buf;
608
609 p = strchr(buf, ':');
610 if (p && *(p+1) == ' ' && *(p+2))
611 s = p + 2;
612 p = strchr(s, '\n');
613 if (p)
614 *p = '\0';
615
616 /* squash extra space characters (branding string) */
617 p = s;
618 while (*p) {
619 if (isspace(*p)) {
620 char *r = p + 1;
621 char *q = r;
622 *p = ' ';
623 while (*q && isspace(*q))
624 q++;
625 if (q != (p+1))
626 while ((*r++ = *q++));
627 }
628 p++;
629 }
630 ret = do_write_string(fd, s);
631done:
632 free(buf);
633 fclose(file);
634 return ret;
635}
636
Wang Nan493c3032014-10-24 09:45:26 +0800637static int write_cpudesc(int fd, struct perf_header *h __maybe_unused,
638 struct perf_evlist *evlist __maybe_unused)
639{
640#ifndef CPUINFO_PROC
641#define CPUINFO_PROC {"model name", }
642#endif
643 const char *cpuinfo_procs[] = CPUINFO_PROC;
644 unsigned int i;
645
646 for (i = 0; i < ARRAY_SIZE(cpuinfo_procs); i++) {
647 int ret;
648 ret = __write_cpudesc(fd, cpuinfo_procs[i]);
649 if (ret >= 0)
650 return ret;
651 }
652 return -1;
653}
654
655
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300656static int write_nrcpus(int fd, struct perf_header *h __maybe_unused,
657 struct perf_evlist *evlist __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200658{
659 long nr;
660 u32 nrc, nra;
661 int ret;
662
663 nr = sysconf(_SC_NPROCESSORS_CONF);
664 if (nr < 0)
665 return -1;
666
667 nrc = (u32)(nr & UINT_MAX);
668
669 nr = sysconf(_SC_NPROCESSORS_ONLN);
670 if (nr < 0)
671 return -1;
672
673 nra = (u32)(nr & UINT_MAX);
674
675 ret = do_write(fd, &nrc, sizeof(nrc));
676 if (ret < 0)
677 return ret;
678
679 return do_write(fd, &nra, sizeof(nra));
680}
681
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300682static int write_event_desc(int fd, struct perf_header *h __maybe_unused,
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200683 struct perf_evlist *evlist)
684{
Robert Richter6606f872012-08-16 21:10:19 +0200685 struct perf_evsel *evsel;
Namhyung Kim74ba9e12012-09-05 14:02:47 +0900686 u32 nre, nri, sz;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200687 int ret;
688
Namhyung Kim74ba9e12012-09-05 14:02:47 +0900689 nre = evlist->nr_entries;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200690
691 /*
692 * write number of events
693 */
694 ret = do_write(fd, &nre, sizeof(nre));
695 if (ret < 0)
696 return ret;
697
698 /*
699 * size of perf_event_attr struct
700 */
Robert Richter6606f872012-08-16 21:10:19 +0200701 sz = (u32)sizeof(evsel->attr);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200702 ret = do_write(fd, &sz, sizeof(sz));
703 if (ret < 0)
704 return ret;
705
Arnaldo Carvalho de Melo0050f7a2014-01-10 10:37:27 -0300706 evlist__for_each(evlist, evsel) {
Robert Richter6606f872012-08-16 21:10:19 +0200707 ret = do_write(fd, &evsel->attr, sz);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200708 if (ret < 0)
709 return ret;
710 /*
711 * write number of unique id per event
712 * there is one id per instance of an event
713 *
714 * copy into an nri to be independent of the
715 * type of ids,
716 */
Robert Richter6606f872012-08-16 21:10:19 +0200717 nri = evsel->ids;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200718 ret = do_write(fd, &nri, sizeof(nri));
719 if (ret < 0)
720 return ret;
721
722 /*
723 * write event string as passed on cmdline
724 */
Robert Richter6606f872012-08-16 21:10:19 +0200725 ret = do_write_string(fd, perf_evsel__name(evsel));
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200726 if (ret < 0)
727 return ret;
728 /*
729 * write unique ids for this event
730 */
Robert Richter6606f872012-08-16 21:10:19 +0200731 ret = do_write(fd, evsel->id, evsel->ids * sizeof(u64));
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200732 if (ret < 0)
733 return ret;
734 }
735 return 0;
736}
737
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300738static int write_cmdline(int fd, struct perf_header *h __maybe_unused,
739 struct perf_evlist *evlist __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200740{
741 char buf[MAXPATHLEN];
742 char proc[32];
743 u32 i, n;
744 int ret;
745
746 /*
747 * actual atual path to perf binary
748 */
749 sprintf(proc, "/proc/%d/exe", getpid());
750 ret = readlink(proc, buf, sizeof(buf));
751 if (ret <= 0)
752 return -1;
753
754 /* readlink() does not add null termination */
755 buf[ret] = '\0';
756
757 /* account for binary path */
758 n = header_argc + 1;
759
760 ret = do_write(fd, &n, sizeof(n));
761 if (ret < 0)
762 return ret;
763
764 ret = do_write_string(fd, buf);
765 if (ret < 0)
766 return ret;
767
768 for (i = 0 ; i < header_argc; i++) {
769 ret = do_write_string(fd, header_argv[i]);
770 if (ret < 0)
771 return ret;
772 }
773 return 0;
774}
775
776#define CORE_SIB_FMT \
777 "/sys/devices/system/cpu/cpu%d/topology/core_siblings_list"
778#define THRD_SIB_FMT \
779 "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list"
780
781struct cpu_topo {
782 u32 core_sib;
783 u32 thread_sib;
784 char **core_siblings;
785 char **thread_siblings;
786};
787
788static int build_cpu_topo(struct cpu_topo *tp, int cpu)
789{
790 FILE *fp;
791 char filename[MAXPATHLEN];
792 char *buf = NULL, *p;
793 size_t len = 0;
Stephane Eranianc5885742013-08-14 12:04:26 +0200794 ssize_t sret;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200795 u32 i = 0;
796 int ret = -1;
797
798 sprintf(filename, CORE_SIB_FMT, cpu);
799 fp = fopen(filename, "r");
800 if (!fp)
Stephane Eranianc5885742013-08-14 12:04:26 +0200801 goto try_threads;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200802
Stephane Eranianc5885742013-08-14 12:04:26 +0200803 sret = getline(&buf, &len, fp);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200804 fclose(fp);
Stephane Eranianc5885742013-08-14 12:04:26 +0200805 if (sret <= 0)
806 goto try_threads;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200807
808 p = strchr(buf, '\n');
809 if (p)
810 *p = '\0';
811
812 for (i = 0; i < tp->core_sib; i++) {
813 if (!strcmp(buf, tp->core_siblings[i]))
814 break;
815 }
816 if (i == tp->core_sib) {
817 tp->core_siblings[i] = buf;
818 tp->core_sib++;
819 buf = NULL;
820 len = 0;
821 }
Stephane Eranianc5885742013-08-14 12:04:26 +0200822 ret = 0;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200823
Stephane Eranianc5885742013-08-14 12:04:26 +0200824try_threads:
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200825 sprintf(filename, THRD_SIB_FMT, cpu);
826 fp = fopen(filename, "r");
827 if (!fp)
828 goto done;
829
830 if (getline(&buf, &len, fp) <= 0)
831 goto done;
832
833 p = strchr(buf, '\n');
834 if (p)
835 *p = '\0';
836
837 for (i = 0; i < tp->thread_sib; i++) {
838 if (!strcmp(buf, tp->thread_siblings[i]))
839 break;
840 }
841 if (i == tp->thread_sib) {
842 tp->thread_siblings[i] = buf;
843 tp->thread_sib++;
844 buf = NULL;
845 }
846 ret = 0;
847done:
848 if(fp)
849 fclose(fp);
850 free(buf);
851 return ret;
852}
853
854static void free_cpu_topo(struct cpu_topo *tp)
855{
856 u32 i;
857
858 if (!tp)
859 return;
860
861 for (i = 0 ; i < tp->core_sib; i++)
Arnaldo Carvalho de Melo74cf2492013-12-27 16:55:14 -0300862 zfree(&tp->core_siblings[i]);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200863
864 for (i = 0 ; i < tp->thread_sib; i++)
Arnaldo Carvalho de Melo74cf2492013-12-27 16:55:14 -0300865 zfree(&tp->thread_siblings[i]);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200866
867 free(tp);
868}
869
870static struct cpu_topo *build_cpu_topology(void)
871{
872 struct cpu_topo *tp;
873 void *addr;
874 u32 nr, i;
875 size_t sz;
876 long ncpus;
877 int ret = -1;
878
879 ncpus = sysconf(_SC_NPROCESSORS_CONF);
880 if (ncpus < 0)
881 return NULL;
882
883 nr = (u32)(ncpus & UINT_MAX);
884
885 sz = nr * sizeof(char *);
886
887 addr = calloc(1, sizeof(*tp) + 2 * sz);
888 if (!addr)
889 return NULL;
890
891 tp = addr;
892
893 addr += sizeof(*tp);
894 tp->core_siblings = addr;
895 addr += sz;
896 tp->thread_siblings = addr;
897
898 for (i = 0; i < nr; i++) {
899 ret = build_cpu_topo(tp, i);
900 if (ret < 0)
901 break;
902 }
903 if (ret) {
904 free_cpu_topo(tp);
905 tp = NULL;
906 }
907 return tp;
908}
909
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300910static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused,
911 struct perf_evlist *evlist __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200912{
913 struct cpu_topo *tp;
914 u32 i;
915 int ret;
916
917 tp = build_cpu_topology();
918 if (!tp)
919 return -1;
920
921 ret = do_write(fd, &tp->core_sib, sizeof(tp->core_sib));
922 if (ret < 0)
923 goto done;
924
925 for (i = 0; i < tp->core_sib; i++) {
926 ret = do_write_string(fd, tp->core_siblings[i]);
927 if (ret < 0)
928 goto done;
929 }
930 ret = do_write(fd, &tp->thread_sib, sizeof(tp->thread_sib));
931 if (ret < 0)
932 goto done;
933
934 for (i = 0; i < tp->thread_sib; i++) {
935 ret = do_write_string(fd, tp->thread_siblings[i]);
936 if (ret < 0)
937 break;
938 }
939done:
940 free_cpu_topo(tp);
941 return ret;
942}
943
944
945
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300946static int write_total_mem(int fd, struct perf_header *h __maybe_unused,
947 struct perf_evlist *evlist __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200948{
949 char *buf = NULL;
950 FILE *fp;
951 size_t len = 0;
952 int ret = -1, n;
953 uint64_t mem;
954
955 fp = fopen("/proc/meminfo", "r");
956 if (!fp)
957 return -1;
958
959 while (getline(&buf, &len, fp) > 0) {
960 ret = strncmp(buf, "MemTotal:", 9);
961 if (!ret)
962 break;
963 }
964 if (!ret) {
965 n = sscanf(buf, "%*s %"PRIu64, &mem);
966 if (n == 1)
967 ret = do_write(fd, &mem, sizeof(mem));
968 }
969 free(buf);
970 fclose(fp);
971 return ret;
972}
973
974static int write_topo_node(int fd, int node)
975{
976 char str[MAXPATHLEN];
977 char field[32];
978 char *buf = NULL, *p;
979 size_t len = 0;
980 FILE *fp;
981 u64 mem_total, mem_free, mem;
982 int ret = -1;
983
984 sprintf(str, "/sys/devices/system/node/node%d/meminfo", node);
985 fp = fopen(str, "r");
986 if (!fp)
987 return -1;
988
989 while (getline(&buf, &len, fp) > 0) {
990 /* skip over invalid lines */
991 if (!strchr(buf, ':'))
992 continue;
Alan Coxa761a2d2014-01-20 19:10:11 +0100993 if (sscanf(buf, "%*s %*d %31s %"PRIu64, field, &mem) != 2)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200994 goto done;
995 if (!strcmp(field, "MemTotal:"))
996 mem_total = mem;
997 if (!strcmp(field, "MemFree:"))
998 mem_free = mem;
999 }
1000
1001 fclose(fp);
Thomas Jarosch5809fde2013-01-28 10:21:14 +01001002 fp = NULL;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001003
1004 ret = do_write(fd, &mem_total, sizeof(u64));
1005 if (ret)
1006 goto done;
1007
1008 ret = do_write(fd, &mem_free, sizeof(u64));
1009 if (ret)
1010 goto done;
1011
1012 ret = -1;
1013 sprintf(str, "/sys/devices/system/node/node%d/cpulist", node);
1014
1015 fp = fopen(str, "r");
1016 if (!fp)
1017 goto done;
1018
1019 if (getline(&buf, &len, fp) <= 0)
1020 goto done;
1021
1022 p = strchr(buf, '\n');
1023 if (p)
1024 *p = '\0';
1025
1026 ret = do_write_string(fd, buf);
1027done:
1028 free(buf);
Thomas Jarosch5809fde2013-01-28 10:21:14 +01001029 if (fp)
1030 fclose(fp);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001031 return ret;
1032}
1033
Irina Tirdea1d037ca2012-09-11 01:15:03 +03001034static int write_numa_topology(int fd, struct perf_header *h __maybe_unused,
1035 struct perf_evlist *evlist __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001036{
1037 char *buf = NULL;
1038 size_t len = 0;
1039 FILE *fp;
1040 struct cpu_map *node_map = NULL;
1041 char *c;
1042 u32 nr, i, j;
1043 int ret = -1;
1044
1045 fp = fopen("/sys/devices/system/node/online", "r");
1046 if (!fp)
1047 return -1;
1048
1049 if (getline(&buf, &len, fp) <= 0)
1050 goto done;
1051
1052 c = strchr(buf, '\n');
1053 if (c)
1054 *c = '\0';
1055
1056 node_map = cpu_map__new(buf);
1057 if (!node_map)
1058 goto done;
1059
1060 nr = (u32)node_map->nr;
1061
1062 ret = do_write(fd, &nr, sizeof(nr));
1063 if (ret < 0)
1064 goto done;
1065
1066 for (i = 0; i < nr; i++) {
1067 j = (u32)node_map->map[i];
1068 ret = do_write(fd, &j, sizeof(j));
1069 if (ret < 0)
1070 break;
1071
1072 ret = write_topo_node(fd, i);
1073 if (ret < 0)
1074 break;
1075 }
1076done:
1077 free(buf);
1078 fclose(fp);
1079 free(node_map);
1080 return ret;
1081}
1082
1083/*
Robert Richter50a96672012-08-16 21:10:24 +02001084 * File format:
1085 *
1086 * struct pmu_mappings {
1087 * u32 pmu_num;
1088 * struct pmu_map {
1089 * u32 type;
1090 * char name[];
1091 * }[pmu_num];
1092 * };
1093 */
1094
Irina Tirdea1d037ca2012-09-11 01:15:03 +03001095static int write_pmu_mappings(int fd, struct perf_header *h __maybe_unused,
1096 struct perf_evlist *evlist __maybe_unused)
Robert Richter50a96672012-08-16 21:10:24 +02001097{
1098 struct perf_pmu *pmu = NULL;
1099 off_t offset = lseek(fd, 0, SEEK_CUR);
1100 __u32 pmu_num = 0;
Namhyung Kim5323f602012-12-17 15:38:54 +09001101 int ret;
Robert Richter50a96672012-08-16 21:10:24 +02001102
1103 /* write real pmu_num later */
Namhyung Kim5323f602012-12-17 15:38:54 +09001104 ret = do_write(fd, &pmu_num, sizeof(pmu_num));
1105 if (ret < 0)
1106 return ret;
Robert Richter50a96672012-08-16 21:10:24 +02001107
1108 while ((pmu = perf_pmu__scan(pmu))) {
1109 if (!pmu->name)
1110 continue;
1111 pmu_num++;
Namhyung Kim5323f602012-12-17 15:38:54 +09001112
1113 ret = do_write(fd, &pmu->type, sizeof(pmu->type));
1114 if (ret < 0)
1115 return ret;
1116
1117 ret = do_write_string(fd, pmu->name);
1118 if (ret < 0)
1119 return ret;
Robert Richter50a96672012-08-16 21:10:24 +02001120 }
1121
1122 if (pwrite(fd, &pmu_num, sizeof(pmu_num), offset) != sizeof(pmu_num)) {
1123 /* discard all */
1124 lseek(fd, offset, SEEK_SET);
1125 return -1;
1126 }
1127
1128 return 0;
1129}
1130
1131/*
Namhyung Kima8bb5592013-01-22 18:09:31 +09001132 * File format:
1133 *
1134 * struct group_descs {
1135 * u32 nr_groups;
1136 * struct group_desc {
1137 * char name[];
1138 * u32 leader_idx;
1139 * u32 nr_members;
1140 * }[nr_groups];
1141 * };
1142 */
1143static int write_group_desc(int fd, struct perf_header *h __maybe_unused,
1144 struct perf_evlist *evlist)
1145{
1146 u32 nr_groups = evlist->nr_groups;
1147 struct perf_evsel *evsel;
1148 int ret;
1149
1150 ret = do_write(fd, &nr_groups, sizeof(nr_groups));
1151 if (ret < 0)
1152 return ret;
1153
Arnaldo Carvalho de Melo0050f7a2014-01-10 10:37:27 -03001154 evlist__for_each(evlist, evsel) {
Namhyung Kima8bb5592013-01-22 18:09:31 +09001155 if (perf_evsel__is_group_leader(evsel) &&
1156 evsel->nr_members > 1) {
1157 const char *name = evsel->group_name ?: "{anon_group}";
1158 u32 leader_idx = evsel->idx;
1159 u32 nr_members = evsel->nr_members;
1160
1161 ret = do_write_string(fd, name);
1162 if (ret < 0)
1163 return ret;
1164
1165 ret = do_write(fd, &leader_idx, sizeof(leader_idx));
1166 if (ret < 0)
1167 return ret;
1168
1169 ret = do_write(fd, &nr_members, sizeof(nr_members));
1170 if (ret < 0)
1171 return ret;
1172 }
1173 }
1174 return 0;
1175}
1176
1177/*
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001178 * default get_cpuid(): nothing gets recorded
1179 * actual implementation must be in arch/$(ARCH)/util/header.c
1180 */
Irina Tirdea1d037ca2012-09-11 01:15:03 +03001181int __attribute__ ((weak)) get_cpuid(char *buffer __maybe_unused,
1182 size_t sz __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001183{
1184 return -1;
1185}
1186
Irina Tirdea1d037ca2012-09-11 01:15:03 +03001187static int write_cpuid(int fd, struct perf_header *h __maybe_unused,
1188 struct perf_evlist *evlist __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001189{
1190 char buffer[64];
1191 int ret;
1192
1193 ret = get_cpuid(buffer, sizeof(buffer));
1194 if (!ret)
1195 goto write_it;
1196
1197 return -1;
1198write_it:
1199 return do_write_string(fd, buffer);
1200}
1201
Irina Tirdea1d037ca2012-09-11 01:15:03 +03001202static int write_branch_stack(int fd __maybe_unused,
1203 struct perf_header *h __maybe_unused,
1204 struct perf_evlist *evlist __maybe_unused)
Stephane Eranian330aa672012-03-08 23:47:46 +01001205{
1206 return 0;
1207}
1208
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001209static void print_hostname(struct perf_header *ph, int fd __maybe_unused,
1210 FILE *fp)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001211{
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001212 fprintf(fp, "# hostname : %s\n", ph->env.hostname);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001213}
1214
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001215static void print_osrelease(struct perf_header *ph, int fd __maybe_unused,
1216 FILE *fp)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001217{
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001218 fprintf(fp, "# os release : %s\n", ph->env.os_release);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001219}
1220
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001221static void print_arch(struct perf_header *ph, int fd __maybe_unused, FILE *fp)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001222{
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001223 fprintf(fp, "# arch : %s\n", ph->env.arch);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001224}
1225
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001226static void print_cpudesc(struct perf_header *ph, int fd __maybe_unused,
1227 FILE *fp)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001228{
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001229 fprintf(fp, "# cpudesc : %s\n", ph->env.cpu_desc);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001230}
1231
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001232static void print_nrcpus(struct perf_header *ph, int fd __maybe_unused,
1233 FILE *fp)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001234{
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001235 fprintf(fp, "# nrcpus online : %u\n", ph->env.nr_cpus_online);
1236 fprintf(fp, "# nrcpus avail : %u\n", ph->env.nr_cpus_avail);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001237}
1238
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001239static void print_version(struct perf_header *ph, int fd __maybe_unused,
1240 FILE *fp)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001241{
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001242 fprintf(fp, "# perf version : %s\n", ph->env.version);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001243}
1244
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001245static void print_cmdline(struct perf_header *ph, int fd __maybe_unused,
1246 FILE *fp)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001247{
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001248 int nr, i;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001249 char *str;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001250
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001251 nr = ph->env.nr_cmdline;
1252 str = ph->env.cmdline;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001253
1254 fprintf(fp, "# cmdline : ");
1255
1256 for (i = 0; i < nr; i++) {
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001257 fprintf(fp, "%s ", str);
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001258 str += strlen(str) + 1;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001259 }
1260 fputc('\n', fp);
1261}
1262
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001263static void print_cpu_topology(struct perf_header *ph, int fd __maybe_unused,
1264 FILE *fp)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001265{
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001266 int nr, i;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001267 char *str;
1268
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001269 nr = ph->env.nr_sibling_cores;
1270 str = ph->env.sibling_cores;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001271
1272 for (i = 0; i < nr; i++) {
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001273 fprintf(fp, "# sibling cores : %s\n", str);
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001274 str += strlen(str) + 1;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001275 }
1276
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001277 nr = ph->env.nr_sibling_threads;
1278 str = ph->env.sibling_threads;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001279
1280 for (i = 0; i < nr; i++) {
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001281 fprintf(fp, "# sibling threads : %s\n", str);
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001282 str += strlen(str) + 1;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001283 }
1284}
1285
Robert Richter4e1b9c62012-08-16 21:10:22 +02001286static void free_event_desc(struct perf_evsel *events)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001287{
Robert Richter4e1b9c62012-08-16 21:10:22 +02001288 struct perf_evsel *evsel;
1289
1290 if (!events)
1291 return;
1292
1293 for (evsel = events; evsel->attr.size; evsel++) {
Arnaldo Carvalho de Melo74cf2492013-12-27 16:55:14 -03001294 zfree(&evsel->name);
1295 zfree(&evsel->id);
Robert Richter4e1b9c62012-08-16 21:10:22 +02001296 }
1297
1298 free(events);
1299}
1300
1301static struct perf_evsel *
1302read_event_desc(struct perf_header *ph, int fd)
1303{
1304 struct perf_evsel *evsel, *events = NULL;
1305 u64 *id;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001306 void *buf = NULL;
Stephane Eranian62db9062012-02-09 23:21:07 +01001307 u32 nre, sz, nr, i, j;
1308 ssize_t ret;
1309 size_t msz;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001310
1311 /* number of events */
Namhyung Kim5323f602012-12-17 15:38:54 +09001312 ret = readn(fd, &nre, sizeof(nre));
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001313 if (ret != (ssize_t)sizeof(nre))
1314 goto error;
1315
1316 if (ph->needs_swap)
1317 nre = bswap_32(nre);
1318
Namhyung Kim5323f602012-12-17 15:38:54 +09001319 ret = readn(fd, &sz, sizeof(sz));
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001320 if (ret != (ssize_t)sizeof(sz))
1321 goto error;
1322
1323 if (ph->needs_swap)
1324 sz = bswap_32(sz);
1325
Stephane Eranian62db9062012-02-09 23:21:07 +01001326 /* buffer to hold on file attr struct */
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001327 buf = malloc(sz);
1328 if (!buf)
1329 goto error;
1330
Robert Richter4e1b9c62012-08-16 21:10:22 +02001331 /* the last event terminates with evsel->attr.size == 0: */
1332 events = calloc(nre + 1, sizeof(*events));
1333 if (!events)
1334 goto error;
1335
1336 msz = sizeof(evsel->attr);
Jiri Olsa9fafd982012-03-20 19:15:39 +01001337 if (sz < msz)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001338 msz = sz;
1339
Robert Richter4e1b9c62012-08-16 21:10:22 +02001340 for (i = 0, evsel = events; i < nre; evsel++, i++) {
1341 evsel->idx = i;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001342
Stephane Eranian62db9062012-02-09 23:21:07 +01001343 /*
1344 * must read entire on-file attr struct to
1345 * sync up with layout.
1346 */
Namhyung Kim5323f602012-12-17 15:38:54 +09001347 ret = readn(fd, buf, sz);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001348 if (ret != (ssize_t)sz)
1349 goto error;
1350
1351 if (ph->needs_swap)
1352 perf_event__attr_swap(buf);
1353
Robert Richter4e1b9c62012-08-16 21:10:22 +02001354 memcpy(&evsel->attr, buf, msz);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001355
Namhyung Kim5323f602012-12-17 15:38:54 +09001356 ret = readn(fd, &nr, sizeof(nr));
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001357 if (ret != (ssize_t)sizeof(nr))
1358 goto error;
1359
Arnaldo Carvalho de Melo0807d2d2012-09-26 12:48:18 -03001360 if (ph->needs_swap) {
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001361 nr = bswap_32(nr);
Arnaldo Carvalho de Melo0807d2d2012-09-26 12:48:18 -03001362 evsel->needs_swap = true;
1363 }
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001364
Robert Richter4e1b9c62012-08-16 21:10:22 +02001365 evsel->name = do_read_string(fd, ph);
1366
1367 if (!nr)
1368 continue;
1369
1370 id = calloc(nr, sizeof(*id));
1371 if (!id)
1372 goto error;
1373 evsel->ids = nr;
1374 evsel->id = id;
1375
1376 for (j = 0 ; j < nr; j++) {
Namhyung Kim5323f602012-12-17 15:38:54 +09001377 ret = readn(fd, id, sizeof(*id));
Robert Richter4e1b9c62012-08-16 21:10:22 +02001378 if (ret != (ssize_t)sizeof(*id))
1379 goto error;
1380 if (ph->needs_swap)
1381 *id = bswap_64(*id);
1382 id++;
1383 }
1384 }
1385out:
Arnaldo Carvalho de Melo04662522013-12-26 17:41:15 -03001386 free(buf);
Robert Richter4e1b9c62012-08-16 21:10:22 +02001387 return events;
1388error:
1389 if (events)
1390 free_event_desc(events);
1391 events = NULL;
1392 goto out;
1393}
1394
1395static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
1396{
1397 struct perf_evsel *evsel, *events = read_event_desc(ph, fd);
1398 u32 j;
1399 u64 *id;
1400
1401 if (!events) {
1402 fprintf(fp, "# event desc: not available or unable to read\n");
1403 return;
1404 }
1405
1406 for (evsel = events; evsel->attr.size; evsel++) {
1407 fprintf(fp, "# event : name = %s, ", evsel->name);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001408
1409 fprintf(fp, "type = %d, config = 0x%"PRIx64
1410 ", config1 = 0x%"PRIx64", config2 = 0x%"PRIx64,
Robert Richter4e1b9c62012-08-16 21:10:22 +02001411 evsel->attr.type,
1412 (u64)evsel->attr.config,
1413 (u64)evsel->attr.config1,
1414 (u64)evsel->attr.config2);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001415
1416 fprintf(fp, ", excl_usr = %d, excl_kern = %d",
Robert Richter4e1b9c62012-08-16 21:10:22 +02001417 evsel->attr.exclude_user,
1418 evsel->attr.exclude_kernel);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001419
David Ahern78b961f2012-07-20 17:25:52 -06001420 fprintf(fp, ", excl_host = %d, excl_guest = %d",
Robert Richter4e1b9c62012-08-16 21:10:22 +02001421 evsel->attr.exclude_host,
1422 evsel->attr.exclude_guest);
David Ahern78b961f2012-07-20 17:25:52 -06001423
Robert Richter4e1b9c62012-08-16 21:10:22 +02001424 fprintf(fp, ", precise_ip = %d", evsel->attr.precise_ip);
David Ahern78b961f2012-07-20 17:25:52 -06001425
Stephane Eranian5c5e8542013-08-21 12:10:25 +02001426 fprintf(fp, ", attr_mmap2 = %d", evsel->attr.mmap2);
1427 fprintf(fp, ", attr_mmap = %d", evsel->attr.mmap);
1428 fprintf(fp, ", attr_mmap_data = %d", evsel->attr.mmap_data);
Robert Richter4e1b9c62012-08-16 21:10:22 +02001429 if (evsel->ids) {
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001430 fprintf(fp, ", id = {");
Robert Richter4e1b9c62012-08-16 21:10:22 +02001431 for (j = 0, id = evsel->id; j < evsel->ids; j++, id++) {
1432 if (j)
1433 fputc(',', fp);
1434 fprintf(fp, " %"PRIu64, *id);
1435 }
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001436 fprintf(fp, " }");
Robert Richter4e1b9c62012-08-16 21:10:22 +02001437 }
1438
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001439 fputc('\n', fp);
1440 }
Robert Richter4e1b9c62012-08-16 21:10:22 +02001441
1442 free_event_desc(events);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001443}
1444
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001445static void print_total_mem(struct perf_header *ph, int fd __maybe_unused,
Irina Tirdea1d037ca2012-09-11 01:15:03 +03001446 FILE *fp)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001447{
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001448 fprintf(fp, "# total memory : %Lu kB\n", ph->env.total_mem);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001449}
1450
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001451static void print_numa_topology(struct perf_header *ph, int fd __maybe_unused,
Irina Tirdea1d037ca2012-09-11 01:15:03 +03001452 FILE *fp)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001453{
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001454 u32 nr, c, i;
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001455 char *str, *tmp;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001456 uint64_t mem_total, mem_free;
1457
1458 /* nr nodes */
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001459 nr = ph->env.nr_numa_nodes;
1460 str = ph->env.numa_nodes;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001461
1462 for (i = 0; i < nr; i++) {
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001463 /* node number */
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001464 c = strtoul(str, &tmp, 0);
1465 if (*tmp != ':')
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001466 goto error;
1467
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001468 str = tmp + 1;
1469 mem_total = strtoull(str, &tmp, 0);
1470 if (*tmp != ':')
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001471 goto error;
1472
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001473 str = tmp + 1;
1474 mem_free = strtoull(str, &tmp, 0);
1475 if (*tmp != ':')
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001476 goto error;
1477
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001478 fprintf(fp, "# node%u meminfo : total = %"PRIu64" kB,"
1479 " free = %"PRIu64" kB\n",
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001480 c, mem_total, mem_free);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001481
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001482 str = tmp + 1;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001483 fprintf(fp, "# node%u cpu list : %s\n", c, str);
Namhyung Kim12344712012-10-23 22:44:49 +09001484
1485 str += strlen(str) + 1;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001486 }
1487 return;
1488error:
1489 fprintf(fp, "# numa topology : not available\n");
1490}
1491
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001492static void print_cpuid(struct perf_header *ph, int fd __maybe_unused, FILE *fp)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001493{
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001494 fprintf(fp, "# cpuid : %s\n", ph->env.cpuid);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001495}
1496
Irina Tirdea1d037ca2012-09-11 01:15:03 +03001497static void print_branch_stack(struct perf_header *ph __maybe_unused,
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001498 int fd __maybe_unused, FILE *fp)
Stephane Eranian330aa672012-03-08 23:47:46 +01001499{
1500 fprintf(fp, "# contains samples with branch stack\n");
1501}
1502
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001503static void print_pmu_mappings(struct perf_header *ph, int fd __maybe_unused,
1504 FILE *fp)
Robert Richter50a96672012-08-16 21:10:24 +02001505{
1506 const char *delimiter = "# pmu mappings: ";
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001507 char *str, *tmp;
Robert Richter50a96672012-08-16 21:10:24 +02001508 u32 pmu_num;
1509 u32 type;
1510
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001511 pmu_num = ph->env.nr_pmu_mappings;
Robert Richter50a96672012-08-16 21:10:24 +02001512 if (!pmu_num) {
1513 fprintf(fp, "# pmu mappings: not available\n");
1514 return;
1515 }
1516
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001517 str = ph->env.pmu_mappings;
Namhyung Kimbe4a2de2012-09-05 14:02:49 +09001518
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001519 while (pmu_num) {
1520 type = strtoul(str, &tmp, 0);
1521 if (*tmp != ':')
1522 goto error;
1523
1524 str = tmp + 1;
1525 fprintf(fp, "%s%s = %" PRIu32, delimiter, str, type);
1526
Robert Richter50a96672012-08-16 21:10:24 +02001527 delimiter = ", ";
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001528 str += strlen(str) + 1;
1529 pmu_num--;
Robert Richter50a96672012-08-16 21:10:24 +02001530 }
1531
1532 fprintf(fp, "\n");
1533
1534 if (!pmu_num)
1535 return;
1536error:
1537 fprintf(fp, "# pmu mappings: unable to read\n");
1538}
1539
Namhyung Kima8bb5592013-01-22 18:09:31 +09001540static void print_group_desc(struct perf_header *ph, int fd __maybe_unused,
1541 FILE *fp)
1542{
1543 struct perf_session *session;
1544 struct perf_evsel *evsel;
1545 u32 nr = 0;
1546
1547 session = container_of(ph, struct perf_session, header);
1548
Arnaldo Carvalho de Melo0050f7a2014-01-10 10:37:27 -03001549 evlist__for_each(session->evlist, evsel) {
Namhyung Kima8bb5592013-01-22 18:09:31 +09001550 if (perf_evsel__is_group_leader(evsel) &&
1551 evsel->nr_members > 1) {
1552 fprintf(fp, "# group: %s{%s", evsel->group_name ?: "",
1553 perf_evsel__name(evsel));
1554
1555 nr = evsel->nr_members - 1;
1556 } else if (nr) {
1557 fprintf(fp, ",%s", perf_evsel__name(evsel));
1558
1559 if (--nr == 0)
1560 fprintf(fp, "}\n");
1561 }
1562 }
1563}
1564
Robert Richter08d95bd2012-02-10 15:41:55 +01001565static int __event_process_build_id(struct build_id_event *bev,
1566 char *filename,
1567 struct perf_session *session)
1568{
1569 int err = -1;
Waiman Long8fa7d872014-09-29 16:07:28 -04001570 struct dsos *dsos;
Robert Richter08d95bd2012-02-10 15:41:55 +01001571 struct machine *machine;
1572 u16 misc;
1573 struct dso *dso;
1574 enum dso_kernel_type dso_type;
1575
1576 machine = perf_session__findnew_machine(session, bev->pid);
1577 if (!machine)
1578 goto out;
1579
1580 misc = bev->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
1581
1582 switch (misc) {
1583 case PERF_RECORD_MISC_KERNEL:
1584 dso_type = DSO_TYPE_KERNEL;
Waiman Long8fa7d872014-09-29 16:07:28 -04001585 dsos = &machine->kernel_dsos;
Robert Richter08d95bd2012-02-10 15:41:55 +01001586 break;
1587 case PERF_RECORD_MISC_GUEST_KERNEL:
1588 dso_type = DSO_TYPE_GUEST_KERNEL;
Waiman Long8fa7d872014-09-29 16:07:28 -04001589 dsos = &machine->kernel_dsos;
Robert Richter08d95bd2012-02-10 15:41:55 +01001590 break;
1591 case PERF_RECORD_MISC_USER:
1592 case PERF_RECORD_MISC_GUEST_USER:
1593 dso_type = DSO_TYPE_USER;
Waiman Long8fa7d872014-09-29 16:07:28 -04001594 dsos = &machine->user_dsos;
Robert Richter08d95bd2012-02-10 15:41:55 +01001595 break;
1596 default:
1597 goto out;
1598 }
1599
Waiman Long8fa7d872014-09-29 16:07:28 -04001600 dso = __dsos__findnew(dsos, filename);
Robert Richter08d95bd2012-02-10 15:41:55 +01001601 if (dso != NULL) {
1602 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
1603
1604 dso__set_build_id(dso, &bev->build_id);
1605
1606 if (filename[0] == '[')
1607 dso->kernel = dso_type;
1608
1609 build_id__sprintf(dso->build_id, sizeof(dso->build_id),
1610 sbuild_id);
1611 pr_debug("build id event received for %s: %s\n",
1612 dso->long_name, sbuild_id);
1613 }
1614
1615 err = 0;
1616out:
1617 return err;
1618}
1619
1620static int perf_header__read_build_ids_abi_quirk(struct perf_header *header,
1621 int input, u64 offset, u64 size)
1622{
1623 struct perf_session *session = container_of(header, struct perf_session, header);
1624 struct {
1625 struct perf_event_header header;
Irina Tirdea9ac3e482012-09-11 01:15:01 +03001626 u8 build_id[PERF_ALIGN(BUILD_ID_SIZE, sizeof(u64))];
Robert Richter08d95bd2012-02-10 15:41:55 +01001627 char filename[0];
1628 } old_bev;
1629 struct build_id_event bev;
1630 char filename[PATH_MAX];
1631 u64 limit = offset + size;
1632
1633 while (offset < limit) {
1634 ssize_t len;
1635
Namhyung Kim5323f602012-12-17 15:38:54 +09001636 if (readn(input, &old_bev, sizeof(old_bev)) != sizeof(old_bev))
Robert Richter08d95bd2012-02-10 15:41:55 +01001637 return -1;
1638
1639 if (header->needs_swap)
1640 perf_event_header__bswap(&old_bev.header);
1641
1642 len = old_bev.header.size - sizeof(old_bev);
Namhyung Kim5323f602012-12-17 15:38:54 +09001643 if (readn(input, filename, len) != len)
Robert Richter08d95bd2012-02-10 15:41:55 +01001644 return -1;
1645
1646 bev.header = old_bev.header;
1647
1648 /*
1649 * As the pid is the missing value, we need to fill
1650 * it properly. The header.misc value give us nice hint.
1651 */
1652 bev.pid = HOST_KERNEL_ID;
1653 if (bev.header.misc == PERF_RECORD_MISC_GUEST_USER ||
1654 bev.header.misc == PERF_RECORD_MISC_GUEST_KERNEL)
1655 bev.pid = DEFAULT_GUEST_KERNEL_ID;
1656
1657 memcpy(bev.build_id, old_bev.build_id, sizeof(bev.build_id));
1658 __event_process_build_id(&bev, filename, session);
1659
1660 offset += bev.header.size;
1661 }
1662
1663 return 0;
1664}
1665
1666static int perf_header__read_build_ids(struct perf_header *header,
1667 int input, u64 offset, u64 size)
1668{
1669 struct perf_session *session = container_of(header, struct perf_session, header);
1670 struct build_id_event bev;
1671 char filename[PATH_MAX];
1672 u64 limit = offset + size, orig_offset = offset;
1673 int err = -1;
1674
1675 while (offset < limit) {
1676 ssize_t len;
1677
Namhyung Kim5323f602012-12-17 15:38:54 +09001678 if (readn(input, &bev, sizeof(bev)) != sizeof(bev))
Robert Richter08d95bd2012-02-10 15:41:55 +01001679 goto out;
1680
1681 if (header->needs_swap)
1682 perf_event_header__bswap(&bev.header);
1683
1684 len = bev.header.size - sizeof(bev);
Namhyung Kim5323f602012-12-17 15:38:54 +09001685 if (readn(input, filename, len) != len)
Robert Richter08d95bd2012-02-10 15:41:55 +01001686 goto out;
1687 /*
1688 * The a1645ce1 changeset:
1689 *
1690 * "perf: 'perf kvm' tool for monitoring guest performance from host"
1691 *
1692 * Added a field to struct build_id_event that broke the file
1693 * format.
1694 *
1695 * Since the kernel build-id is the first entry, process the
1696 * table using the old format if the well known
1697 * '[kernel.kallsyms]' string for the kernel build-id has the
1698 * first 4 characters chopped off (where the pid_t sits).
1699 */
1700 if (memcmp(filename, "nel.kallsyms]", 13) == 0) {
1701 if (lseek(input, orig_offset, SEEK_SET) == (off_t)-1)
1702 return -1;
1703 return perf_header__read_build_ids_abi_quirk(header, input, offset, size);
1704 }
1705
1706 __event_process_build_id(&bev, filename, session);
1707
1708 offset += bev.header.size;
1709 }
1710 err = 0;
1711out:
1712 return err;
1713}
1714
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001715static int process_tracing_data(struct perf_file_section *section __maybe_unused,
1716 struct perf_header *ph __maybe_unused,
1717 int fd, void *data)
Robert Richterf1c67db2012-02-10 15:41:56 +01001718{
Namhyung Kim3dce2ce2013-03-21 16:18:48 +09001719 ssize_t ret = trace_report(fd, data, false);
1720 return ret < 0 ? -1 : 0;
Robert Richterf1c67db2012-02-10 15:41:56 +01001721}
1722
1723static int process_build_id(struct perf_file_section *section,
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001724 struct perf_header *ph, int fd,
Irina Tirdea1d037ca2012-09-11 01:15:03 +03001725 void *data __maybe_unused)
Robert Richterf1c67db2012-02-10 15:41:56 +01001726{
1727 if (perf_header__read_build_ids(ph, fd, section->offset, section->size))
1728 pr_debug("Failed to read buildids, continuing...\n");
1729 return 0;
1730}
1731
Namhyung Kima1ae5652012-09-24 17:14:59 +09001732static int process_hostname(struct perf_file_section *section __maybe_unused,
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001733 struct perf_header *ph, int fd,
1734 void *data __maybe_unused)
Namhyung Kima1ae5652012-09-24 17:14:59 +09001735{
1736 ph->env.hostname = do_read_string(fd, ph);
1737 return ph->env.hostname ? 0 : -ENOMEM;
1738}
1739
1740static int process_osrelease(struct perf_file_section *section __maybe_unused,
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001741 struct perf_header *ph, int fd,
1742 void *data __maybe_unused)
Namhyung Kima1ae5652012-09-24 17:14:59 +09001743{
1744 ph->env.os_release = do_read_string(fd, ph);
1745 return ph->env.os_release ? 0 : -ENOMEM;
1746}
1747
1748static int process_version(struct perf_file_section *section __maybe_unused,
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001749 struct perf_header *ph, int fd,
1750 void *data __maybe_unused)
Namhyung Kima1ae5652012-09-24 17:14:59 +09001751{
1752 ph->env.version = do_read_string(fd, ph);
1753 return ph->env.version ? 0 : -ENOMEM;
1754}
1755
1756static int process_arch(struct perf_file_section *section __maybe_unused,
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001757 struct perf_header *ph, int fd,
1758 void *data __maybe_unused)
Namhyung Kima1ae5652012-09-24 17:14:59 +09001759{
1760 ph->env.arch = do_read_string(fd, ph);
1761 return ph->env.arch ? 0 : -ENOMEM;
1762}
1763
1764static int process_nrcpus(struct perf_file_section *section __maybe_unused,
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001765 struct perf_header *ph, int fd,
1766 void *data __maybe_unused)
Namhyung Kima1ae5652012-09-24 17:14:59 +09001767{
Jiri Olsa727ebd52013-11-28 11:30:14 +01001768 ssize_t ret;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001769 u32 nr;
1770
Namhyung Kim5323f602012-12-17 15:38:54 +09001771 ret = readn(fd, &nr, sizeof(nr));
Namhyung Kima1ae5652012-09-24 17:14:59 +09001772 if (ret != sizeof(nr))
1773 return -1;
1774
1775 if (ph->needs_swap)
1776 nr = bswap_32(nr);
1777
1778 ph->env.nr_cpus_online = nr;
1779
Namhyung Kim5323f602012-12-17 15:38:54 +09001780 ret = readn(fd, &nr, sizeof(nr));
Namhyung Kima1ae5652012-09-24 17:14:59 +09001781 if (ret != sizeof(nr))
1782 return -1;
1783
1784 if (ph->needs_swap)
1785 nr = bswap_32(nr);
1786
1787 ph->env.nr_cpus_avail = nr;
1788 return 0;
1789}
1790
1791static int process_cpudesc(struct perf_file_section *section __maybe_unused,
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001792 struct perf_header *ph, int fd,
1793 void *data __maybe_unused)
Namhyung Kima1ae5652012-09-24 17:14:59 +09001794{
1795 ph->env.cpu_desc = do_read_string(fd, ph);
1796 return ph->env.cpu_desc ? 0 : -ENOMEM;
1797}
1798
1799static int process_cpuid(struct perf_file_section *section __maybe_unused,
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001800 struct perf_header *ph, int fd,
1801 void *data __maybe_unused)
Namhyung Kima1ae5652012-09-24 17:14:59 +09001802{
1803 ph->env.cpuid = do_read_string(fd, ph);
1804 return ph->env.cpuid ? 0 : -ENOMEM;
1805}
1806
1807static int process_total_mem(struct perf_file_section *section __maybe_unused,
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001808 struct perf_header *ph, int fd,
1809 void *data __maybe_unused)
Namhyung Kima1ae5652012-09-24 17:14:59 +09001810{
1811 uint64_t mem;
Jiri Olsa727ebd52013-11-28 11:30:14 +01001812 ssize_t ret;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001813
Namhyung Kim5323f602012-12-17 15:38:54 +09001814 ret = readn(fd, &mem, sizeof(mem));
Namhyung Kima1ae5652012-09-24 17:14:59 +09001815 if (ret != sizeof(mem))
1816 return -1;
1817
1818 if (ph->needs_swap)
1819 mem = bswap_64(mem);
1820
1821 ph->env.total_mem = mem;
1822 return 0;
1823}
1824
Robert Richter7c2f7af2012-08-16 21:10:23 +02001825static struct perf_evsel *
1826perf_evlist__find_by_index(struct perf_evlist *evlist, int idx)
1827{
1828 struct perf_evsel *evsel;
1829
Arnaldo Carvalho de Melo0050f7a2014-01-10 10:37:27 -03001830 evlist__for_each(evlist, evsel) {
Robert Richter7c2f7af2012-08-16 21:10:23 +02001831 if (evsel->idx == idx)
1832 return evsel;
1833 }
1834
1835 return NULL;
1836}
1837
1838static void
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001839perf_evlist__set_event_name(struct perf_evlist *evlist,
1840 struct perf_evsel *event)
Robert Richter7c2f7af2012-08-16 21:10:23 +02001841{
1842 struct perf_evsel *evsel;
1843
1844 if (!event->name)
1845 return;
1846
1847 evsel = perf_evlist__find_by_index(evlist, event->idx);
1848 if (!evsel)
1849 return;
1850
1851 if (evsel->name)
1852 return;
1853
1854 evsel->name = strdup(event->name);
1855}
1856
1857static int
Irina Tirdea1d037ca2012-09-11 01:15:03 +03001858process_event_desc(struct perf_file_section *section __maybe_unused,
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001859 struct perf_header *header, int fd,
Irina Tirdea1d037ca2012-09-11 01:15:03 +03001860 void *data __maybe_unused)
Robert Richter7c2f7af2012-08-16 21:10:23 +02001861{
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001862 struct perf_session *session;
Robert Richter7c2f7af2012-08-16 21:10:23 +02001863 struct perf_evsel *evsel, *events = read_event_desc(header, fd);
1864
1865 if (!events)
1866 return 0;
1867
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001868 session = container_of(header, struct perf_session, header);
Robert Richter7c2f7af2012-08-16 21:10:23 +02001869 for (evsel = events; evsel->attr.size; evsel++)
1870 perf_evlist__set_event_name(session->evlist, evsel);
1871
1872 free_event_desc(events);
1873
1874 return 0;
1875}
1876
Namhyung Kima1ae5652012-09-24 17:14:59 +09001877static int process_cmdline(struct perf_file_section *section __maybe_unused,
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001878 struct perf_header *ph, int fd,
1879 void *data __maybe_unused)
Namhyung Kima1ae5652012-09-24 17:14:59 +09001880{
Jiri Olsa727ebd52013-11-28 11:30:14 +01001881 ssize_t ret;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001882 char *str;
1883 u32 nr, i;
1884 struct strbuf sb;
1885
Namhyung Kim5323f602012-12-17 15:38:54 +09001886 ret = readn(fd, &nr, sizeof(nr));
Namhyung Kima1ae5652012-09-24 17:14:59 +09001887 if (ret != sizeof(nr))
1888 return -1;
1889
1890 if (ph->needs_swap)
1891 nr = bswap_32(nr);
1892
1893 ph->env.nr_cmdline = nr;
1894 strbuf_init(&sb, 128);
1895
1896 for (i = 0; i < nr; i++) {
1897 str = do_read_string(fd, ph);
1898 if (!str)
1899 goto error;
1900
1901 /* include a NULL character at the end */
1902 strbuf_add(&sb, str, strlen(str) + 1);
1903 free(str);
1904 }
1905 ph->env.cmdline = strbuf_detach(&sb, NULL);
1906 return 0;
1907
1908error:
1909 strbuf_release(&sb);
1910 return -1;
1911}
1912
1913static int process_cpu_topology(struct perf_file_section *section __maybe_unused,
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001914 struct perf_header *ph, int fd,
1915 void *data __maybe_unused)
Namhyung Kima1ae5652012-09-24 17:14:59 +09001916{
Jiri Olsa727ebd52013-11-28 11:30:14 +01001917 ssize_t ret;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001918 u32 nr, i;
1919 char *str;
1920 struct strbuf sb;
1921
Namhyung Kim5323f602012-12-17 15:38:54 +09001922 ret = readn(fd, &nr, sizeof(nr));
Namhyung Kima1ae5652012-09-24 17:14:59 +09001923 if (ret != sizeof(nr))
1924 return -1;
1925
1926 if (ph->needs_swap)
1927 nr = bswap_32(nr);
1928
1929 ph->env.nr_sibling_cores = nr;
1930 strbuf_init(&sb, 128);
1931
1932 for (i = 0; i < nr; i++) {
1933 str = do_read_string(fd, ph);
1934 if (!str)
1935 goto error;
1936
1937 /* include a NULL character at the end */
1938 strbuf_add(&sb, str, strlen(str) + 1);
1939 free(str);
1940 }
1941 ph->env.sibling_cores = strbuf_detach(&sb, NULL);
1942
Namhyung Kim5323f602012-12-17 15:38:54 +09001943 ret = readn(fd, &nr, sizeof(nr));
Namhyung Kima1ae5652012-09-24 17:14:59 +09001944 if (ret != sizeof(nr))
1945 return -1;
1946
1947 if (ph->needs_swap)
1948 nr = bswap_32(nr);
1949
1950 ph->env.nr_sibling_threads = nr;
1951
1952 for (i = 0; i < nr; i++) {
1953 str = do_read_string(fd, ph);
1954 if (!str)
1955 goto error;
1956
1957 /* include a NULL character at the end */
1958 strbuf_add(&sb, str, strlen(str) + 1);
1959 free(str);
1960 }
1961 ph->env.sibling_threads = strbuf_detach(&sb, NULL);
1962 return 0;
1963
1964error:
1965 strbuf_release(&sb);
1966 return -1;
1967}
1968
1969static int process_numa_topology(struct perf_file_section *section __maybe_unused,
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001970 struct perf_header *ph, int fd,
1971 void *data __maybe_unused)
Namhyung Kima1ae5652012-09-24 17:14:59 +09001972{
Jiri Olsa727ebd52013-11-28 11:30:14 +01001973 ssize_t ret;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001974 u32 nr, node, i;
1975 char *str;
1976 uint64_t mem_total, mem_free;
1977 struct strbuf sb;
1978
1979 /* nr nodes */
Namhyung Kim5323f602012-12-17 15:38:54 +09001980 ret = readn(fd, &nr, sizeof(nr));
Namhyung Kima1ae5652012-09-24 17:14:59 +09001981 if (ret != sizeof(nr))
1982 goto error;
1983
1984 if (ph->needs_swap)
1985 nr = bswap_32(nr);
1986
1987 ph->env.nr_numa_nodes = nr;
1988 strbuf_init(&sb, 256);
1989
1990 for (i = 0; i < nr; i++) {
1991 /* node number */
Namhyung Kim5323f602012-12-17 15:38:54 +09001992 ret = readn(fd, &node, sizeof(node));
Namhyung Kima1ae5652012-09-24 17:14:59 +09001993 if (ret != sizeof(node))
1994 goto error;
1995
Namhyung Kim5323f602012-12-17 15:38:54 +09001996 ret = readn(fd, &mem_total, sizeof(u64));
Namhyung Kima1ae5652012-09-24 17:14:59 +09001997 if (ret != sizeof(u64))
1998 goto error;
1999
Namhyung Kim5323f602012-12-17 15:38:54 +09002000 ret = readn(fd, &mem_free, sizeof(u64));
Namhyung Kima1ae5652012-09-24 17:14:59 +09002001 if (ret != sizeof(u64))
2002 goto error;
2003
2004 if (ph->needs_swap) {
2005 node = bswap_32(node);
2006 mem_total = bswap_64(mem_total);
2007 mem_free = bswap_64(mem_free);
2008 }
2009
2010 strbuf_addf(&sb, "%u:%"PRIu64":%"PRIu64":",
2011 node, mem_total, mem_free);
2012
2013 str = do_read_string(fd, ph);
2014 if (!str)
2015 goto error;
2016
2017 /* include a NULL character at the end */
2018 strbuf_add(&sb, str, strlen(str) + 1);
2019 free(str);
2020 }
2021 ph->env.numa_nodes = strbuf_detach(&sb, NULL);
2022 return 0;
2023
2024error:
2025 strbuf_release(&sb);
2026 return -1;
2027}
2028
2029static int process_pmu_mappings(struct perf_file_section *section __maybe_unused,
Namhyung Kim3d7eb862012-09-24 17:15:01 +09002030 struct perf_header *ph, int fd,
2031 void *data __maybe_unused)
Namhyung Kima1ae5652012-09-24 17:14:59 +09002032{
Jiri Olsa727ebd52013-11-28 11:30:14 +01002033 ssize_t ret;
Namhyung Kima1ae5652012-09-24 17:14:59 +09002034 char *name;
2035 u32 pmu_num;
2036 u32 type;
2037 struct strbuf sb;
2038
Namhyung Kim5323f602012-12-17 15:38:54 +09002039 ret = readn(fd, &pmu_num, sizeof(pmu_num));
Namhyung Kima1ae5652012-09-24 17:14:59 +09002040 if (ret != sizeof(pmu_num))
2041 return -1;
2042
2043 if (ph->needs_swap)
2044 pmu_num = bswap_32(pmu_num);
2045
2046 if (!pmu_num) {
2047 pr_debug("pmu mappings not available\n");
2048 return 0;
2049 }
2050
2051 ph->env.nr_pmu_mappings = pmu_num;
2052 strbuf_init(&sb, 128);
2053
2054 while (pmu_num) {
Namhyung Kim5323f602012-12-17 15:38:54 +09002055 if (readn(fd, &type, sizeof(type)) != sizeof(type))
Namhyung Kima1ae5652012-09-24 17:14:59 +09002056 goto error;
2057 if (ph->needs_swap)
2058 type = bswap_32(type);
2059
2060 name = do_read_string(fd, ph);
2061 if (!name)
2062 goto error;
2063
2064 strbuf_addf(&sb, "%u:%s", type, name);
2065 /* include a NULL character at the end */
2066 strbuf_add(&sb, "", 1);
2067
2068 free(name);
2069 pmu_num--;
2070 }
2071 ph->env.pmu_mappings = strbuf_detach(&sb, NULL);
2072 return 0;
2073
2074error:
2075 strbuf_release(&sb);
2076 return -1;
2077}
2078
Namhyung Kima8bb5592013-01-22 18:09:31 +09002079static int process_group_desc(struct perf_file_section *section __maybe_unused,
2080 struct perf_header *ph, int fd,
2081 void *data __maybe_unused)
2082{
2083 size_t ret = -1;
2084 u32 i, nr, nr_groups;
2085 struct perf_session *session;
2086 struct perf_evsel *evsel, *leader = NULL;
2087 struct group_desc {
2088 char *name;
2089 u32 leader_idx;
2090 u32 nr_members;
2091 } *desc;
2092
2093 if (readn(fd, &nr_groups, sizeof(nr_groups)) != sizeof(nr_groups))
2094 return -1;
2095
2096 if (ph->needs_swap)
2097 nr_groups = bswap_32(nr_groups);
2098
2099 ph->env.nr_groups = nr_groups;
2100 if (!nr_groups) {
2101 pr_debug("group desc not available\n");
2102 return 0;
2103 }
2104
2105 desc = calloc(nr_groups, sizeof(*desc));
2106 if (!desc)
2107 return -1;
2108
2109 for (i = 0; i < nr_groups; i++) {
2110 desc[i].name = do_read_string(fd, ph);
2111 if (!desc[i].name)
2112 goto out_free;
2113
2114 if (readn(fd, &desc[i].leader_idx, sizeof(u32)) != sizeof(u32))
2115 goto out_free;
2116
2117 if (readn(fd, &desc[i].nr_members, sizeof(u32)) != sizeof(u32))
2118 goto out_free;
2119
2120 if (ph->needs_swap) {
2121 desc[i].leader_idx = bswap_32(desc[i].leader_idx);
2122 desc[i].nr_members = bswap_32(desc[i].nr_members);
2123 }
2124 }
2125
2126 /*
2127 * Rebuild group relationship based on the group_desc
2128 */
2129 session = container_of(ph, struct perf_session, header);
2130 session->evlist->nr_groups = nr_groups;
2131
2132 i = nr = 0;
Arnaldo Carvalho de Melo0050f7a2014-01-10 10:37:27 -03002133 evlist__for_each(session->evlist, evsel) {
Namhyung Kima8bb5592013-01-22 18:09:31 +09002134 if (evsel->idx == (int) desc[i].leader_idx) {
2135 evsel->leader = evsel;
2136 /* {anon_group} is a dummy name */
Namhyung Kim210e8122013-11-18 11:20:43 +09002137 if (strcmp(desc[i].name, "{anon_group}")) {
Namhyung Kima8bb5592013-01-22 18:09:31 +09002138 evsel->group_name = desc[i].name;
Namhyung Kim210e8122013-11-18 11:20:43 +09002139 desc[i].name = NULL;
2140 }
Namhyung Kima8bb5592013-01-22 18:09:31 +09002141 evsel->nr_members = desc[i].nr_members;
2142
2143 if (i >= nr_groups || nr > 0) {
2144 pr_debug("invalid group desc\n");
2145 goto out_free;
2146 }
2147
2148 leader = evsel;
2149 nr = evsel->nr_members - 1;
2150 i++;
2151 } else if (nr) {
2152 /* This is a group member */
2153 evsel->leader = leader;
2154
2155 nr--;
2156 }
2157 }
2158
2159 if (i != nr_groups || nr != 0) {
2160 pr_debug("invalid group desc\n");
2161 goto out_free;
2162 }
2163
2164 ret = 0;
2165out_free:
Namhyung Kim50a27402013-11-18 11:20:44 +09002166 for (i = 0; i < nr_groups; i++)
Arnaldo Carvalho de Melo74cf2492013-12-27 16:55:14 -03002167 zfree(&desc[i].name);
Namhyung Kima8bb5592013-01-22 18:09:31 +09002168 free(desc);
2169
2170 return ret;
2171}
2172
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002173struct feature_ops {
2174 int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist);
2175 void (*print)(struct perf_header *h, int fd, FILE *fp);
Robert Richterf1c67db2012-02-10 15:41:56 +01002176 int (*process)(struct perf_file_section *section,
Namhyung Kim3d7eb862012-09-24 17:15:01 +09002177 struct perf_header *h, int fd, void *data);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002178 const char *name;
2179 bool full_only;
2180};
2181
Robert Richter8cdfa782011-12-07 10:02:56 +01002182#define FEAT_OPA(n, func) \
2183 [n] = { .name = #n, .write = write_##func, .print = print_##func }
Robert Richterf1c67db2012-02-10 15:41:56 +01002184#define FEAT_OPP(n, func) \
2185 [n] = { .name = #n, .write = write_##func, .print = print_##func, \
2186 .process = process_##func }
Robert Richter8cdfa782011-12-07 10:02:56 +01002187#define FEAT_OPF(n, func) \
Robert Richterf1c67db2012-02-10 15:41:56 +01002188 [n] = { .name = #n, .write = write_##func, .print = print_##func, \
Namhyung Kima1ae5652012-09-24 17:14:59 +09002189 .process = process_##func, .full_only = true }
Robert Richter8cdfa782011-12-07 10:02:56 +01002190
2191/* feature_ops not implemented: */
Stephane Eranian2eeaaa02012-05-15 13:28:13 +02002192#define print_tracing_data NULL
2193#define print_build_id NULL
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002194
2195static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
Stephane Eranian2eeaaa02012-05-15 13:28:13 +02002196 FEAT_OPP(HEADER_TRACING_DATA, tracing_data),
Robert Richterf1c67db2012-02-10 15:41:56 +01002197 FEAT_OPP(HEADER_BUILD_ID, build_id),
Namhyung Kima1ae5652012-09-24 17:14:59 +09002198 FEAT_OPP(HEADER_HOSTNAME, hostname),
2199 FEAT_OPP(HEADER_OSRELEASE, osrelease),
2200 FEAT_OPP(HEADER_VERSION, version),
2201 FEAT_OPP(HEADER_ARCH, arch),
2202 FEAT_OPP(HEADER_NRCPUS, nrcpus),
2203 FEAT_OPP(HEADER_CPUDESC, cpudesc),
Namhyung Kim37e9d752012-09-24 17:15:03 +09002204 FEAT_OPP(HEADER_CPUID, cpuid),
Namhyung Kima1ae5652012-09-24 17:14:59 +09002205 FEAT_OPP(HEADER_TOTAL_MEM, total_mem),
Robert Richter7c2f7af2012-08-16 21:10:23 +02002206 FEAT_OPP(HEADER_EVENT_DESC, event_desc),
Namhyung Kima1ae5652012-09-24 17:14:59 +09002207 FEAT_OPP(HEADER_CMDLINE, cmdline),
Robert Richter8cdfa782011-12-07 10:02:56 +01002208 FEAT_OPF(HEADER_CPU_TOPOLOGY, cpu_topology),
2209 FEAT_OPF(HEADER_NUMA_TOPOLOGY, numa_topology),
Stephane Eranian330aa672012-03-08 23:47:46 +01002210 FEAT_OPA(HEADER_BRANCH_STACK, branch_stack),
Namhyung Kima1ae5652012-09-24 17:14:59 +09002211 FEAT_OPP(HEADER_PMU_MAPPINGS, pmu_mappings),
Namhyung Kima8bb5592013-01-22 18:09:31 +09002212 FEAT_OPP(HEADER_GROUP_DESC, group_desc),
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002213};
2214
2215struct header_print_data {
2216 FILE *fp;
2217 bool full; /* extended list of headers */
2218};
2219
2220static int perf_file_section__fprintf_info(struct perf_file_section *section,
2221 struct perf_header *ph,
2222 int feat, int fd, void *data)
2223{
2224 struct header_print_data *hd = data;
2225
2226 if (lseek(fd, section->offset, SEEK_SET) == (off_t)-1) {
2227 pr_debug("Failed to lseek to %" PRIu64 " offset for feature "
2228 "%d, continuing...\n", section->offset, feat);
2229 return 0;
2230 }
Robert Richterb1e5a9b2011-12-07 10:02:57 +01002231 if (feat >= HEADER_LAST_FEATURE) {
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002232 pr_warning("unknown feature %d\n", feat);
Robert Richterf7a8a132011-12-07 10:02:51 +01002233 return 0;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002234 }
2235 if (!feat_ops[feat].print)
2236 return 0;
2237
2238 if (!feat_ops[feat].full_only || hd->full)
2239 feat_ops[feat].print(ph, fd, hd->fp);
2240 else
2241 fprintf(hd->fp, "# %s info available, use -I to display\n",
2242 feat_ops[feat].name);
2243
2244 return 0;
2245}
2246
2247int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full)
2248{
2249 struct header_print_data hd;
2250 struct perf_header *header = &session->header;
Jiri Olsacc9784bd2013-10-15 16:27:34 +02002251 int fd = perf_data_file__fd(session->file);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002252 hd.fp = fp;
2253 hd.full = full;
2254
2255 perf_header__process_sections(header, fd, &hd,
2256 perf_file_section__fprintf_info);
2257 return 0;
2258}
2259
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002260static int do_write_feat(int fd, struct perf_header *h, int type,
2261 struct perf_file_section **p,
2262 struct perf_evlist *evlist)
2263{
2264 int err;
2265 int ret = 0;
2266
2267 if (perf_header__has_feat(h, type)) {
Robert Richterb1e5a9b2011-12-07 10:02:57 +01002268 if (!feat_ops[type].write)
2269 return -1;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002270
2271 (*p)->offset = lseek(fd, 0, SEEK_CUR);
2272
2273 err = feat_ops[type].write(fd, h, evlist);
2274 if (err < 0) {
2275 pr_debug("failed to write feature %d\n", type);
2276
2277 /* undo anything written */
2278 lseek(fd, (*p)->offset, SEEK_SET);
2279
2280 return -1;
2281 }
2282 (*p)->size = lseek(fd, 0, SEEK_CUR) - (*p)->offset;
2283 (*p)++;
2284 }
2285 return ret;
2286}
2287
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002288static int perf_header__adds_write(struct perf_header *header,
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -02002289 struct perf_evlist *evlist, int fd)
Frederic Weisbecker2ba08252009-10-17 17:12:34 +02002290{
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002291 int nr_sections;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002292 struct perf_file_section *feat_sec, *p;
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002293 int sec_size;
2294 u64 sec_start;
Robert Richterb1e5a9b2011-12-07 10:02:57 +01002295 int feat;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002296 int err;
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002297
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002298 nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS);
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002299 if (!nr_sections)
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -02002300 return 0;
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002301
Paul Gortmaker91b98802013-01-30 20:05:49 -05002302 feat_sec = p = calloc(nr_sections, sizeof(*feat_sec));
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -02002303 if (feat_sec == NULL)
2304 return -ENOMEM;
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002305
2306 sec_size = sizeof(*feat_sec) * nr_sections;
2307
Jiri Olsa8d541e92013-07-17 19:49:44 +02002308 sec_start = header->feat_offset;
Xiao Guangrongf887f302010-02-04 16:46:42 +08002309 lseek(fd, sec_start + sec_size, SEEK_SET);
Frederic Weisbecker2ba08252009-10-17 17:12:34 +02002310
Robert Richterb1e5a9b2011-12-07 10:02:57 +01002311 for_each_set_bit(feat, header->adds_features, HEADER_FEAT_BITS) {
2312 if (do_write_feat(fd, header, feat, &p, evlist))
2313 perf_header__clear_feat(header, feat);
2314 }
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002315
Xiao Guangrongf887f302010-02-04 16:46:42 +08002316 lseek(fd, sec_start, SEEK_SET);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002317 /*
2318 * may write more than needed due to dropped feature, but
2319 * this is okay, reader will skip the mising entries
2320 */
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -02002321 err = do_write(fd, feat_sec, sec_size);
2322 if (err < 0)
2323 pr_debug("failed to write feature section\n");
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002324 free(feat_sec);
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -02002325 return err;
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002326}
Frederic Weisbecker2ba08252009-10-17 17:12:34 +02002327
Tom Zanussi8dc58102010-04-01 23:59:15 -05002328int perf_header__write_pipe(int fd)
2329{
2330 struct perf_pipe_file_header f_header;
2331 int err;
2332
2333 f_header = (struct perf_pipe_file_header){
2334 .magic = PERF_MAGIC,
2335 .size = sizeof(f_header),
2336 };
2337
2338 err = do_write(fd, &f_header, sizeof(f_header));
2339 if (err < 0) {
2340 pr_debug("failed to write perf pipe header\n");
2341 return err;
2342 }
2343
2344 return 0;
2345}
2346
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002347int perf_session__write_header(struct perf_session *session,
2348 struct perf_evlist *evlist,
2349 int fd, bool at_exit)
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002350{
2351 struct perf_file_header f_header;
2352 struct perf_file_attr f_attr;
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002353 struct perf_header *header = &session->header;
Jiri Olsa563aecb2013-06-05 13:35:06 +02002354 struct perf_evsel *evsel;
Jiri Olsa944d62b2013-07-17 19:49:43 +02002355 u64 attr_offset;
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002356 int err;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002357
2358 lseek(fd, sizeof(f_header), SEEK_SET);
2359
Arnaldo Carvalho de Melo0050f7a2014-01-10 10:37:27 -03002360 evlist__for_each(session->evlist, evsel) {
Robert Richter6606f872012-08-16 21:10:19 +02002361 evsel->id_offset = lseek(fd, 0, SEEK_CUR);
2362 err = do_write(fd, evsel->id, evsel->ids * sizeof(u64));
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -02002363 if (err < 0) {
2364 pr_debug("failed to write perf header\n");
2365 return err;
2366 }
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002367 }
2368
Jiri Olsa944d62b2013-07-17 19:49:43 +02002369 attr_offset = lseek(fd, 0, SEEK_CUR);
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002370
Arnaldo Carvalho de Melo0050f7a2014-01-10 10:37:27 -03002371 evlist__for_each(evlist, evsel) {
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002372 f_attr = (struct perf_file_attr){
Robert Richter6606f872012-08-16 21:10:19 +02002373 .attr = evsel->attr,
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002374 .ids = {
Robert Richter6606f872012-08-16 21:10:19 +02002375 .offset = evsel->id_offset,
2376 .size = evsel->ids * sizeof(u64),
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002377 }
2378 };
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -02002379 err = do_write(fd, &f_attr, sizeof(f_attr));
2380 if (err < 0) {
2381 pr_debug("failed to write perf header attribute\n");
2382 return err;
2383 }
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002384 }
2385
Adrian Hunterd645c442013-12-11 14:36:28 +02002386 if (!header->data_offset)
2387 header->data_offset = lseek(fd, 0, SEEK_CUR);
Jiri Olsa8d541e92013-07-17 19:49:44 +02002388 header->feat_offset = header->data_offset + header->data_size;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002389
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -02002390 if (at_exit) {
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002391 err = perf_header__adds_write(header, evlist, fd);
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -02002392 if (err < 0)
2393 return err;
2394 }
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002395
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002396 f_header = (struct perf_file_header){
2397 .magic = PERF_MAGIC,
2398 .size = sizeof(f_header),
2399 .attr_size = sizeof(f_attr),
2400 .attrs = {
Jiri Olsa944d62b2013-07-17 19:49:43 +02002401 .offset = attr_offset,
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002402 .size = evlist->nr_entries * sizeof(f_attr),
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002403 },
2404 .data = {
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002405 .offset = header->data_offset,
2406 .size = header->data_size,
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002407 },
Jiri Olsa44b3c572013-07-11 17:28:31 +02002408 /* event_types is ignored, store zeros */
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002409 };
2410
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002411 memcpy(&f_header.adds_features, &header->adds_features, sizeof(header->adds_features));
Frederic Weisbecker2ba08252009-10-17 17:12:34 +02002412
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002413 lseek(fd, 0, SEEK_SET);
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -02002414 err = do_write(fd, &f_header, sizeof(f_header));
2415 if (err < 0) {
2416 pr_debug("failed to write perf header\n");
2417 return err;
2418 }
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002419 lseek(fd, header->data_offset + header->data_size, SEEK_SET);
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002420
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -02002421 return 0;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002422}
2423
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002424static int perf_header__getbuffer64(struct perf_header *header,
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -02002425 int fd, void *buf, size_t size)
2426{
Arnaldo Carvalho de Melo1e7972c2011-01-03 16:50:55 -02002427 if (readn(fd, buf, size) <= 0)
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -02002428 return -1;
2429
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002430 if (header->needs_swap)
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -02002431 mem_bswap_64(buf, size);
2432
2433 return 0;
2434}
2435
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002436int perf_header__process_sections(struct perf_header *header, int fd,
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002437 void *data,
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002438 int (*process)(struct perf_file_section *section,
Robert Richterb1e5a9b2011-12-07 10:02:57 +01002439 struct perf_header *ph,
2440 int feat, int fd, void *data))
Frederic Weisbecker2ba08252009-10-17 17:12:34 +02002441{
Robert Richterb1e5a9b2011-12-07 10:02:57 +01002442 struct perf_file_section *feat_sec, *sec;
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002443 int nr_sections;
2444 int sec_size;
Robert Richterb1e5a9b2011-12-07 10:02:57 +01002445 int feat;
2446 int err;
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002447
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002448 nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS);
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002449 if (!nr_sections)
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002450 return 0;
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002451
Paul Gortmaker91b98802013-01-30 20:05:49 -05002452 feat_sec = sec = calloc(nr_sections, sizeof(*feat_sec));
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002453 if (!feat_sec)
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002454 return -1;
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002455
2456 sec_size = sizeof(*feat_sec) * nr_sections;
2457
Jiri Olsa8d541e92013-07-17 19:49:44 +02002458 lseek(fd, header->feat_offset, SEEK_SET);
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002459
Robert Richterb1e5a9b2011-12-07 10:02:57 +01002460 err = perf_header__getbuffer64(header, fd, feat_sec, sec_size);
2461 if (err < 0)
Arnaldo Carvalho de Melo769885f2009-12-28 22:48:32 -02002462 goto out_free;
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002463
Robert Richterb1e5a9b2011-12-07 10:02:57 +01002464 for_each_set_bit(feat, header->adds_features, HEADER_LAST_FEATURE) {
2465 err = process(sec++, header, feat, fd, data);
2466 if (err < 0)
2467 goto out_free;
Frederic Weisbecker4778d2e2009-11-11 04:51:05 +01002468 }
Robert Richterb1e5a9b2011-12-07 10:02:57 +01002469 err = 0;
Arnaldo Carvalho de Melo769885f2009-12-28 22:48:32 -02002470out_free:
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002471 free(feat_sec);
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002472 return err;
Arnaldo Carvalho de Melo769885f2009-12-28 22:48:32 -02002473}
Frederic Weisbecker2ba08252009-10-17 17:12:34 +02002474
Stephane Eranian114382a2012-02-09 23:21:08 +01002475static const int attr_file_abi_sizes[] = {
2476 [0] = PERF_ATTR_SIZE_VER0,
2477 [1] = PERF_ATTR_SIZE_VER1,
Jiri Olsa239cc472012-08-07 15:20:42 +02002478 [2] = PERF_ATTR_SIZE_VER2,
Jiri Olsa0f6a3012012-08-07 15:20:45 +02002479 [3] = PERF_ATTR_SIZE_VER3,
Stephane Eranian114382a2012-02-09 23:21:08 +01002480 0,
2481};
2482
2483/*
2484 * In the legacy file format, the magic number is not used to encode endianness.
2485 * hdr_sz was used to encode endianness. But given that hdr_sz can vary based
2486 * on ABI revisions, we need to try all combinations for all endianness to
2487 * detect the endianness.
2488 */
2489static int try_all_file_abis(uint64_t hdr_sz, struct perf_header *ph)
2490{
2491 uint64_t ref_size, attr_size;
2492 int i;
2493
2494 for (i = 0 ; attr_file_abi_sizes[i]; i++) {
2495 ref_size = attr_file_abi_sizes[i]
2496 + sizeof(struct perf_file_section);
2497 if (hdr_sz != ref_size) {
2498 attr_size = bswap_64(hdr_sz);
2499 if (attr_size != ref_size)
2500 continue;
2501
2502 ph->needs_swap = true;
2503 }
2504 pr_debug("ABI%d perf.data file detected, need_swap=%d\n",
2505 i,
2506 ph->needs_swap);
2507 return 0;
2508 }
2509 /* could not determine endianness */
2510 return -1;
2511}
2512
2513#define PERF_PIPE_HDR_VER0 16
2514
2515static const size_t attr_pipe_abi_sizes[] = {
2516 [0] = PERF_PIPE_HDR_VER0,
2517 0,
2518};
2519
2520/*
2521 * In the legacy pipe format, there is an implicit assumption that endiannesss
2522 * between host recording the samples, and host parsing the samples is the
2523 * same. This is not always the case given that the pipe output may always be
2524 * redirected into a file and analyzed on a different machine with possibly a
2525 * different endianness and perf_event ABI revsions in the perf tool itself.
2526 */
2527static int try_all_pipe_abis(uint64_t hdr_sz, struct perf_header *ph)
2528{
2529 u64 attr_size;
2530 int i;
2531
2532 for (i = 0 ; attr_pipe_abi_sizes[i]; i++) {
2533 if (hdr_sz != attr_pipe_abi_sizes[i]) {
2534 attr_size = bswap_64(hdr_sz);
2535 if (attr_size != hdr_sz)
2536 continue;
2537
2538 ph->needs_swap = true;
2539 }
2540 pr_debug("Pipe ABI%d perf.data file detected\n", i);
2541 return 0;
2542 }
2543 return -1;
2544}
2545
Feng Tange84ba4e2012-10-30 11:56:07 +08002546bool is_perf_magic(u64 magic)
2547{
2548 if (!memcmp(&magic, __perf_magic1, sizeof(magic))
2549 || magic == __perf_magic2
2550 || magic == __perf_magic2_sw)
2551 return true;
2552
2553 return false;
2554}
2555
Stephane Eranian114382a2012-02-09 23:21:08 +01002556static int check_magic_endian(u64 magic, uint64_t hdr_sz,
2557 bool is_pipe, struct perf_header *ph)
Stephane Eranian73323f52012-02-02 13:54:44 +01002558{
2559 int ret;
2560
2561 /* check for legacy format */
Stephane Eranian114382a2012-02-09 23:21:08 +01002562 ret = memcmp(&magic, __perf_magic1, sizeof(magic));
Stephane Eranian73323f52012-02-02 13:54:44 +01002563 if (ret == 0) {
Jiri Olsa2a08c3e2013-07-17 19:49:47 +02002564 ph->version = PERF_HEADER_VERSION_1;
Stephane Eranian73323f52012-02-02 13:54:44 +01002565 pr_debug("legacy perf.data format\n");
Stephane Eranian114382a2012-02-09 23:21:08 +01002566 if (is_pipe)
2567 return try_all_pipe_abis(hdr_sz, ph);
Stephane Eranian73323f52012-02-02 13:54:44 +01002568
Stephane Eranian114382a2012-02-09 23:21:08 +01002569 return try_all_file_abis(hdr_sz, ph);
Stephane Eranian73323f52012-02-02 13:54:44 +01002570 }
Stephane Eranian114382a2012-02-09 23:21:08 +01002571 /*
2572 * the new magic number serves two purposes:
2573 * - unique number to identify actual perf.data files
2574 * - encode endianness of file
2575 */
Stephane Eranian73323f52012-02-02 13:54:44 +01002576
Stephane Eranian114382a2012-02-09 23:21:08 +01002577 /* check magic number with one endianness */
2578 if (magic == __perf_magic2)
Stephane Eranian73323f52012-02-02 13:54:44 +01002579 return 0;
2580
Stephane Eranian114382a2012-02-09 23:21:08 +01002581 /* check magic number with opposite endianness */
2582 if (magic != __perf_magic2_sw)
Stephane Eranian73323f52012-02-02 13:54:44 +01002583 return -1;
2584
2585 ph->needs_swap = true;
Jiri Olsa2a08c3e2013-07-17 19:49:47 +02002586 ph->version = PERF_HEADER_VERSION_2;
Stephane Eranian73323f52012-02-02 13:54:44 +01002587
2588 return 0;
2589}
2590
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002591int perf_file_header__read(struct perf_file_header *header,
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002592 struct perf_header *ph, int fd)
2593{
Jiri Olsa727ebd52013-11-28 11:30:14 +01002594 ssize_t ret;
Stephane Eranian73323f52012-02-02 13:54:44 +01002595
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002596 lseek(fd, 0, SEEK_SET);
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002597
Stephane Eranian73323f52012-02-02 13:54:44 +01002598 ret = readn(fd, header, sizeof(*header));
2599 if (ret <= 0)
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002600 return -1;
2601
Stephane Eranian114382a2012-02-09 23:21:08 +01002602 if (check_magic_endian(header->magic,
2603 header->attr_size, false, ph) < 0) {
2604 pr_debug("magic/endian check failed\n");
Stephane Eranian73323f52012-02-02 13:54:44 +01002605 return -1;
Stephane Eranian114382a2012-02-09 23:21:08 +01002606 }
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -02002607
Stephane Eranian73323f52012-02-02 13:54:44 +01002608 if (ph->needs_swap) {
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002609 mem_bswap_64(header, offsetof(struct perf_file_header,
Stephane Eranian73323f52012-02-02 13:54:44 +01002610 adds_features));
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -02002611 }
2612
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002613 if (header->size != sizeof(*header)) {
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002614 /* Support the previous format */
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002615 if (header->size == offsetof(typeof(*header), adds_features))
2616 bitmap_zero(header->adds_features, HEADER_FEAT_BITS);
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002617 else
2618 return -1;
David Ahernd327fa42011-10-18 17:34:01 -06002619 } else if (ph->needs_swap) {
David Ahernd327fa42011-10-18 17:34:01 -06002620 /*
2621 * feature bitmap is declared as an array of unsigned longs --
2622 * not good since its size can differ between the host that
2623 * generated the data file and the host analyzing the file.
2624 *
2625 * We need to handle endianness, but we don't know the size of
2626 * the unsigned long where the file was generated. Take a best
2627 * guess at determining it: try 64-bit swap first (ie., file
2628 * created on a 64-bit host), and check if the hostname feature
2629 * bit is set (this feature bit is forced on as of fbe96f2).
2630 * If the bit is not, undo the 64-bit swap and try a 32-bit
2631 * swap. If the hostname bit is still not set (e.g., older data
2632 * file), punt and fallback to the original behavior --
2633 * clearing all feature bits and setting buildid.
2634 */
David Ahern80c01202012-06-08 11:47:51 -03002635 mem_bswap_64(&header->adds_features,
2636 BITS_TO_U64(HEADER_FEAT_BITS));
David Ahernd327fa42011-10-18 17:34:01 -06002637
2638 if (!test_bit(HEADER_HOSTNAME, header->adds_features)) {
David Ahern80c01202012-06-08 11:47:51 -03002639 /* unswap as u64 */
2640 mem_bswap_64(&header->adds_features,
2641 BITS_TO_U64(HEADER_FEAT_BITS));
2642
2643 /* unswap as u32 */
2644 mem_bswap_32(&header->adds_features,
2645 BITS_TO_U32(HEADER_FEAT_BITS));
David Ahernd327fa42011-10-18 17:34:01 -06002646 }
2647
2648 if (!test_bit(HEADER_HOSTNAME, header->adds_features)) {
2649 bitmap_zero(header->adds_features, HEADER_FEAT_BITS);
2650 set_bit(HEADER_BUILD_ID, header->adds_features);
2651 }
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002652 }
2653
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002654 memcpy(&ph->adds_features, &header->adds_features,
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -02002655 sizeof(ph->adds_features));
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002656
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002657 ph->data_offset = header->data.offset;
2658 ph->data_size = header->data.size;
Jiri Olsa8d541e92013-07-17 19:49:44 +02002659 ph->feat_offset = header->data.offset + header->data.size;
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002660 return 0;
2661}
2662
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002663static int perf_file_section__process(struct perf_file_section *section,
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -02002664 struct perf_header *ph,
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -03002665 int feat, int fd, void *data)
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002666{
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002667 if (lseek(fd, section->offset, SEEK_SET) == (off_t)-1) {
Arnaldo Carvalho de Melo9486aa32011-01-22 20:37:02 -02002668 pr_debug("Failed to lseek to %" PRIu64 " offset for feature "
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002669 "%d, continuing...\n", section->offset, feat);
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002670 return 0;
2671 }
2672
Robert Richterb1e5a9b2011-12-07 10:02:57 +01002673 if (feat >= HEADER_LAST_FEATURE) {
2674 pr_debug("unknown feature %d, continuing...\n", feat);
2675 return 0;
2676 }
2677
Robert Richterf1c67db2012-02-10 15:41:56 +01002678 if (!feat_ops[feat].process)
2679 return 0;
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002680
Namhyung Kim3d7eb862012-09-24 17:15:01 +09002681 return feat_ops[feat].process(section, ph, fd, data);
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002682}
2683
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002684static int perf_file_header__read_pipe(struct perf_pipe_file_header *header,
Tom Zanussi454c4072010-05-01 01:41:20 -05002685 struct perf_header *ph, int fd,
2686 bool repipe)
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002687{
Jiri Olsa727ebd52013-11-28 11:30:14 +01002688 ssize_t ret;
Stephane Eranian73323f52012-02-02 13:54:44 +01002689
2690 ret = readn(fd, header, sizeof(*header));
2691 if (ret <= 0)
2692 return -1;
2693
Stephane Eranian114382a2012-02-09 23:21:08 +01002694 if (check_magic_endian(header->magic, header->size, true, ph) < 0) {
2695 pr_debug("endian/magic failed\n");
Tom Zanussi8dc58102010-04-01 23:59:15 -05002696 return -1;
Stephane Eranian114382a2012-02-09 23:21:08 +01002697 }
2698
2699 if (ph->needs_swap)
2700 header->size = bswap_64(header->size);
Tom Zanussi8dc58102010-04-01 23:59:15 -05002701
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002702 if (repipe && do_write(STDOUT_FILENO, header, sizeof(*header)) < 0)
Tom Zanussi454c4072010-05-01 01:41:20 -05002703 return -1;
2704
Tom Zanussi8dc58102010-04-01 23:59:15 -05002705 return 0;
2706}
2707
Jiri Olsad4339562013-07-17 19:49:41 +02002708static int perf_header__read_pipe(struct perf_session *session)
Tom Zanussi8dc58102010-04-01 23:59:15 -05002709{
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002710 struct perf_header *header = &session->header;
Tom Zanussi8dc58102010-04-01 23:59:15 -05002711 struct perf_pipe_file_header f_header;
2712
Jiri Olsacc9784bd2013-10-15 16:27:34 +02002713 if (perf_file_header__read_pipe(&f_header, header,
2714 perf_data_file__fd(session->file),
Tom Zanussi454c4072010-05-01 01:41:20 -05002715 session->repipe) < 0) {
Tom Zanussi8dc58102010-04-01 23:59:15 -05002716 pr_debug("incompatible file format\n");
2717 return -EINVAL;
2718 }
2719
Tom Zanussi8dc58102010-04-01 23:59:15 -05002720 return 0;
2721}
2722
Stephane Eranian69996df2012-02-09 23:21:06 +01002723static int read_attr(int fd, struct perf_header *ph,
2724 struct perf_file_attr *f_attr)
2725{
2726 struct perf_event_attr *attr = &f_attr->attr;
2727 size_t sz, left;
2728 size_t our_sz = sizeof(f_attr->attr);
Jiri Olsa727ebd52013-11-28 11:30:14 +01002729 ssize_t ret;
Stephane Eranian69996df2012-02-09 23:21:06 +01002730
2731 memset(f_attr, 0, sizeof(*f_attr));
2732
2733 /* read minimal guaranteed structure */
2734 ret = readn(fd, attr, PERF_ATTR_SIZE_VER0);
2735 if (ret <= 0) {
2736 pr_debug("cannot read %d bytes of header attr\n",
2737 PERF_ATTR_SIZE_VER0);
2738 return -1;
2739 }
2740
2741 /* on file perf_event_attr size */
2742 sz = attr->size;
Stephane Eranian114382a2012-02-09 23:21:08 +01002743
Stephane Eranian69996df2012-02-09 23:21:06 +01002744 if (ph->needs_swap)
2745 sz = bswap_32(sz);
2746
2747 if (sz == 0) {
2748 /* assume ABI0 */
2749 sz = PERF_ATTR_SIZE_VER0;
2750 } else if (sz > our_sz) {
2751 pr_debug("file uses a more recent and unsupported ABI"
2752 " (%zu bytes extra)\n", sz - our_sz);
2753 return -1;
2754 }
2755 /* what we have not yet read and that we know about */
2756 left = sz - PERF_ATTR_SIZE_VER0;
2757 if (left) {
2758 void *ptr = attr;
2759 ptr += PERF_ATTR_SIZE_VER0;
2760
2761 ret = readn(fd, ptr, left);
2762 }
2763 /* read perf_file_section, ids are read in caller */
2764 ret = readn(fd, &f_attr->ids, sizeof(f_attr->ids));
2765
2766 return ret <= 0 ? -1 : 0;
2767}
2768
Namhyung Kim831394b2012-09-06 11:10:46 +09002769static int perf_evsel__prepare_tracepoint_event(struct perf_evsel *evsel,
2770 struct pevent *pevent)
Arnaldo Carvalho de Melocb9dd492012-06-11 19:03:32 -03002771{
Namhyung Kim831394b2012-09-06 11:10:46 +09002772 struct event_format *event;
Arnaldo Carvalho de Melocb9dd492012-06-11 19:03:32 -03002773 char bf[128];
2774
Namhyung Kim831394b2012-09-06 11:10:46 +09002775 /* already prepared */
2776 if (evsel->tp_format)
2777 return 0;
2778
Namhyung Kim3dce2ce2013-03-21 16:18:48 +09002779 if (pevent == NULL) {
2780 pr_debug("broken or missing trace data\n");
2781 return -1;
2782 }
2783
Namhyung Kim831394b2012-09-06 11:10:46 +09002784 event = pevent_find_event(pevent, evsel->attr.config);
Arnaldo Carvalho de Melocb9dd492012-06-11 19:03:32 -03002785 if (event == NULL)
2786 return -1;
2787
Namhyung Kim831394b2012-09-06 11:10:46 +09002788 if (!evsel->name) {
2789 snprintf(bf, sizeof(bf), "%s:%s", event->system, event->name);
2790 evsel->name = strdup(bf);
2791 if (evsel->name == NULL)
2792 return -1;
2793 }
Arnaldo Carvalho de Melocb9dd492012-06-11 19:03:32 -03002794
Arnaldo Carvalho de Melofcf65bf2012-08-07 09:58:03 -03002795 evsel->tp_format = event;
Arnaldo Carvalho de Melocb9dd492012-06-11 19:03:32 -03002796 return 0;
2797}
2798
Namhyung Kim831394b2012-09-06 11:10:46 +09002799static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist,
2800 struct pevent *pevent)
Arnaldo Carvalho de Melocb9dd492012-06-11 19:03:32 -03002801{
2802 struct perf_evsel *pos;
2803
Arnaldo Carvalho de Melo0050f7a2014-01-10 10:37:27 -03002804 evlist__for_each(evlist, pos) {
Namhyung Kim831394b2012-09-06 11:10:46 +09002805 if (pos->attr.type == PERF_TYPE_TRACEPOINT &&
2806 perf_evsel__prepare_tracepoint_event(pos, pevent))
Arnaldo Carvalho de Melocb9dd492012-06-11 19:03:32 -03002807 return -1;
2808 }
2809
2810 return 0;
2811}
2812
Jiri Olsad4339562013-07-17 19:49:41 +02002813int perf_session__read_header(struct perf_session *session)
Tom Zanussi8dc58102010-04-01 23:59:15 -05002814{
Jiri Olsacc9784bd2013-10-15 16:27:34 +02002815 struct perf_data_file *file = session->file;
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002816 struct perf_header *header = &session->header;
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -02002817 struct perf_file_header f_header;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002818 struct perf_file_attr f_attr;
2819 u64 f_id;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002820 int nr_attrs, nr_ids, i, j;
Jiri Olsacc9784bd2013-10-15 16:27:34 +02002821 int fd = perf_data_file__fd(file);
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002822
Namhyung Kim334fe7a2013-03-11 16:43:12 +09002823 session->evlist = perf_evlist__new();
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002824 if (session->evlist == NULL)
2825 return -ENOMEM;
2826
Jiri Olsacc9784bd2013-10-15 16:27:34 +02002827 if (perf_data_file__is_pipe(file))
Jiri Olsad4339562013-07-17 19:49:41 +02002828 return perf_header__read_pipe(session);
Tom Zanussi8dc58102010-04-01 23:59:15 -05002829
Stephane Eranian69996df2012-02-09 23:21:06 +01002830 if (perf_file_header__read(&f_header, header, fd) < 0)
Arnaldo Carvalho de Melo4dc0a042009-11-19 14:55:55 -02002831 return -EINVAL;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002832
Namhyung Kimb314e5c2013-09-30 17:19:48 +09002833 /*
2834 * Sanity check that perf.data was written cleanly; data size is
2835 * initialized to 0 and updated only if the on_exit function is run.
2836 * If data size is still 0 then the file contains only partial
2837 * information. Just warn user and process it as much as it can.
2838 */
2839 if (f_header.data.size == 0) {
2840 pr_warning("WARNING: The %s file's data size field is 0 which is unexpected.\n"
2841 "Was the 'perf record' command properly terminated?\n",
Jiri Olsacc9784bd2013-10-15 16:27:34 +02002842 file->path);
Namhyung Kimb314e5c2013-09-30 17:19:48 +09002843 }
2844
Stephane Eranian69996df2012-02-09 23:21:06 +01002845 nr_attrs = f_header.attrs.size / f_header.attr_size;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002846 lseek(fd, f_header.attrs.offset, SEEK_SET);
2847
2848 for (i = 0; i < nr_attrs; i++) {
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002849 struct perf_evsel *evsel;
Peter Zijlstra1c222bc2009-08-06 20:57:41 +02002850 off_t tmp;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002851
Stephane Eranian69996df2012-02-09 23:21:06 +01002852 if (read_attr(fd, header, &f_attr) < 0)
Arnaldo Carvalho de Melo769885f2009-12-28 22:48:32 -02002853 goto out_errno;
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -02002854
David Aherneda39132011-07-15 12:34:09 -06002855 if (header->needs_swap)
2856 perf_event__attr_swap(&f_attr.attr);
2857
Peter Zijlstra1c222bc2009-08-06 20:57:41 +02002858 tmp = lseek(fd, 0, SEEK_CUR);
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -03002859 evsel = perf_evsel__new(&f_attr.attr);
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002860
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002861 if (evsel == NULL)
2862 goto out_delete_evlist;
Arnaldo Carvalho de Melo0807d2d2012-09-26 12:48:18 -03002863
2864 evsel->needs_swap = header->needs_swap;
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002865 /*
2866 * Do it before so that if perf_evsel__alloc_id fails, this
2867 * entry gets purged too at perf_evlist__delete().
2868 */
2869 perf_evlist__add(session->evlist, evsel);
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002870
2871 nr_ids = f_attr.ids.size / sizeof(u64);
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002872 /*
2873 * We don't have the cpu and thread maps on the header, so
2874 * for allocating the perf_sample_id table we fake 1 cpu and
2875 * hattr->ids threads.
2876 */
2877 if (perf_evsel__alloc_id(evsel, 1, nr_ids))
2878 goto out_delete_evlist;
2879
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002880 lseek(fd, f_attr.ids.offset, SEEK_SET);
2881
2882 for (j = 0; j < nr_ids; j++) {
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002883 if (perf_header__getbuffer64(header, fd, &f_id, sizeof(f_id)))
Arnaldo Carvalho de Melo769885f2009-12-28 22:48:32 -02002884 goto out_errno;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002885
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002886 perf_evlist__id_add(session->evlist, evsel, 0, j, f_id);
Arnaldo Carvalho de Melo4dc0a042009-11-19 14:55:55 -02002887 }
Arnaldo Carvalho de Melo11deb1f2009-11-17 01:18:09 -02002888
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002889 lseek(fd, tmp, SEEK_SET);
2890 }
2891
Arnaldo Carvalho de Melod04b35f2011-11-11 22:17:32 -02002892 symbol_conf.nr_events = nr_attrs;
2893
Jiri Olsa29f5ffd2013-12-03 14:09:23 +01002894 perf_header__process_sections(header, fd, &session->tevent,
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002895 perf_file_section__process);
Frederic Weisbecker4778d2e2009-11-11 04:51:05 +01002896
Namhyung Kim831394b2012-09-06 11:10:46 +09002897 if (perf_evlist__prepare_tracepoint_events(session->evlist,
Jiri Olsa29f5ffd2013-12-03 14:09:23 +01002898 session->tevent.pevent))
Arnaldo Carvalho de Melocb9dd492012-06-11 19:03:32 -03002899 goto out_delete_evlist;
2900
Arnaldo Carvalho de Melo4dc0a042009-11-19 14:55:55 -02002901 return 0;
Arnaldo Carvalho de Melo769885f2009-12-28 22:48:32 -02002902out_errno:
2903 return -errno;
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002904
2905out_delete_evlist:
2906 perf_evlist__delete(session->evlist);
2907 session->evlist = NULL;
2908 return -ENOMEM;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002909}
Frederic Weisbecker0d3a5c82009-08-16 20:56:37 +02002910
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -02002911int perf_event__synthesize_attr(struct perf_tool *tool,
Robert Richterf4d83432012-08-16 21:10:17 +02002912 struct perf_event_attr *attr, u32 ids, u64 *id,
Arnaldo Carvalho de Melo743eb862011-11-28 07:56:39 -02002913 perf_event__handler_t process)
Frederic Weisbecker0d3a5c82009-08-16 20:56:37 +02002914{
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -02002915 union perf_event *ev;
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05002916 size_t size;
2917 int err;
2918
2919 size = sizeof(struct perf_event_attr);
Irina Tirdea9ac3e482012-09-11 01:15:01 +03002920 size = PERF_ALIGN(size, sizeof(u64));
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05002921 size += sizeof(struct perf_event_header);
2922 size += ids * sizeof(u64);
2923
2924 ev = malloc(size);
2925
Chris Samuelce47dc52010-11-13 13:35:06 +11002926 if (ev == NULL)
2927 return -ENOMEM;
2928
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05002929 ev->attr.attr = *attr;
2930 memcpy(ev->attr.id, id, ids * sizeof(u64));
2931
2932 ev->attr.header.type = PERF_RECORD_HEADER_ATTR;
Robert Richterf4d83432012-08-16 21:10:17 +02002933 ev->attr.header.size = (u16)size;
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05002934
Robert Richterf4d83432012-08-16 21:10:17 +02002935 if (ev->attr.header.size == size)
2936 err = process(tool, ev, NULL, NULL);
2937 else
2938 err = -E2BIG;
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05002939
2940 free(ev);
2941
2942 return err;
2943}
2944
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -02002945int perf_event__synthesize_attrs(struct perf_tool *tool,
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -02002946 struct perf_session *session,
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002947 perf_event__handler_t process)
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05002948{
Robert Richter6606f872012-08-16 21:10:19 +02002949 struct perf_evsel *evsel;
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002950 int err = 0;
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05002951
Arnaldo Carvalho de Melo0050f7a2014-01-10 10:37:27 -03002952 evlist__for_each(session->evlist, evsel) {
Robert Richter6606f872012-08-16 21:10:19 +02002953 err = perf_event__synthesize_attr(tool, &evsel->attr, evsel->ids,
2954 evsel->id, process);
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05002955 if (err) {
2956 pr_debug("failed to create perf header attribute\n");
2957 return err;
2958 }
2959 }
2960
2961 return err;
2962}
2963
Adrian Hunter47c3d102013-07-04 16:20:21 +03002964int perf_event__process_attr(struct perf_tool *tool __maybe_unused,
2965 union perf_event *event,
Arnaldo Carvalho de Melo10d0f082011-11-11 22:45:41 -02002966 struct perf_evlist **pevlist)
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05002967{
Robert Richterf4d83432012-08-16 21:10:17 +02002968 u32 i, ids, n_ids;
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002969 struct perf_evsel *evsel;
Arnaldo Carvalho de Melo10d0f082011-11-11 22:45:41 -02002970 struct perf_evlist *evlist = *pevlist;
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05002971
Arnaldo Carvalho de Melo10d0f082011-11-11 22:45:41 -02002972 if (evlist == NULL) {
Namhyung Kim334fe7a2013-03-11 16:43:12 +09002973 *pevlist = evlist = perf_evlist__new();
Arnaldo Carvalho de Melo10d0f082011-11-11 22:45:41 -02002974 if (evlist == NULL)
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05002975 return -ENOMEM;
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05002976 }
2977
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -03002978 evsel = perf_evsel__new(&event->attr.attr);
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002979 if (evsel == NULL)
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05002980 return -ENOMEM;
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05002981
Arnaldo Carvalho de Melo10d0f082011-11-11 22:45:41 -02002982 perf_evlist__add(evlist, evsel);
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002983
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -02002984 ids = event->header.size;
2985 ids -= (void *)&event->attr.id - (void *)event;
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05002986 n_ids = ids / sizeof(u64);
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002987 /*
2988 * We don't have the cpu and thread maps on the header, so
2989 * for allocating the perf_sample_id table we fake 1 cpu and
2990 * hattr->ids threads.
2991 */
2992 if (perf_evsel__alloc_id(evsel, 1, n_ids))
2993 return -ENOMEM;
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05002994
2995 for (i = 0; i < n_ids; i++) {
Arnaldo Carvalho de Melo10d0f082011-11-11 22:45:41 -02002996 perf_evlist__id_add(evlist, evsel, 0, i, event->attr.id[i]);
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05002997 }
2998
Adrian Hunter7e0d6fc2013-07-04 16:20:29 +03002999 symbol_conf.nr_events = evlist->nr_entries;
3000
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05003001 return 0;
3002}
Tom Zanussicd19a032010-04-01 23:59:20 -05003003
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -02003004int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -02003005 struct perf_evlist *evlist,
Arnaldo Carvalho de Melo743eb862011-11-28 07:56:39 -02003006 perf_event__handler_t process)
Tom Zanussi92155452010-04-01 23:59:21 -05003007{
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -02003008 union perf_event ev;
Jiri Olsa29208e52011-10-20 15:59:43 +02003009 struct tracing_data *tdata;
Tom Zanussi92155452010-04-01 23:59:21 -05003010 ssize_t size = 0, aligned_size = 0, padding;
Irina Tirdea1d037ca2012-09-11 01:15:03 +03003011 int err __maybe_unused = 0;
Tom Zanussi92155452010-04-01 23:59:21 -05003012
Jiri Olsa29208e52011-10-20 15:59:43 +02003013 /*
3014 * We are going to store the size of the data followed
3015 * by the data contents. Since the fd descriptor is a pipe,
3016 * we cannot seek back to store the size of the data once
3017 * we know it. Instead we:
3018 *
3019 * - write the tracing data to the temp file
3020 * - get/write the data size to pipe
3021 * - write the tracing data from the temp file
3022 * to the pipe
3023 */
3024 tdata = tracing_data_get(&evlist->entries, fd, true);
3025 if (!tdata)
3026 return -1;
3027
Tom Zanussi92155452010-04-01 23:59:21 -05003028 memset(&ev, 0, sizeof(ev));
3029
3030 ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA;
Jiri Olsa29208e52011-10-20 15:59:43 +02003031 size = tdata->size;
Irina Tirdea9ac3e482012-09-11 01:15:01 +03003032 aligned_size = PERF_ALIGN(size, sizeof(u64));
Tom Zanussi92155452010-04-01 23:59:21 -05003033 padding = aligned_size - size;
3034 ev.tracing_data.header.size = sizeof(ev.tracing_data);
3035 ev.tracing_data.size = aligned_size;
3036
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -02003037 process(tool, &ev, NULL, NULL);
Tom Zanussi92155452010-04-01 23:59:21 -05003038
Jiri Olsa29208e52011-10-20 15:59:43 +02003039 /*
3040 * The put function will copy all the tracing data
3041 * stored in temp file to the pipe.
3042 */
3043 tracing_data_put(tdata);
3044
Tom Zanussi92155452010-04-01 23:59:21 -05003045 write_padded(fd, NULL, 0, padding);
3046
3047 return aligned_size;
3048}
3049
Adrian Hunter47c3d102013-07-04 16:20:21 +03003050int perf_event__process_tracing_data(struct perf_tool *tool __maybe_unused,
3051 union perf_event *event,
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -02003052 struct perf_session *session)
Tom Zanussi92155452010-04-01 23:59:21 -05003053{
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -02003054 ssize_t size_read, padding, size = event->tracing_data.size;
Jiri Olsacc9784bd2013-10-15 16:27:34 +02003055 int fd = perf_data_file__fd(session->file);
3056 off_t offset = lseek(fd, 0, SEEK_CUR);
Tom Zanussi92155452010-04-01 23:59:21 -05003057 char buf[BUFSIZ];
3058
3059 /* setup for reading amidst mmap */
Jiri Olsacc9784bd2013-10-15 16:27:34 +02003060 lseek(fd, offset + sizeof(struct tracing_data_event),
Tom Zanussi92155452010-04-01 23:59:21 -05003061 SEEK_SET);
3062
Jiri Olsa29f5ffd2013-12-03 14:09:23 +01003063 size_read = trace_report(fd, &session->tevent,
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -03003064 session->repipe);
Irina Tirdea9ac3e482012-09-11 01:15:01 +03003065 padding = PERF_ALIGN(size_read, sizeof(u64)) - size_read;
Tom Zanussi92155452010-04-01 23:59:21 -05003066
Jiri Olsacc9784bd2013-10-15 16:27:34 +02003067 if (readn(fd, buf, padding) < 0) {
Arnaldo Carvalho de Melo2caa48a2013-01-24 22:34:33 -03003068 pr_err("%s: reading input file", __func__);
3069 return -1;
3070 }
Tom Zanussi454c4072010-05-01 01:41:20 -05003071 if (session->repipe) {
3072 int retw = write(STDOUT_FILENO, buf, padding);
Arnaldo Carvalho de Melo2caa48a2013-01-24 22:34:33 -03003073 if (retw <= 0 || retw != padding) {
3074 pr_err("%s: repiping tracing data padding", __func__);
3075 return -1;
3076 }
Tom Zanussi454c4072010-05-01 01:41:20 -05003077 }
Tom Zanussi92155452010-04-01 23:59:21 -05003078
Arnaldo Carvalho de Melo2caa48a2013-01-24 22:34:33 -03003079 if (size_read + padding != size) {
3080 pr_err("%s: tracing data size mismatch", __func__);
3081 return -1;
3082 }
Tom Zanussi92155452010-04-01 23:59:21 -05003083
Namhyung Kim831394b2012-09-06 11:10:46 +09003084 perf_evlist__prepare_tracepoint_events(session->evlist,
Jiri Olsa29f5ffd2013-12-03 14:09:23 +01003085 session->tevent.pevent);
Arnaldo Carvalho de Melo8b6ee4c2012-08-07 23:36:16 -03003086
Tom Zanussi92155452010-04-01 23:59:21 -05003087 return size_read + padding;
3088}
Tom Zanussic7929e42010-04-01 23:59:22 -05003089
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -02003090int perf_event__synthesize_build_id(struct perf_tool *tool,
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -02003091 struct dso *pos, u16 misc,
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -02003092 perf_event__handler_t process,
Arnaldo Carvalho de Melo743eb862011-11-28 07:56:39 -02003093 struct machine *machine)
Tom Zanussic7929e42010-04-01 23:59:22 -05003094{
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -02003095 union perf_event ev;
Tom Zanussic7929e42010-04-01 23:59:22 -05003096 size_t len;
3097 int err = 0;
3098
3099 if (!pos->hit)
3100 return err;
3101
3102 memset(&ev, 0, sizeof(ev));
3103
3104 len = pos->long_name_len + 1;
Irina Tirdea9ac3e482012-09-11 01:15:01 +03003105 len = PERF_ALIGN(len, NAME_ALIGN);
Tom Zanussic7929e42010-04-01 23:59:22 -05003106 memcpy(&ev.build_id.build_id, pos->build_id, sizeof(pos->build_id));
3107 ev.build_id.header.type = PERF_RECORD_HEADER_BUILD_ID;
3108 ev.build_id.header.misc = misc;
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -03003109 ev.build_id.pid = machine->pid;
Tom Zanussic7929e42010-04-01 23:59:22 -05003110 ev.build_id.header.size = sizeof(ev.build_id) + len;
3111 memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len);
3112
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -02003113 err = process(tool, &ev, NULL, machine);
Tom Zanussic7929e42010-04-01 23:59:22 -05003114
3115 return err;
3116}
3117
Irina Tirdea1d037ca2012-09-11 01:15:03 +03003118int perf_event__process_build_id(struct perf_tool *tool __maybe_unused,
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -02003119 union perf_event *event,
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -02003120 struct perf_session *session)
Tom Zanussic7929e42010-04-01 23:59:22 -05003121{
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -02003122 __event_process_build_id(&event->build_id,
3123 event->build_id.filename,
Zhang, Yanmina1645ce2010-04-19 13:32:50 +08003124 session);
Tom Zanussic7929e42010-04-01 23:59:22 -05003125 return 0;
3126}
Stephane Eraniana1ac1d32010-06-17 11:39:01 +02003127
3128void disable_buildid_cache(void)
3129{
3130 no_buildid_cache = true;
3131}