blob: 28a3acb7b3135eaf9e95acb5a342b98d89aaea2b [file] [log] [blame]
Arnaldo Carvalho de Meloa43783a2017-04-18 10:46:11 -03001#include <errno.h>
Arnaldo Carvalho de Melofd20e812017-04-17 15:23:08 -03002#include <inttypes.h>
Arnaldo Carvalho de Meloa9072bc2011-10-26 12:41:38 -02003#include "util.h"
Arnaldo Carvalho de Meloa0675582017-04-17 16:51:59 -03004#include "string2.h"
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02005#include <sys/types.h>
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -02006#include <byteswap.h>
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02007#include <unistd.h>
8#include <stdio.h>
9#include <stdlib.h>
Frederic Weisbecker8671dab2009-11-11 04:51:03 +010010#include <linux/list.h>
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -020011#include <linux/kernel.h>
Robert Richterb1e5a9b2011-12-07 10:02:57 +010012#include <linux/bitops.h>
Stephane Eranianfbe96f22011-09-30 15:40:40 +020013#include <sys/utsname.h>
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020014
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -020015#include "evlist.h"
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -030016#include "evsel.h"
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020017#include "header.h"
Frederic Weisbecker03456a12009-10-06 23:36:47 +020018#include "../perf.h"
19#include "trace-event.h"
Arnaldo Carvalho de Melo301a0b02009-12-13 19:50:25 -020020#include "session.h"
Frederic Weisbecker8671dab2009-11-11 04:51:03 +010021#include "symbol.h"
Frederic Weisbecker4778d2e2009-11-11 04:51:05 +010022#include "debug.h"
Stephane Eranianfbe96f22011-09-30 15:40:40 +020023#include "cpumap.h"
Robert Richter50a96672012-08-16 21:10:24 +020024#include "pmu.h"
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +020025#include "vdso.h"
Namhyung Kima1ae5652012-09-24 17:14:59 +090026#include "strbuf.h"
Jiri Olsaebb296c2012-10-27 23:18:28 +020027#include "build-id.h"
Jiri Olsacc9784bd2013-10-15 16:27:34 +020028#include "data.h"
Jiri Olsa720e98b2016-02-16 16:01:43 +010029#include <api/fs/fs.h>
30#include "asm/bug.h"
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020031
Arnaldo Carvalho de Melo3d689ed2017-04-17 16:10:49 -030032#include "sane_ctype.h"
33
Stephane Eranian73323f52012-02-02 13:54:44 +010034/*
35 * magic2 = "PERFILE2"
36 * must be a numerical value to let the endianness
37 * determine the memory layout. That way we are able
38 * to detect endianness when reading the perf.data file
39 * back.
40 *
41 * we check for legacy (PERFFILE) format.
42 */
43static const char *__perf_magic1 = "PERFFILE";
44static const u64 __perf_magic2 = 0x32454c4946524550ULL;
45static const u64 __perf_magic2_sw = 0x50455246494c4532ULL;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020046
Stephane Eranian73323f52012-02-02 13:54:44 +010047#define PERF_MAGIC __perf_magic2
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020048
Soramichi AKIYAMAd25ed5d2017-01-17 00:22:37 +090049const char perf_version_string[] = PERF_VERSION;
50
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020051struct perf_file_attr {
Ingo Molnarcdd6c482009-09-21 12:02:48 +020052 struct perf_event_attr attr;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020053 struct perf_file_section ids;
54};
55
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -030056void perf_header__set_feat(struct perf_header *header, int feat)
Arnaldo Carvalho de Melo8d063672009-11-04 18:50:43 -020057{
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -030058 set_bit(feat, header->adds_features);
Arnaldo Carvalho de Melo8d063672009-11-04 18:50:43 -020059}
60
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -030061void perf_header__clear_feat(struct perf_header *header, int feat)
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -020062{
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -030063 clear_bit(feat, header->adds_features);
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -020064}
65
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -030066bool perf_header__has_feat(const struct perf_header *header, int feat)
Arnaldo Carvalho de Melo8d063672009-11-04 18:50:43 -020067{
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -030068 return test_bit(feat, header->adds_features);
Arnaldo Carvalho de Melo8d063672009-11-04 18:50:43 -020069}
70
Arnaldo Carvalho de Melo3726cc72009-11-17 01:18:12 -020071static int do_write(int fd, const void *buf, size_t size)
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020072{
73 while (size) {
74 int ret = write(fd, buf, size);
75
76 if (ret < 0)
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -020077 return -errno;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020078
79 size -= ret;
80 buf += ret;
81 }
Arnaldo Carvalho de Melo3726cc72009-11-17 01:18:12 -020082
83 return 0;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020084}
85
Namhyung Kime195fac2014-11-04 10:14:30 +090086int write_padded(int fd, const void *bf, size_t count, size_t count_aligned)
Arnaldo Carvalho de Melof92cb242010-01-04 16:19:28 -020087{
88 static const char zero_buf[NAME_ALIGN];
89 int err = do_write(fd, bf, count);
90
91 if (!err)
92 err = do_write(fd, zero_buf, count_aligned - count);
93
94 return err;
95}
96
Kan Liang2bb00d22015-09-01 09:58:12 -040097#define string_size(str) \
98 (PERF_ALIGN((strlen(str) + 1), NAME_ALIGN) + sizeof(u32))
99
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200100static int do_write_string(int fd, const char *str)
101{
102 u32 len, olen;
103 int ret;
104
105 olen = strlen(str) + 1;
Irina Tirdea9ac3e482012-09-11 01:15:01 +0300106 len = PERF_ALIGN(olen, NAME_ALIGN);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200107
108 /* write len, incl. \0 */
109 ret = do_write(fd, &len, sizeof(len));
110 if (ret < 0)
111 return ret;
112
113 return write_padded(fd, str, olen, len);
114}
115
116static char *do_read_string(int fd, struct perf_header *ph)
117{
118 ssize_t sz, ret;
119 u32 len;
120 char *buf;
121
Namhyung Kim5323f602012-12-17 15:38:54 +0900122 sz = readn(fd, &len, sizeof(len));
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200123 if (sz < (ssize_t)sizeof(len))
124 return NULL;
125
126 if (ph->needs_swap)
127 len = bswap_32(len);
128
129 buf = malloc(len);
130 if (!buf)
131 return NULL;
132
Namhyung Kim5323f602012-12-17 15:38:54 +0900133 ret = readn(fd, buf, len);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200134 if (ret == (ssize_t)len) {
135 /*
136 * strings are padded by zeroes
137 * thus the actual strlen of buf
138 * may be less than len
139 */
140 return buf;
141 }
142
143 free(buf);
144 return NULL;
145}
146
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300147static int write_tracing_data(int fd, struct perf_header *h __maybe_unused,
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200148 struct perf_evlist *evlist)
149{
150 return read_tracing_data(fd, &evlist->entries);
151}
152
153
154static int write_build_id(int fd, struct perf_header *h,
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300155 struct perf_evlist *evlist __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200156{
157 struct perf_session *session;
158 int err;
159
160 session = container_of(h, struct perf_session, header);
161
Robert Richtere20960c2011-12-07 10:02:55 +0100162 if (!perf_session__read_build_ids(session, true))
163 return -1;
164
Namhyung Kim714c9c42014-11-04 10:14:29 +0900165 err = perf_session__write_buildid_table(session, fd);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200166 if (err < 0) {
167 pr_debug("failed to write buildid table\n");
168 return err;
169 }
Namhyung Kim73c5d222014-11-07 22:57:56 +0900170 perf_session__cache_build_ids(session);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200171
172 return 0;
173}
174
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300175static int write_hostname(int fd, struct perf_header *h __maybe_unused,
176 struct perf_evlist *evlist __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200177{
178 struct utsname uts;
179 int ret;
180
181 ret = uname(&uts);
182 if (ret < 0)
183 return -1;
184
185 return do_write_string(fd, uts.nodename);
186}
187
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300188static int write_osrelease(int fd, struct perf_header *h __maybe_unused,
189 struct perf_evlist *evlist __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200190{
191 struct utsname uts;
192 int ret;
193
194 ret = uname(&uts);
195 if (ret < 0)
196 return -1;
197
198 return do_write_string(fd, uts.release);
199}
200
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300201static int write_arch(int fd, struct perf_header *h __maybe_unused,
202 struct perf_evlist *evlist __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200203{
204 struct utsname uts;
205 int ret;
206
207 ret = uname(&uts);
208 if (ret < 0)
209 return -1;
210
211 return do_write_string(fd, uts.machine);
212}
213
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300214static int write_version(int fd, struct perf_header *h __maybe_unused,
215 struct perf_evlist *evlist __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200216{
217 return do_write_string(fd, perf_version_string);
218}
219
Wang Nan493c3032014-10-24 09:45:26 +0800220static int __write_cpudesc(int fd, const char *cpuinfo_proc)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200221{
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200222 FILE *file;
223 char *buf = NULL;
224 char *s, *p;
Wang Nan493c3032014-10-24 09:45:26 +0800225 const char *search = cpuinfo_proc;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200226 size_t len = 0;
227 int ret = -1;
228
229 if (!search)
230 return -1;
231
232 file = fopen("/proc/cpuinfo", "r");
233 if (!file)
234 return -1;
235
236 while (getline(&buf, &len, file) > 0) {
237 ret = strncmp(buf, search, strlen(search));
238 if (!ret)
239 break;
240 }
241
Wang Naned307752014-10-16 11:08:29 +0800242 if (ret) {
243 ret = -1;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200244 goto done;
Wang Naned307752014-10-16 11:08:29 +0800245 }
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200246
247 s = buf;
248
249 p = strchr(buf, ':');
250 if (p && *(p+1) == ' ' && *(p+2))
251 s = p + 2;
252 p = strchr(s, '\n');
253 if (p)
254 *p = '\0';
255
256 /* squash extra space characters (branding string) */
257 p = s;
258 while (*p) {
259 if (isspace(*p)) {
260 char *r = p + 1;
261 char *q = r;
262 *p = ' ';
263 while (*q && isspace(*q))
264 q++;
265 if (q != (p+1))
266 while ((*r++ = *q++));
267 }
268 p++;
269 }
270 ret = do_write_string(fd, s);
271done:
272 free(buf);
273 fclose(file);
274 return ret;
275}
276
Wang Nan493c3032014-10-24 09:45:26 +0800277static int write_cpudesc(int fd, struct perf_header *h __maybe_unused,
278 struct perf_evlist *evlist __maybe_unused)
279{
280#ifndef CPUINFO_PROC
281#define CPUINFO_PROC {"model name", }
282#endif
283 const char *cpuinfo_procs[] = CPUINFO_PROC;
284 unsigned int i;
285
286 for (i = 0; i < ARRAY_SIZE(cpuinfo_procs); i++) {
287 int ret;
288 ret = __write_cpudesc(fd, cpuinfo_procs[i]);
289 if (ret >= 0)
290 return ret;
291 }
292 return -1;
293}
294
295
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300296static int write_nrcpus(int fd, struct perf_header *h __maybe_unused,
297 struct perf_evlist *evlist __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200298{
299 long nr;
300 u32 nrc, nra;
301 int ret;
302
Jan Stancekda8a58b2017-02-17 12:10:26 +0100303 nrc = cpu__max_present_cpu();
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200304
305 nr = sysconf(_SC_NPROCESSORS_ONLN);
306 if (nr < 0)
307 return -1;
308
309 nra = (u32)(nr & UINT_MAX);
310
311 ret = do_write(fd, &nrc, sizeof(nrc));
312 if (ret < 0)
313 return ret;
314
315 return do_write(fd, &nra, sizeof(nra));
316}
317
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300318static int write_event_desc(int fd, struct perf_header *h __maybe_unused,
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200319 struct perf_evlist *evlist)
320{
Robert Richter6606f872012-08-16 21:10:19 +0200321 struct perf_evsel *evsel;
Namhyung Kim74ba9e12012-09-05 14:02:47 +0900322 u32 nre, nri, sz;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200323 int ret;
324
Namhyung Kim74ba9e12012-09-05 14:02:47 +0900325 nre = evlist->nr_entries;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200326
327 /*
328 * write number of events
329 */
330 ret = do_write(fd, &nre, sizeof(nre));
331 if (ret < 0)
332 return ret;
333
334 /*
335 * size of perf_event_attr struct
336 */
Robert Richter6606f872012-08-16 21:10:19 +0200337 sz = (u32)sizeof(evsel->attr);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200338 ret = do_write(fd, &sz, sizeof(sz));
339 if (ret < 0)
340 return ret;
341
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -0300342 evlist__for_each_entry(evlist, evsel) {
Robert Richter6606f872012-08-16 21:10:19 +0200343 ret = do_write(fd, &evsel->attr, sz);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200344 if (ret < 0)
345 return ret;
346 /*
347 * write number of unique id per event
348 * there is one id per instance of an event
349 *
350 * copy into an nri to be independent of the
351 * type of ids,
352 */
Robert Richter6606f872012-08-16 21:10:19 +0200353 nri = evsel->ids;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200354 ret = do_write(fd, &nri, sizeof(nri));
355 if (ret < 0)
356 return ret;
357
358 /*
359 * write event string as passed on cmdline
360 */
Robert Richter6606f872012-08-16 21:10:19 +0200361 ret = do_write_string(fd, perf_evsel__name(evsel));
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200362 if (ret < 0)
363 return ret;
364 /*
365 * write unique ids for this event
366 */
Robert Richter6606f872012-08-16 21:10:19 +0200367 ret = do_write(fd, evsel->id, evsel->ids * sizeof(u64));
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200368 if (ret < 0)
369 return ret;
370 }
371 return 0;
372}
373
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300374static int write_cmdline(int fd, struct perf_header *h __maybe_unused,
375 struct perf_evlist *evlist __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200376{
377 char buf[MAXPATHLEN];
Arnaldo Carvalho de Melob6998692015-09-08 16:58:20 -0300378 u32 n;
379 int i, ret;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200380
Tommi Rantala55f771282017-03-22 15:06:24 +0200381 /* actual path to perf binary */
382 ret = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200383 if (ret <= 0)
384 return -1;
385
386 /* readlink() does not add null termination */
387 buf[ret] = '\0';
388
389 /* account for binary path */
Arnaldo Carvalho de Melob6998692015-09-08 16:58:20 -0300390 n = perf_env.nr_cmdline + 1;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200391
392 ret = do_write(fd, &n, sizeof(n));
393 if (ret < 0)
394 return ret;
395
396 ret = do_write_string(fd, buf);
397 if (ret < 0)
398 return ret;
399
Arnaldo Carvalho de Melob6998692015-09-08 16:58:20 -0300400 for (i = 0 ; i < perf_env.nr_cmdline; i++) {
401 ret = do_write_string(fd, perf_env.cmdline_argv[i]);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200402 if (ret < 0)
403 return ret;
404 }
405 return 0;
406}
407
408#define CORE_SIB_FMT \
409 "/sys/devices/system/cpu/cpu%d/topology/core_siblings_list"
410#define THRD_SIB_FMT \
411 "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list"
412
413struct cpu_topo {
Kan Liang2bb00d22015-09-01 09:58:12 -0400414 u32 cpu_nr;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200415 u32 core_sib;
416 u32 thread_sib;
417 char **core_siblings;
418 char **thread_siblings;
419};
420
421static int build_cpu_topo(struct cpu_topo *tp, int cpu)
422{
423 FILE *fp;
424 char filename[MAXPATHLEN];
425 char *buf = NULL, *p;
426 size_t len = 0;
Stephane Eranianc5885742013-08-14 12:04:26 +0200427 ssize_t sret;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200428 u32 i = 0;
429 int ret = -1;
430
431 sprintf(filename, CORE_SIB_FMT, cpu);
432 fp = fopen(filename, "r");
433 if (!fp)
Stephane Eranianc5885742013-08-14 12:04:26 +0200434 goto try_threads;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200435
Stephane Eranianc5885742013-08-14 12:04:26 +0200436 sret = getline(&buf, &len, fp);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200437 fclose(fp);
Stephane Eranianc5885742013-08-14 12:04:26 +0200438 if (sret <= 0)
439 goto try_threads;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200440
441 p = strchr(buf, '\n');
442 if (p)
443 *p = '\0';
444
445 for (i = 0; i < tp->core_sib; i++) {
446 if (!strcmp(buf, tp->core_siblings[i]))
447 break;
448 }
449 if (i == tp->core_sib) {
450 tp->core_siblings[i] = buf;
451 tp->core_sib++;
452 buf = NULL;
453 len = 0;
454 }
Stephane Eranianc5885742013-08-14 12:04:26 +0200455 ret = 0;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200456
Stephane Eranianc5885742013-08-14 12:04:26 +0200457try_threads:
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200458 sprintf(filename, THRD_SIB_FMT, cpu);
459 fp = fopen(filename, "r");
460 if (!fp)
461 goto done;
462
463 if (getline(&buf, &len, fp) <= 0)
464 goto done;
465
466 p = strchr(buf, '\n');
467 if (p)
468 *p = '\0';
469
470 for (i = 0; i < tp->thread_sib; i++) {
471 if (!strcmp(buf, tp->thread_siblings[i]))
472 break;
473 }
474 if (i == tp->thread_sib) {
475 tp->thread_siblings[i] = buf;
476 tp->thread_sib++;
477 buf = NULL;
478 }
479 ret = 0;
480done:
481 if(fp)
482 fclose(fp);
483 free(buf);
484 return ret;
485}
486
487static void free_cpu_topo(struct cpu_topo *tp)
488{
489 u32 i;
490
491 if (!tp)
492 return;
493
494 for (i = 0 ; i < tp->core_sib; i++)
Arnaldo Carvalho de Melo74cf2492013-12-27 16:55:14 -0300495 zfree(&tp->core_siblings[i]);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200496
497 for (i = 0 ; i < tp->thread_sib; i++)
Arnaldo Carvalho de Melo74cf2492013-12-27 16:55:14 -0300498 zfree(&tp->thread_siblings[i]);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200499
500 free(tp);
501}
502
503static struct cpu_topo *build_cpu_topology(void)
504{
Jan Stancek43db2842017-02-17 12:10:25 +0100505 struct cpu_topo *tp = NULL;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200506 void *addr;
507 u32 nr, i;
Arnaldo Carvalho de Meloaa36ddd2015-09-09 10:37:01 -0300508 size_t sz;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200509 long ncpus;
510 int ret = -1;
Jan Stancek43db2842017-02-17 12:10:25 +0100511 struct cpu_map *map;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200512
Jan Stancekda8a58b2017-02-17 12:10:26 +0100513 ncpus = cpu__max_present_cpu();
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200514
Jan Stancek43db2842017-02-17 12:10:25 +0100515 /* build online CPU map */
516 map = cpu_map__new(NULL);
517 if (map == NULL) {
518 pr_debug("failed to get system cpumap\n");
519 return NULL;
520 }
521
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200522 nr = (u32)(ncpus & UINT_MAX);
523
524 sz = nr * sizeof(char *);
Arnaldo Carvalho de Meloaa36ddd2015-09-09 10:37:01 -0300525 addr = calloc(1, sizeof(*tp) + 2 * sz);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200526 if (!addr)
Jan Stancek43db2842017-02-17 12:10:25 +0100527 goto out_free;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200528
529 tp = addr;
Kan Liang2bb00d22015-09-01 09:58:12 -0400530 tp->cpu_nr = nr;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200531 addr += sizeof(*tp);
532 tp->core_siblings = addr;
533 addr += sz;
534 tp->thread_siblings = addr;
535
536 for (i = 0; i < nr; i++) {
Jan Stancek43db2842017-02-17 12:10:25 +0100537 if (!cpu_map__has(map, i))
538 continue;
539
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200540 ret = build_cpu_topo(tp, i);
541 if (ret < 0)
542 break;
543 }
Jan Stancek43db2842017-02-17 12:10:25 +0100544
545out_free:
546 cpu_map__put(map);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200547 if (ret) {
548 free_cpu_topo(tp);
549 tp = NULL;
550 }
551 return tp;
552}
553
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300554static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused,
555 struct perf_evlist *evlist __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200556{
557 struct cpu_topo *tp;
558 u32 i;
Arnaldo Carvalho de Meloaa36ddd2015-09-09 10:37:01 -0300559 int ret, j;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200560
561 tp = build_cpu_topology();
562 if (!tp)
563 return -1;
564
565 ret = do_write(fd, &tp->core_sib, sizeof(tp->core_sib));
566 if (ret < 0)
567 goto done;
568
569 for (i = 0; i < tp->core_sib; i++) {
570 ret = do_write_string(fd, tp->core_siblings[i]);
571 if (ret < 0)
572 goto done;
573 }
574 ret = do_write(fd, &tp->thread_sib, sizeof(tp->thread_sib));
575 if (ret < 0)
576 goto done;
577
578 for (i = 0; i < tp->thread_sib; i++) {
579 ret = do_write_string(fd, tp->thread_siblings[i]);
580 if (ret < 0)
581 break;
582 }
Kan Liang2bb00d22015-09-01 09:58:12 -0400583
Arnaldo Carvalho de Meloaa36ddd2015-09-09 10:37:01 -0300584 ret = perf_env__read_cpu_topology_map(&perf_env);
585 if (ret < 0)
586 goto done;
587
588 for (j = 0; j < perf_env.nr_cpus_avail; j++) {
589 ret = do_write(fd, &perf_env.cpu[j].core_id,
590 sizeof(perf_env.cpu[j].core_id));
Kan Liang2bb00d22015-09-01 09:58:12 -0400591 if (ret < 0)
592 return ret;
Arnaldo Carvalho de Meloaa36ddd2015-09-09 10:37:01 -0300593 ret = do_write(fd, &perf_env.cpu[j].socket_id,
594 sizeof(perf_env.cpu[j].socket_id));
Kan Liang2bb00d22015-09-01 09:58:12 -0400595 if (ret < 0)
596 return ret;
597 }
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200598done:
599 free_cpu_topo(tp);
600 return ret;
601}
602
603
604
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300605static int write_total_mem(int fd, struct perf_header *h __maybe_unused,
606 struct perf_evlist *evlist __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200607{
608 char *buf = NULL;
609 FILE *fp;
610 size_t len = 0;
611 int ret = -1, n;
612 uint64_t mem;
613
614 fp = fopen("/proc/meminfo", "r");
615 if (!fp)
616 return -1;
617
618 while (getline(&buf, &len, fp) > 0) {
619 ret = strncmp(buf, "MemTotal:", 9);
620 if (!ret)
621 break;
622 }
623 if (!ret) {
624 n = sscanf(buf, "%*s %"PRIu64, &mem);
625 if (n == 1)
626 ret = do_write(fd, &mem, sizeof(mem));
Wang Naned307752014-10-16 11:08:29 +0800627 } else
628 ret = -1;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200629 free(buf);
630 fclose(fp);
631 return ret;
632}
633
634static int write_topo_node(int fd, int node)
635{
636 char str[MAXPATHLEN];
637 char field[32];
638 char *buf = NULL, *p;
639 size_t len = 0;
640 FILE *fp;
641 u64 mem_total, mem_free, mem;
642 int ret = -1;
643
644 sprintf(str, "/sys/devices/system/node/node%d/meminfo", node);
645 fp = fopen(str, "r");
646 if (!fp)
647 return -1;
648
649 while (getline(&buf, &len, fp) > 0) {
650 /* skip over invalid lines */
651 if (!strchr(buf, ':'))
652 continue;
Alan Coxa761a2d2014-01-20 19:10:11 +0100653 if (sscanf(buf, "%*s %*d %31s %"PRIu64, field, &mem) != 2)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200654 goto done;
655 if (!strcmp(field, "MemTotal:"))
656 mem_total = mem;
657 if (!strcmp(field, "MemFree:"))
658 mem_free = mem;
659 }
660
661 fclose(fp);
Thomas Jarosch5809fde2013-01-28 10:21:14 +0100662 fp = NULL;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200663
664 ret = do_write(fd, &mem_total, sizeof(u64));
665 if (ret)
666 goto done;
667
668 ret = do_write(fd, &mem_free, sizeof(u64));
669 if (ret)
670 goto done;
671
672 ret = -1;
673 sprintf(str, "/sys/devices/system/node/node%d/cpulist", node);
674
675 fp = fopen(str, "r");
676 if (!fp)
677 goto done;
678
679 if (getline(&buf, &len, fp) <= 0)
680 goto done;
681
682 p = strchr(buf, '\n');
683 if (p)
684 *p = '\0';
685
686 ret = do_write_string(fd, buf);
687done:
688 free(buf);
Thomas Jarosch5809fde2013-01-28 10:21:14 +0100689 if (fp)
690 fclose(fp);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200691 return ret;
692}
693
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300694static int write_numa_topology(int fd, struct perf_header *h __maybe_unused,
695 struct perf_evlist *evlist __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200696{
697 char *buf = NULL;
698 size_t len = 0;
699 FILE *fp;
700 struct cpu_map *node_map = NULL;
701 char *c;
702 u32 nr, i, j;
703 int ret = -1;
704
705 fp = fopen("/sys/devices/system/node/online", "r");
706 if (!fp)
707 return -1;
708
709 if (getline(&buf, &len, fp) <= 0)
710 goto done;
711
712 c = strchr(buf, '\n');
713 if (c)
714 *c = '\0';
715
716 node_map = cpu_map__new(buf);
717 if (!node_map)
718 goto done;
719
720 nr = (u32)node_map->nr;
721
722 ret = do_write(fd, &nr, sizeof(nr));
723 if (ret < 0)
724 goto done;
725
726 for (i = 0; i < nr; i++) {
727 j = (u32)node_map->map[i];
728 ret = do_write(fd, &j, sizeof(j));
729 if (ret < 0)
730 break;
731
732 ret = write_topo_node(fd, i);
733 if (ret < 0)
734 break;
735 }
736done:
737 free(buf);
738 fclose(fp);
Masami Hiramatsu5191d8872015-12-09 11:11:35 +0900739 cpu_map__put(node_map);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200740 return ret;
741}
742
743/*
Robert Richter50a96672012-08-16 21:10:24 +0200744 * File format:
745 *
746 * struct pmu_mappings {
747 * u32 pmu_num;
748 * struct pmu_map {
749 * u32 type;
750 * char name[];
751 * }[pmu_num];
752 * };
753 */
754
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300755static int write_pmu_mappings(int fd, struct perf_header *h __maybe_unused,
756 struct perf_evlist *evlist __maybe_unused)
Robert Richter50a96672012-08-16 21:10:24 +0200757{
758 struct perf_pmu *pmu = NULL;
759 off_t offset = lseek(fd, 0, SEEK_CUR);
760 __u32 pmu_num = 0;
Namhyung Kim5323f602012-12-17 15:38:54 +0900761 int ret;
Robert Richter50a96672012-08-16 21:10:24 +0200762
763 /* write real pmu_num later */
Namhyung Kim5323f602012-12-17 15:38:54 +0900764 ret = do_write(fd, &pmu_num, sizeof(pmu_num));
765 if (ret < 0)
766 return ret;
Robert Richter50a96672012-08-16 21:10:24 +0200767
768 while ((pmu = perf_pmu__scan(pmu))) {
769 if (!pmu->name)
770 continue;
771 pmu_num++;
Namhyung Kim5323f602012-12-17 15:38:54 +0900772
773 ret = do_write(fd, &pmu->type, sizeof(pmu->type));
774 if (ret < 0)
775 return ret;
776
777 ret = do_write_string(fd, pmu->name);
778 if (ret < 0)
779 return ret;
Robert Richter50a96672012-08-16 21:10:24 +0200780 }
781
782 if (pwrite(fd, &pmu_num, sizeof(pmu_num), offset) != sizeof(pmu_num)) {
783 /* discard all */
784 lseek(fd, offset, SEEK_SET);
785 return -1;
786 }
787
788 return 0;
789}
790
791/*
Namhyung Kima8bb5592013-01-22 18:09:31 +0900792 * File format:
793 *
794 * struct group_descs {
795 * u32 nr_groups;
796 * struct group_desc {
797 * char name[];
798 * u32 leader_idx;
799 * u32 nr_members;
800 * }[nr_groups];
801 * };
802 */
803static int write_group_desc(int fd, struct perf_header *h __maybe_unused,
804 struct perf_evlist *evlist)
805{
806 u32 nr_groups = evlist->nr_groups;
807 struct perf_evsel *evsel;
808 int ret;
809
810 ret = do_write(fd, &nr_groups, sizeof(nr_groups));
811 if (ret < 0)
812 return ret;
813
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -0300814 evlist__for_each_entry(evlist, evsel) {
Namhyung Kima8bb5592013-01-22 18:09:31 +0900815 if (perf_evsel__is_group_leader(evsel) &&
816 evsel->nr_members > 1) {
817 const char *name = evsel->group_name ?: "{anon_group}";
818 u32 leader_idx = evsel->idx;
819 u32 nr_members = evsel->nr_members;
820
821 ret = do_write_string(fd, name);
822 if (ret < 0)
823 return ret;
824
825 ret = do_write(fd, &leader_idx, sizeof(leader_idx));
826 if (ret < 0)
827 return ret;
828
829 ret = do_write(fd, &nr_members, sizeof(nr_members));
830 if (ret < 0)
831 return ret;
832 }
833 }
834 return 0;
835}
836
837/*
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200838 * default get_cpuid(): nothing gets recorded
839 * actual implementation must be in arch/$(ARCH)/util/header.c
840 */
Rui Teng11d8f872016-07-28 10:05:57 +0800841int __weak get_cpuid(char *buffer __maybe_unused, size_t sz __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200842{
843 return -1;
844}
845
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300846static int write_cpuid(int fd, struct perf_header *h __maybe_unused,
847 struct perf_evlist *evlist __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200848{
849 char buffer[64];
850 int ret;
851
852 ret = get_cpuid(buffer, sizeof(buffer));
853 if (!ret)
854 goto write_it;
855
856 return -1;
857write_it:
858 return do_write_string(fd, buffer);
859}
860
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300861static int write_branch_stack(int fd __maybe_unused,
862 struct perf_header *h __maybe_unused,
863 struct perf_evlist *evlist __maybe_unused)
Stephane Eranian330aa672012-03-08 23:47:46 +0100864{
865 return 0;
866}
867
Adrian Hunter99fa2982015-04-30 17:37:25 +0300868static int write_auxtrace(int fd, struct perf_header *h,
Adrian Hunter4025ea42015-04-09 18:53:41 +0300869 struct perf_evlist *evlist __maybe_unused)
870{
Adrian Hunter99fa2982015-04-30 17:37:25 +0300871 struct perf_session *session;
872 int err;
873
874 session = container_of(h, struct perf_session, header);
875
876 err = auxtrace_index__write(fd, &session->auxtrace_index);
877 if (err < 0)
878 pr_err("Failed to write auxtrace index\n");
879 return err;
Adrian Hunter4025ea42015-04-09 18:53:41 +0300880}
881
Jiri Olsa720e98b2016-02-16 16:01:43 +0100882static int cpu_cache_level__sort(const void *a, const void *b)
883{
884 struct cpu_cache_level *cache_a = (struct cpu_cache_level *)a;
885 struct cpu_cache_level *cache_b = (struct cpu_cache_level *)b;
886
887 return cache_a->level - cache_b->level;
888}
889
890static bool cpu_cache_level__cmp(struct cpu_cache_level *a, struct cpu_cache_level *b)
891{
892 if (a->level != b->level)
893 return false;
894
895 if (a->line_size != b->line_size)
896 return false;
897
898 if (a->sets != b->sets)
899 return false;
900
901 if (a->ways != b->ways)
902 return false;
903
904 if (strcmp(a->type, b->type))
905 return false;
906
907 if (strcmp(a->size, b->size))
908 return false;
909
910 if (strcmp(a->map, b->map))
911 return false;
912
913 return true;
914}
915
916static int cpu_cache_level__read(struct cpu_cache_level *cache, u32 cpu, u16 level)
917{
918 char path[PATH_MAX], file[PATH_MAX];
919 struct stat st;
920 size_t len;
921
922 scnprintf(path, PATH_MAX, "devices/system/cpu/cpu%d/cache/index%d/", cpu, level);
923 scnprintf(file, PATH_MAX, "%s/%s", sysfs__mountpoint(), path);
924
925 if (stat(file, &st))
926 return 1;
927
928 scnprintf(file, PATH_MAX, "%s/level", path);
929 if (sysfs__read_int(file, (int *) &cache->level))
930 return -1;
931
932 scnprintf(file, PATH_MAX, "%s/coherency_line_size", path);
933 if (sysfs__read_int(file, (int *) &cache->line_size))
934 return -1;
935
936 scnprintf(file, PATH_MAX, "%s/number_of_sets", path);
937 if (sysfs__read_int(file, (int *) &cache->sets))
938 return -1;
939
940 scnprintf(file, PATH_MAX, "%s/ways_of_associativity", path);
941 if (sysfs__read_int(file, (int *) &cache->ways))
942 return -1;
943
944 scnprintf(file, PATH_MAX, "%s/type", path);
945 if (sysfs__read_str(file, &cache->type, &len))
946 return -1;
947
948 cache->type[len] = 0;
949 cache->type = rtrim(cache->type);
950
951 scnprintf(file, PATH_MAX, "%s/size", path);
952 if (sysfs__read_str(file, &cache->size, &len)) {
953 free(cache->type);
954 return -1;
955 }
956
957 cache->size[len] = 0;
958 cache->size = rtrim(cache->size);
959
960 scnprintf(file, PATH_MAX, "%s/shared_cpu_list", path);
961 if (sysfs__read_str(file, &cache->map, &len)) {
962 free(cache->map);
963 free(cache->type);
964 return -1;
965 }
966
967 cache->map[len] = 0;
968 cache->map = rtrim(cache->map);
969 return 0;
970}
971
972static void cpu_cache_level__fprintf(FILE *out, struct cpu_cache_level *c)
973{
974 fprintf(out, "L%d %-15s %8s [%s]\n", c->level, c->type, c->size, c->map);
975}
976
977static int build_caches(struct cpu_cache_level caches[], u32 size, u32 *cntp)
978{
979 u32 i, cnt = 0;
980 long ncpus;
981 u32 nr, cpu;
982 u16 level;
983
984 ncpus = sysconf(_SC_NPROCESSORS_CONF);
985 if (ncpus < 0)
986 return -1;
987
988 nr = (u32)(ncpus & UINT_MAX);
989
990 for (cpu = 0; cpu < nr; cpu++) {
991 for (level = 0; level < 10; level++) {
992 struct cpu_cache_level c;
993 int err;
994
995 err = cpu_cache_level__read(&c, cpu, level);
996 if (err < 0)
997 return err;
998
999 if (err == 1)
1000 break;
1001
1002 for (i = 0; i < cnt; i++) {
1003 if (cpu_cache_level__cmp(&c, &caches[i]))
1004 break;
1005 }
1006
1007 if (i == cnt)
1008 caches[cnt++] = c;
1009 else
1010 cpu_cache_level__free(&c);
1011
1012 if (WARN_ONCE(cnt == size, "way too many cpu caches.."))
1013 goto out;
1014 }
1015 }
1016 out:
1017 *cntp = cnt;
1018 return 0;
1019}
1020
1021#define MAX_CACHES 2000
1022
1023static int write_cache(int fd, struct perf_header *h __maybe_unused,
1024 struct perf_evlist *evlist __maybe_unused)
1025{
1026 struct cpu_cache_level caches[MAX_CACHES];
1027 u32 cnt = 0, i, version = 1;
1028 int ret;
1029
1030 ret = build_caches(caches, MAX_CACHES, &cnt);
1031 if (ret)
1032 goto out;
1033
1034 qsort(&caches, cnt, sizeof(struct cpu_cache_level), cpu_cache_level__sort);
1035
1036 ret = do_write(fd, &version, sizeof(u32));
1037 if (ret < 0)
1038 goto out;
1039
1040 ret = do_write(fd, &cnt, sizeof(u32));
1041 if (ret < 0)
1042 goto out;
1043
1044 for (i = 0; i < cnt; i++) {
1045 struct cpu_cache_level *c = &caches[i];
1046
1047 #define _W(v) \
1048 ret = do_write(fd, &c->v, sizeof(u32)); \
1049 if (ret < 0) \
1050 goto out;
1051
1052 _W(level)
1053 _W(line_size)
1054 _W(sets)
1055 _W(ways)
1056 #undef _W
1057
1058 #define _W(v) \
1059 ret = do_write_string(fd, (const char *) c->v); \
1060 if (ret < 0) \
1061 goto out;
1062
1063 _W(type)
1064 _W(size)
1065 _W(map)
1066 #undef _W
1067 }
1068
1069out:
1070 for (i = 0; i < cnt; i++)
1071 cpu_cache_level__free(&caches[i]);
1072 return ret;
1073}
1074
Jiri Olsaffa517a2015-10-25 15:51:43 +01001075static int write_stat(int fd __maybe_unused,
1076 struct perf_header *h __maybe_unused,
1077 struct perf_evlist *evlist __maybe_unused)
1078{
1079 return 0;
1080}
1081
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001082static void print_hostname(struct perf_header *ph, int fd __maybe_unused,
1083 FILE *fp)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001084{
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001085 fprintf(fp, "# hostname : %s\n", ph->env.hostname);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001086}
1087
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001088static void print_osrelease(struct perf_header *ph, int fd __maybe_unused,
1089 FILE *fp)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001090{
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001091 fprintf(fp, "# os release : %s\n", ph->env.os_release);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001092}
1093
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001094static void print_arch(struct perf_header *ph, int fd __maybe_unused, FILE *fp)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001095{
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001096 fprintf(fp, "# arch : %s\n", ph->env.arch);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001097}
1098
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001099static void print_cpudesc(struct perf_header *ph, int fd __maybe_unused,
1100 FILE *fp)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001101{
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001102 fprintf(fp, "# cpudesc : %s\n", ph->env.cpu_desc);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001103}
1104
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001105static void print_nrcpus(struct perf_header *ph, int fd __maybe_unused,
1106 FILE *fp)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001107{
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001108 fprintf(fp, "# nrcpus online : %u\n", ph->env.nr_cpus_online);
1109 fprintf(fp, "# nrcpus avail : %u\n", ph->env.nr_cpus_avail);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001110}
1111
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001112static void print_version(struct perf_header *ph, int fd __maybe_unused,
1113 FILE *fp)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001114{
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001115 fprintf(fp, "# perf version : %s\n", ph->env.version);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001116}
1117
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001118static void print_cmdline(struct perf_header *ph, int fd __maybe_unused,
1119 FILE *fp)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001120{
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001121 int nr, i;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001122
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001123 nr = ph->env.nr_cmdline;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001124
1125 fprintf(fp, "# cmdline : ");
1126
Jiri Olsa768dd3f2015-07-21 14:31:31 +02001127 for (i = 0; i < nr; i++)
1128 fprintf(fp, "%s ", ph->env.cmdline_argv[i]);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001129 fputc('\n', fp);
1130}
1131
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001132static void print_cpu_topology(struct perf_header *ph, int fd __maybe_unused,
1133 FILE *fp)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001134{
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001135 int nr, i;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001136 char *str;
Jan Stancekda8a58b2017-02-17 12:10:26 +01001137 int cpu_nr = ph->env.nr_cpus_avail;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001138
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001139 nr = ph->env.nr_sibling_cores;
1140 str = ph->env.sibling_cores;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001141
1142 for (i = 0; i < nr; i++) {
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001143 fprintf(fp, "# sibling cores : %s\n", str);
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001144 str += strlen(str) + 1;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001145 }
1146
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001147 nr = ph->env.nr_sibling_threads;
1148 str = ph->env.sibling_threads;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001149
1150 for (i = 0; i < nr; i++) {
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001151 fprintf(fp, "# sibling threads : %s\n", str);
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001152 str += strlen(str) + 1;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001153 }
Kan Liang2bb00d22015-09-01 09:58:12 -04001154
1155 if (ph->env.cpu != NULL) {
1156 for (i = 0; i < cpu_nr; i++)
1157 fprintf(fp, "# CPU %d: Core ID %d, Socket ID %d\n", i,
1158 ph->env.cpu[i].core_id, ph->env.cpu[i].socket_id);
1159 } else
1160 fprintf(fp, "# Core ID and Socket ID information is not available\n");
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001161}
1162
Robert Richter4e1b9c62012-08-16 21:10:22 +02001163static void free_event_desc(struct perf_evsel *events)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001164{
Robert Richter4e1b9c62012-08-16 21:10:22 +02001165 struct perf_evsel *evsel;
1166
1167 if (!events)
1168 return;
1169
1170 for (evsel = events; evsel->attr.size; evsel++) {
Arnaldo Carvalho de Melo74cf2492013-12-27 16:55:14 -03001171 zfree(&evsel->name);
1172 zfree(&evsel->id);
Robert Richter4e1b9c62012-08-16 21:10:22 +02001173 }
1174
1175 free(events);
1176}
1177
1178static struct perf_evsel *
1179read_event_desc(struct perf_header *ph, int fd)
1180{
1181 struct perf_evsel *evsel, *events = NULL;
1182 u64 *id;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001183 void *buf = NULL;
Stephane Eranian62db9062012-02-09 23:21:07 +01001184 u32 nre, sz, nr, i, j;
1185 ssize_t ret;
1186 size_t msz;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001187
1188 /* number of events */
Namhyung Kim5323f602012-12-17 15:38:54 +09001189 ret = readn(fd, &nre, sizeof(nre));
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001190 if (ret != (ssize_t)sizeof(nre))
1191 goto error;
1192
1193 if (ph->needs_swap)
1194 nre = bswap_32(nre);
1195
Namhyung Kim5323f602012-12-17 15:38:54 +09001196 ret = readn(fd, &sz, sizeof(sz));
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001197 if (ret != (ssize_t)sizeof(sz))
1198 goto error;
1199
1200 if (ph->needs_swap)
1201 sz = bswap_32(sz);
1202
Stephane Eranian62db9062012-02-09 23:21:07 +01001203 /* buffer to hold on file attr struct */
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001204 buf = malloc(sz);
1205 if (!buf)
1206 goto error;
1207
Robert Richter4e1b9c62012-08-16 21:10:22 +02001208 /* the last event terminates with evsel->attr.size == 0: */
1209 events = calloc(nre + 1, sizeof(*events));
1210 if (!events)
1211 goto error;
1212
1213 msz = sizeof(evsel->attr);
Jiri Olsa9fafd982012-03-20 19:15:39 +01001214 if (sz < msz)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001215 msz = sz;
1216
Robert Richter4e1b9c62012-08-16 21:10:22 +02001217 for (i = 0, evsel = events; i < nre; evsel++, i++) {
1218 evsel->idx = i;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001219
Stephane Eranian62db9062012-02-09 23:21:07 +01001220 /*
1221 * must read entire on-file attr struct to
1222 * sync up with layout.
1223 */
Namhyung Kim5323f602012-12-17 15:38:54 +09001224 ret = readn(fd, buf, sz);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001225 if (ret != (ssize_t)sz)
1226 goto error;
1227
1228 if (ph->needs_swap)
1229 perf_event__attr_swap(buf);
1230
Robert Richter4e1b9c62012-08-16 21:10:22 +02001231 memcpy(&evsel->attr, buf, msz);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001232
Namhyung Kim5323f602012-12-17 15:38:54 +09001233 ret = readn(fd, &nr, sizeof(nr));
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001234 if (ret != (ssize_t)sizeof(nr))
1235 goto error;
1236
Arnaldo Carvalho de Melo0807d2d2012-09-26 12:48:18 -03001237 if (ph->needs_swap) {
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001238 nr = bswap_32(nr);
Arnaldo Carvalho de Melo0807d2d2012-09-26 12:48:18 -03001239 evsel->needs_swap = true;
1240 }
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001241
Robert Richter4e1b9c62012-08-16 21:10:22 +02001242 evsel->name = do_read_string(fd, ph);
1243
1244 if (!nr)
1245 continue;
1246
1247 id = calloc(nr, sizeof(*id));
1248 if (!id)
1249 goto error;
1250 evsel->ids = nr;
1251 evsel->id = id;
1252
1253 for (j = 0 ; j < nr; j++) {
Namhyung Kim5323f602012-12-17 15:38:54 +09001254 ret = readn(fd, id, sizeof(*id));
Robert Richter4e1b9c62012-08-16 21:10:22 +02001255 if (ret != (ssize_t)sizeof(*id))
1256 goto error;
1257 if (ph->needs_swap)
1258 *id = bswap_64(*id);
1259 id++;
1260 }
1261 }
1262out:
Arnaldo Carvalho de Melo04662522013-12-26 17:41:15 -03001263 free(buf);
Robert Richter4e1b9c62012-08-16 21:10:22 +02001264 return events;
1265error:
Markus Elfring4cc97612015-06-25 17:12:32 +02001266 free_event_desc(events);
Robert Richter4e1b9c62012-08-16 21:10:22 +02001267 events = NULL;
1268 goto out;
1269}
1270
Peter Zijlstra2c5e8c52015-04-07 11:09:54 +02001271static int __desc_attr__fprintf(FILE *fp, const char *name, const char *val,
1272 void *priv __attribute__((unused)))
1273{
1274 return fprintf(fp, ", %s = %s", name, val);
1275}
1276
Robert Richter4e1b9c62012-08-16 21:10:22 +02001277static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
1278{
1279 struct perf_evsel *evsel, *events = read_event_desc(ph, fd);
1280 u32 j;
1281 u64 *id;
1282
1283 if (!events) {
1284 fprintf(fp, "# event desc: not available or unable to read\n");
1285 return;
1286 }
1287
1288 for (evsel = events; evsel->attr.size; evsel++) {
1289 fprintf(fp, "# event : name = %s, ", evsel->name);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001290
Robert Richter4e1b9c62012-08-16 21:10:22 +02001291 if (evsel->ids) {
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001292 fprintf(fp, ", id = {");
Robert Richter4e1b9c62012-08-16 21:10:22 +02001293 for (j = 0, id = evsel->id; j < evsel->ids; j++, id++) {
1294 if (j)
1295 fputc(',', fp);
1296 fprintf(fp, " %"PRIu64, *id);
1297 }
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001298 fprintf(fp, " }");
Robert Richter4e1b9c62012-08-16 21:10:22 +02001299 }
Peter Zijlstra814c8c32015-03-31 00:19:31 +02001300
Peter Zijlstra2c5e8c52015-04-07 11:09:54 +02001301 perf_event_attr__fprintf(fp, &evsel->attr, __desc_attr__fprintf, NULL);
Robert Richter4e1b9c62012-08-16 21:10:22 +02001302
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001303 fputc('\n', fp);
1304 }
Robert Richter4e1b9c62012-08-16 21:10:22 +02001305
1306 free_event_desc(events);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001307}
1308
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001309static void print_total_mem(struct perf_header *ph, int fd __maybe_unused,
Irina Tirdea1d037ca2012-09-11 01:15:03 +03001310 FILE *fp)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001311{
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001312 fprintf(fp, "# total memory : %Lu kB\n", ph->env.total_mem);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001313}
1314
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001315static void print_numa_topology(struct perf_header *ph, int fd __maybe_unused,
Irina Tirdea1d037ca2012-09-11 01:15:03 +03001316 FILE *fp)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001317{
Jiri Olsac60da222016-07-04 14:16:20 +02001318 int i;
1319 struct numa_node *n;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001320
Jiri Olsac60da222016-07-04 14:16:20 +02001321 for (i = 0; i < ph->env.nr_numa_nodes; i++) {
1322 n = &ph->env.numa_nodes[i];
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001323
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001324 fprintf(fp, "# node%u meminfo : total = %"PRIu64" kB,"
1325 " free = %"PRIu64" kB\n",
Jiri Olsac60da222016-07-04 14:16:20 +02001326 n->node, n->mem_total, n->mem_free);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001327
Jiri Olsac60da222016-07-04 14:16:20 +02001328 fprintf(fp, "# node%u cpu list : ", n->node);
1329 cpu_map__fprintf(n->map, fp);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001330 }
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001331}
1332
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001333static void print_cpuid(struct perf_header *ph, int fd __maybe_unused, FILE *fp)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001334{
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001335 fprintf(fp, "# cpuid : %s\n", ph->env.cpuid);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001336}
1337
Irina Tirdea1d037ca2012-09-11 01:15:03 +03001338static void print_branch_stack(struct perf_header *ph __maybe_unused,
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001339 int fd __maybe_unused, FILE *fp)
Stephane Eranian330aa672012-03-08 23:47:46 +01001340{
1341 fprintf(fp, "# contains samples with branch stack\n");
1342}
1343
Adrian Hunter4025ea42015-04-09 18:53:41 +03001344static void print_auxtrace(struct perf_header *ph __maybe_unused,
1345 int fd __maybe_unused, FILE *fp)
1346{
1347 fprintf(fp, "# contains AUX area data (e.g. instruction trace)\n");
1348}
1349
Jiri Olsaffa517a2015-10-25 15:51:43 +01001350static void print_stat(struct perf_header *ph __maybe_unused,
1351 int fd __maybe_unused, FILE *fp)
1352{
1353 fprintf(fp, "# contains stat data\n");
1354}
1355
Jiri Olsa720e98b2016-02-16 16:01:43 +01001356static void print_cache(struct perf_header *ph __maybe_unused,
1357 int fd __maybe_unused, FILE *fp __maybe_unused)
1358{
1359 int i;
1360
1361 fprintf(fp, "# CPU cache info:\n");
1362 for (i = 0; i < ph->env.caches_cnt; i++) {
1363 fprintf(fp, "# ");
1364 cpu_cache_level__fprintf(fp, &ph->env.caches[i]);
1365 }
1366}
1367
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001368static void print_pmu_mappings(struct perf_header *ph, int fd __maybe_unused,
1369 FILE *fp)
Robert Richter50a96672012-08-16 21:10:24 +02001370{
1371 const char *delimiter = "# pmu mappings: ";
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001372 char *str, *tmp;
Robert Richter50a96672012-08-16 21:10:24 +02001373 u32 pmu_num;
1374 u32 type;
1375
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001376 pmu_num = ph->env.nr_pmu_mappings;
Robert Richter50a96672012-08-16 21:10:24 +02001377 if (!pmu_num) {
1378 fprintf(fp, "# pmu mappings: not available\n");
1379 return;
1380 }
1381
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001382 str = ph->env.pmu_mappings;
Namhyung Kimbe4a2de2012-09-05 14:02:49 +09001383
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001384 while (pmu_num) {
1385 type = strtoul(str, &tmp, 0);
1386 if (*tmp != ':')
1387 goto error;
1388
1389 str = tmp + 1;
1390 fprintf(fp, "%s%s = %" PRIu32, delimiter, str, type);
1391
Robert Richter50a96672012-08-16 21:10:24 +02001392 delimiter = ", ";
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001393 str += strlen(str) + 1;
1394 pmu_num--;
Robert Richter50a96672012-08-16 21:10:24 +02001395 }
1396
1397 fprintf(fp, "\n");
1398
1399 if (!pmu_num)
1400 return;
1401error:
1402 fprintf(fp, "# pmu mappings: unable to read\n");
1403}
1404
Namhyung Kima8bb5592013-01-22 18:09:31 +09001405static void print_group_desc(struct perf_header *ph, int fd __maybe_unused,
1406 FILE *fp)
1407{
1408 struct perf_session *session;
1409 struct perf_evsel *evsel;
1410 u32 nr = 0;
1411
1412 session = container_of(ph, struct perf_session, header);
1413
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -03001414 evlist__for_each_entry(session->evlist, evsel) {
Namhyung Kima8bb5592013-01-22 18:09:31 +09001415 if (perf_evsel__is_group_leader(evsel) &&
1416 evsel->nr_members > 1) {
1417 fprintf(fp, "# group: %s{%s", evsel->group_name ?: "",
1418 perf_evsel__name(evsel));
1419
1420 nr = evsel->nr_members - 1;
1421 } else if (nr) {
1422 fprintf(fp, ",%s", perf_evsel__name(evsel));
1423
1424 if (--nr == 0)
1425 fprintf(fp, "}\n");
1426 }
1427 }
1428}
1429
Robert Richter08d95bd2012-02-10 15:41:55 +01001430static int __event_process_build_id(struct build_id_event *bev,
1431 char *filename,
1432 struct perf_session *session)
1433{
1434 int err = -1;
Robert Richter08d95bd2012-02-10 15:41:55 +01001435 struct machine *machine;
Wang Nan1f121b02015-06-03 08:52:21 +00001436 u16 cpumode;
Robert Richter08d95bd2012-02-10 15:41:55 +01001437 struct dso *dso;
1438 enum dso_kernel_type dso_type;
1439
1440 machine = perf_session__findnew_machine(session, bev->pid);
1441 if (!machine)
1442 goto out;
1443
Wang Nan1f121b02015-06-03 08:52:21 +00001444 cpumode = bev->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
Robert Richter08d95bd2012-02-10 15:41:55 +01001445
Wang Nan1f121b02015-06-03 08:52:21 +00001446 switch (cpumode) {
Robert Richter08d95bd2012-02-10 15:41:55 +01001447 case PERF_RECORD_MISC_KERNEL:
1448 dso_type = DSO_TYPE_KERNEL;
Robert Richter08d95bd2012-02-10 15:41:55 +01001449 break;
1450 case PERF_RECORD_MISC_GUEST_KERNEL:
1451 dso_type = DSO_TYPE_GUEST_KERNEL;
Robert Richter08d95bd2012-02-10 15:41:55 +01001452 break;
1453 case PERF_RECORD_MISC_USER:
1454 case PERF_RECORD_MISC_GUEST_USER:
1455 dso_type = DSO_TYPE_USER;
Robert Richter08d95bd2012-02-10 15:41:55 +01001456 break;
1457 default:
1458 goto out;
1459 }
1460
Arnaldo Carvalho de Meloaa7cc2a2015-05-29 11:31:12 -03001461 dso = machine__findnew_dso(machine, filename);
Robert Richter08d95bd2012-02-10 15:41:55 +01001462 if (dso != NULL) {
Masami Hiramatsub5d8bbe2016-05-11 22:51:59 +09001463 char sbuild_id[SBUILD_ID_SIZE];
Robert Richter08d95bd2012-02-10 15:41:55 +01001464
1465 dso__set_build_id(dso, &bev->build_id);
1466
Wang Nan1f121b02015-06-03 08:52:21 +00001467 if (!is_kernel_module(filename, cpumode))
Robert Richter08d95bd2012-02-10 15:41:55 +01001468 dso->kernel = dso_type;
1469
1470 build_id__sprintf(dso->build_id, sizeof(dso->build_id),
1471 sbuild_id);
1472 pr_debug("build id event received for %s: %s\n",
1473 dso->long_name, sbuild_id);
Arnaldo Carvalho de Melod3a7c482015-06-02 11:53:26 -03001474 dso__put(dso);
Robert Richter08d95bd2012-02-10 15:41:55 +01001475 }
1476
1477 err = 0;
1478out:
1479 return err;
1480}
1481
1482static int perf_header__read_build_ids_abi_quirk(struct perf_header *header,
1483 int input, u64 offset, u64 size)
1484{
1485 struct perf_session *session = container_of(header, struct perf_session, header);
1486 struct {
1487 struct perf_event_header header;
Irina Tirdea9ac3e482012-09-11 01:15:01 +03001488 u8 build_id[PERF_ALIGN(BUILD_ID_SIZE, sizeof(u64))];
Robert Richter08d95bd2012-02-10 15:41:55 +01001489 char filename[0];
1490 } old_bev;
1491 struct build_id_event bev;
1492 char filename[PATH_MAX];
1493 u64 limit = offset + size;
1494
1495 while (offset < limit) {
1496 ssize_t len;
1497
Namhyung Kim5323f602012-12-17 15:38:54 +09001498 if (readn(input, &old_bev, sizeof(old_bev)) != sizeof(old_bev))
Robert Richter08d95bd2012-02-10 15:41:55 +01001499 return -1;
1500
1501 if (header->needs_swap)
1502 perf_event_header__bswap(&old_bev.header);
1503
1504 len = old_bev.header.size - sizeof(old_bev);
Namhyung Kim5323f602012-12-17 15:38:54 +09001505 if (readn(input, filename, len) != len)
Robert Richter08d95bd2012-02-10 15:41:55 +01001506 return -1;
1507
1508 bev.header = old_bev.header;
1509
1510 /*
1511 * As the pid is the missing value, we need to fill
1512 * it properly. The header.misc value give us nice hint.
1513 */
1514 bev.pid = HOST_KERNEL_ID;
1515 if (bev.header.misc == PERF_RECORD_MISC_GUEST_USER ||
1516 bev.header.misc == PERF_RECORD_MISC_GUEST_KERNEL)
1517 bev.pid = DEFAULT_GUEST_KERNEL_ID;
1518
1519 memcpy(bev.build_id, old_bev.build_id, sizeof(bev.build_id));
1520 __event_process_build_id(&bev, filename, session);
1521
1522 offset += bev.header.size;
1523 }
1524
1525 return 0;
1526}
1527
1528static int perf_header__read_build_ids(struct perf_header *header,
1529 int input, u64 offset, u64 size)
1530{
1531 struct perf_session *session = container_of(header, struct perf_session, header);
1532 struct build_id_event bev;
1533 char filename[PATH_MAX];
1534 u64 limit = offset + size, orig_offset = offset;
1535 int err = -1;
1536
1537 while (offset < limit) {
1538 ssize_t len;
1539
Namhyung Kim5323f602012-12-17 15:38:54 +09001540 if (readn(input, &bev, sizeof(bev)) != sizeof(bev))
Robert Richter08d95bd2012-02-10 15:41:55 +01001541 goto out;
1542
1543 if (header->needs_swap)
1544 perf_event_header__bswap(&bev.header);
1545
1546 len = bev.header.size - sizeof(bev);
Namhyung Kim5323f602012-12-17 15:38:54 +09001547 if (readn(input, filename, len) != len)
Robert Richter08d95bd2012-02-10 15:41:55 +01001548 goto out;
1549 /*
1550 * The a1645ce1 changeset:
1551 *
1552 * "perf: 'perf kvm' tool for monitoring guest performance from host"
1553 *
1554 * Added a field to struct build_id_event that broke the file
1555 * format.
1556 *
1557 * Since the kernel build-id is the first entry, process the
1558 * table using the old format if the well known
1559 * '[kernel.kallsyms]' string for the kernel build-id has the
1560 * first 4 characters chopped off (where the pid_t sits).
1561 */
1562 if (memcmp(filename, "nel.kallsyms]", 13) == 0) {
1563 if (lseek(input, orig_offset, SEEK_SET) == (off_t)-1)
1564 return -1;
1565 return perf_header__read_build_ids_abi_quirk(header, input, offset, size);
1566 }
1567
1568 __event_process_build_id(&bev, filename, session);
1569
1570 offset += bev.header.size;
1571 }
1572 err = 0;
1573out:
1574 return err;
1575}
1576
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001577static int process_tracing_data(struct perf_file_section *section __maybe_unused,
1578 struct perf_header *ph __maybe_unused,
1579 int fd, void *data)
Robert Richterf1c67db2012-02-10 15:41:56 +01001580{
Namhyung Kim3dce2ce2013-03-21 16:18:48 +09001581 ssize_t ret = trace_report(fd, data, false);
1582 return ret < 0 ? -1 : 0;
Robert Richterf1c67db2012-02-10 15:41:56 +01001583}
1584
1585static int process_build_id(struct perf_file_section *section,
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001586 struct perf_header *ph, int fd,
Irina Tirdea1d037ca2012-09-11 01:15:03 +03001587 void *data __maybe_unused)
Robert Richterf1c67db2012-02-10 15:41:56 +01001588{
1589 if (perf_header__read_build_ids(ph, fd, section->offset, section->size))
1590 pr_debug("Failed to read buildids, continuing...\n");
1591 return 0;
1592}
1593
Namhyung Kima1ae5652012-09-24 17:14:59 +09001594static int process_hostname(struct perf_file_section *section __maybe_unused,
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001595 struct perf_header *ph, int fd,
1596 void *data __maybe_unused)
Namhyung Kima1ae5652012-09-24 17:14:59 +09001597{
1598 ph->env.hostname = do_read_string(fd, ph);
1599 return ph->env.hostname ? 0 : -ENOMEM;
1600}
1601
1602static int process_osrelease(struct perf_file_section *section __maybe_unused,
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001603 struct perf_header *ph, int fd,
1604 void *data __maybe_unused)
Namhyung Kima1ae5652012-09-24 17:14:59 +09001605{
1606 ph->env.os_release = do_read_string(fd, ph);
1607 return ph->env.os_release ? 0 : -ENOMEM;
1608}
1609
1610static int process_version(struct perf_file_section *section __maybe_unused,
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001611 struct perf_header *ph, int fd,
1612 void *data __maybe_unused)
Namhyung Kima1ae5652012-09-24 17:14:59 +09001613{
1614 ph->env.version = do_read_string(fd, ph);
1615 return ph->env.version ? 0 : -ENOMEM;
1616}
1617
1618static int process_arch(struct perf_file_section *section __maybe_unused,
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001619 struct perf_header *ph, int fd,
1620 void *data __maybe_unused)
Namhyung Kima1ae5652012-09-24 17:14:59 +09001621{
1622 ph->env.arch = do_read_string(fd, ph);
1623 return ph->env.arch ? 0 : -ENOMEM;
1624}
1625
1626static int process_nrcpus(struct perf_file_section *section __maybe_unused,
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001627 struct perf_header *ph, int fd,
1628 void *data __maybe_unused)
Namhyung Kima1ae5652012-09-24 17:14:59 +09001629{
Jiri Olsa727ebd52013-11-28 11:30:14 +01001630 ssize_t ret;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001631 u32 nr;
1632
Namhyung Kim5323f602012-12-17 15:38:54 +09001633 ret = readn(fd, &nr, sizeof(nr));
Namhyung Kima1ae5652012-09-24 17:14:59 +09001634 if (ret != sizeof(nr))
1635 return -1;
1636
1637 if (ph->needs_swap)
1638 nr = bswap_32(nr);
1639
Arnaldo Carvalho de Melocaa47042015-09-11 12:36:12 -03001640 ph->env.nr_cpus_avail = nr;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001641
Namhyung Kim5323f602012-12-17 15:38:54 +09001642 ret = readn(fd, &nr, sizeof(nr));
Namhyung Kima1ae5652012-09-24 17:14:59 +09001643 if (ret != sizeof(nr))
1644 return -1;
1645
1646 if (ph->needs_swap)
1647 nr = bswap_32(nr);
1648
Arnaldo Carvalho de Melocaa47042015-09-11 12:36:12 -03001649 ph->env.nr_cpus_online = nr;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001650 return 0;
1651}
1652
1653static int process_cpudesc(struct perf_file_section *section __maybe_unused,
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001654 struct perf_header *ph, int fd,
1655 void *data __maybe_unused)
Namhyung Kima1ae5652012-09-24 17:14:59 +09001656{
1657 ph->env.cpu_desc = do_read_string(fd, ph);
1658 return ph->env.cpu_desc ? 0 : -ENOMEM;
1659}
1660
1661static int process_cpuid(struct perf_file_section *section __maybe_unused,
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001662 struct perf_header *ph, int fd,
1663 void *data __maybe_unused)
Namhyung Kima1ae5652012-09-24 17:14:59 +09001664{
1665 ph->env.cpuid = do_read_string(fd, ph);
1666 return ph->env.cpuid ? 0 : -ENOMEM;
1667}
1668
1669static int process_total_mem(struct perf_file_section *section __maybe_unused,
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001670 struct perf_header *ph, int fd,
1671 void *data __maybe_unused)
Namhyung Kima1ae5652012-09-24 17:14:59 +09001672{
1673 uint64_t mem;
Jiri Olsa727ebd52013-11-28 11:30:14 +01001674 ssize_t ret;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001675
Namhyung Kim5323f602012-12-17 15:38:54 +09001676 ret = readn(fd, &mem, sizeof(mem));
Namhyung Kima1ae5652012-09-24 17:14:59 +09001677 if (ret != sizeof(mem))
1678 return -1;
1679
1680 if (ph->needs_swap)
1681 mem = bswap_64(mem);
1682
1683 ph->env.total_mem = mem;
1684 return 0;
1685}
1686
Robert Richter7c2f7af2012-08-16 21:10:23 +02001687static struct perf_evsel *
1688perf_evlist__find_by_index(struct perf_evlist *evlist, int idx)
1689{
1690 struct perf_evsel *evsel;
1691
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -03001692 evlist__for_each_entry(evlist, evsel) {
Robert Richter7c2f7af2012-08-16 21:10:23 +02001693 if (evsel->idx == idx)
1694 return evsel;
1695 }
1696
1697 return NULL;
1698}
1699
1700static void
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001701perf_evlist__set_event_name(struct perf_evlist *evlist,
1702 struct perf_evsel *event)
Robert Richter7c2f7af2012-08-16 21:10:23 +02001703{
1704 struct perf_evsel *evsel;
1705
1706 if (!event->name)
1707 return;
1708
1709 evsel = perf_evlist__find_by_index(evlist, event->idx);
1710 if (!evsel)
1711 return;
1712
1713 if (evsel->name)
1714 return;
1715
1716 evsel->name = strdup(event->name);
1717}
1718
1719static int
Irina Tirdea1d037ca2012-09-11 01:15:03 +03001720process_event_desc(struct perf_file_section *section __maybe_unused,
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001721 struct perf_header *header, int fd,
Irina Tirdea1d037ca2012-09-11 01:15:03 +03001722 void *data __maybe_unused)
Robert Richter7c2f7af2012-08-16 21:10:23 +02001723{
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001724 struct perf_session *session;
Robert Richter7c2f7af2012-08-16 21:10:23 +02001725 struct perf_evsel *evsel, *events = read_event_desc(header, fd);
1726
1727 if (!events)
1728 return 0;
1729
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001730 session = container_of(header, struct perf_session, header);
Robert Richter7c2f7af2012-08-16 21:10:23 +02001731 for (evsel = events; evsel->attr.size; evsel++)
1732 perf_evlist__set_event_name(session->evlist, evsel);
1733
1734 free_event_desc(events);
1735
1736 return 0;
1737}
1738
Jiri Olsa768dd3f2015-07-21 14:31:31 +02001739static int process_cmdline(struct perf_file_section *section,
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001740 struct perf_header *ph, int fd,
1741 void *data __maybe_unused)
Namhyung Kima1ae5652012-09-24 17:14:59 +09001742{
Jiri Olsa727ebd52013-11-28 11:30:14 +01001743 ssize_t ret;
Jiri Olsa768dd3f2015-07-21 14:31:31 +02001744 char *str, *cmdline = NULL, **argv = NULL;
1745 u32 nr, i, len = 0;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001746
Namhyung Kim5323f602012-12-17 15:38:54 +09001747 ret = readn(fd, &nr, sizeof(nr));
Namhyung Kima1ae5652012-09-24 17:14:59 +09001748 if (ret != sizeof(nr))
1749 return -1;
1750
1751 if (ph->needs_swap)
1752 nr = bswap_32(nr);
1753
1754 ph->env.nr_cmdline = nr;
Jiri Olsa768dd3f2015-07-21 14:31:31 +02001755
1756 cmdline = zalloc(section->size + nr + 1);
1757 if (!cmdline)
1758 return -1;
1759
1760 argv = zalloc(sizeof(char *) * (nr + 1));
1761 if (!argv)
1762 goto error;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001763
1764 for (i = 0; i < nr; i++) {
1765 str = do_read_string(fd, ph);
1766 if (!str)
1767 goto error;
1768
Jiri Olsa768dd3f2015-07-21 14:31:31 +02001769 argv[i] = cmdline + len;
1770 memcpy(argv[i], str, strlen(str) + 1);
1771 len += strlen(str) + 1;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001772 free(str);
1773 }
Jiri Olsa768dd3f2015-07-21 14:31:31 +02001774 ph->env.cmdline = cmdline;
1775 ph->env.cmdline_argv = (const char **) argv;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001776 return 0;
1777
1778error:
Jiri Olsa768dd3f2015-07-21 14:31:31 +02001779 free(argv);
1780 free(cmdline);
Namhyung Kima1ae5652012-09-24 17:14:59 +09001781 return -1;
1782}
1783
Kan Liang2bb00d22015-09-01 09:58:12 -04001784static int process_cpu_topology(struct perf_file_section *section,
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001785 struct perf_header *ph, int fd,
1786 void *data __maybe_unused)
Namhyung Kima1ae5652012-09-24 17:14:59 +09001787{
Jiri Olsa727ebd52013-11-28 11:30:14 +01001788 ssize_t ret;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001789 u32 nr, i;
1790 char *str;
1791 struct strbuf sb;
Jan Stancekda8a58b2017-02-17 12:10:26 +01001792 int cpu_nr = ph->env.nr_cpus_avail;
Kan Liang2bb00d22015-09-01 09:58:12 -04001793 u64 size = 0;
1794
1795 ph->env.cpu = calloc(cpu_nr, sizeof(*ph->env.cpu));
1796 if (!ph->env.cpu)
1797 return -1;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001798
Namhyung Kim5323f602012-12-17 15:38:54 +09001799 ret = readn(fd, &nr, sizeof(nr));
Namhyung Kima1ae5652012-09-24 17:14:59 +09001800 if (ret != sizeof(nr))
Kan Liang2bb00d22015-09-01 09:58:12 -04001801 goto free_cpu;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001802
1803 if (ph->needs_swap)
1804 nr = bswap_32(nr);
1805
1806 ph->env.nr_sibling_cores = nr;
Kan Liang2bb00d22015-09-01 09:58:12 -04001807 size += sizeof(u32);
Masami Hiramatsu642aada2016-05-10 14:47:35 +09001808 if (strbuf_init(&sb, 128) < 0)
1809 goto free_cpu;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001810
1811 for (i = 0; i < nr; i++) {
1812 str = do_read_string(fd, ph);
1813 if (!str)
1814 goto error;
1815
1816 /* include a NULL character at the end */
Masami Hiramatsu642aada2016-05-10 14:47:35 +09001817 if (strbuf_add(&sb, str, strlen(str) + 1) < 0)
1818 goto error;
Kan Liang2bb00d22015-09-01 09:58:12 -04001819 size += string_size(str);
Namhyung Kima1ae5652012-09-24 17:14:59 +09001820 free(str);
1821 }
1822 ph->env.sibling_cores = strbuf_detach(&sb, NULL);
1823
Namhyung Kim5323f602012-12-17 15:38:54 +09001824 ret = readn(fd, &nr, sizeof(nr));
Namhyung Kima1ae5652012-09-24 17:14:59 +09001825 if (ret != sizeof(nr))
1826 return -1;
1827
1828 if (ph->needs_swap)
1829 nr = bswap_32(nr);
1830
1831 ph->env.nr_sibling_threads = nr;
Kan Liang2bb00d22015-09-01 09:58:12 -04001832 size += sizeof(u32);
Namhyung Kima1ae5652012-09-24 17:14:59 +09001833
1834 for (i = 0; i < nr; i++) {
1835 str = do_read_string(fd, ph);
1836 if (!str)
1837 goto error;
1838
1839 /* include a NULL character at the end */
Masami Hiramatsu642aada2016-05-10 14:47:35 +09001840 if (strbuf_add(&sb, str, strlen(str) + 1) < 0)
1841 goto error;
Kan Liang2bb00d22015-09-01 09:58:12 -04001842 size += string_size(str);
Namhyung Kima1ae5652012-09-24 17:14:59 +09001843 free(str);
1844 }
1845 ph->env.sibling_threads = strbuf_detach(&sb, NULL);
Kan Liang2bb00d22015-09-01 09:58:12 -04001846
1847 /*
1848 * The header may be from old perf,
1849 * which doesn't include core id and socket id information.
1850 */
1851 if (section->size <= size) {
1852 zfree(&ph->env.cpu);
1853 return 0;
1854 }
1855
1856 for (i = 0; i < (u32)cpu_nr; i++) {
1857 ret = readn(fd, &nr, sizeof(nr));
1858 if (ret != sizeof(nr))
1859 goto free_cpu;
1860
1861 if (ph->needs_swap)
1862 nr = bswap_32(nr);
1863
Kan Liang2bb00d22015-09-01 09:58:12 -04001864 ph->env.cpu[i].core_id = nr;
1865
1866 ret = readn(fd, &nr, sizeof(nr));
1867 if (ret != sizeof(nr))
1868 goto free_cpu;
1869
1870 if (ph->needs_swap)
1871 nr = bswap_32(nr);
1872
Jan Stancekda8a58b2017-02-17 12:10:26 +01001873 if (nr != (u32)-1 && nr > (u32)cpu_nr) {
Kan Liang2bb00d22015-09-01 09:58:12 -04001874 pr_debug("socket_id number is too big."
1875 "You may need to upgrade the perf tool.\n");
1876 goto free_cpu;
1877 }
1878
1879 ph->env.cpu[i].socket_id = nr;
1880 }
1881
Namhyung Kima1ae5652012-09-24 17:14:59 +09001882 return 0;
1883
1884error:
1885 strbuf_release(&sb);
Kan Liang2bb00d22015-09-01 09:58:12 -04001886free_cpu:
1887 zfree(&ph->env.cpu);
Namhyung Kima1ae5652012-09-24 17:14:59 +09001888 return -1;
1889}
1890
1891static int process_numa_topology(struct perf_file_section *section __maybe_unused,
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001892 struct perf_header *ph, int fd,
1893 void *data __maybe_unused)
Namhyung Kima1ae5652012-09-24 17:14:59 +09001894{
Jiri Olsac60da222016-07-04 14:16:20 +02001895 struct numa_node *nodes, *n;
Jiri Olsa727ebd52013-11-28 11:30:14 +01001896 ssize_t ret;
Jiri Olsac60da222016-07-04 14:16:20 +02001897 u32 nr, i;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001898 char *str;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001899
1900 /* nr nodes */
Namhyung Kim5323f602012-12-17 15:38:54 +09001901 ret = readn(fd, &nr, sizeof(nr));
Namhyung Kima1ae5652012-09-24 17:14:59 +09001902 if (ret != sizeof(nr))
Masami Hiramatsu642aada2016-05-10 14:47:35 +09001903 return -1;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001904
1905 if (ph->needs_swap)
1906 nr = bswap_32(nr);
1907
Jiri Olsac60da222016-07-04 14:16:20 +02001908 nodes = zalloc(sizeof(*nodes) * nr);
1909 if (!nodes)
1910 return -ENOMEM;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001911
1912 for (i = 0; i < nr; i++) {
Jiri Olsac60da222016-07-04 14:16:20 +02001913 n = &nodes[i];
1914
Namhyung Kima1ae5652012-09-24 17:14:59 +09001915 /* node number */
Jiri Olsac60da222016-07-04 14:16:20 +02001916 ret = readn(fd, &n->node, sizeof(u32));
1917 if (ret != sizeof(n->node))
Namhyung Kima1ae5652012-09-24 17:14:59 +09001918 goto error;
1919
Jiri Olsac60da222016-07-04 14:16:20 +02001920 ret = readn(fd, &n->mem_total, sizeof(u64));
Namhyung Kima1ae5652012-09-24 17:14:59 +09001921 if (ret != sizeof(u64))
1922 goto error;
1923
Jiri Olsac60da222016-07-04 14:16:20 +02001924 ret = readn(fd, &n->mem_free, sizeof(u64));
Namhyung Kima1ae5652012-09-24 17:14:59 +09001925 if (ret != sizeof(u64))
1926 goto error;
1927
1928 if (ph->needs_swap) {
Jiri Olsac60da222016-07-04 14:16:20 +02001929 n->node = bswap_32(n->node);
1930 n->mem_total = bswap_64(n->mem_total);
1931 n->mem_free = bswap_64(n->mem_free);
Namhyung Kima1ae5652012-09-24 17:14:59 +09001932 }
1933
Namhyung Kima1ae5652012-09-24 17:14:59 +09001934 str = do_read_string(fd, ph);
1935 if (!str)
1936 goto error;
1937
Jiri Olsac60da222016-07-04 14:16:20 +02001938 n->map = cpu_map__new(str);
1939 if (!n->map)
Masami Hiramatsu642aada2016-05-10 14:47:35 +09001940 goto error;
Jiri Olsac60da222016-07-04 14:16:20 +02001941
Namhyung Kima1ae5652012-09-24 17:14:59 +09001942 free(str);
1943 }
Jiri Olsaf957a532016-10-10 09:56:32 +02001944 ph->env.nr_numa_nodes = nr;
Jiri Olsac60da222016-07-04 14:16:20 +02001945 ph->env.numa_nodes = nodes;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001946 return 0;
1947
1948error:
Jiri Olsac60da222016-07-04 14:16:20 +02001949 free(nodes);
Namhyung Kima1ae5652012-09-24 17:14:59 +09001950 return -1;
1951}
1952
1953static int process_pmu_mappings(struct perf_file_section *section __maybe_unused,
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001954 struct perf_header *ph, int fd,
1955 void *data __maybe_unused)
Namhyung Kima1ae5652012-09-24 17:14:59 +09001956{
Jiri Olsa727ebd52013-11-28 11:30:14 +01001957 ssize_t ret;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001958 char *name;
1959 u32 pmu_num;
1960 u32 type;
1961 struct strbuf sb;
1962
Namhyung Kim5323f602012-12-17 15:38:54 +09001963 ret = readn(fd, &pmu_num, sizeof(pmu_num));
Namhyung Kima1ae5652012-09-24 17:14:59 +09001964 if (ret != sizeof(pmu_num))
1965 return -1;
1966
1967 if (ph->needs_swap)
1968 pmu_num = bswap_32(pmu_num);
1969
1970 if (!pmu_num) {
1971 pr_debug("pmu mappings not available\n");
1972 return 0;
1973 }
1974
1975 ph->env.nr_pmu_mappings = pmu_num;
Masami Hiramatsu642aada2016-05-10 14:47:35 +09001976 if (strbuf_init(&sb, 128) < 0)
1977 return -1;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001978
1979 while (pmu_num) {
Namhyung Kim5323f602012-12-17 15:38:54 +09001980 if (readn(fd, &type, sizeof(type)) != sizeof(type))
Namhyung Kima1ae5652012-09-24 17:14:59 +09001981 goto error;
1982 if (ph->needs_swap)
1983 type = bswap_32(type);
1984
1985 name = do_read_string(fd, ph);
1986 if (!name)
1987 goto error;
1988
Masami Hiramatsu642aada2016-05-10 14:47:35 +09001989 if (strbuf_addf(&sb, "%u:%s", type, name) < 0)
1990 goto error;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001991 /* include a NULL character at the end */
Masami Hiramatsu642aada2016-05-10 14:47:35 +09001992 if (strbuf_add(&sb, "", 1) < 0)
1993 goto error;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001994
Kan Liange0838e02015-09-10 11:03:05 -03001995 if (!strcmp(name, "msr"))
1996 ph->env.msr_pmu_type = type;
1997
Namhyung Kima1ae5652012-09-24 17:14:59 +09001998 free(name);
1999 pmu_num--;
2000 }
2001 ph->env.pmu_mappings = strbuf_detach(&sb, NULL);
2002 return 0;
2003
2004error:
2005 strbuf_release(&sb);
2006 return -1;
2007}
2008
Namhyung Kima8bb5592013-01-22 18:09:31 +09002009static int process_group_desc(struct perf_file_section *section __maybe_unused,
2010 struct perf_header *ph, int fd,
2011 void *data __maybe_unused)
2012{
2013 size_t ret = -1;
2014 u32 i, nr, nr_groups;
2015 struct perf_session *session;
2016 struct perf_evsel *evsel, *leader = NULL;
2017 struct group_desc {
2018 char *name;
2019 u32 leader_idx;
2020 u32 nr_members;
2021 } *desc;
2022
2023 if (readn(fd, &nr_groups, sizeof(nr_groups)) != sizeof(nr_groups))
2024 return -1;
2025
2026 if (ph->needs_swap)
2027 nr_groups = bswap_32(nr_groups);
2028
2029 ph->env.nr_groups = nr_groups;
2030 if (!nr_groups) {
2031 pr_debug("group desc not available\n");
2032 return 0;
2033 }
2034
2035 desc = calloc(nr_groups, sizeof(*desc));
2036 if (!desc)
2037 return -1;
2038
2039 for (i = 0; i < nr_groups; i++) {
2040 desc[i].name = do_read_string(fd, ph);
2041 if (!desc[i].name)
2042 goto out_free;
2043
2044 if (readn(fd, &desc[i].leader_idx, sizeof(u32)) != sizeof(u32))
2045 goto out_free;
2046
2047 if (readn(fd, &desc[i].nr_members, sizeof(u32)) != sizeof(u32))
2048 goto out_free;
2049
2050 if (ph->needs_swap) {
2051 desc[i].leader_idx = bswap_32(desc[i].leader_idx);
2052 desc[i].nr_members = bswap_32(desc[i].nr_members);
2053 }
2054 }
2055
2056 /*
2057 * Rebuild group relationship based on the group_desc
2058 */
2059 session = container_of(ph, struct perf_session, header);
2060 session->evlist->nr_groups = nr_groups;
2061
2062 i = nr = 0;
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -03002063 evlist__for_each_entry(session->evlist, evsel) {
Namhyung Kima8bb5592013-01-22 18:09:31 +09002064 if (evsel->idx == (int) desc[i].leader_idx) {
2065 evsel->leader = evsel;
2066 /* {anon_group} is a dummy name */
Namhyung Kim210e8122013-11-18 11:20:43 +09002067 if (strcmp(desc[i].name, "{anon_group}")) {
Namhyung Kima8bb5592013-01-22 18:09:31 +09002068 evsel->group_name = desc[i].name;
Namhyung Kim210e8122013-11-18 11:20:43 +09002069 desc[i].name = NULL;
2070 }
Namhyung Kima8bb5592013-01-22 18:09:31 +09002071 evsel->nr_members = desc[i].nr_members;
2072
2073 if (i >= nr_groups || nr > 0) {
2074 pr_debug("invalid group desc\n");
2075 goto out_free;
2076 }
2077
2078 leader = evsel;
2079 nr = evsel->nr_members - 1;
2080 i++;
2081 } else if (nr) {
2082 /* This is a group member */
2083 evsel->leader = leader;
2084
2085 nr--;
2086 }
2087 }
2088
2089 if (i != nr_groups || nr != 0) {
2090 pr_debug("invalid group desc\n");
2091 goto out_free;
2092 }
2093
2094 ret = 0;
2095out_free:
Namhyung Kim50a27402013-11-18 11:20:44 +09002096 for (i = 0; i < nr_groups; i++)
Arnaldo Carvalho de Melo74cf2492013-12-27 16:55:14 -03002097 zfree(&desc[i].name);
Namhyung Kima8bb5592013-01-22 18:09:31 +09002098 free(desc);
2099
2100 return ret;
2101}
2102
Adrian Hunter99fa2982015-04-30 17:37:25 +03002103static int process_auxtrace(struct perf_file_section *section,
2104 struct perf_header *ph, int fd,
2105 void *data __maybe_unused)
2106{
2107 struct perf_session *session;
2108 int err;
2109
2110 session = container_of(ph, struct perf_session, header);
2111
2112 err = auxtrace_index__process(fd, section->size, session,
2113 ph->needs_swap);
2114 if (err < 0)
2115 pr_err("Failed to process auxtrace index\n");
2116 return err;
2117}
2118
Jiri Olsa720e98b2016-02-16 16:01:43 +01002119static int process_cache(struct perf_file_section *section __maybe_unused,
2120 struct perf_header *ph __maybe_unused, int fd __maybe_unused,
2121 void *data __maybe_unused)
2122{
2123 struct cpu_cache_level *caches;
2124 u32 cnt, i, version;
2125
2126 if (readn(fd, &version, sizeof(version)) != sizeof(version))
2127 return -1;
2128
2129 if (ph->needs_swap)
2130 version = bswap_32(version);
2131
2132 if (version != 1)
2133 return -1;
2134
2135 if (readn(fd, &cnt, sizeof(cnt)) != sizeof(cnt))
2136 return -1;
2137
2138 if (ph->needs_swap)
2139 cnt = bswap_32(cnt);
2140
2141 caches = zalloc(sizeof(*caches) * cnt);
2142 if (!caches)
2143 return -1;
2144
2145 for (i = 0; i < cnt; i++) {
2146 struct cpu_cache_level c;
2147
2148 #define _R(v) \
2149 if (readn(fd, &c.v, sizeof(u32)) != sizeof(u32))\
2150 goto out_free_caches; \
2151 if (ph->needs_swap) \
2152 c.v = bswap_32(c.v); \
2153
2154 _R(level)
2155 _R(line_size)
2156 _R(sets)
2157 _R(ways)
2158 #undef _R
2159
2160 #define _R(v) \
2161 c.v = do_read_string(fd, ph); \
2162 if (!c.v) \
2163 goto out_free_caches;
2164
2165 _R(type)
2166 _R(size)
2167 _R(map)
2168 #undef _R
2169
2170 caches[i] = c;
2171 }
2172
2173 ph->env.caches = caches;
2174 ph->env.caches_cnt = cnt;
2175 return 0;
2176out_free_caches:
2177 free(caches);
2178 return -1;
2179}
2180
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002181struct feature_ops {
2182 int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist);
2183 void (*print)(struct perf_header *h, int fd, FILE *fp);
Robert Richterf1c67db2012-02-10 15:41:56 +01002184 int (*process)(struct perf_file_section *section,
Namhyung Kim3d7eb862012-09-24 17:15:01 +09002185 struct perf_header *h, int fd, void *data);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002186 const char *name;
2187 bool full_only;
2188};
2189
Robert Richter8cdfa782011-12-07 10:02:56 +01002190#define FEAT_OPA(n, func) \
2191 [n] = { .name = #n, .write = write_##func, .print = print_##func }
Robert Richterf1c67db2012-02-10 15:41:56 +01002192#define FEAT_OPP(n, func) \
2193 [n] = { .name = #n, .write = write_##func, .print = print_##func, \
2194 .process = process_##func }
Robert Richter8cdfa782011-12-07 10:02:56 +01002195#define FEAT_OPF(n, func) \
Robert Richterf1c67db2012-02-10 15:41:56 +01002196 [n] = { .name = #n, .write = write_##func, .print = print_##func, \
Namhyung Kima1ae5652012-09-24 17:14:59 +09002197 .process = process_##func, .full_only = true }
Robert Richter8cdfa782011-12-07 10:02:56 +01002198
2199/* feature_ops not implemented: */
Stephane Eranian2eeaaa02012-05-15 13:28:13 +02002200#define print_tracing_data NULL
2201#define print_build_id NULL
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002202
2203static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
Stephane Eranian2eeaaa02012-05-15 13:28:13 +02002204 FEAT_OPP(HEADER_TRACING_DATA, tracing_data),
Robert Richterf1c67db2012-02-10 15:41:56 +01002205 FEAT_OPP(HEADER_BUILD_ID, build_id),
Namhyung Kima1ae5652012-09-24 17:14:59 +09002206 FEAT_OPP(HEADER_HOSTNAME, hostname),
2207 FEAT_OPP(HEADER_OSRELEASE, osrelease),
2208 FEAT_OPP(HEADER_VERSION, version),
2209 FEAT_OPP(HEADER_ARCH, arch),
2210 FEAT_OPP(HEADER_NRCPUS, nrcpus),
2211 FEAT_OPP(HEADER_CPUDESC, cpudesc),
Namhyung Kim37e9d752012-09-24 17:15:03 +09002212 FEAT_OPP(HEADER_CPUID, cpuid),
Namhyung Kima1ae5652012-09-24 17:14:59 +09002213 FEAT_OPP(HEADER_TOTAL_MEM, total_mem),
Robert Richter7c2f7af2012-08-16 21:10:23 +02002214 FEAT_OPP(HEADER_EVENT_DESC, event_desc),
Namhyung Kima1ae5652012-09-24 17:14:59 +09002215 FEAT_OPP(HEADER_CMDLINE, cmdline),
Robert Richter8cdfa782011-12-07 10:02:56 +01002216 FEAT_OPF(HEADER_CPU_TOPOLOGY, cpu_topology),
2217 FEAT_OPF(HEADER_NUMA_TOPOLOGY, numa_topology),
Stephane Eranian330aa672012-03-08 23:47:46 +01002218 FEAT_OPA(HEADER_BRANCH_STACK, branch_stack),
Namhyung Kima1ae5652012-09-24 17:14:59 +09002219 FEAT_OPP(HEADER_PMU_MAPPINGS, pmu_mappings),
Namhyung Kima8bb5592013-01-22 18:09:31 +09002220 FEAT_OPP(HEADER_GROUP_DESC, group_desc),
Adrian Hunter99fa2982015-04-30 17:37:25 +03002221 FEAT_OPP(HEADER_AUXTRACE, auxtrace),
Jiri Olsaffa517a2015-10-25 15:51:43 +01002222 FEAT_OPA(HEADER_STAT, stat),
Jiri Olsa720e98b2016-02-16 16:01:43 +01002223 FEAT_OPF(HEADER_CACHE, cache),
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002224};
2225
2226struct header_print_data {
2227 FILE *fp;
2228 bool full; /* extended list of headers */
2229};
2230
2231static int perf_file_section__fprintf_info(struct perf_file_section *section,
2232 struct perf_header *ph,
2233 int feat, int fd, void *data)
2234{
2235 struct header_print_data *hd = data;
2236
2237 if (lseek(fd, section->offset, SEEK_SET) == (off_t)-1) {
2238 pr_debug("Failed to lseek to %" PRIu64 " offset for feature "
2239 "%d, continuing...\n", section->offset, feat);
2240 return 0;
2241 }
Robert Richterb1e5a9b2011-12-07 10:02:57 +01002242 if (feat >= HEADER_LAST_FEATURE) {
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002243 pr_warning("unknown feature %d\n", feat);
Robert Richterf7a8a132011-12-07 10:02:51 +01002244 return 0;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002245 }
2246 if (!feat_ops[feat].print)
2247 return 0;
2248
2249 if (!feat_ops[feat].full_only || hd->full)
2250 feat_ops[feat].print(ph, fd, hd->fp);
2251 else
2252 fprintf(hd->fp, "# %s info available, use -I to display\n",
2253 feat_ops[feat].name);
2254
2255 return 0;
2256}
2257
2258int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full)
2259{
2260 struct header_print_data hd;
2261 struct perf_header *header = &session->header;
Jiri Olsacc9784bd2013-10-15 16:27:34 +02002262 int fd = perf_data_file__fd(session->file);
Jiri Olsaf45f5612016-10-10 09:03:07 +02002263 struct stat st;
Jiri Olsaaabae162016-10-10 09:35:50 +02002264 int ret, bit;
Jiri Olsaf45f5612016-10-10 09:03:07 +02002265
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002266 hd.fp = fp;
2267 hd.full = full;
2268
Jiri Olsaf45f5612016-10-10 09:03:07 +02002269 ret = fstat(fd, &st);
2270 if (ret == -1)
2271 return -1;
2272
2273 fprintf(fp, "# captured on: %s", ctime(&st.st_ctime));
2274
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002275 perf_header__process_sections(header, fd, &hd,
2276 perf_file_section__fprintf_info);
Jiri Olsaaabae162016-10-10 09:35:50 +02002277
David Carrillo-Cisnerosc9d1c932017-04-10 13:14:32 -07002278 if (session->file->is_pipe)
2279 return 0;
2280
Jiri Olsaaabae162016-10-10 09:35:50 +02002281 fprintf(fp, "# missing features: ");
2282 for_each_clear_bit(bit, header->adds_features, HEADER_LAST_FEATURE) {
2283 if (bit)
2284 fprintf(fp, "%s ", feat_ops[bit].name);
2285 }
2286
2287 fprintf(fp, "\n");
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002288 return 0;
2289}
2290
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002291static int do_write_feat(int fd, struct perf_header *h, int type,
2292 struct perf_file_section **p,
2293 struct perf_evlist *evlist)
2294{
2295 int err;
2296 int ret = 0;
2297
2298 if (perf_header__has_feat(h, type)) {
Robert Richterb1e5a9b2011-12-07 10:02:57 +01002299 if (!feat_ops[type].write)
2300 return -1;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002301
2302 (*p)->offset = lseek(fd, 0, SEEK_CUR);
2303
2304 err = feat_ops[type].write(fd, h, evlist);
2305 if (err < 0) {
Jiri Olsa0c2aff42016-10-10 09:38:02 +02002306 pr_debug("failed to write feature %s\n", feat_ops[type].name);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002307
2308 /* undo anything written */
2309 lseek(fd, (*p)->offset, SEEK_SET);
2310
2311 return -1;
2312 }
2313 (*p)->size = lseek(fd, 0, SEEK_CUR) - (*p)->offset;
2314 (*p)++;
2315 }
2316 return ret;
2317}
2318
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002319static int perf_header__adds_write(struct perf_header *header,
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -02002320 struct perf_evlist *evlist, int fd)
Frederic Weisbecker2ba08252009-10-17 17:12:34 +02002321{
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002322 int nr_sections;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002323 struct perf_file_section *feat_sec, *p;
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002324 int sec_size;
2325 u64 sec_start;
Robert Richterb1e5a9b2011-12-07 10:02:57 +01002326 int feat;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002327 int err;
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002328
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002329 nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS);
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002330 if (!nr_sections)
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -02002331 return 0;
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002332
Paul Gortmaker91b98802013-01-30 20:05:49 -05002333 feat_sec = p = calloc(nr_sections, sizeof(*feat_sec));
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -02002334 if (feat_sec == NULL)
2335 return -ENOMEM;
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002336
2337 sec_size = sizeof(*feat_sec) * nr_sections;
2338
Jiri Olsa8d541e92013-07-17 19:49:44 +02002339 sec_start = header->feat_offset;
Xiao Guangrongf887f302010-02-04 16:46:42 +08002340 lseek(fd, sec_start + sec_size, SEEK_SET);
Frederic Weisbecker2ba08252009-10-17 17:12:34 +02002341
Robert Richterb1e5a9b2011-12-07 10:02:57 +01002342 for_each_set_bit(feat, header->adds_features, HEADER_FEAT_BITS) {
2343 if (do_write_feat(fd, header, feat, &p, evlist))
2344 perf_header__clear_feat(header, feat);
2345 }
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002346
Xiao Guangrongf887f302010-02-04 16:46:42 +08002347 lseek(fd, sec_start, SEEK_SET);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002348 /*
2349 * may write more than needed due to dropped feature, but
2350 * this is okay, reader will skip the mising entries
2351 */
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -02002352 err = do_write(fd, feat_sec, sec_size);
2353 if (err < 0)
2354 pr_debug("failed to write feature section\n");
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002355 free(feat_sec);
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -02002356 return err;
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002357}
Frederic Weisbecker2ba08252009-10-17 17:12:34 +02002358
Tom Zanussi8dc58102010-04-01 23:59:15 -05002359int perf_header__write_pipe(int fd)
2360{
2361 struct perf_pipe_file_header f_header;
2362 int err;
2363
2364 f_header = (struct perf_pipe_file_header){
2365 .magic = PERF_MAGIC,
2366 .size = sizeof(f_header),
2367 };
2368
2369 err = do_write(fd, &f_header, sizeof(f_header));
2370 if (err < 0) {
2371 pr_debug("failed to write perf pipe header\n");
2372 return err;
2373 }
2374
2375 return 0;
2376}
2377
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002378int perf_session__write_header(struct perf_session *session,
2379 struct perf_evlist *evlist,
2380 int fd, bool at_exit)
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002381{
2382 struct perf_file_header f_header;
2383 struct perf_file_attr f_attr;
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002384 struct perf_header *header = &session->header;
Jiri Olsa563aecb2013-06-05 13:35:06 +02002385 struct perf_evsel *evsel;
Jiri Olsa944d62b2013-07-17 19:49:43 +02002386 u64 attr_offset;
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002387 int err;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002388
2389 lseek(fd, sizeof(f_header), SEEK_SET);
2390
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -03002391 evlist__for_each_entry(session->evlist, evsel) {
Robert Richter6606f872012-08-16 21:10:19 +02002392 evsel->id_offset = lseek(fd, 0, SEEK_CUR);
2393 err = do_write(fd, evsel->id, evsel->ids * sizeof(u64));
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -02002394 if (err < 0) {
2395 pr_debug("failed to write perf header\n");
2396 return err;
2397 }
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002398 }
2399
Jiri Olsa944d62b2013-07-17 19:49:43 +02002400 attr_offset = lseek(fd, 0, SEEK_CUR);
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002401
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -03002402 evlist__for_each_entry(evlist, evsel) {
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002403 f_attr = (struct perf_file_attr){
Robert Richter6606f872012-08-16 21:10:19 +02002404 .attr = evsel->attr,
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002405 .ids = {
Robert Richter6606f872012-08-16 21:10:19 +02002406 .offset = evsel->id_offset,
2407 .size = evsel->ids * sizeof(u64),
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002408 }
2409 };
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -02002410 err = do_write(fd, &f_attr, sizeof(f_attr));
2411 if (err < 0) {
2412 pr_debug("failed to write perf header attribute\n");
2413 return err;
2414 }
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002415 }
2416
Adrian Hunterd645c442013-12-11 14:36:28 +02002417 if (!header->data_offset)
2418 header->data_offset = lseek(fd, 0, SEEK_CUR);
Jiri Olsa8d541e92013-07-17 19:49:44 +02002419 header->feat_offset = header->data_offset + header->data_size;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002420
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -02002421 if (at_exit) {
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002422 err = perf_header__adds_write(header, evlist, fd);
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -02002423 if (err < 0)
2424 return err;
2425 }
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002426
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002427 f_header = (struct perf_file_header){
2428 .magic = PERF_MAGIC,
2429 .size = sizeof(f_header),
2430 .attr_size = sizeof(f_attr),
2431 .attrs = {
Jiri Olsa944d62b2013-07-17 19:49:43 +02002432 .offset = attr_offset,
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002433 .size = evlist->nr_entries * sizeof(f_attr),
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002434 },
2435 .data = {
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002436 .offset = header->data_offset,
2437 .size = header->data_size,
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002438 },
Jiri Olsa44b3c572013-07-11 17:28:31 +02002439 /* event_types is ignored, store zeros */
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002440 };
2441
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002442 memcpy(&f_header.adds_features, &header->adds_features, sizeof(header->adds_features));
Frederic Weisbecker2ba08252009-10-17 17:12:34 +02002443
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002444 lseek(fd, 0, SEEK_SET);
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -02002445 err = do_write(fd, &f_header, sizeof(f_header));
2446 if (err < 0) {
2447 pr_debug("failed to write perf header\n");
2448 return err;
2449 }
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002450 lseek(fd, header->data_offset + header->data_size, SEEK_SET);
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002451
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -02002452 return 0;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002453}
2454
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002455static int perf_header__getbuffer64(struct perf_header *header,
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -02002456 int fd, void *buf, size_t size)
2457{
Arnaldo Carvalho de Melo1e7972c2011-01-03 16:50:55 -02002458 if (readn(fd, buf, size) <= 0)
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -02002459 return -1;
2460
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002461 if (header->needs_swap)
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -02002462 mem_bswap_64(buf, size);
2463
2464 return 0;
2465}
2466
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002467int perf_header__process_sections(struct perf_header *header, int fd,
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002468 void *data,
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002469 int (*process)(struct perf_file_section *section,
Robert Richterb1e5a9b2011-12-07 10:02:57 +01002470 struct perf_header *ph,
2471 int feat, int fd, void *data))
Frederic Weisbecker2ba08252009-10-17 17:12:34 +02002472{
Robert Richterb1e5a9b2011-12-07 10:02:57 +01002473 struct perf_file_section *feat_sec, *sec;
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002474 int nr_sections;
2475 int sec_size;
Robert Richterb1e5a9b2011-12-07 10:02:57 +01002476 int feat;
2477 int err;
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002478
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002479 nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS);
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002480 if (!nr_sections)
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002481 return 0;
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002482
Paul Gortmaker91b98802013-01-30 20:05:49 -05002483 feat_sec = sec = calloc(nr_sections, sizeof(*feat_sec));
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002484 if (!feat_sec)
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002485 return -1;
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002486
2487 sec_size = sizeof(*feat_sec) * nr_sections;
2488
Jiri Olsa8d541e92013-07-17 19:49:44 +02002489 lseek(fd, header->feat_offset, SEEK_SET);
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002490
Robert Richterb1e5a9b2011-12-07 10:02:57 +01002491 err = perf_header__getbuffer64(header, fd, feat_sec, sec_size);
2492 if (err < 0)
Arnaldo Carvalho de Melo769885f2009-12-28 22:48:32 -02002493 goto out_free;
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002494
Robert Richterb1e5a9b2011-12-07 10:02:57 +01002495 for_each_set_bit(feat, header->adds_features, HEADER_LAST_FEATURE) {
2496 err = process(sec++, header, feat, fd, data);
2497 if (err < 0)
2498 goto out_free;
Frederic Weisbecker4778d2e2009-11-11 04:51:05 +01002499 }
Robert Richterb1e5a9b2011-12-07 10:02:57 +01002500 err = 0;
Arnaldo Carvalho de Melo769885f2009-12-28 22:48:32 -02002501out_free:
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002502 free(feat_sec);
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002503 return err;
Arnaldo Carvalho de Melo769885f2009-12-28 22:48:32 -02002504}
Frederic Weisbecker2ba08252009-10-17 17:12:34 +02002505
Stephane Eranian114382a2012-02-09 23:21:08 +01002506static const int attr_file_abi_sizes[] = {
2507 [0] = PERF_ATTR_SIZE_VER0,
2508 [1] = PERF_ATTR_SIZE_VER1,
Jiri Olsa239cc472012-08-07 15:20:42 +02002509 [2] = PERF_ATTR_SIZE_VER2,
Jiri Olsa0f6a3012012-08-07 15:20:45 +02002510 [3] = PERF_ATTR_SIZE_VER3,
Stephane Eranian6a21c0b2014-09-24 13:48:39 +02002511 [4] = PERF_ATTR_SIZE_VER4,
Stephane Eranian114382a2012-02-09 23:21:08 +01002512 0,
2513};
2514
2515/*
2516 * In the legacy file format, the magic number is not used to encode endianness.
2517 * hdr_sz was used to encode endianness. But given that hdr_sz can vary based
2518 * on ABI revisions, we need to try all combinations for all endianness to
2519 * detect the endianness.
2520 */
2521static int try_all_file_abis(uint64_t hdr_sz, struct perf_header *ph)
2522{
2523 uint64_t ref_size, attr_size;
2524 int i;
2525
2526 for (i = 0 ; attr_file_abi_sizes[i]; i++) {
2527 ref_size = attr_file_abi_sizes[i]
2528 + sizeof(struct perf_file_section);
2529 if (hdr_sz != ref_size) {
2530 attr_size = bswap_64(hdr_sz);
2531 if (attr_size != ref_size)
2532 continue;
2533
2534 ph->needs_swap = true;
2535 }
2536 pr_debug("ABI%d perf.data file detected, need_swap=%d\n",
2537 i,
2538 ph->needs_swap);
2539 return 0;
2540 }
2541 /* could not determine endianness */
2542 return -1;
2543}
2544
2545#define PERF_PIPE_HDR_VER0 16
2546
2547static const size_t attr_pipe_abi_sizes[] = {
2548 [0] = PERF_PIPE_HDR_VER0,
2549 0,
2550};
2551
2552/*
2553 * In the legacy pipe format, there is an implicit assumption that endiannesss
2554 * between host recording the samples, and host parsing the samples is the
2555 * same. This is not always the case given that the pipe output may always be
2556 * redirected into a file and analyzed on a different machine with possibly a
2557 * different endianness and perf_event ABI revsions in the perf tool itself.
2558 */
2559static int try_all_pipe_abis(uint64_t hdr_sz, struct perf_header *ph)
2560{
2561 u64 attr_size;
2562 int i;
2563
2564 for (i = 0 ; attr_pipe_abi_sizes[i]; i++) {
2565 if (hdr_sz != attr_pipe_abi_sizes[i]) {
2566 attr_size = bswap_64(hdr_sz);
2567 if (attr_size != hdr_sz)
2568 continue;
2569
2570 ph->needs_swap = true;
2571 }
2572 pr_debug("Pipe ABI%d perf.data file detected\n", i);
2573 return 0;
2574 }
2575 return -1;
2576}
2577
Feng Tange84ba4e2012-10-30 11:56:07 +08002578bool is_perf_magic(u64 magic)
2579{
2580 if (!memcmp(&magic, __perf_magic1, sizeof(magic))
2581 || magic == __perf_magic2
2582 || magic == __perf_magic2_sw)
2583 return true;
2584
2585 return false;
2586}
2587
Stephane Eranian114382a2012-02-09 23:21:08 +01002588static int check_magic_endian(u64 magic, uint64_t hdr_sz,
2589 bool is_pipe, struct perf_header *ph)
Stephane Eranian73323f52012-02-02 13:54:44 +01002590{
2591 int ret;
2592
2593 /* check for legacy format */
Stephane Eranian114382a2012-02-09 23:21:08 +01002594 ret = memcmp(&magic, __perf_magic1, sizeof(magic));
Stephane Eranian73323f52012-02-02 13:54:44 +01002595 if (ret == 0) {
Jiri Olsa2a08c3e2013-07-17 19:49:47 +02002596 ph->version = PERF_HEADER_VERSION_1;
Stephane Eranian73323f52012-02-02 13:54:44 +01002597 pr_debug("legacy perf.data format\n");
Stephane Eranian114382a2012-02-09 23:21:08 +01002598 if (is_pipe)
2599 return try_all_pipe_abis(hdr_sz, ph);
Stephane Eranian73323f52012-02-02 13:54:44 +01002600
Stephane Eranian114382a2012-02-09 23:21:08 +01002601 return try_all_file_abis(hdr_sz, ph);
Stephane Eranian73323f52012-02-02 13:54:44 +01002602 }
Stephane Eranian114382a2012-02-09 23:21:08 +01002603 /*
2604 * the new magic number serves two purposes:
2605 * - unique number to identify actual perf.data files
2606 * - encode endianness of file
2607 */
Namhyung Kimf7913972015-01-29 17:06:45 +09002608 ph->version = PERF_HEADER_VERSION_2;
Stephane Eranian73323f52012-02-02 13:54:44 +01002609
Stephane Eranian114382a2012-02-09 23:21:08 +01002610 /* check magic number with one endianness */
2611 if (magic == __perf_magic2)
Stephane Eranian73323f52012-02-02 13:54:44 +01002612 return 0;
2613
Stephane Eranian114382a2012-02-09 23:21:08 +01002614 /* check magic number with opposite endianness */
2615 if (magic != __perf_magic2_sw)
Stephane Eranian73323f52012-02-02 13:54:44 +01002616 return -1;
2617
2618 ph->needs_swap = true;
2619
2620 return 0;
2621}
2622
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002623int perf_file_header__read(struct perf_file_header *header,
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002624 struct perf_header *ph, int fd)
2625{
Jiri Olsa727ebd52013-11-28 11:30:14 +01002626 ssize_t ret;
Stephane Eranian73323f52012-02-02 13:54:44 +01002627
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002628 lseek(fd, 0, SEEK_SET);
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002629
Stephane Eranian73323f52012-02-02 13:54:44 +01002630 ret = readn(fd, header, sizeof(*header));
2631 if (ret <= 0)
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002632 return -1;
2633
Stephane Eranian114382a2012-02-09 23:21:08 +01002634 if (check_magic_endian(header->magic,
2635 header->attr_size, false, ph) < 0) {
2636 pr_debug("magic/endian check failed\n");
Stephane Eranian73323f52012-02-02 13:54:44 +01002637 return -1;
Stephane Eranian114382a2012-02-09 23:21:08 +01002638 }
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -02002639
Stephane Eranian73323f52012-02-02 13:54:44 +01002640 if (ph->needs_swap) {
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002641 mem_bswap_64(header, offsetof(struct perf_file_header,
Stephane Eranian73323f52012-02-02 13:54:44 +01002642 adds_features));
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -02002643 }
2644
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002645 if (header->size != sizeof(*header)) {
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002646 /* Support the previous format */
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002647 if (header->size == offsetof(typeof(*header), adds_features))
2648 bitmap_zero(header->adds_features, HEADER_FEAT_BITS);
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002649 else
2650 return -1;
David Ahernd327fa42011-10-18 17:34:01 -06002651 } else if (ph->needs_swap) {
David Ahernd327fa42011-10-18 17:34:01 -06002652 /*
2653 * feature bitmap is declared as an array of unsigned longs --
2654 * not good since its size can differ between the host that
2655 * generated the data file and the host analyzing the file.
2656 *
2657 * We need to handle endianness, but we don't know the size of
2658 * the unsigned long where the file was generated. Take a best
2659 * guess at determining it: try 64-bit swap first (ie., file
2660 * created on a 64-bit host), and check if the hostname feature
2661 * bit is set (this feature bit is forced on as of fbe96f2).
2662 * If the bit is not, undo the 64-bit swap and try a 32-bit
2663 * swap. If the hostname bit is still not set (e.g., older data
2664 * file), punt and fallback to the original behavior --
2665 * clearing all feature bits and setting buildid.
2666 */
David Ahern80c01202012-06-08 11:47:51 -03002667 mem_bswap_64(&header->adds_features,
2668 BITS_TO_U64(HEADER_FEAT_BITS));
David Ahernd327fa42011-10-18 17:34:01 -06002669
2670 if (!test_bit(HEADER_HOSTNAME, header->adds_features)) {
David Ahern80c01202012-06-08 11:47:51 -03002671 /* unswap as u64 */
2672 mem_bswap_64(&header->adds_features,
2673 BITS_TO_U64(HEADER_FEAT_BITS));
2674
2675 /* unswap as u32 */
2676 mem_bswap_32(&header->adds_features,
2677 BITS_TO_U32(HEADER_FEAT_BITS));
David Ahernd327fa42011-10-18 17:34:01 -06002678 }
2679
2680 if (!test_bit(HEADER_HOSTNAME, header->adds_features)) {
2681 bitmap_zero(header->adds_features, HEADER_FEAT_BITS);
2682 set_bit(HEADER_BUILD_ID, header->adds_features);
2683 }
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002684 }
2685
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002686 memcpy(&ph->adds_features, &header->adds_features,
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -02002687 sizeof(ph->adds_features));
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002688
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002689 ph->data_offset = header->data.offset;
2690 ph->data_size = header->data.size;
Jiri Olsa8d541e92013-07-17 19:49:44 +02002691 ph->feat_offset = header->data.offset + header->data.size;
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002692 return 0;
2693}
2694
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002695static int perf_file_section__process(struct perf_file_section *section,
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -02002696 struct perf_header *ph,
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -03002697 int feat, int fd, void *data)
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002698{
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002699 if (lseek(fd, section->offset, SEEK_SET) == (off_t)-1) {
Arnaldo Carvalho de Melo9486aa32011-01-22 20:37:02 -02002700 pr_debug("Failed to lseek to %" PRIu64 " offset for feature "
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002701 "%d, continuing...\n", section->offset, feat);
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002702 return 0;
2703 }
2704
Robert Richterb1e5a9b2011-12-07 10:02:57 +01002705 if (feat >= HEADER_LAST_FEATURE) {
2706 pr_debug("unknown feature %d, continuing...\n", feat);
2707 return 0;
2708 }
2709
Robert Richterf1c67db2012-02-10 15:41:56 +01002710 if (!feat_ops[feat].process)
2711 return 0;
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002712
Namhyung Kim3d7eb862012-09-24 17:15:01 +09002713 return feat_ops[feat].process(section, ph, fd, data);
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002714}
2715
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002716static int perf_file_header__read_pipe(struct perf_pipe_file_header *header,
Tom Zanussi454c4072010-05-01 01:41:20 -05002717 struct perf_header *ph, int fd,
2718 bool repipe)
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002719{
Jiri Olsa727ebd52013-11-28 11:30:14 +01002720 ssize_t ret;
Stephane Eranian73323f52012-02-02 13:54:44 +01002721
2722 ret = readn(fd, header, sizeof(*header));
2723 if (ret <= 0)
2724 return -1;
2725
Stephane Eranian114382a2012-02-09 23:21:08 +01002726 if (check_magic_endian(header->magic, header->size, true, ph) < 0) {
2727 pr_debug("endian/magic failed\n");
Tom Zanussi8dc58102010-04-01 23:59:15 -05002728 return -1;
Stephane Eranian114382a2012-02-09 23:21:08 +01002729 }
2730
2731 if (ph->needs_swap)
2732 header->size = bswap_64(header->size);
Tom Zanussi8dc58102010-04-01 23:59:15 -05002733
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002734 if (repipe && do_write(STDOUT_FILENO, header, sizeof(*header)) < 0)
Tom Zanussi454c4072010-05-01 01:41:20 -05002735 return -1;
2736
Tom Zanussi8dc58102010-04-01 23:59:15 -05002737 return 0;
2738}
2739
Jiri Olsad4339562013-07-17 19:49:41 +02002740static int perf_header__read_pipe(struct perf_session *session)
Tom Zanussi8dc58102010-04-01 23:59:15 -05002741{
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002742 struct perf_header *header = &session->header;
Tom Zanussi8dc58102010-04-01 23:59:15 -05002743 struct perf_pipe_file_header f_header;
2744
Jiri Olsacc9784bd2013-10-15 16:27:34 +02002745 if (perf_file_header__read_pipe(&f_header, header,
2746 perf_data_file__fd(session->file),
Tom Zanussi454c4072010-05-01 01:41:20 -05002747 session->repipe) < 0) {
Tom Zanussi8dc58102010-04-01 23:59:15 -05002748 pr_debug("incompatible file format\n");
2749 return -EINVAL;
2750 }
2751
Tom Zanussi8dc58102010-04-01 23:59:15 -05002752 return 0;
2753}
2754
Stephane Eranian69996df2012-02-09 23:21:06 +01002755static int read_attr(int fd, struct perf_header *ph,
2756 struct perf_file_attr *f_attr)
2757{
2758 struct perf_event_attr *attr = &f_attr->attr;
2759 size_t sz, left;
2760 size_t our_sz = sizeof(f_attr->attr);
Jiri Olsa727ebd52013-11-28 11:30:14 +01002761 ssize_t ret;
Stephane Eranian69996df2012-02-09 23:21:06 +01002762
2763 memset(f_attr, 0, sizeof(*f_attr));
2764
2765 /* read minimal guaranteed structure */
2766 ret = readn(fd, attr, PERF_ATTR_SIZE_VER0);
2767 if (ret <= 0) {
2768 pr_debug("cannot read %d bytes of header attr\n",
2769 PERF_ATTR_SIZE_VER0);
2770 return -1;
2771 }
2772
2773 /* on file perf_event_attr size */
2774 sz = attr->size;
Stephane Eranian114382a2012-02-09 23:21:08 +01002775
Stephane Eranian69996df2012-02-09 23:21:06 +01002776 if (ph->needs_swap)
2777 sz = bswap_32(sz);
2778
2779 if (sz == 0) {
2780 /* assume ABI0 */
2781 sz = PERF_ATTR_SIZE_VER0;
2782 } else if (sz > our_sz) {
2783 pr_debug("file uses a more recent and unsupported ABI"
2784 " (%zu bytes extra)\n", sz - our_sz);
2785 return -1;
2786 }
2787 /* what we have not yet read and that we know about */
2788 left = sz - PERF_ATTR_SIZE_VER0;
2789 if (left) {
2790 void *ptr = attr;
2791 ptr += PERF_ATTR_SIZE_VER0;
2792
2793 ret = readn(fd, ptr, left);
2794 }
2795 /* read perf_file_section, ids are read in caller */
2796 ret = readn(fd, &f_attr->ids, sizeof(f_attr->ids));
2797
2798 return ret <= 0 ? -1 : 0;
2799}
2800
Namhyung Kim831394b2012-09-06 11:10:46 +09002801static int perf_evsel__prepare_tracepoint_event(struct perf_evsel *evsel,
2802 struct pevent *pevent)
Arnaldo Carvalho de Melocb9dd492012-06-11 19:03:32 -03002803{
Namhyung Kim831394b2012-09-06 11:10:46 +09002804 struct event_format *event;
Arnaldo Carvalho de Melocb9dd492012-06-11 19:03:32 -03002805 char bf[128];
2806
Namhyung Kim831394b2012-09-06 11:10:46 +09002807 /* already prepared */
2808 if (evsel->tp_format)
2809 return 0;
2810
Namhyung Kim3dce2ce2013-03-21 16:18:48 +09002811 if (pevent == NULL) {
2812 pr_debug("broken or missing trace data\n");
2813 return -1;
2814 }
2815
Namhyung Kim831394b2012-09-06 11:10:46 +09002816 event = pevent_find_event(pevent, evsel->attr.config);
Namhyung Kima7619ae2013-04-18 21:24:16 +09002817 if (event == NULL) {
2818 pr_debug("cannot find event format for %d\n", (int)evsel->attr.config);
Arnaldo Carvalho de Melocb9dd492012-06-11 19:03:32 -03002819 return -1;
Namhyung Kima7619ae2013-04-18 21:24:16 +09002820 }
Arnaldo Carvalho de Melocb9dd492012-06-11 19:03:32 -03002821
Namhyung Kim831394b2012-09-06 11:10:46 +09002822 if (!evsel->name) {
2823 snprintf(bf, sizeof(bf), "%s:%s", event->system, event->name);
2824 evsel->name = strdup(bf);
2825 if (evsel->name == NULL)
2826 return -1;
2827 }
Arnaldo Carvalho de Melocb9dd492012-06-11 19:03:32 -03002828
Arnaldo Carvalho de Melofcf65bf2012-08-07 09:58:03 -03002829 evsel->tp_format = event;
Arnaldo Carvalho de Melocb9dd492012-06-11 19:03:32 -03002830 return 0;
2831}
2832
Namhyung Kim831394b2012-09-06 11:10:46 +09002833static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist,
2834 struct pevent *pevent)
Arnaldo Carvalho de Melocb9dd492012-06-11 19:03:32 -03002835{
2836 struct perf_evsel *pos;
2837
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -03002838 evlist__for_each_entry(evlist, pos) {
Namhyung Kim831394b2012-09-06 11:10:46 +09002839 if (pos->attr.type == PERF_TYPE_TRACEPOINT &&
2840 perf_evsel__prepare_tracepoint_event(pos, pevent))
Arnaldo Carvalho de Melocb9dd492012-06-11 19:03:32 -03002841 return -1;
2842 }
2843
2844 return 0;
2845}
2846
Jiri Olsad4339562013-07-17 19:49:41 +02002847int perf_session__read_header(struct perf_session *session)
Tom Zanussi8dc58102010-04-01 23:59:15 -05002848{
Jiri Olsacc9784bd2013-10-15 16:27:34 +02002849 struct perf_data_file *file = session->file;
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002850 struct perf_header *header = &session->header;
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -02002851 struct perf_file_header f_header;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002852 struct perf_file_attr f_attr;
2853 u64 f_id;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002854 int nr_attrs, nr_ids, i, j;
Jiri Olsacc9784bd2013-10-15 16:27:34 +02002855 int fd = perf_data_file__fd(file);
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002856
Namhyung Kim334fe7a2013-03-11 16:43:12 +09002857 session->evlist = perf_evlist__new();
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002858 if (session->evlist == NULL)
2859 return -ENOMEM;
2860
Kan Liang2c071442015-08-28 05:48:05 -04002861 session->evlist->env = &header->env;
Arnaldo Carvalho de Melo4cde9982015-09-09 12:25:00 -03002862 session->machines.host.env = &header->env;
Jiri Olsacc9784bd2013-10-15 16:27:34 +02002863 if (perf_data_file__is_pipe(file))
Jiri Olsad4339562013-07-17 19:49:41 +02002864 return perf_header__read_pipe(session);
Tom Zanussi8dc58102010-04-01 23:59:15 -05002865
Stephane Eranian69996df2012-02-09 23:21:06 +01002866 if (perf_file_header__read(&f_header, header, fd) < 0)
Arnaldo Carvalho de Melo4dc0a042009-11-19 14:55:55 -02002867 return -EINVAL;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002868
Namhyung Kimb314e5c2013-09-30 17:19:48 +09002869 /*
2870 * Sanity check that perf.data was written cleanly; data size is
2871 * initialized to 0 and updated only if the on_exit function is run.
2872 * If data size is still 0 then the file contains only partial
2873 * information. Just warn user and process it as much as it can.
2874 */
2875 if (f_header.data.size == 0) {
2876 pr_warning("WARNING: The %s file's data size field is 0 which is unexpected.\n"
2877 "Was the 'perf record' command properly terminated?\n",
Jiri Olsacc9784bd2013-10-15 16:27:34 +02002878 file->path);
Namhyung Kimb314e5c2013-09-30 17:19:48 +09002879 }
2880
Stephane Eranian69996df2012-02-09 23:21:06 +01002881 nr_attrs = f_header.attrs.size / f_header.attr_size;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002882 lseek(fd, f_header.attrs.offset, SEEK_SET);
2883
2884 for (i = 0; i < nr_attrs; i++) {
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002885 struct perf_evsel *evsel;
Peter Zijlstra1c222bc2009-08-06 20:57:41 +02002886 off_t tmp;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002887
Stephane Eranian69996df2012-02-09 23:21:06 +01002888 if (read_attr(fd, header, &f_attr) < 0)
Arnaldo Carvalho de Melo769885f2009-12-28 22:48:32 -02002889 goto out_errno;
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -02002890
David Ahern1060ab82015-04-09 16:15:46 -04002891 if (header->needs_swap) {
2892 f_attr.ids.size = bswap_64(f_attr.ids.size);
2893 f_attr.ids.offset = bswap_64(f_attr.ids.offset);
David Aherneda39132011-07-15 12:34:09 -06002894 perf_event__attr_swap(&f_attr.attr);
David Ahern1060ab82015-04-09 16:15:46 -04002895 }
David Aherneda39132011-07-15 12:34:09 -06002896
Peter Zijlstra1c222bc2009-08-06 20:57:41 +02002897 tmp = lseek(fd, 0, SEEK_CUR);
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -03002898 evsel = perf_evsel__new(&f_attr.attr);
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002899
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002900 if (evsel == NULL)
2901 goto out_delete_evlist;
Arnaldo Carvalho de Melo0807d2d2012-09-26 12:48:18 -03002902
2903 evsel->needs_swap = header->needs_swap;
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002904 /*
2905 * Do it before so that if perf_evsel__alloc_id fails, this
2906 * entry gets purged too at perf_evlist__delete().
2907 */
2908 perf_evlist__add(session->evlist, evsel);
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002909
2910 nr_ids = f_attr.ids.size / sizeof(u64);
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002911 /*
2912 * We don't have the cpu and thread maps on the header, so
2913 * for allocating the perf_sample_id table we fake 1 cpu and
2914 * hattr->ids threads.
2915 */
2916 if (perf_evsel__alloc_id(evsel, 1, nr_ids))
2917 goto out_delete_evlist;
2918
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002919 lseek(fd, f_attr.ids.offset, SEEK_SET);
2920
2921 for (j = 0; j < nr_ids; j++) {
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002922 if (perf_header__getbuffer64(header, fd, &f_id, sizeof(f_id)))
Arnaldo Carvalho de Melo769885f2009-12-28 22:48:32 -02002923 goto out_errno;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002924
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002925 perf_evlist__id_add(session->evlist, evsel, 0, j, f_id);
Arnaldo Carvalho de Melo4dc0a042009-11-19 14:55:55 -02002926 }
Arnaldo Carvalho de Melo11deb1f2009-11-17 01:18:09 -02002927
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002928 lseek(fd, tmp, SEEK_SET);
2929 }
2930
Arnaldo Carvalho de Melod04b35f2011-11-11 22:17:32 -02002931 symbol_conf.nr_events = nr_attrs;
2932
Jiri Olsa29f5ffd2013-12-03 14:09:23 +01002933 perf_header__process_sections(header, fd, &session->tevent,
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002934 perf_file_section__process);
Frederic Weisbecker4778d2e2009-11-11 04:51:05 +01002935
Namhyung Kim831394b2012-09-06 11:10:46 +09002936 if (perf_evlist__prepare_tracepoint_events(session->evlist,
Jiri Olsa29f5ffd2013-12-03 14:09:23 +01002937 session->tevent.pevent))
Arnaldo Carvalho de Melocb9dd492012-06-11 19:03:32 -03002938 goto out_delete_evlist;
2939
Arnaldo Carvalho de Melo4dc0a042009-11-19 14:55:55 -02002940 return 0;
Arnaldo Carvalho de Melo769885f2009-12-28 22:48:32 -02002941out_errno:
2942 return -errno;
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002943
2944out_delete_evlist:
2945 perf_evlist__delete(session->evlist);
2946 session->evlist = NULL;
2947 return -ENOMEM;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002948}
Frederic Weisbecker0d3a5c82009-08-16 20:56:37 +02002949
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -02002950int perf_event__synthesize_attr(struct perf_tool *tool,
Robert Richterf4d83432012-08-16 21:10:17 +02002951 struct perf_event_attr *attr, u32 ids, u64 *id,
Arnaldo Carvalho de Melo743eb862011-11-28 07:56:39 -02002952 perf_event__handler_t process)
Frederic Weisbecker0d3a5c82009-08-16 20:56:37 +02002953{
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -02002954 union perf_event *ev;
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05002955 size_t size;
2956 int err;
2957
2958 size = sizeof(struct perf_event_attr);
Irina Tirdea9ac3e482012-09-11 01:15:01 +03002959 size = PERF_ALIGN(size, sizeof(u64));
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05002960 size += sizeof(struct perf_event_header);
2961 size += ids * sizeof(u64);
2962
2963 ev = malloc(size);
2964
Chris Samuelce47dc52010-11-13 13:35:06 +11002965 if (ev == NULL)
2966 return -ENOMEM;
2967
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05002968 ev->attr.attr = *attr;
2969 memcpy(ev->attr.id, id, ids * sizeof(u64));
2970
2971 ev->attr.header.type = PERF_RECORD_HEADER_ATTR;
Robert Richterf4d83432012-08-16 21:10:17 +02002972 ev->attr.header.size = (u16)size;
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05002973
Robert Richterf4d83432012-08-16 21:10:17 +02002974 if (ev->attr.header.size == size)
2975 err = process(tool, ev, NULL, NULL);
2976 else
2977 err = -E2BIG;
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05002978
2979 free(ev);
2980
2981 return err;
2982}
2983
Jiri Olsaa6e52812015-10-25 15:51:37 +01002984static struct event_update_event *
2985event_update_event__new(size_t size, u64 type, u64 id)
2986{
2987 struct event_update_event *ev;
2988
2989 size += sizeof(*ev);
2990 size = PERF_ALIGN(size, sizeof(u64));
2991
2992 ev = zalloc(size);
2993 if (ev) {
2994 ev->header.type = PERF_RECORD_EVENT_UPDATE;
2995 ev->header.size = (u16)size;
2996 ev->type = type;
2997 ev->id = id;
2998 }
2999 return ev;
3000}
3001
3002int
3003perf_event__synthesize_event_update_unit(struct perf_tool *tool,
3004 struct perf_evsel *evsel,
3005 perf_event__handler_t process)
3006{
3007 struct event_update_event *ev;
3008 size_t size = strlen(evsel->unit);
3009 int err;
3010
3011 ev = event_update_event__new(size + 1, PERF_EVENT_UPDATE__UNIT, evsel->id[0]);
3012 if (ev == NULL)
3013 return -ENOMEM;
3014
3015 strncpy(ev->data, evsel->unit, size);
3016 err = process(tool, (union perf_event *)ev, NULL, NULL);
3017 free(ev);
3018 return err;
3019}
3020
Jiri Olsadaeecbc2015-10-25 15:51:38 +01003021int
3022perf_event__synthesize_event_update_scale(struct perf_tool *tool,
3023 struct perf_evsel *evsel,
3024 perf_event__handler_t process)
3025{
3026 struct event_update_event *ev;
3027 struct event_update_event_scale *ev_data;
3028 int err;
3029
3030 ev = event_update_event__new(sizeof(*ev_data), PERF_EVENT_UPDATE__SCALE, evsel->id[0]);
3031 if (ev == NULL)
3032 return -ENOMEM;
3033
3034 ev_data = (struct event_update_event_scale *) ev->data;
3035 ev_data->scale = evsel->scale;
3036 err = process(tool, (union perf_event*) ev, NULL, NULL);
3037 free(ev);
3038 return err;
3039}
3040
Jiri Olsa802c9042015-10-25 15:51:39 +01003041int
3042perf_event__synthesize_event_update_name(struct perf_tool *tool,
3043 struct perf_evsel *evsel,
3044 perf_event__handler_t process)
3045{
3046 struct event_update_event *ev;
3047 size_t len = strlen(evsel->name);
3048 int err;
3049
3050 ev = event_update_event__new(len + 1, PERF_EVENT_UPDATE__NAME, evsel->id[0]);
3051 if (ev == NULL)
3052 return -ENOMEM;
3053
3054 strncpy(ev->data, evsel->name, len);
3055 err = process(tool, (union perf_event*) ev, NULL, NULL);
3056 free(ev);
3057 return err;
3058}
Jiri Olsadaeecbc2015-10-25 15:51:38 +01003059
Jiri Olsa86ebb092015-10-25 15:51:40 +01003060int
3061perf_event__synthesize_event_update_cpus(struct perf_tool *tool,
3062 struct perf_evsel *evsel,
3063 perf_event__handler_t process)
3064{
3065 size_t size = sizeof(struct event_update_event);
3066 struct event_update_event *ev;
3067 int max, err;
3068 u16 type;
3069
3070 if (!evsel->own_cpus)
3071 return 0;
3072
3073 ev = cpu_map_data__alloc(evsel->own_cpus, &size, &type, &max);
3074 if (!ev)
3075 return -ENOMEM;
3076
3077 ev->header.type = PERF_RECORD_EVENT_UPDATE;
3078 ev->header.size = (u16)size;
3079 ev->type = PERF_EVENT_UPDATE__CPUS;
3080 ev->id = evsel->id[0];
3081
3082 cpu_map_data__synthesize((struct cpu_map_data *) ev->data,
3083 evsel->own_cpus,
3084 type, max);
3085
3086 err = process(tool, (union perf_event*) ev, NULL, NULL);
3087 free(ev);
3088 return err;
3089}
3090
Jiri Olsac853f932015-10-25 15:51:41 +01003091size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp)
3092{
3093 struct event_update_event *ev = &event->event_update;
3094 struct event_update_event_scale *ev_scale;
3095 struct event_update_event_cpus *ev_cpus;
3096 struct cpu_map *map;
3097 size_t ret;
3098
3099 ret = fprintf(fp, "\n... id: %" PRIu64 "\n", ev->id);
3100
3101 switch (ev->type) {
3102 case PERF_EVENT_UPDATE__SCALE:
3103 ev_scale = (struct event_update_event_scale *) ev->data;
3104 ret += fprintf(fp, "... scale: %f\n", ev_scale->scale);
3105 break;
3106 case PERF_EVENT_UPDATE__UNIT:
3107 ret += fprintf(fp, "... unit: %s\n", ev->data);
3108 break;
3109 case PERF_EVENT_UPDATE__NAME:
3110 ret += fprintf(fp, "... name: %s\n", ev->data);
3111 break;
3112 case PERF_EVENT_UPDATE__CPUS:
3113 ev_cpus = (struct event_update_event_cpus *) ev->data;
3114 ret += fprintf(fp, "... ");
3115
3116 map = cpu_map__new_data(&ev_cpus->cpus);
3117 if (map)
3118 ret += cpu_map__fprintf(map, fp);
3119 else
3120 ret += fprintf(fp, "failed to get cpus\n");
3121 break;
3122 default:
3123 ret += fprintf(fp, "... unknown type\n");
3124 break;
3125 }
3126
3127 return ret;
3128}
Jiri Olsa86ebb092015-10-25 15:51:40 +01003129
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -02003130int perf_event__synthesize_attrs(struct perf_tool *tool,
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -02003131 struct perf_session *session,
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03003132 perf_event__handler_t process)
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05003133{
Robert Richter6606f872012-08-16 21:10:19 +02003134 struct perf_evsel *evsel;
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03003135 int err = 0;
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05003136
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -03003137 evlist__for_each_entry(session->evlist, evsel) {
Robert Richter6606f872012-08-16 21:10:19 +02003138 err = perf_event__synthesize_attr(tool, &evsel->attr, evsel->ids,
3139 evsel->id, process);
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05003140 if (err) {
3141 pr_debug("failed to create perf header attribute\n");
3142 return err;
3143 }
3144 }
3145
3146 return err;
3147}
3148
Adrian Hunter47c3d102013-07-04 16:20:21 +03003149int perf_event__process_attr(struct perf_tool *tool __maybe_unused,
3150 union perf_event *event,
Arnaldo Carvalho de Melo10d0f082011-11-11 22:45:41 -02003151 struct perf_evlist **pevlist)
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05003152{
Robert Richterf4d83432012-08-16 21:10:17 +02003153 u32 i, ids, n_ids;
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03003154 struct perf_evsel *evsel;
Arnaldo Carvalho de Melo10d0f082011-11-11 22:45:41 -02003155 struct perf_evlist *evlist = *pevlist;
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05003156
Arnaldo Carvalho de Melo10d0f082011-11-11 22:45:41 -02003157 if (evlist == NULL) {
Namhyung Kim334fe7a2013-03-11 16:43:12 +09003158 *pevlist = evlist = perf_evlist__new();
Arnaldo Carvalho de Melo10d0f082011-11-11 22:45:41 -02003159 if (evlist == NULL)
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05003160 return -ENOMEM;
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05003161 }
3162
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -03003163 evsel = perf_evsel__new(&event->attr.attr);
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03003164 if (evsel == NULL)
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05003165 return -ENOMEM;
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05003166
Arnaldo Carvalho de Melo10d0f082011-11-11 22:45:41 -02003167 perf_evlist__add(evlist, evsel);
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03003168
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -02003169 ids = event->header.size;
3170 ids -= (void *)&event->attr.id - (void *)event;
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05003171 n_ids = ids / sizeof(u64);
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03003172 /*
3173 * We don't have the cpu and thread maps on the header, so
3174 * for allocating the perf_sample_id table we fake 1 cpu and
3175 * hattr->ids threads.
3176 */
3177 if (perf_evsel__alloc_id(evsel, 1, n_ids))
3178 return -ENOMEM;
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05003179
3180 for (i = 0; i < n_ids; i++) {
Arnaldo Carvalho de Melo10d0f082011-11-11 22:45:41 -02003181 perf_evlist__id_add(evlist, evsel, 0, i, event->attr.id[i]);
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05003182 }
3183
Adrian Hunter7e0d6fc2013-07-04 16:20:29 +03003184 symbol_conf.nr_events = evlist->nr_entries;
3185
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05003186 return 0;
3187}
Tom Zanussicd19a032010-04-01 23:59:20 -05003188
Jiri Olsaffe777252015-10-25 15:51:36 +01003189int perf_event__process_event_update(struct perf_tool *tool __maybe_unused,
3190 union perf_event *event,
3191 struct perf_evlist **pevlist)
3192{
3193 struct event_update_event *ev = &event->event_update;
Jiri Olsadaeecbc2015-10-25 15:51:38 +01003194 struct event_update_event_scale *ev_scale;
Jiri Olsa86ebb092015-10-25 15:51:40 +01003195 struct event_update_event_cpus *ev_cpus;
Jiri Olsaffe777252015-10-25 15:51:36 +01003196 struct perf_evlist *evlist;
3197 struct perf_evsel *evsel;
Jiri Olsa86ebb092015-10-25 15:51:40 +01003198 struct cpu_map *map;
Jiri Olsaffe777252015-10-25 15:51:36 +01003199
3200 if (!pevlist || *pevlist == NULL)
3201 return -EINVAL;
3202
3203 evlist = *pevlist;
3204
3205 evsel = perf_evlist__id2evsel(evlist, ev->id);
3206 if (evsel == NULL)
3207 return -EINVAL;
3208
Jiri Olsaa6e52812015-10-25 15:51:37 +01003209 switch (ev->type) {
3210 case PERF_EVENT_UPDATE__UNIT:
3211 evsel->unit = strdup(ev->data);
Jiri Olsadaeecbc2015-10-25 15:51:38 +01003212 break;
Jiri Olsa802c9042015-10-25 15:51:39 +01003213 case PERF_EVENT_UPDATE__NAME:
3214 evsel->name = strdup(ev->data);
3215 break;
Jiri Olsadaeecbc2015-10-25 15:51:38 +01003216 case PERF_EVENT_UPDATE__SCALE:
3217 ev_scale = (struct event_update_event_scale *) ev->data;
3218 evsel->scale = ev_scale->scale;
Arnaldo Carvalho de Melo8434a2e2017-02-08 21:57:22 -03003219 break;
Jiri Olsa86ebb092015-10-25 15:51:40 +01003220 case PERF_EVENT_UPDATE__CPUS:
3221 ev_cpus = (struct event_update_event_cpus *) ev->data;
3222
3223 map = cpu_map__new_data(&ev_cpus->cpus);
3224 if (map)
3225 evsel->own_cpus = map;
3226 else
3227 pr_err("failed to get event_update cpus\n");
Jiri Olsaa6e52812015-10-25 15:51:37 +01003228 default:
3229 break;
3230 }
3231
Jiri Olsaffe777252015-10-25 15:51:36 +01003232 return 0;
3233}
3234
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -02003235int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -02003236 struct perf_evlist *evlist,
Arnaldo Carvalho de Melo743eb862011-11-28 07:56:39 -02003237 perf_event__handler_t process)
Tom Zanussi92155452010-04-01 23:59:21 -05003238{
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -02003239 union perf_event ev;
Jiri Olsa29208e52011-10-20 15:59:43 +02003240 struct tracing_data *tdata;
Tom Zanussi92155452010-04-01 23:59:21 -05003241 ssize_t size = 0, aligned_size = 0, padding;
Irina Tirdea1d037ca2012-09-11 01:15:03 +03003242 int err __maybe_unused = 0;
Tom Zanussi92155452010-04-01 23:59:21 -05003243
Jiri Olsa29208e52011-10-20 15:59:43 +02003244 /*
3245 * We are going to store the size of the data followed
3246 * by the data contents. Since the fd descriptor is a pipe,
3247 * we cannot seek back to store the size of the data once
3248 * we know it. Instead we:
3249 *
3250 * - write the tracing data to the temp file
3251 * - get/write the data size to pipe
3252 * - write the tracing data from the temp file
3253 * to the pipe
3254 */
3255 tdata = tracing_data_get(&evlist->entries, fd, true);
3256 if (!tdata)
3257 return -1;
3258
Tom Zanussi92155452010-04-01 23:59:21 -05003259 memset(&ev, 0, sizeof(ev));
3260
3261 ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA;
Jiri Olsa29208e52011-10-20 15:59:43 +02003262 size = tdata->size;
Irina Tirdea9ac3e482012-09-11 01:15:01 +03003263 aligned_size = PERF_ALIGN(size, sizeof(u64));
Tom Zanussi92155452010-04-01 23:59:21 -05003264 padding = aligned_size - size;
3265 ev.tracing_data.header.size = sizeof(ev.tracing_data);
3266 ev.tracing_data.size = aligned_size;
3267
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -02003268 process(tool, &ev, NULL, NULL);
Tom Zanussi92155452010-04-01 23:59:21 -05003269
Jiri Olsa29208e52011-10-20 15:59:43 +02003270 /*
3271 * The put function will copy all the tracing data
3272 * stored in temp file to the pipe.
3273 */
3274 tracing_data_put(tdata);
3275
Tom Zanussi92155452010-04-01 23:59:21 -05003276 write_padded(fd, NULL, 0, padding);
3277
3278 return aligned_size;
3279}
3280
Adrian Hunter47c3d102013-07-04 16:20:21 +03003281int perf_event__process_tracing_data(struct perf_tool *tool __maybe_unused,
3282 union perf_event *event,
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -02003283 struct perf_session *session)
Tom Zanussi92155452010-04-01 23:59:21 -05003284{
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -02003285 ssize_t size_read, padding, size = event->tracing_data.size;
Jiri Olsacc9784bd2013-10-15 16:27:34 +02003286 int fd = perf_data_file__fd(session->file);
3287 off_t offset = lseek(fd, 0, SEEK_CUR);
Tom Zanussi92155452010-04-01 23:59:21 -05003288 char buf[BUFSIZ];
3289
3290 /* setup for reading amidst mmap */
Jiri Olsacc9784bd2013-10-15 16:27:34 +02003291 lseek(fd, offset + sizeof(struct tracing_data_event),
Tom Zanussi92155452010-04-01 23:59:21 -05003292 SEEK_SET);
3293
Jiri Olsa29f5ffd2013-12-03 14:09:23 +01003294 size_read = trace_report(fd, &session->tevent,
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -03003295 session->repipe);
Irina Tirdea9ac3e482012-09-11 01:15:01 +03003296 padding = PERF_ALIGN(size_read, sizeof(u64)) - size_read;
Tom Zanussi92155452010-04-01 23:59:21 -05003297
Jiri Olsacc9784bd2013-10-15 16:27:34 +02003298 if (readn(fd, buf, padding) < 0) {
Arnaldo Carvalho de Melo2caa48a2013-01-24 22:34:33 -03003299 pr_err("%s: reading input file", __func__);
3300 return -1;
3301 }
Tom Zanussi454c4072010-05-01 01:41:20 -05003302 if (session->repipe) {
3303 int retw = write(STDOUT_FILENO, buf, padding);
Arnaldo Carvalho de Melo2caa48a2013-01-24 22:34:33 -03003304 if (retw <= 0 || retw != padding) {
3305 pr_err("%s: repiping tracing data padding", __func__);
3306 return -1;
3307 }
Tom Zanussi454c4072010-05-01 01:41:20 -05003308 }
Tom Zanussi92155452010-04-01 23:59:21 -05003309
Arnaldo Carvalho de Melo2caa48a2013-01-24 22:34:33 -03003310 if (size_read + padding != size) {
3311 pr_err("%s: tracing data size mismatch", __func__);
3312 return -1;
3313 }
Tom Zanussi92155452010-04-01 23:59:21 -05003314
Namhyung Kim831394b2012-09-06 11:10:46 +09003315 perf_evlist__prepare_tracepoint_events(session->evlist,
Jiri Olsa29f5ffd2013-12-03 14:09:23 +01003316 session->tevent.pevent);
Arnaldo Carvalho de Melo8b6ee4c2012-08-07 23:36:16 -03003317
Tom Zanussi92155452010-04-01 23:59:21 -05003318 return size_read + padding;
3319}
Tom Zanussic7929e42010-04-01 23:59:22 -05003320
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -02003321int perf_event__synthesize_build_id(struct perf_tool *tool,
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -02003322 struct dso *pos, u16 misc,
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -02003323 perf_event__handler_t process,
Arnaldo Carvalho de Melo743eb862011-11-28 07:56:39 -02003324 struct machine *machine)
Tom Zanussic7929e42010-04-01 23:59:22 -05003325{
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -02003326 union perf_event ev;
Tom Zanussic7929e42010-04-01 23:59:22 -05003327 size_t len;
3328 int err = 0;
3329
3330 if (!pos->hit)
3331 return err;
3332
3333 memset(&ev, 0, sizeof(ev));
3334
3335 len = pos->long_name_len + 1;
Irina Tirdea9ac3e482012-09-11 01:15:01 +03003336 len = PERF_ALIGN(len, NAME_ALIGN);
Tom Zanussic7929e42010-04-01 23:59:22 -05003337 memcpy(&ev.build_id.build_id, pos->build_id, sizeof(pos->build_id));
3338 ev.build_id.header.type = PERF_RECORD_HEADER_BUILD_ID;
3339 ev.build_id.header.misc = misc;
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -03003340 ev.build_id.pid = machine->pid;
Tom Zanussic7929e42010-04-01 23:59:22 -05003341 ev.build_id.header.size = sizeof(ev.build_id) + len;
3342 memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len);
3343
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -02003344 err = process(tool, &ev, NULL, machine);
Tom Zanussic7929e42010-04-01 23:59:22 -05003345
3346 return err;
3347}
3348
Irina Tirdea1d037ca2012-09-11 01:15:03 +03003349int perf_event__process_build_id(struct perf_tool *tool __maybe_unused,
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -02003350 union perf_event *event,
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -02003351 struct perf_session *session)
Tom Zanussic7929e42010-04-01 23:59:22 -05003352{
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -02003353 __event_process_build_id(&event->build_id,
3354 event->build_id.filename,
Zhang, Yanmina1645ce2010-04-19 13:32:50 +08003355 session);
Tom Zanussic7929e42010-04-01 23:59:22 -05003356 return 0;
3357}