blob: ca73aa7be70820c4dd153af375a64a35080121b2 [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001// SPDX-License-Identifier: GPL-2.0
Arnaldo Carvalho de Meloa43783a2017-04-18 10:46:11 -03002#include <errno.h>
Arnaldo Carvalho de Melofd20e812017-04-17 15:23:08 -03003#include <inttypes.h>
Arnaldo Carvalho de Meloa9072bc2011-10-26 12:41:38 -02004#include "util.h"
Arnaldo Carvalho de Meloa0675582017-04-17 16:51:59 -03005#include "string2.h"
Arnaldo Carvalho de Melo391e4202017-04-19 18:51:14 -03006#include <sys/param.h>
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02007#include <sys/types.h>
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -02008#include <byteswap.h>
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02009#include <unistd.h>
10#include <stdio.h>
11#include <stdlib.h>
Arnaldo Carvalho de Melo03536312017-06-16 12:18:27 -030012#include <linux/compiler.h>
Frederic Weisbecker8671dab2009-11-11 04:51:03 +010013#include <linux/list.h>
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -020014#include <linux/kernel.h>
Robert Richterb1e5a9b2011-12-07 10:02:57 +010015#include <linux/bitops.h>
David Carrillo-Cisnerosa4d8c982017-07-17 21:25:46 -070016#include <linux/stringify.h>
Arnaldo Carvalho de Melo7a8ef4c2017-04-19 20:57:47 -030017#include <sys/stat.h>
Stephane Eranianfbe96f22011-09-30 15:40:40 +020018#include <sys/utsname.h>
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020019
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -020020#include "evlist.h"
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -030021#include "evsel.h"
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020022#include "header.h"
Arnaldo Carvalho de Melo98521b32017-04-25 15:45:35 -030023#include "memswap.h"
Frederic Weisbecker03456a12009-10-06 23:36:47 +020024#include "../perf.h"
25#include "trace-event.h"
Arnaldo Carvalho de Melo301a0b02009-12-13 19:50:25 -020026#include "session.h"
Frederic Weisbecker8671dab2009-11-11 04:51:03 +010027#include "symbol.h"
Frederic Weisbecker4778d2e2009-11-11 04:51:05 +010028#include "debug.h"
Stephane Eranianfbe96f22011-09-30 15:40:40 +020029#include "cpumap.h"
Robert Richter50a96672012-08-16 21:10:24 +020030#include "pmu.h"
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +020031#include "vdso.h"
Namhyung Kima1ae5652012-09-24 17:14:59 +090032#include "strbuf.h"
Jiri Olsaebb296c2012-10-27 23:18:28 +020033#include "build-id.h"
Jiri Olsacc9784bd2013-10-15 16:27:34 +020034#include "data.h"
Jiri Olsa720e98b2016-02-16 16:01:43 +010035#include <api/fs/fs.h>
36#include "asm/bug.h"
David Carrillo-Cisnerose9def1b2017-07-17 21:25:48 -070037#include "tool.h"
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020038
Arnaldo Carvalho de Melo3d689ed2017-04-17 16:10:49 -030039#include "sane_ctype.h"
40
Stephane Eranian73323f52012-02-02 13:54:44 +010041/*
42 * magic2 = "PERFILE2"
43 * must be a numerical value to let the endianness
44 * determine the memory layout. That way we are able
45 * to detect endianness when reading the perf.data file
46 * back.
47 *
48 * we check for legacy (PERFFILE) format.
49 */
50static const char *__perf_magic1 = "PERFFILE";
51static const u64 __perf_magic2 = 0x32454c4946524550ULL;
52static const u64 __perf_magic2_sw = 0x50455246494c4532ULL;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020053
Stephane Eranian73323f52012-02-02 13:54:44 +010054#define PERF_MAGIC __perf_magic2
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020055
Soramichi AKIYAMAd25ed5d2017-01-17 00:22:37 +090056const char perf_version_string[] = PERF_VERSION;
57
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020058struct perf_file_attr {
Ingo Molnarcdd6c482009-09-21 12:02:48 +020059 struct perf_event_attr attr;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020060 struct perf_file_section ids;
61};
62
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -070063struct feat_fd {
64 struct perf_header *ph;
65 int fd;
David Carrillo-Cisneros0b3d3412017-07-17 21:25:45 -070066 void *buf; /* Either buf != NULL or fd >= 0 */
David Carrillo-Cisneros62552452017-07-17 21:25:42 -070067 ssize_t offset;
68 size_t size;
David Carrillo-Cisnerosf9ebdcc2017-07-17 21:25:49 -070069 struct perf_evsel *events;
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -070070};
71
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -030072void perf_header__set_feat(struct perf_header *header, int feat)
Arnaldo Carvalho de Melo8d063672009-11-04 18:50:43 -020073{
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -030074 set_bit(feat, header->adds_features);
Arnaldo Carvalho de Melo8d063672009-11-04 18:50:43 -020075}
76
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -030077void perf_header__clear_feat(struct perf_header *header, int feat)
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -020078{
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -030079 clear_bit(feat, header->adds_features);
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -020080}
81
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -030082bool perf_header__has_feat(const struct perf_header *header, int feat)
Arnaldo Carvalho de Melo8d063672009-11-04 18:50:43 -020083{
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -030084 return test_bit(feat, header->adds_features);
Arnaldo Carvalho de Melo8d063672009-11-04 18:50:43 -020085}
86
David Carrillo-Cisneros0b3d3412017-07-17 21:25:45 -070087static int __do_write_fd(struct feat_fd *ff, const void *buf, size_t size)
88{
89 ssize_t ret = writen(ff->fd, buf, size);
90
91 if (ret != (ssize_t)size)
92 return ret < 0 ? (int)ret : -1;
93 return 0;
94}
95
96static int __do_write_buf(struct feat_fd *ff, const void *buf, size_t size)
97{
98 /* struct perf_event_header::size is u16 */
99 const size_t max_size = 0xffff - sizeof(struct perf_event_header);
100 size_t new_size = ff->size;
101 void *addr;
102
103 if (size + ff->offset > max_size)
104 return -E2BIG;
105
106 while (size > (new_size - ff->offset))
107 new_size <<= 1;
108 new_size = min(max_size, new_size);
109
110 if (ff->size < new_size) {
111 addr = realloc(ff->buf, new_size);
112 if (!addr)
113 return -ENOMEM;
114 ff->buf = addr;
115 ff->size = new_size;
116 }
117
118 memcpy(ff->buf + ff->offset, buf, size);
119 ff->offset += size;
120
121 return 0;
122}
123
David Carrillo-Cisneros2ff53652017-07-17 21:25:36 -0700124/* Return: 0 if succeded, -ERR if failed. */
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700125int do_write(struct feat_fd *ff, const void *buf, size_t size)
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +0200126{
David Carrillo-Cisneros0b3d3412017-07-17 21:25:45 -0700127 if (!ff->buf)
128 return __do_write_fd(ff, buf, size);
129 return __do_write_buf(ff, buf, size);
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +0200130}
131
David Carrillo-Cisneros2ff53652017-07-17 21:25:36 -0700132/* Return: 0 if succeded, -ERR if failed. */
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700133int write_padded(struct feat_fd *ff, const void *bf,
134 size_t count, size_t count_aligned)
Arnaldo Carvalho de Melof92cb242010-01-04 16:19:28 -0200135{
136 static const char zero_buf[NAME_ALIGN];
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700137 int err = do_write(ff, bf, count);
Arnaldo Carvalho de Melof92cb242010-01-04 16:19:28 -0200138
139 if (!err)
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700140 err = do_write(ff, zero_buf, count_aligned - count);
Arnaldo Carvalho de Melof92cb242010-01-04 16:19:28 -0200141
142 return err;
143}
144
Kan Liang2bb00d22015-09-01 09:58:12 -0400145#define string_size(str) \
146 (PERF_ALIGN((strlen(str) + 1), NAME_ALIGN) + sizeof(u32))
147
David Carrillo-Cisneros2ff53652017-07-17 21:25:36 -0700148/* Return: 0 if succeded, -ERR if failed. */
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700149static int do_write_string(struct feat_fd *ff, const char *str)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200150{
151 u32 len, olen;
152 int ret;
153
154 olen = strlen(str) + 1;
Irina Tirdea9ac3e482012-09-11 01:15:01 +0300155 len = PERF_ALIGN(olen, NAME_ALIGN);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200156
157 /* write len, incl. \0 */
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700158 ret = do_write(ff, &len, sizeof(len));
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200159 if (ret < 0)
160 return ret;
161
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700162 return write_padded(ff, str, olen, len);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200163}
164
David Carrillo-Cisneros0b3d3412017-07-17 21:25:45 -0700165static int __do_read_fd(struct feat_fd *ff, void *addr, ssize_t size)
David Carrillo-Cisneros6200e4942017-07-17 21:25:34 -0700166{
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -0700167 ssize_t ret = readn(ff->fd, addr, size);
David Carrillo-Cisneros6200e4942017-07-17 21:25:34 -0700168
169 if (ret != size)
170 return ret < 0 ? (int)ret : -1;
171 return 0;
172}
173
David Carrillo-Cisneros0b3d3412017-07-17 21:25:45 -0700174static int __do_read_buf(struct feat_fd *ff, void *addr, ssize_t size)
175{
176 if (size > (ssize_t)ff->size - ff->offset)
177 return -1;
178
179 memcpy(addr, ff->buf + ff->offset, size);
180 ff->offset += size;
181
182 return 0;
183
184}
185
186static int __do_read(struct feat_fd *ff, void *addr, ssize_t size)
187{
188 if (!ff->buf)
189 return __do_read_fd(ff, addr, size);
190 return __do_read_buf(ff, addr, size);
191}
192
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -0700193static int do_read_u32(struct feat_fd *ff, u32 *addr)
David Carrillo-Cisneros6200e4942017-07-17 21:25:34 -0700194{
195 int ret;
196
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -0700197 ret = __do_read(ff, addr, sizeof(*addr));
David Carrillo-Cisneros6200e4942017-07-17 21:25:34 -0700198 if (ret)
199 return ret;
200
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -0700201 if (ff->ph->needs_swap)
David Carrillo-Cisneros6200e4942017-07-17 21:25:34 -0700202 *addr = bswap_32(*addr);
203 return 0;
204}
205
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -0700206static int do_read_u64(struct feat_fd *ff, u64 *addr)
David Carrillo-Cisneros6200e4942017-07-17 21:25:34 -0700207{
208 int ret;
209
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -0700210 ret = __do_read(ff, addr, sizeof(*addr));
David Carrillo-Cisneros6200e4942017-07-17 21:25:34 -0700211 if (ret)
212 return ret;
213
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -0700214 if (ff->ph->needs_swap)
David Carrillo-Cisneros6200e4942017-07-17 21:25:34 -0700215 *addr = bswap_64(*addr);
216 return 0;
217}
218
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -0700219static char *do_read_string(struct feat_fd *ff)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200220{
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200221 u32 len;
222 char *buf;
223
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -0700224 if (do_read_u32(ff, &len))
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200225 return NULL;
226
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200227 buf = malloc(len);
228 if (!buf)
229 return NULL;
230
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -0700231 if (!__do_read(ff, buf, len)) {
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200232 /*
233 * strings are padded by zeroes
234 * thus the actual strlen of buf
235 * may be less than len
236 */
237 return buf;
238 }
239
240 free(buf);
241 return NULL;
242}
243
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700244static int write_tracing_data(struct feat_fd *ff,
245 struct perf_evlist *evlist)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200246{
David Carrillo-Cisneros0b3d3412017-07-17 21:25:45 -0700247 if (WARN(ff->buf, "Error: calling %s in pipe-mode.\n", __func__))
248 return -1;
249
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700250 return read_tracing_data(ff->fd, &evlist->entries);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200251}
252
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700253static int write_build_id(struct feat_fd *ff,
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300254 struct perf_evlist *evlist __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200255{
256 struct perf_session *session;
257 int err;
258
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700259 session = container_of(ff->ph, struct perf_session, header);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200260
Robert Richtere20960c2011-12-07 10:02:55 +0100261 if (!perf_session__read_build_ids(session, true))
262 return -1;
263
David Carrillo-Cisneros0b3d3412017-07-17 21:25:45 -0700264 if (WARN(ff->buf, "Error: calling %s in pipe-mode.\n", __func__))
265 return -1;
266
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700267 err = perf_session__write_buildid_table(session, ff);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200268 if (err < 0) {
269 pr_debug("failed to write buildid table\n");
270 return err;
271 }
Namhyung Kim73c5d222014-11-07 22:57:56 +0900272 perf_session__cache_build_ids(session);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200273
274 return 0;
275}
276
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700277static int write_hostname(struct feat_fd *ff,
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300278 struct perf_evlist *evlist __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200279{
280 struct utsname uts;
281 int ret;
282
283 ret = uname(&uts);
284 if (ret < 0)
285 return -1;
286
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700287 return do_write_string(ff, uts.nodename);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200288}
289
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700290static int write_osrelease(struct feat_fd *ff,
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300291 struct perf_evlist *evlist __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200292{
293 struct utsname uts;
294 int ret;
295
296 ret = uname(&uts);
297 if (ret < 0)
298 return -1;
299
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700300 return do_write_string(ff, uts.release);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200301}
302
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700303static int write_arch(struct feat_fd *ff,
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300304 struct perf_evlist *evlist __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200305{
306 struct utsname uts;
307 int ret;
308
309 ret = uname(&uts);
310 if (ret < 0)
311 return -1;
312
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700313 return do_write_string(ff, uts.machine);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200314}
315
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700316static int write_version(struct feat_fd *ff,
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300317 struct perf_evlist *evlist __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200318{
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700319 return do_write_string(ff, perf_version_string);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200320}
321
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700322static int __write_cpudesc(struct feat_fd *ff, const char *cpuinfo_proc)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200323{
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200324 FILE *file;
325 char *buf = NULL;
326 char *s, *p;
Wang Nan493c3032014-10-24 09:45:26 +0800327 const char *search = cpuinfo_proc;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200328 size_t len = 0;
329 int ret = -1;
330
331 if (!search)
332 return -1;
333
334 file = fopen("/proc/cpuinfo", "r");
335 if (!file)
336 return -1;
337
338 while (getline(&buf, &len, file) > 0) {
339 ret = strncmp(buf, search, strlen(search));
340 if (!ret)
341 break;
342 }
343
Wang Naned307752014-10-16 11:08:29 +0800344 if (ret) {
345 ret = -1;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200346 goto done;
Wang Naned307752014-10-16 11:08:29 +0800347 }
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200348
349 s = buf;
350
351 p = strchr(buf, ':');
352 if (p && *(p+1) == ' ' && *(p+2))
353 s = p + 2;
354 p = strchr(s, '\n');
355 if (p)
356 *p = '\0';
357
358 /* squash extra space characters (branding string) */
359 p = s;
360 while (*p) {
361 if (isspace(*p)) {
362 char *r = p + 1;
363 char *q = r;
364 *p = ' ';
365 while (*q && isspace(*q))
366 q++;
367 if (q != (p+1))
368 while ((*r++ = *q++));
369 }
370 p++;
371 }
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700372 ret = do_write_string(ff, s);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200373done:
374 free(buf);
375 fclose(file);
376 return ret;
377}
378
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700379static int write_cpudesc(struct feat_fd *ff,
Wang Nan493c3032014-10-24 09:45:26 +0800380 struct perf_evlist *evlist __maybe_unused)
381{
Wang Nan493c3032014-10-24 09:45:26 +0800382 const char *cpuinfo_procs[] = CPUINFO_PROC;
383 unsigned int i;
384
385 for (i = 0; i < ARRAY_SIZE(cpuinfo_procs); i++) {
386 int ret;
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700387 ret = __write_cpudesc(ff, cpuinfo_procs[i]);
Wang Nan493c3032014-10-24 09:45:26 +0800388 if (ret >= 0)
389 return ret;
390 }
391 return -1;
392}
393
394
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700395static int write_nrcpus(struct feat_fd *ff,
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300396 struct perf_evlist *evlist __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200397{
398 long nr;
399 u32 nrc, nra;
400 int ret;
401
Jan Stancekda8a58b2017-02-17 12:10:26 +0100402 nrc = cpu__max_present_cpu();
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200403
404 nr = sysconf(_SC_NPROCESSORS_ONLN);
405 if (nr < 0)
406 return -1;
407
408 nra = (u32)(nr & UINT_MAX);
409
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700410 ret = do_write(ff, &nrc, sizeof(nrc));
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200411 if (ret < 0)
412 return ret;
413
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700414 return do_write(ff, &nra, sizeof(nra));
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200415}
416
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700417static int write_event_desc(struct feat_fd *ff,
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200418 struct perf_evlist *evlist)
419{
Robert Richter6606f872012-08-16 21:10:19 +0200420 struct perf_evsel *evsel;
Namhyung Kim74ba9e12012-09-05 14:02:47 +0900421 u32 nre, nri, sz;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200422 int ret;
423
Namhyung Kim74ba9e12012-09-05 14:02:47 +0900424 nre = evlist->nr_entries;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200425
426 /*
427 * write number of events
428 */
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700429 ret = do_write(ff, &nre, sizeof(nre));
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200430 if (ret < 0)
431 return ret;
432
433 /*
434 * size of perf_event_attr struct
435 */
Robert Richter6606f872012-08-16 21:10:19 +0200436 sz = (u32)sizeof(evsel->attr);
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700437 ret = do_write(ff, &sz, sizeof(sz));
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200438 if (ret < 0)
439 return ret;
440
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -0300441 evlist__for_each_entry(evlist, evsel) {
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700442 ret = do_write(ff, &evsel->attr, sz);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200443 if (ret < 0)
444 return ret;
445 /*
446 * write number of unique id per event
447 * there is one id per instance of an event
448 *
449 * copy into an nri to be independent of the
450 * type of ids,
451 */
Robert Richter6606f872012-08-16 21:10:19 +0200452 nri = evsel->ids;
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700453 ret = do_write(ff, &nri, sizeof(nri));
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200454 if (ret < 0)
455 return ret;
456
457 /*
458 * write event string as passed on cmdline
459 */
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700460 ret = do_write_string(ff, perf_evsel__name(evsel));
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200461 if (ret < 0)
462 return ret;
463 /*
464 * write unique ids for this event
465 */
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700466 ret = do_write(ff, evsel->id, evsel->ids * sizeof(u64));
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200467 if (ret < 0)
468 return ret;
469 }
470 return 0;
471}
472
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700473static int write_cmdline(struct feat_fd *ff,
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300474 struct perf_evlist *evlist __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200475{
476 char buf[MAXPATHLEN];
Arnaldo Carvalho de Melob6998692015-09-08 16:58:20 -0300477 u32 n;
478 int i, ret;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200479
Tommi Rantala55f771282017-03-22 15:06:24 +0200480 /* actual path to perf binary */
481 ret = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200482 if (ret <= 0)
483 return -1;
484
485 /* readlink() does not add null termination */
486 buf[ret] = '\0';
487
488 /* account for binary path */
Arnaldo Carvalho de Melob6998692015-09-08 16:58:20 -0300489 n = perf_env.nr_cmdline + 1;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200490
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700491 ret = do_write(ff, &n, sizeof(n));
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200492 if (ret < 0)
493 return ret;
494
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700495 ret = do_write_string(ff, buf);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200496 if (ret < 0)
497 return ret;
498
Arnaldo Carvalho de Melob6998692015-09-08 16:58:20 -0300499 for (i = 0 ; i < perf_env.nr_cmdline; i++) {
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700500 ret = do_write_string(ff, perf_env.cmdline_argv[i]);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200501 if (ret < 0)
502 return ret;
503 }
504 return 0;
505}
506
507#define CORE_SIB_FMT \
508 "/sys/devices/system/cpu/cpu%d/topology/core_siblings_list"
509#define THRD_SIB_FMT \
510 "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list"
511
512struct cpu_topo {
Kan Liang2bb00d22015-09-01 09:58:12 -0400513 u32 cpu_nr;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200514 u32 core_sib;
515 u32 thread_sib;
516 char **core_siblings;
517 char **thread_siblings;
518};
519
520static int build_cpu_topo(struct cpu_topo *tp, int cpu)
521{
522 FILE *fp;
523 char filename[MAXPATHLEN];
524 char *buf = NULL, *p;
525 size_t len = 0;
Stephane Eranianc5885742013-08-14 12:04:26 +0200526 ssize_t sret;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200527 u32 i = 0;
528 int ret = -1;
529
530 sprintf(filename, CORE_SIB_FMT, cpu);
531 fp = fopen(filename, "r");
532 if (!fp)
Stephane Eranianc5885742013-08-14 12:04:26 +0200533 goto try_threads;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200534
Stephane Eranianc5885742013-08-14 12:04:26 +0200535 sret = getline(&buf, &len, fp);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200536 fclose(fp);
Stephane Eranianc5885742013-08-14 12:04:26 +0200537 if (sret <= 0)
538 goto try_threads;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200539
540 p = strchr(buf, '\n');
541 if (p)
542 *p = '\0';
543
544 for (i = 0; i < tp->core_sib; i++) {
545 if (!strcmp(buf, tp->core_siblings[i]))
546 break;
547 }
548 if (i == tp->core_sib) {
549 tp->core_siblings[i] = buf;
550 tp->core_sib++;
551 buf = NULL;
552 len = 0;
553 }
Stephane Eranianc5885742013-08-14 12:04:26 +0200554 ret = 0;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200555
Stephane Eranianc5885742013-08-14 12:04:26 +0200556try_threads:
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200557 sprintf(filename, THRD_SIB_FMT, cpu);
558 fp = fopen(filename, "r");
559 if (!fp)
560 goto done;
561
562 if (getline(&buf, &len, fp) <= 0)
563 goto done;
564
565 p = strchr(buf, '\n');
566 if (p)
567 *p = '\0';
568
569 for (i = 0; i < tp->thread_sib; i++) {
570 if (!strcmp(buf, tp->thread_siblings[i]))
571 break;
572 }
573 if (i == tp->thread_sib) {
574 tp->thread_siblings[i] = buf;
575 tp->thread_sib++;
576 buf = NULL;
577 }
578 ret = 0;
579done:
580 if(fp)
581 fclose(fp);
582 free(buf);
583 return ret;
584}
585
586static void free_cpu_topo(struct cpu_topo *tp)
587{
588 u32 i;
589
590 if (!tp)
591 return;
592
593 for (i = 0 ; i < tp->core_sib; i++)
Arnaldo Carvalho de Melo74cf2492013-12-27 16:55:14 -0300594 zfree(&tp->core_siblings[i]);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200595
596 for (i = 0 ; i < tp->thread_sib; i++)
Arnaldo Carvalho de Melo74cf2492013-12-27 16:55:14 -0300597 zfree(&tp->thread_siblings[i]);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200598
599 free(tp);
600}
601
602static struct cpu_topo *build_cpu_topology(void)
603{
Jan Stancek43db2842017-02-17 12:10:25 +0100604 struct cpu_topo *tp = NULL;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200605 void *addr;
606 u32 nr, i;
Arnaldo Carvalho de Meloaa36ddd2015-09-09 10:37:01 -0300607 size_t sz;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200608 long ncpus;
609 int ret = -1;
Jan Stancek43db2842017-02-17 12:10:25 +0100610 struct cpu_map *map;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200611
Jan Stancekda8a58b2017-02-17 12:10:26 +0100612 ncpus = cpu__max_present_cpu();
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200613
Jan Stancek43db2842017-02-17 12:10:25 +0100614 /* build online CPU map */
615 map = cpu_map__new(NULL);
616 if (map == NULL) {
617 pr_debug("failed to get system cpumap\n");
618 return NULL;
619 }
620
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200621 nr = (u32)(ncpus & UINT_MAX);
622
623 sz = nr * sizeof(char *);
Arnaldo Carvalho de Meloaa36ddd2015-09-09 10:37:01 -0300624 addr = calloc(1, sizeof(*tp) + 2 * sz);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200625 if (!addr)
Jan Stancek43db2842017-02-17 12:10:25 +0100626 goto out_free;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200627
628 tp = addr;
Kan Liang2bb00d22015-09-01 09:58:12 -0400629 tp->cpu_nr = nr;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200630 addr += sizeof(*tp);
631 tp->core_siblings = addr;
632 addr += sz;
633 tp->thread_siblings = addr;
634
635 for (i = 0; i < nr; i++) {
Jan Stancek43db2842017-02-17 12:10:25 +0100636 if (!cpu_map__has(map, i))
637 continue;
638
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200639 ret = build_cpu_topo(tp, i);
640 if (ret < 0)
641 break;
642 }
Jan Stancek43db2842017-02-17 12:10:25 +0100643
644out_free:
645 cpu_map__put(map);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200646 if (ret) {
647 free_cpu_topo(tp);
648 tp = NULL;
649 }
650 return tp;
651}
652
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700653static int write_cpu_topology(struct feat_fd *ff,
654 struct perf_evlist *evlist __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200655{
656 struct cpu_topo *tp;
657 u32 i;
Arnaldo Carvalho de Meloaa36ddd2015-09-09 10:37:01 -0300658 int ret, j;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200659
660 tp = build_cpu_topology();
661 if (!tp)
662 return -1;
663
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700664 ret = do_write(ff, &tp->core_sib, sizeof(tp->core_sib));
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200665 if (ret < 0)
666 goto done;
667
668 for (i = 0; i < tp->core_sib; i++) {
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700669 ret = do_write_string(ff, tp->core_siblings[i]);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200670 if (ret < 0)
671 goto done;
672 }
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700673 ret = do_write(ff, &tp->thread_sib, sizeof(tp->thread_sib));
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200674 if (ret < 0)
675 goto done;
676
677 for (i = 0; i < tp->thread_sib; i++) {
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700678 ret = do_write_string(ff, tp->thread_siblings[i]);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200679 if (ret < 0)
680 break;
681 }
Kan Liang2bb00d22015-09-01 09:58:12 -0400682
Arnaldo Carvalho de Meloaa36ddd2015-09-09 10:37:01 -0300683 ret = perf_env__read_cpu_topology_map(&perf_env);
684 if (ret < 0)
685 goto done;
686
687 for (j = 0; j < perf_env.nr_cpus_avail; j++) {
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700688 ret = do_write(ff, &perf_env.cpu[j].core_id,
Arnaldo Carvalho de Meloaa36ddd2015-09-09 10:37:01 -0300689 sizeof(perf_env.cpu[j].core_id));
Kan Liang2bb00d22015-09-01 09:58:12 -0400690 if (ret < 0)
691 return ret;
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700692 ret = do_write(ff, &perf_env.cpu[j].socket_id,
Arnaldo Carvalho de Meloaa36ddd2015-09-09 10:37:01 -0300693 sizeof(perf_env.cpu[j].socket_id));
Kan Liang2bb00d22015-09-01 09:58:12 -0400694 if (ret < 0)
695 return ret;
696 }
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200697done:
698 free_cpu_topo(tp);
699 return ret;
700}
701
702
703
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700704static int write_total_mem(struct feat_fd *ff,
705 struct perf_evlist *evlist __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200706{
707 char *buf = NULL;
708 FILE *fp;
709 size_t len = 0;
710 int ret = -1, n;
711 uint64_t mem;
712
713 fp = fopen("/proc/meminfo", "r");
714 if (!fp)
715 return -1;
716
717 while (getline(&buf, &len, fp) > 0) {
718 ret = strncmp(buf, "MemTotal:", 9);
719 if (!ret)
720 break;
721 }
722 if (!ret) {
723 n = sscanf(buf, "%*s %"PRIu64, &mem);
724 if (n == 1)
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700725 ret = do_write(ff, &mem, sizeof(mem));
Wang Naned307752014-10-16 11:08:29 +0800726 } else
727 ret = -1;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200728 free(buf);
729 fclose(fp);
730 return ret;
731}
732
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700733static int write_topo_node(struct feat_fd *ff, int node)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200734{
735 char str[MAXPATHLEN];
736 char field[32];
737 char *buf = NULL, *p;
738 size_t len = 0;
739 FILE *fp;
740 u64 mem_total, mem_free, mem;
741 int ret = -1;
742
743 sprintf(str, "/sys/devices/system/node/node%d/meminfo", node);
744 fp = fopen(str, "r");
745 if (!fp)
746 return -1;
747
748 while (getline(&buf, &len, fp) > 0) {
749 /* skip over invalid lines */
750 if (!strchr(buf, ':'))
751 continue;
Alan Coxa761a2d2014-01-20 19:10:11 +0100752 if (sscanf(buf, "%*s %*d %31s %"PRIu64, field, &mem) != 2)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200753 goto done;
754 if (!strcmp(field, "MemTotal:"))
755 mem_total = mem;
756 if (!strcmp(field, "MemFree:"))
757 mem_free = mem;
758 }
759
760 fclose(fp);
Thomas Jarosch5809fde2013-01-28 10:21:14 +0100761 fp = NULL;
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200762
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700763 ret = do_write(ff, &mem_total, sizeof(u64));
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200764 if (ret)
765 goto done;
766
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700767 ret = do_write(ff, &mem_free, sizeof(u64));
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200768 if (ret)
769 goto done;
770
771 ret = -1;
772 sprintf(str, "/sys/devices/system/node/node%d/cpulist", node);
773
774 fp = fopen(str, "r");
775 if (!fp)
776 goto done;
777
778 if (getline(&buf, &len, fp) <= 0)
779 goto done;
780
781 p = strchr(buf, '\n');
782 if (p)
783 *p = '\0';
784
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700785 ret = do_write_string(ff, buf);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200786done:
787 free(buf);
Thomas Jarosch5809fde2013-01-28 10:21:14 +0100788 if (fp)
789 fclose(fp);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200790 return ret;
791}
792
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700793static int write_numa_topology(struct feat_fd *ff,
794 struct perf_evlist *evlist __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200795{
796 char *buf = NULL;
797 size_t len = 0;
798 FILE *fp;
799 struct cpu_map *node_map = NULL;
800 char *c;
801 u32 nr, i, j;
802 int ret = -1;
803
804 fp = fopen("/sys/devices/system/node/online", "r");
805 if (!fp)
806 return -1;
807
808 if (getline(&buf, &len, fp) <= 0)
809 goto done;
810
811 c = strchr(buf, '\n');
812 if (c)
813 *c = '\0';
814
815 node_map = cpu_map__new(buf);
816 if (!node_map)
817 goto done;
818
819 nr = (u32)node_map->nr;
820
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700821 ret = do_write(ff, &nr, sizeof(nr));
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200822 if (ret < 0)
823 goto done;
824
825 for (i = 0; i < nr; i++) {
826 j = (u32)node_map->map[i];
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700827 ret = do_write(ff, &j, sizeof(j));
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200828 if (ret < 0)
829 break;
830
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700831 ret = write_topo_node(ff, i);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200832 if (ret < 0)
833 break;
834 }
835done:
836 free(buf);
837 fclose(fp);
Masami Hiramatsu5191d8872015-12-09 11:11:35 +0900838 cpu_map__put(node_map);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200839 return ret;
840}
841
842/*
Robert Richter50a96672012-08-16 21:10:24 +0200843 * File format:
844 *
845 * struct pmu_mappings {
846 * u32 pmu_num;
847 * struct pmu_map {
848 * u32 type;
849 * char name[];
850 * }[pmu_num];
851 * };
852 */
853
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700854static int write_pmu_mappings(struct feat_fd *ff,
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300855 struct perf_evlist *evlist __maybe_unused)
Robert Richter50a96672012-08-16 21:10:24 +0200856{
857 struct perf_pmu *pmu = NULL;
David Carrillo-Cisnerosa02c3952017-07-17 21:25:44 -0700858 u32 pmu_num = 0;
Namhyung Kim5323f602012-12-17 15:38:54 +0900859 int ret;
Robert Richter50a96672012-08-16 21:10:24 +0200860
David Carrillo-Cisnerosa02c3952017-07-17 21:25:44 -0700861 /*
862 * Do a first pass to count number of pmu to avoid lseek so this
863 * works in pipe mode as well.
864 */
865 while ((pmu = perf_pmu__scan(pmu))) {
866 if (!pmu->name)
867 continue;
868 pmu_num++;
869 }
870
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700871 ret = do_write(ff, &pmu_num, sizeof(pmu_num));
Namhyung Kim5323f602012-12-17 15:38:54 +0900872 if (ret < 0)
873 return ret;
Robert Richter50a96672012-08-16 21:10:24 +0200874
875 while ((pmu = perf_pmu__scan(pmu))) {
876 if (!pmu->name)
877 continue;
Namhyung Kim5323f602012-12-17 15:38:54 +0900878
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700879 ret = do_write(ff, &pmu->type, sizeof(pmu->type));
Namhyung Kim5323f602012-12-17 15:38:54 +0900880 if (ret < 0)
881 return ret;
882
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700883 ret = do_write_string(ff, pmu->name);
Namhyung Kim5323f602012-12-17 15:38:54 +0900884 if (ret < 0)
885 return ret;
Robert Richter50a96672012-08-16 21:10:24 +0200886 }
887
Robert Richter50a96672012-08-16 21:10:24 +0200888 return 0;
889}
890
891/*
Namhyung Kima8bb5592013-01-22 18:09:31 +0900892 * File format:
893 *
894 * struct group_descs {
895 * u32 nr_groups;
896 * struct group_desc {
897 * char name[];
898 * u32 leader_idx;
899 * u32 nr_members;
900 * }[nr_groups];
901 * };
902 */
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700903static int write_group_desc(struct feat_fd *ff,
Namhyung Kima8bb5592013-01-22 18:09:31 +0900904 struct perf_evlist *evlist)
905{
906 u32 nr_groups = evlist->nr_groups;
907 struct perf_evsel *evsel;
908 int ret;
909
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700910 ret = do_write(ff, &nr_groups, sizeof(nr_groups));
Namhyung Kima8bb5592013-01-22 18:09:31 +0900911 if (ret < 0)
912 return ret;
913
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -0300914 evlist__for_each_entry(evlist, evsel) {
Namhyung Kima8bb5592013-01-22 18:09:31 +0900915 if (perf_evsel__is_group_leader(evsel) &&
916 evsel->nr_members > 1) {
917 const char *name = evsel->group_name ?: "{anon_group}";
918 u32 leader_idx = evsel->idx;
919 u32 nr_members = evsel->nr_members;
920
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700921 ret = do_write_string(ff, name);
Namhyung Kima8bb5592013-01-22 18:09:31 +0900922 if (ret < 0)
923 return ret;
924
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700925 ret = do_write(ff, &leader_idx, sizeof(leader_idx));
Namhyung Kima8bb5592013-01-22 18:09:31 +0900926 if (ret < 0)
927 return ret;
928
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700929 ret = do_write(ff, &nr_members, sizeof(nr_members));
Namhyung Kima8bb5592013-01-22 18:09:31 +0900930 if (ret < 0)
931 return ret;
932 }
933 }
934 return 0;
935}
936
937/*
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200938 * default get_cpuid(): nothing gets recorded
Jiada Wang7a759cd2017-04-09 20:02:37 -0700939 * actual implementation must be in arch/$(SRCARCH)/util/header.c
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200940 */
Rui Teng11d8f872016-07-28 10:05:57 +0800941int __weak get_cpuid(char *buffer __maybe_unused, size_t sz __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200942{
943 return -1;
944}
945
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700946static int write_cpuid(struct feat_fd *ff,
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300947 struct perf_evlist *evlist __maybe_unused)
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200948{
949 char buffer[64];
950 int ret;
951
952 ret = get_cpuid(buffer, sizeof(buffer));
953 if (!ret)
954 goto write_it;
955
956 return -1;
957write_it:
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700958 return do_write_string(ff, buffer);
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200959}
960
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700961static int write_branch_stack(struct feat_fd *ff __maybe_unused,
962 struct perf_evlist *evlist __maybe_unused)
Stephane Eranian330aa672012-03-08 23:47:46 +0100963{
964 return 0;
965}
966
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700967static int write_auxtrace(struct feat_fd *ff,
Adrian Hunter4025ea42015-04-09 18:53:41 +0300968 struct perf_evlist *evlist __maybe_unused)
969{
Adrian Hunter99fa2982015-04-30 17:37:25 +0300970 struct perf_session *session;
971 int err;
972
David Carrillo-Cisneros0b3d3412017-07-17 21:25:45 -0700973 if (WARN(ff->buf, "Error: calling %s in pipe-mode.\n", __func__))
974 return -1;
975
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700976 session = container_of(ff->ph, struct perf_session, header);
Adrian Hunter99fa2982015-04-30 17:37:25 +0300977
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -0700978 err = auxtrace_index__write(ff->fd, &session->auxtrace_index);
Adrian Hunter99fa2982015-04-30 17:37:25 +0300979 if (err < 0)
980 pr_err("Failed to write auxtrace index\n");
981 return err;
Adrian Hunter4025ea42015-04-09 18:53:41 +0300982}
983
Jiri Olsa720e98b2016-02-16 16:01:43 +0100984static int cpu_cache_level__sort(const void *a, const void *b)
985{
986 struct cpu_cache_level *cache_a = (struct cpu_cache_level *)a;
987 struct cpu_cache_level *cache_b = (struct cpu_cache_level *)b;
988
989 return cache_a->level - cache_b->level;
990}
991
992static bool cpu_cache_level__cmp(struct cpu_cache_level *a, struct cpu_cache_level *b)
993{
994 if (a->level != b->level)
995 return false;
996
997 if (a->line_size != b->line_size)
998 return false;
999
1000 if (a->sets != b->sets)
1001 return false;
1002
1003 if (a->ways != b->ways)
1004 return false;
1005
1006 if (strcmp(a->type, b->type))
1007 return false;
1008
1009 if (strcmp(a->size, b->size))
1010 return false;
1011
1012 if (strcmp(a->map, b->map))
1013 return false;
1014
1015 return true;
1016}
1017
1018static int cpu_cache_level__read(struct cpu_cache_level *cache, u32 cpu, u16 level)
1019{
1020 char path[PATH_MAX], file[PATH_MAX];
1021 struct stat st;
1022 size_t len;
1023
1024 scnprintf(path, PATH_MAX, "devices/system/cpu/cpu%d/cache/index%d/", cpu, level);
1025 scnprintf(file, PATH_MAX, "%s/%s", sysfs__mountpoint(), path);
1026
1027 if (stat(file, &st))
1028 return 1;
1029
1030 scnprintf(file, PATH_MAX, "%s/level", path);
1031 if (sysfs__read_int(file, (int *) &cache->level))
1032 return -1;
1033
1034 scnprintf(file, PATH_MAX, "%s/coherency_line_size", path);
1035 if (sysfs__read_int(file, (int *) &cache->line_size))
1036 return -1;
1037
1038 scnprintf(file, PATH_MAX, "%s/number_of_sets", path);
1039 if (sysfs__read_int(file, (int *) &cache->sets))
1040 return -1;
1041
1042 scnprintf(file, PATH_MAX, "%s/ways_of_associativity", path);
1043 if (sysfs__read_int(file, (int *) &cache->ways))
1044 return -1;
1045
1046 scnprintf(file, PATH_MAX, "%s/type", path);
1047 if (sysfs__read_str(file, &cache->type, &len))
1048 return -1;
1049
1050 cache->type[len] = 0;
1051 cache->type = rtrim(cache->type);
1052
1053 scnprintf(file, PATH_MAX, "%s/size", path);
1054 if (sysfs__read_str(file, &cache->size, &len)) {
1055 free(cache->type);
1056 return -1;
1057 }
1058
1059 cache->size[len] = 0;
1060 cache->size = rtrim(cache->size);
1061
1062 scnprintf(file, PATH_MAX, "%s/shared_cpu_list", path);
1063 if (sysfs__read_str(file, &cache->map, &len)) {
1064 free(cache->map);
1065 free(cache->type);
1066 return -1;
1067 }
1068
1069 cache->map[len] = 0;
1070 cache->map = rtrim(cache->map);
1071 return 0;
1072}
1073
1074static void cpu_cache_level__fprintf(FILE *out, struct cpu_cache_level *c)
1075{
1076 fprintf(out, "L%d %-15s %8s [%s]\n", c->level, c->type, c->size, c->map);
1077}
1078
1079static int build_caches(struct cpu_cache_level caches[], u32 size, u32 *cntp)
1080{
1081 u32 i, cnt = 0;
1082 long ncpus;
1083 u32 nr, cpu;
1084 u16 level;
1085
1086 ncpus = sysconf(_SC_NPROCESSORS_CONF);
1087 if (ncpus < 0)
1088 return -1;
1089
1090 nr = (u32)(ncpus & UINT_MAX);
1091
1092 for (cpu = 0; cpu < nr; cpu++) {
1093 for (level = 0; level < 10; level++) {
1094 struct cpu_cache_level c;
1095 int err;
1096
1097 err = cpu_cache_level__read(&c, cpu, level);
1098 if (err < 0)
1099 return err;
1100
1101 if (err == 1)
1102 break;
1103
1104 for (i = 0; i < cnt; i++) {
1105 if (cpu_cache_level__cmp(&c, &caches[i]))
1106 break;
1107 }
1108
1109 if (i == cnt)
1110 caches[cnt++] = c;
1111 else
1112 cpu_cache_level__free(&c);
1113
1114 if (WARN_ONCE(cnt == size, "way too many cpu caches.."))
1115 goto out;
1116 }
1117 }
1118 out:
1119 *cntp = cnt;
1120 return 0;
1121}
1122
1123#define MAX_CACHES 2000
1124
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -07001125static int write_cache(struct feat_fd *ff,
1126 struct perf_evlist *evlist __maybe_unused)
Jiri Olsa720e98b2016-02-16 16:01:43 +01001127{
1128 struct cpu_cache_level caches[MAX_CACHES];
1129 u32 cnt = 0, i, version = 1;
1130 int ret;
1131
1132 ret = build_caches(caches, MAX_CACHES, &cnt);
1133 if (ret)
1134 goto out;
1135
1136 qsort(&caches, cnt, sizeof(struct cpu_cache_level), cpu_cache_level__sort);
1137
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -07001138 ret = do_write(ff, &version, sizeof(u32));
Jiri Olsa720e98b2016-02-16 16:01:43 +01001139 if (ret < 0)
1140 goto out;
1141
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -07001142 ret = do_write(ff, &cnt, sizeof(u32));
Jiri Olsa720e98b2016-02-16 16:01:43 +01001143 if (ret < 0)
1144 goto out;
1145
1146 for (i = 0; i < cnt; i++) {
1147 struct cpu_cache_level *c = &caches[i];
1148
1149 #define _W(v) \
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -07001150 ret = do_write(ff, &c->v, sizeof(u32)); \
Jiri Olsa720e98b2016-02-16 16:01:43 +01001151 if (ret < 0) \
1152 goto out;
1153
1154 _W(level)
1155 _W(line_size)
1156 _W(sets)
1157 _W(ways)
1158 #undef _W
1159
1160 #define _W(v) \
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -07001161 ret = do_write_string(ff, (const char *) c->v); \
Jiri Olsa720e98b2016-02-16 16:01:43 +01001162 if (ret < 0) \
1163 goto out;
1164
1165 _W(type)
1166 _W(size)
1167 _W(map)
1168 #undef _W
1169 }
1170
1171out:
1172 for (i = 0; i < cnt; i++)
1173 cpu_cache_level__free(&caches[i]);
1174 return ret;
1175}
1176
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -07001177static int write_stat(struct feat_fd *ff __maybe_unused,
Jiri Olsaffa517a2015-10-25 15:51:43 +01001178 struct perf_evlist *evlist __maybe_unused)
1179{
1180 return 0;
1181}
1182
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001183static void print_hostname(struct feat_fd *ff, FILE *fp)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001184{
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001185 fprintf(fp, "# hostname : %s\n", ff->ph->env.hostname);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001186}
1187
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001188static void print_osrelease(struct feat_fd *ff, FILE *fp)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001189{
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001190 fprintf(fp, "# os release : %s\n", ff->ph->env.os_release);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001191}
1192
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001193static void print_arch(struct feat_fd *ff, FILE *fp)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001194{
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001195 fprintf(fp, "# arch : %s\n", ff->ph->env.arch);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001196}
1197
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001198static void print_cpudesc(struct feat_fd *ff, FILE *fp)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001199{
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001200 fprintf(fp, "# cpudesc : %s\n", ff->ph->env.cpu_desc);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001201}
1202
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001203static void print_nrcpus(struct feat_fd *ff, FILE *fp)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001204{
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001205 fprintf(fp, "# nrcpus online : %u\n", ff->ph->env.nr_cpus_online);
1206 fprintf(fp, "# nrcpus avail : %u\n", ff->ph->env.nr_cpus_avail);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001207}
1208
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001209static void print_version(struct feat_fd *ff, FILE *fp)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001210{
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001211 fprintf(fp, "# perf version : %s\n", ff->ph->env.version);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001212}
1213
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001214static void print_cmdline(struct feat_fd *ff, FILE *fp)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001215{
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001216 int nr, i;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001217
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001218 nr = ff->ph->env.nr_cmdline;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001219
1220 fprintf(fp, "# cmdline : ");
1221
Jiri Olsa768dd3f2015-07-21 14:31:31 +02001222 for (i = 0; i < nr; i++)
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001223 fprintf(fp, "%s ", ff->ph->env.cmdline_argv[i]);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001224 fputc('\n', fp);
1225}
1226
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001227static void print_cpu_topology(struct feat_fd *ff, FILE *fp)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001228{
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001229 struct perf_header *ph = ff->ph;
1230 int cpu_nr = ph->env.nr_cpus_avail;
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001231 int nr, i;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001232 char *str;
1233
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001234 nr = ph->env.nr_sibling_cores;
1235 str = ph->env.sibling_cores;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001236
1237 for (i = 0; i < nr; i++) {
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001238 fprintf(fp, "# sibling cores : %s\n", str);
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001239 str += strlen(str) + 1;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001240 }
1241
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001242 nr = ph->env.nr_sibling_threads;
1243 str = ph->env.sibling_threads;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001244
1245 for (i = 0; i < nr; i++) {
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001246 fprintf(fp, "# sibling threads : %s\n", str);
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001247 str += strlen(str) + 1;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001248 }
Kan Liang2bb00d22015-09-01 09:58:12 -04001249
1250 if (ph->env.cpu != NULL) {
1251 for (i = 0; i < cpu_nr; i++)
1252 fprintf(fp, "# CPU %d: Core ID %d, Socket ID %d\n", i,
1253 ph->env.cpu[i].core_id, ph->env.cpu[i].socket_id);
1254 } else
1255 fprintf(fp, "# Core ID and Socket ID information is not available\n");
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001256}
1257
Robert Richter4e1b9c62012-08-16 21:10:22 +02001258static void free_event_desc(struct perf_evsel *events)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001259{
Robert Richter4e1b9c62012-08-16 21:10:22 +02001260 struct perf_evsel *evsel;
1261
1262 if (!events)
1263 return;
1264
1265 for (evsel = events; evsel->attr.size; evsel++) {
Arnaldo Carvalho de Melo74cf2492013-12-27 16:55:14 -03001266 zfree(&evsel->name);
1267 zfree(&evsel->id);
Robert Richter4e1b9c62012-08-16 21:10:22 +02001268 }
1269
1270 free(events);
1271}
1272
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07001273static struct perf_evsel *read_event_desc(struct feat_fd *ff)
Robert Richter4e1b9c62012-08-16 21:10:22 +02001274{
1275 struct perf_evsel *evsel, *events = NULL;
1276 u64 *id;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001277 void *buf = NULL;
Stephane Eranian62db9062012-02-09 23:21:07 +01001278 u32 nre, sz, nr, i, j;
Stephane Eranian62db9062012-02-09 23:21:07 +01001279 size_t msz;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001280
1281 /* number of events */
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07001282 if (do_read_u32(ff, &nre))
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001283 goto error;
1284
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07001285 if (do_read_u32(ff, &sz))
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001286 goto error;
1287
Stephane Eranian62db9062012-02-09 23:21:07 +01001288 /* buffer to hold on file attr struct */
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001289 buf = malloc(sz);
1290 if (!buf)
1291 goto error;
1292
Robert Richter4e1b9c62012-08-16 21:10:22 +02001293 /* the last event terminates with evsel->attr.size == 0: */
1294 events = calloc(nre + 1, sizeof(*events));
1295 if (!events)
1296 goto error;
1297
1298 msz = sizeof(evsel->attr);
Jiri Olsa9fafd982012-03-20 19:15:39 +01001299 if (sz < msz)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001300 msz = sz;
1301
Robert Richter4e1b9c62012-08-16 21:10:22 +02001302 for (i = 0, evsel = events; i < nre; evsel++, i++) {
1303 evsel->idx = i;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001304
Stephane Eranian62db9062012-02-09 23:21:07 +01001305 /*
1306 * must read entire on-file attr struct to
1307 * sync up with layout.
1308 */
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07001309 if (__do_read(ff, buf, sz))
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001310 goto error;
1311
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07001312 if (ff->ph->needs_swap)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001313 perf_event__attr_swap(buf);
1314
Robert Richter4e1b9c62012-08-16 21:10:22 +02001315 memcpy(&evsel->attr, buf, msz);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001316
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07001317 if (do_read_u32(ff, &nr))
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001318 goto error;
1319
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07001320 if (ff->ph->needs_swap)
Arnaldo Carvalho de Melo0807d2d2012-09-26 12:48:18 -03001321 evsel->needs_swap = true;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001322
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07001323 evsel->name = do_read_string(ff);
David Carrillo-Cisneros6200e4942017-07-17 21:25:34 -07001324 if (!evsel->name)
1325 goto error;
Robert Richter4e1b9c62012-08-16 21:10:22 +02001326
1327 if (!nr)
1328 continue;
1329
1330 id = calloc(nr, sizeof(*id));
1331 if (!id)
1332 goto error;
1333 evsel->ids = nr;
1334 evsel->id = id;
1335
1336 for (j = 0 ; j < nr; j++) {
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07001337 if (do_read_u64(ff, id))
Robert Richter4e1b9c62012-08-16 21:10:22 +02001338 goto error;
Robert Richter4e1b9c62012-08-16 21:10:22 +02001339 id++;
1340 }
1341 }
1342out:
Arnaldo Carvalho de Melo04662522013-12-26 17:41:15 -03001343 free(buf);
Robert Richter4e1b9c62012-08-16 21:10:22 +02001344 return events;
1345error:
Markus Elfring4cc97612015-06-25 17:12:32 +02001346 free_event_desc(events);
Robert Richter4e1b9c62012-08-16 21:10:22 +02001347 events = NULL;
1348 goto out;
1349}
1350
Peter Zijlstra2c5e8c52015-04-07 11:09:54 +02001351static int __desc_attr__fprintf(FILE *fp, const char *name, const char *val,
Arnaldo Carvalho de Melo03536312017-06-16 12:18:27 -03001352 void *priv __maybe_unused)
Peter Zijlstra2c5e8c52015-04-07 11:09:54 +02001353{
1354 return fprintf(fp, ", %s = %s", name, val);
1355}
1356
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001357static void print_event_desc(struct feat_fd *ff, FILE *fp)
Robert Richter4e1b9c62012-08-16 21:10:22 +02001358{
David Carrillo-Cisnerosf9ebdcc2017-07-17 21:25:49 -07001359 struct perf_evsel *evsel, *events;
Robert Richter4e1b9c62012-08-16 21:10:22 +02001360 u32 j;
1361 u64 *id;
1362
David Carrillo-Cisnerosf9ebdcc2017-07-17 21:25:49 -07001363 if (ff->events)
1364 events = ff->events;
1365 else
1366 events = read_event_desc(ff);
1367
Robert Richter4e1b9c62012-08-16 21:10:22 +02001368 if (!events) {
1369 fprintf(fp, "# event desc: not available or unable to read\n");
1370 return;
1371 }
1372
1373 for (evsel = events; evsel->attr.size; evsel++) {
1374 fprintf(fp, "# event : name = %s, ", evsel->name);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001375
Robert Richter4e1b9c62012-08-16 21:10:22 +02001376 if (evsel->ids) {
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001377 fprintf(fp, ", id = {");
Robert Richter4e1b9c62012-08-16 21:10:22 +02001378 for (j = 0, id = evsel->id; j < evsel->ids; j++, id++) {
1379 if (j)
1380 fputc(',', fp);
1381 fprintf(fp, " %"PRIu64, *id);
1382 }
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001383 fprintf(fp, " }");
Robert Richter4e1b9c62012-08-16 21:10:22 +02001384 }
Peter Zijlstra814c8c32015-03-31 00:19:31 +02001385
Peter Zijlstra2c5e8c52015-04-07 11:09:54 +02001386 perf_event_attr__fprintf(fp, &evsel->attr, __desc_attr__fprintf, NULL);
Robert Richter4e1b9c62012-08-16 21:10:22 +02001387
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001388 fputc('\n', fp);
1389 }
Robert Richter4e1b9c62012-08-16 21:10:22 +02001390
1391 free_event_desc(events);
David Carrillo-Cisnerosf9ebdcc2017-07-17 21:25:49 -07001392 ff->events = NULL;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001393}
1394
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001395static void print_total_mem(struct feat_fd *ff, FILE *fp)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001396{
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001397 fprintf(fp, "# total memory : %llu kB\n", ff->ph->env.total_mem);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001398}
1399
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001400static void print_numa_topology(struct feat_fd *ff, FILE *fp)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001401{
Jiri Olsac60da222016-07-04 14:16:20 +02001402 int i;
1403 struct numa_node *n;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001404
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001405 for (i = 0; i < ff->ph->env.nr_numa_nodes; i++) {
1406 n = &ff->ph->env.numa_nodes[i];
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001407
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001408 fprintf(fp, "# node%u meminfo : total = %"PRIu64" kB,"
1409 " free = %"PRIu64" kB\n",
Jiri Olsac60da222016-07-04 14:16:20 +02001410 n->node, n->mem_total, n->mem_free);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001411
Jiri Olsac60da222016-07-04 14:16:20 +02001412 fprintf(fp, "# node%u cpu list : ", n->node);
1413 cpu_map__fprintf(n->map, fp);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001414 }
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001415}
1416
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001417static void print_cpuid(struct feat_fd *ff, FILE *fp)
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001418{
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001419 fprintf(fp, "# cpuid : %s\n", ff->ph->env.cpuid);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02001420}
1421
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001422static void print_branch_stack(struct feat_fd *ff __maybe_unused, FILE *fp)
Stephane Eranian330aa672012-03-08 23:47:46 +01001423{
1424 fprintf(fp, "# contains samples with branch stack\n");
1425}
1426
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001427static void print_auxtrace(struct feat_fd *ff __maybe_unused, FILE *fp)
Adrian Hunter4025ea42015-04-09 18:53:41 +03001428{
1429 fprintf(fp, "# contains AUX area data (e.g. instruction trace)\n");
1430}
1431
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001432static void print_stat(struct feat_fd *ff __maybe_unused, FILE *fp)
Jiri Olsaffa517a2015-10-25 15:51:43 +01001433{
1434 fprintf(fp, "# contains stat data\n");
1435}
1436
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001437static void print_cache(struct feat_fd *ff, FILE *fp __maybe_unused)
Jiri Olsa720e98b2016-02-16 16:01:43 +01001438{
1439 int i;
1440
1441 fprintf(fp, "# CPU cache info:\n");
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001442 for (i = 0; i < ff->ph->env.caches_cnt; i++) {
Jiri Olsa720e98b2016-02-16 16:01:43 +01001443 fprintf(fp, "# ");
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001444 cpu_cache_level__fprintf(fp, &ff->ph->env.caches[i]);
Jiri Olsa720e98b2016-02-16 16:01:43 +01001445 }
1446}
1447
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001448static void print_pmu_mappings(struct feat_fd *ff, FILE *fp)
Robert Richter50a96672012-08-16 21:10:24 +02001449{
1450 const char *delimiter = "# pmu mappings: ";
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001451 char *str, *tmp;
Robert Richter50a96672012-08-16 21:10:24 +02001452 u32 pmu_num;
1453 u32 type;
1454
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001455 pmu_num = ff->ph->env.nr_pmu_mappings;
Robert Richter50a96672012-08-16 21:10:24 +02001456 if (!pmu_num) {
1457 fprintf(fp, "# pmu mappings: not available\n");
1458 return;
1459 }
1460
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001461 str = ff->ph->env.pmu_mappings;
Namhyung Kimbe4a2de2012-09-05 14:02:49 +09001462
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001463 while (pmu_num) {
1464 type = strtoul(str, &tmp, 0);
1465 if (*tmp != ':')
1466 goto error;
1467
1468 str = tmp + 1;
1469 fprintf(fp, "%s%s = %" PRIu32, delimiter, str, type);
1470
Robert Richter50a96672012-08-16 21:10:24 +02001471 delimiter = ", ";
Namhyung Kim7e94cfc2012-09-24 17:15:00 +09001472 str += strlen(str) + 1;
1473 pmu_num--;
Robert Richter50a96672012-08-16 21:10:24 +02001474 }
1475
1476 fprintf(fp, "\n");
1477
1478 if (!pmu_num)
1479 return;
1480error:
1481 fprintf(fp, "# pmu mappings: unable to read\n");
1482}
1483
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001484static void print_group_desc(struct feat_fd *ff, FILE *fp)
Namhyung Kima8bb5592013-01-22 18:09:31 +09001485{
1486 struct perf_session *session;
1487 struct perf_evsel *evsel;
1488 u32 nr = 0;
1489
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07001490 session = container_of(ff->ph, struct perf_session, header);
Namhyung Kima8bb5592013-01-22 18:09:31 +09001491
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -03001492 evlist__for_each_entry(session->evlist, evsel) {
Namhyung Kima8bb5592013-01-22 18:09:31 +09001493 if (perf_evsel__is_group_leader(evsel) &&
1494 evsel->nr_members > 1) {
1495 fprintf(fp, "# group: %s{%s", evsel->group_name ?: "",
1496 perf_evsel__name(evsel));
1497
1498 nr = evsel->nr_members - 1;
1499 } else if (nr) {
1500 fprintf(fp, ",%s", perf_evsel__name(evsel));
1501
1502 if (--nr == 0)
1503 fprintf(fp, "}\n");
1504 }
1505 }
1506}
1507
Robert Richter08d95bd2012-02-10 15:41:55 +01001508static int __event_process_build_id(struct build_id_event *bev,
1509 char *filename,
1510 struct perf_session *session)
1511{
1512 int err = -1;
Robert Richter08d95bd2012-02-10 15:41:55 +01001513 struct machine *machine;
Wang Nan1f121b02015-06-03 08:52:21 +00001514 u16 cpumode;
Robert Richter08d95bd2012-02-10 15:41:55 +01001515 struct dso *dso;
1516 enum dso_kernel_type dso_type;
1517
1518 machine = perf_session__findnew_machine(session, bev->pid);
1519 if (!machine)
1520 goto out;
1521
Wang Nan1f121b02015-06-03 08:52:21 +00001522 cpumode = bev->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
Robert Richter08d95bd2012-02-10 15:41:55 +01001523
Wang Nan1f121b02015-06-03 08:52:21 +00001524 switch (cpumode) {
Robert Richter08d95bd2012-02-10 15:41:55 +01001525 case PERF_RECORD_MISC_KERNEL:
1526 dso_type = DSO_TYPE_KERNEL;
Robert Richter08d95bd2012-02-10 15:41:55 +01001527 break;
1528 case PERF_RECORD_MISC_GUEST_KERNEL:
1529 dso_type = DSO_TYPE_GUEST_KERNEL;
Robert Richter08d95bd2012-02-10 15:41:55 +01001530 break;
1531 case PERF_RECORD_MISC_USER:
1532 case PERF_RECORD_MISC_GUEST_USER:
1533 dso_type = DSO_TYPE_USER;
Robert Richter08d95bd2012-02-10 15:41:55 +01001534 break;
1535 default:
1536 goto out;
1537 }
1538
Arnaldo Carvalho de Meloaa7cc2a2015-05-29 11:31:12 -03001539 dso = machine__findnew_dso(machine, filename);
Robert Richter08d95bd2012-02-10 15:41:55 +01001540 if (dso != NULL) {
Masami Hiramatsub5d8bbe2016-05-11 22:51:59 +09001541 char sbuild_id[SBUILD_ID_SIZE];
Robert Richter08d95bd2012-02-10 15:41:55 +01001542
1543 dso__set_build_id(dso, &bev->build_id);
1544
Namhyung Kim1deec1b2017-05-31 21:01:03 +09001545 if (dso_type != DSO_TYPE_USER) {
1546 struct kmod_path m = { .name = NULL, };
1547
1548 if (!kmod_path__parse_name(&m, filename) && m.kmod)
Namhyung Kim6b335e82017-05-31 21:01:04 +09001549 dso__set_module_info(dso, &m, machine);
Namhyung Kim1deec1b2017-05-31 21:01:03 +09001550 else
1551 dso->kernel = dso_type;
1552
1553 free(m.name);
1554 }
Robert Richter08d95bd2012-02-10 15:41:55 +01001555
1556 build_id__sprintf(dso->build_id, sizeof(dso->build_id),
1557 sbuild_id);
1558 pr_debug("build id event received for %s: %s\n",
1559 dso->long_name, sbuild_id);
Arnaldo Carvalho de Melod3a7c482015-06-02 11:53:26 -03001560 dso__put(dso);
Robert Richter08d95bd2012-02-10 15:41:55 +01001561 }
1562
1563 err = 0;
1564out:
1565 return err;
1566}
1567
1568static int perf_header__read_build_ids_abi_quirk(struct perf_header *header,
1569 int input, u64 offset, u64 size)
1570{
1571 struct perf_session *session = container_of(header, struct perf_session, header);
1572 struct {
1573 struct perf_event_header header;
Irina Tirdea9ac3e482012-09-11 01:15:01 +03001574 u8 build_id[PERF_ALIGN(BUILD_ID_SIZE, sizeof(u64))];
Robert Richter08d95bd2012-02-10 15:41:55 +01001575 char filename[0];
1576 } old_bev;
1577 struct build_id_event bev;
1578 char filename[PATH_MAX];
1579 u64 limit = offset + size;
1580
1581 while (offset < limit) {
1582 ssize_t len;
1583
Namhyung Kim5323f602012-12-17 15:38:54 +09001584 if (readn(input, &old_bev, sizeof(old_bev)) != sizeof(old_bev))
Robert Richter08d95bd2012-02-10 15:41:55 +01001585 return -1;
1586
1587 if (header->needs_swap)
1588 perf_event_header__bswap(&old_bev.header);
1589
1590 len = old_bev.header.size - sizeof(old_bev);
Namhyung Kim5323f602012-12-17 15:38:54 +09001591 if (readn(input, filename, len) != len)
Robert Richter08d95bd2012-02-10 15:41:55 +01001592 return -1;
1593
1594 bev.header = old_bev.header;
1595
1596 /*
1597 * As the pid is the missing value, we need to fill
1598 * it properly. The header.misc value give us nice hint.
1599 */
1600 bev.pid = HOST_KERNEL_ID;
1601 if (bev.header.misc == PERF_RECORD_MISC_GUEST_USER ||
1602 bev.header.misc == PERF_RECORD_MISC_GUEST_KERNEL)
1603 bev.pid = DEFAULT_GUEST_KERNEL_ID;
1604
1605 memcpy(bev.build_id, old_bev.build_id, sizeof(bev.build_id));
1606 __event_process_build_id(&bev, filename, session);
1607
1608 offset += bev.header.size;
1609 }
1610
1611 return 0;
1612}
1613
1614static int perf_header__read_build_ids(struct perf_header *header,
1615 int input, u64 offset, u64 size)
1616{
1617 struct perf_session *session = container_of(header, struct perf_session, header);
1618 struct build_id_event bev;
1619 char filename[PATH_MAX];
1620 u64 limit = offset + size, orig_offset = offset;
1621 int err = -1;
1622
1623 while (offset < limit) {
1624 ssize_t len;
1625
Namhyung Kim5323f602012-12-17 15:38:54 +09001626 if (readn(input, &bev, sizeof(bev)) != sizeof(bev))
Robert Richter08d95bd2012-02-10 15:41:55 +01001627 goto out;
1628
1629 if (header->needs_swap)
1630 perf_event_header__bswap(&bev.header);
1631
1632 len = bev.header.size - sizeof(bev);
Namhyung Kim5323f602012-12-17 15:38:54 +09001633 if (readn(input, filename, len) != len)
Robert Richter08d95bd2012-02-10 15:41:55 +01001634 goto out;
1635 /*
1636 * The a1645ce1 changeset:
1637 *
1638 * "perf: 'perf kvm' tool for monitoring guest performance from host"
1639 *
1640 * Added a field to struct build_id_event that broke the file
1641 * format.
1642 *
1643 * Since the kernel build-id is the first entry, process the
1644 * table using the old format if the well known
1645 * '[kernel.kallsyms]' string for the kernel build-id has the
1646 * first 4 characters chopped off (where the pid_t sits).
1647 */
1648 if (memcmp(filename, "nel.kallsyms]", 13) == 0) {
1649 if (lseek(input, orig_offset, SEEK_SET) == (off_t)-1)
1650 return -1;
1651 return perf_header__read_build_ids_abi_quirk(header, input, offset, size);
1652 }
1653
1654 __event_process_build_id(&bev, filename, session);
1655
1656 offset += bev.header.size;
1657 }
1658 err = 0;
1659out:
1660 return err;
1661}
1662
David Carrillo-Cisnerosdfaa1582017-07-17 21:25:35 -07001663/* Macro for features that simply need to read and store a string. */
1664#define FEAT_PROCESS_STR_FUN(__feat, __feat_env) \
David Carrillo-Cisneros62552452017-07-17 21:25:42 -07001665static int process_##__feat(struct feat_fd *ff, void *data __maybe_unused) \
David Carrillo-Cisnerosdfaa1582017-07-17 21:25:35 -07001666{\
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07001667 ff->ph->env.__feat_env = do_read_string(ff); \
David Carrillo-Cisneros1a222752017-07-17 21:25:41 -07001668 return ff->ph->env.__feat_env ? 0 : -ENOMEM; \
David Carrillo-Cisnerosdfaa1582017-07-17 21:25:35 -07001669}
1670
1671FEAT_PROCESS_STR_FUN(hostname, hostname);
1672FEAT_PROCESS_STR_FUN(osrelease, os_release);
1673FEAT_PROCESS_STR_FUN(version, version);
1674FEAT_PROCESS_STR_FUN(arch, arch);
1675FEAT_PROCESS_STR_FUN(cpudesc, cpu_desc);
1676FEAT_PROCESS_STR_FUN(cpuid, cpuid);
1677
David Carrillo-Cisneros62552452017-07-17 21:25:42 -07001678static int process_tracing_data(struct feat_fd *ff, void *data)
Robert Richterf1c67db2012-02-10 15:41:56 +01001679{
David Carrillo-Cisneros1a222752017-07-17 21:25:41 -07001680 ssize_t ret = trace_report(ff->fd, data, false);
1681
Namhyung Kim3dce2ce2013-03-21 16:18:48 +09001682 return ret < 0 ? -1 : 0;
Robert Richterf1c67db2012-02-10 15:41:56 +01001683}
1684
David Carrillo-Cisneros62552452017-07-17 21:25:42 -07001685static int process_build_id(struct feat_fd *ff, void *data __maybe_unused)
Robert Richterf1c67db2012-02-10 15:41:56 +01001686{
David Carrillo-Cisneros62552452017-07-17 21:25:42 -07001687 if (perf_header__read_build_ids(ff->ph, ff->fd, ff->offset, ff->size))
Robert Richterf1c67db2012-02-10 15:41:56 +01001688 pr_debug("Failed to read buildids, continuing...\n");
1689 return 0;
1690}
1691
David Carrillo-Cisneros62552452017-07-17 21:25:42 -07001692static int process_nrcpus(struct feat_fd *ff, void *data __maybe_unused)
Namhyung Kima1ae5652012-09-24 17:14:59 +09001693{
David Carrillo-Cisneros6200e4942017-07-17 21:25:34 -07001694 int ret;
1695 u32 nr_cpus_avail, nr_cpus_online;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001696
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07001697 ret = do_read_u32(ff, &nr_cpus_avail);
David Carrillo-Cisneros6200e4942017-07-17 21:25:34 -07001698 if (ret)
1699 return ret;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001700
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07001701 ret = do_read_u32(ff, &nr_cpus_online);
David Carrillo-Cisneros6200e4942017-07-17 21:25:34 -07001702 if (ret)
1703 return ret;
David Carrillo-Cisneros1a222752017-07-17 21:25:41 -07001704 ff->ph->env.nr_cpus_avail = (int)nr_cpus_avail;
1705 ff->ph->env.nr_cpus_online = (int)nr_cpus_online;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001706 return 0;
1707}
1708
David Carrillo-Cisneros62552452017-07-17 21:25:42 -07001709static int process_total_mem(struct feat_fd *ff, void *data __maybe_unused)
Namhyung Kima1ae5652012-09-24 17:14:59 +09001710{
David Carrillo-Cisneros6200e4942017-07-17 21:25:34 -07001711 u64 total_mem;
1712 int ret;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001713
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07001714 ret = do_read_u64(ff, &total_mem);
David Carrillo-Cisneros6200e4942017-07-17 21:25:34 -07001715 if (ret)
Namhyung Kima1ae5652012-09-24 17:14:59 +09001716 return -1;
David Carrillo-Cisneros1a222752017-07-17 21:25:41 -07001717 ff->ph->env.total_mem = (unsigned long long)total_mem;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001718 return 0;
1719}
1720
Robert Richter7c2f7af2012-08-16 21:10:23 +02001721static struct perf_evsel *
1722perf_evlist__find_by_index(struct perf_evlist *evlist, int idx)
1723{
1724 struct perf_evsel *evsel;
1725
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -03001726 evlist__for_each_entry(evlist, evsel) {
Robert Richter7c2f7af2012-08-16 21:10:23 +02001727 if (evsel->idx == idx)
1728 return evsel;
1729 }
1730
1731 return NULL;
1732}
1733
1734static void
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001735perf_evlist__set_event_name(struct perf_evlist *evlist,
1736 struct perf_evsel *event)
Robert Richter7c2f7af2012-08-16 21:10:23 +02001737{
1738 struct perf_evsel *evsel;
1739
1740 if (!event->name)
1741 return;
1742
1743 evsel = perf_evlist__find_by_index(evlist, event->idx);
1744 if (!evsel)
1745 return;
1746
1747 if (evsel->name)
1748 return;
1749
1750 evsel->name = strdup(event->name);
1751}
1752
1753static int
David Carrillo-Cisneros62552452017-07-17 21:25:42 -07001754process_event_desc(struct feat_fd *ff, void *data __maybe_unused)
Robert Richter7c2f7af2012-08-16 21:10:23 +02001755{
Namhyung Kim3d7eb862012-09-24 17:15:01 +09001756 struct perf_session *session;
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07001757 struct perf_evsel *evsel, *events = read_event_desc(ff);
Robert Richter7c2f7af2012-08-16 21:10:23 +02001758
1759 if (!events)
1760 return 0;
1761
David Carrillo-Cisneros1a222752017-07-17 21:25:41 -07001762 session = container_of(ff->ph, struct perf_session, header);
David Carrillo-Cisnerosf9ebdcc2017-07-17 21:25:49 -07001763
Jiri Olsa8ceb41d2017-01-23 22:07:59 +01001764 if (session->data->is_pipe) {
David Carrillo-Cisnerosf9ebdcc2017-07-17 21:25:49 -07001765 /* Save events for reading later by print_event_desc,
1766 * since they can't be read again in pipe mode. */
1767 ff->events = events;
1768 }
1769
Robert Richter7c2f7af2012-08-16 21:10:23 +02001770 for (evsel = events; evsel->attr.size; evsel++)
1771 perf_evlist__set_event_name(session->evlist, evsel);
1772
Jiri Olsa8ceb41d2017-01-23 22:07:59 +01001773 if (!session->data->is_pipe)
David Carrillo-Cisnerosf9ebdcc2017-07-17 21:25:49 -07001774 free_event_desc(events);
Robert Richter7c2f7af2012-08-16 21:10:23 +02001775
1776 return 0;
1777}
1778
David Carrillo-Cisneros62552452017-07-17 21:25:42 -07001779static int process_cmdline(struct feat_fd *ff, void *data __maybe_unused)
Namhyung Kima1ae5652012-09-24 17:14:59 +09001780{
Jiri Olsa768dd3f2015-07-21 14:31:31 +02001781 char *str, *cmdline = NULL, **argv = NULL;
1782 u32 nr, i, len = 0;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001783
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07001784 if (do_read_u32(ff, &nr))
Namhyung Kima1ae5652012-09-24 17:14:59 +09001785 return -1;
1786
David Carrillo-Cisneros1a222752017-07-17 21:25:41 -07001787 ff->ph->env.nr_cmdline = nr;
Jiri Olsa768dd3f2015-07-21 14:31:31 +02001788
David Carrillo-Cisneros62552452017-07-17 21:25:42 -07001789 cmdline = zalloc(ff->size + nr + 1);
Jiri Olsa768dd3f2015-07-21 14:31:31 +02001790 if (!cmdline)
1791 return -1;
1792
1793 argv = zalloc(sizeof(char *) * (nr + 1));
1794 if (!argv)
1795 goto error;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001796
1797 for (i = 0; i < nr; i++) {
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07001798 str = do_read_string(ff);
Namhyung Kima1ae5652012-09-24 17:14:59 +09001799 if (!str)
1800 goto error;
1801
Jiri Olsa768dd3f2015-07-21 14:31:31 +02001802 argv[i] = cmdline + len;
1803 memcpy(argv[i], str, strlen(str) + 1);
1804 len += strlen(str) + 1;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001805 free(str);
1806 }
David Carrillo-Cisneros1a222752017-07-17 21:25:41 -07001807 ff->ph->env.cmdline = cmdline;
1808 ff->ph->env.cmdline_argv = (const char **) argv;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001809 return 0;
1810
1811error:
Jiri Olsa768dd3f2015-07-21 14:31:31 +02001812 free(argv);
1813 free(cmdline);
Namhyung Kima1ae5652012-09-24 17:14:59 +09001814 return -1;
1815}
1816
David Carrillo-Cisneros62552452017-07-17 21:25:42 -07001817static int process_cpu_topology(struct feat_fd *ff, void *data __maybe_unused)
Namhyung Kima1ae5652012-09-24 17:14:59 +09001818{
Namhyung Kima1ae5652012-09-24 17:14:59 +09001819 u32 nr, i;
1820 char *str;
1821 struct strbuf sb;
David Carrillo-Cisneros1a222752017-07-17 21:25:41 -07001822 int cpu_nr = ff->ph->env.nr_cpus_avail;
Kan Liang2bb00d22015-09-01 09:58:12 -04001823 u64 size = 0;
David Carrillo-Cisneros1a222752017-07-17 21:25:41 -07001824 struct perf_header *ph = ff->ph;
Kan Liang2bb00d22015-09-01 09:58:12 -04001825
1826 ph->env.cpu = calloc(cpu_nr, sizeof(*ph->env.cpu));
1827 if (!ph->env.cpu)
1828 return -1;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001829
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07001830 if (do_read_u32(ff, &nr))
Kan Liang2bb00d22015-09-01 09:58:12 -04001831 goto free_cpu;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001832
Namhyung Kima1ae5652012-09-24 17:14:59 +09001833 ph->env.nr_sibling_cores = nr;
Kan Liang2bb00d22015-09-01 09:58:12 -04001834 size += sizeof(u32);
Masami Hiramatsu642aada2016-05-10 14:47:35 +09001835 if (strbuf_init(&sb, 128) < 0)
1836 goto free_cpu;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001837
1838 for (i = 0; i < nr; i++) {
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07001839 str = do_read_string(ff);
Namhyung Kima1ae5652012-09-24 17:14:59 +09001840 if (!str)
1841 goto error;
1842
1843 /* include a NULL character at the end */
Masami Hiramatsu642aada2016-05-10 14:47:35 +09001844 if (strbuf_add(&sb, str, strlen(str) + 1) < 0)
1845 goto error;
Kan Liang2bb00d22015-09-01 09:58:12 -04001846 size += string_size(str);
Namhyung Kima1ae5652012-09-24 17:14:59 +09001847 free(str);
1848 }
1849 ph->env.sibling_cores = strbuf_detach(&sb, NULL);
1850
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07001851 if (do_read_u32(ff, &nr))
Namhyung Kima1ae5652012-09-24 17:14:59 +09001852 return -1;
1853
Namhyung Kima1ae5652012-09-24 17:14:59 +09001854 ph->env.nr_sibling_threads = nr;
Kan Liang2bb00d22015-09-01 09:58:12 -04001855 size += sizeof(u32);
Namhyung Kima1ae5652012-09-24 17:14:59 +09001856
1857 for (i = 0; i < nr; i++) {
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07001858 str = do_read_string(ff);
Namhyung Kima1ae5652012-09-24 17:14:59 +09001859 if (!str)
1860 goto error;
1861
1862 /* include a NULL character at the end */
Masami Hiramatsu642aada2016-05-10 14:47:35 +09001863 if (strbuf_add(&sb, str, strlen(str) + 1) < 0)
1864 goto error;
Kan Liang2bb00d22015-09-01 09:58:12 -04001865 size += string_size(str);
Namhyung Kima1ae5652012-09-24 17:14:59 +09001866 free(str);
1867 }
1868 ph->env.sibling_threads = strbuf_detach(&sb, NULL);
Kan Liang2bb00d22015-09-01 09:58:12 -04001869
1870 /*
1871 * The header may be from old perf,
1872 * which doesn't include core id and socket id information.
1873 */
David Carrillo-Cisneros62552452017-07-17 21:25:42 -07001874 if (ff->size <= size) {
Kan Liang2bb00d22015-09-01 09:58:12 -04001875 zfree(&ph->env.cpu);
1876 return 0;
1877 }
1878
1879 for (i = 0; i < (u32)cpu_nr; i++) {
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07001880 if (do_read_u32(ff, &nr))
Kan Liang2bb00d22015-09-01 09:58:12 -04001881 goto free_cpu;
1882
Kan Liang2bb00d22015-09-01 09:58:12 -04001883 ph->env.cpu[i].core_id = nr;
1884
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07001885 if (do_read_u32(ff, &nr))
Kan Liang2bb00d22015-09-01 09:58:12 -04001886 goto free_cpu;
1887
Jan Stancekda8a58b2017-02-17 12:10:26 +01001888 if (nr != (u32)-1 && nr > (u32)cpu_nr) {
Kan Liang2bb00d22015-09-01 09:58:12 -04001889 pr_debug("socket_id number is too big."
1890 "You may need to upgrade the perf tool.\n");
1891 goto free_cpu;
1892 }
1893
1894 ph->env.cpu[i].socket_id = nr;
1895 }
1896
Namhyung Kima1ae5652012-09-24 17:14:59 +09001897 return 0;
1898
1899error:
1900 strbuf_release(&sb);
Kan Liang2bb00d22015-09-01 09:58:12 -04001901free_cpu:
1902 zfree(&ph->env.cpu);
Namhyung Kima1ae5652012-09-24 17:14:59 +09001903 return -1;
1904}
1905
David Carrillo-Cisneros62552452017-07-17 21:25:42 -07001906static int process_numa_topology(struct feat_fd *ff, void *data __maybe_unused)
Namhyung Kima1ae5652012-09-24 17:14:59 +09001907{
Jiri Olsac60da222016-07-04 14:16:20 +02001908 struct numa_node *nodes, *n;
Jiri Olsac60da222016-07-04 14:16:20 +02001909 u32 nr, i;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001910 char *str;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001911
1912 /* nr nodes */
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07001913 if (do_read_u32(ff, &nr))
Masami Hiramatsu642aada2016-05-10 14:47:35 +09001914 return -1;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001915
Jiri Olsac60da222016-07-04 14:16:20 +02001916 nodes = zalloc(sizeof(*nodes) * nr);
1917 if (!nodes)
1918 return -ENOMEM;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001919
1920 for (i = 0; i < nr; i++) {
Jiri Olsac60da222016-07-04 14:16:20 +02001921 n = &nodes[i];
1922
Namhyung Kima1ae5652012-09-24 17:14:59 +09001923 /* node number */
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07001924 if (do_read_u32(ff, &n->node))
Namhyung Kima1ae5652012-09-24 17:14:59 +09001925 goto error;
1926
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07001927 if (do_read_u64(ff, &n->mem_total))
Namhyung Kima1ae5652012-09-24 17:14:59 +09001928 goto error;
1929
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07001930 if (do_read_u64(ff, &n->mem_free))
Namhyung Kima1ae5652012-09-24 17:14:59 +09001931 goto error;
1932
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07001933 str = do_read_string(ff);
Namhyung Kima1ae5652012-09-24 17:14:59 +09001934 if (!str)
1935 goto error;
1936
Jiri Olsac60da222016-07-04 14:16:20 +02001937 n->map = cpu_map__new(str);
1938 if (!n->map)
Masami Hiramatsu642aada2016-05-10 14:47:35 +09001939 goto error;
Jiri Olsac60da222016-07-04 14:16:20 +02001940
Namhyung Kima1ae5652012-09-24 17:14:59 +09001941 free(str);
1942 }
David Carrillo-Cisneros1a222752017-07-17 21:25:41 -07001943 ff->ph->env.nr_numa_nodes = nr;
1944 ff->ph->env.numa_nodes = nodes;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001945 return 0;
1946
1947error:
Jiri Olsac60da222016-07-04 14:16:20 +02001948 free(nodes);
Namhyung Kima1ae5652012-09-24 17:14:59 +09001949 return -1;
1950}
1951
David Carrillo-Cisneros62552452017-07-17 21:25:42 -07001952static int process_pmu_mappings(struct feat_fd *ff, void *data __maybe_unused)
Namhyung Kima1ae5652012-09-24 17:14:59 +09001953{
Namhyung Kima1ae5652012-09-24 17:14:59 +09001954 char *name;
1955 u32 pmu_num;
1956 u32 type;
1957 struct strbuf sb;
1958
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07001959 if (do_read_u32(ff, &pmu_num))
Namhyung Kima1ae5652012-09-24 17:14:59 +09001960 return -1;
1961
Namhyung Kima1ae5652012-09-24 17:14:59 +09001962 if (!pmu_num) {
1963 pr_debug("pmu mappings not available\n");
1964 return 0;
1965 }
1966
David Carrillo-Cisneros1a222752017-07-17 21:25:41 -07001967 ff->ph->env.nr_pmu_mappings = pmu_num;
Masami Hiramatsu642aada2016-05-10 14:47:35 +09001968 if (strbuf_init(&sb, 128) < 0)
1969 return -1;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001970
1971 while (pmu_num) {
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07001972 if (do_read_u32(ff, &type))
Namhyung Kima1ae5652012-09-24 17:14:59 +09001973 goto error;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001974
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07001975 name = do_read_string(ff);
Namhyung Kima1ae5652012-09-24 17:14:59 +09001976 if (!name)
1977 goto error;
1978
Masami Hiramatsu642aada2016-05-10 14:47:35 +09001979 if (strbuf_addf(&sb, "%u:%s", type, name) < 0)
1980 goto error;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001981 /* include a NULL character at the end */
Masami Hiramatsu642aada2016-05-10 14:47:35 +09001982 if (strbuf_add(&sb, "", 1) < 0)
1983 goto error;
Namhyung Kima1ae5652012-09-24 17:14:59 +09001984
Kan Liange0838e02015-09-10 11:03:05 -03001985 if (!strcmp(name, "msr"))
David Carrillo-Cisneros1a222752017-07-17 21:25:41 -07001986 ff->ph->env.msr_pmu_type = type;
Kan Liange0838e02015-09-10 11:03:05 -03001987
Namhyung Kima1ae5652012-09-24 17:14:59 +09001988 free(name);
1989 pmu_num--;
1990 }
David Carrillo-Cisneros1a222752017-07-17 21:25:41 -07001991 ff->ph->env.pmu_mappings = strbuf_detach(&sb, NULL);
Namhyung Kima1ae5652012-09-24 17:14:59 +09001992 return 0;
1993
1994error:
1995 strbuf_release(&sb);
1996 return -1;
1997}
1998
David Carrillo-Cisneros62552452017-07-17 21:25:42 -07001999static int process_group_desc(struct feat_fd *ff, void *data __maybe_unused)
Namhyung Kima8bb5592013-01-22 18:09:31 +09002000{
2001 size_t ret = -1;
2002 u32 i, nr, nr_groups;
2003 struct perf_session *session;
2004 struct perf_evsel *evsel, *leader = NULL;
2005 struct group_desc {
2006 char *name;
2007 u32 leader_idx;
2008 u32 nr_members;
2009 } *desc;
2010
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07002011 if (do_read_u32(ff, &nr_groups))
Namhyung Kima8bb5592013-01-22 18:09:31 +09002012 return -1;
2013
David Carrillo-Cisneros1a222752017-07-17 21:25:41 -07002014 ff->ph->env.nr_groups = nr_groups;
Namhyung Kima8bb5592013-01-22 18:09:31 +09002015 if (!nr_groups) {
2016 pr_debug("group desc not available\n");
2017 return 0;
2018 }
2019
2020 desc = calloc(nr_groups, sizeof(*desc));
2021 if (!desc)
2022 return -1;
2023
2024 for (i = 0; i < nr_groups; i++) {
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07002025 desc[i].name = do_read_string(ff);
Namhyung Kima8bb5592013-01-22 18:09:31 +09002026 if (!desc[i].name)
2027 goto out_free;
2028
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07002029 if (do_read_u32(ff, &desc[i].leader_idx))
Namhyung Kima8bb5592013-01-22 18:09:31 +09002030 goto out_free;
2031
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07002032 if (do_read_u32(ff, &desc[i].nr_members))
Namhyung Kima8bb5592013-01-22 18:09:31 +09002033 goto out_free;
Namhyung Kima8bb5592013-01-22 18:09:31 +09002034 }
2035
2036 /*
2037 * Rebuild group relationship based on the group_desc
2038 */
David Carrillo-Cisneros1a222752017-07-17 21:25:41 -07002039 session = container_of(ff->ph, struct perf_session, header);
Namhyung Kima8bb5592013-01-22 18:09:31 +09002040 session->evlist->nr_groups = nr_groups;
2041
2042 i = nr = 0;
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -03002043 evlist__for_each_entry(session->evlist, evsel) {
Namhyung Kima8bb5592013-01-22 18:09:31 +09002044 if (evsel->idx == (int) desc[i].leader_idx) {
2045 evsel->leader = evsel;
2046 /* {anon_group} is a dummy name */
Namhyung Kim210e8122013-11-18 11:20:43 +09002047 if (strcmp(desc[i].name, "{anon_group}")) {
Namhyung Kima8bb5592013-01-22 18:09:31 +09002048 evsel->group_name = desc[i].name;
Namhyung Kim210e8122013-11-18 11:20:43 +09002049 desc[i].name = NULL;
2050 }
Namhyung Kima8bb5592013-01-22 18:09:31 +09002051 evsel->nr_members = desc[i].nr_members;
2052
2053 if (i >= nr_groups || nr > 0) {
2054 pr_debug("invalid group desc\n");
2055 goto out_free;
2056 }
2057
2058 leader = evsel;
2059 nr = evsel->nr_members - 1;
2060 i++;
2061 } else if (nr) {
2062 /* This is a group member */
2063 evsel->leader = leader;
2064
2065 nr--;
2066 }
2067 }
2068
2069 if (i != nr_groups || nr != 0) {
2070 pr_debug("invalid group desc\n");
2071 goto out_free;
2072 }
2073
2074 ret = 0;
2075out_free:
Namhyung Kim50a27402013-11-18 11:20:44 +09002076 for (i = 0; i < nr_groups; i++)
Arnaldo Carvalho de Melo74cf2492013-12-27 16:55:14 -03002077 zfree(&desc[i].name);
Namhyung Kima8bb5592013-01-22 18:09:31 +09002078 free(desc);
2079
2080 return ret;
2081}
2082
David Carrillo-Cisneros62552452017-07-17 21:25:42 -07002083static int process_auxtrace(struct feat_fd *ff, void *data __maybe_unused)
Adrian Hunter99fa2982015-04-30 17:37:25 +03002084{
2085 struct perf_session *session;
2086 int err;
2087
David Carrillo-Cisneros1a222752017-07-17 21:25:41 -07002088 session = container_of(ff->ph, struct perf_session, header);
Adrian Hunter99fa2982015-04-30 17:37:25 +03002089
David Carrillo-Cisneros62552452017-07-17 21:25:42 -07002090 err = auxtrace_index__process(ff->fd, ff->size, session,
David Carrillo-Cisneros1a222752017-07-17 21:25:41 -07002091 ff->ph->needs_swap);
Adrian Hunter99fa2982015-04-30 17:37:25 +03002092 if (err < 0)
2093 pr_err("Failed to process auxtrace index\n");
2094 return err;
2095}
2096
David Carrillo-Cisneros62552452017-07-17 21:25:42 -07002097static int process_cache(struct feat_fd *ff, void *data __maybe_unused)
Jiri Olsa720e98b2016-02-16 16:01:43 +01002098{
2099 struct cpu_cache_level *caches;
2100 u32 cnt, i, version;
2101
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07002102 if (do_read_u32(ff, &version))
Jiri Olsa720e98b2016-02-16 16:01:43 +01002103 return -1;
2104
Jiri Olsa720e98b2016-02-16 16:01:43 +01002105 if (version != 1)
2106 return -1;
2107
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07002108 if (do_read_u32(ff, &cnt))
Jiri Olsa720e98b2016-02-16 16:01:43 +01002109 return -1;
2110
Jiri Olsa720e98b2016-02-16 16:01:43 +01002111 caches = zalloc(sizeof(*caches) * cnt);
2112 if (!caches)
2113 return -1;
2114
2115 for (i = 0; i < cnt; i++) {
2116 struct cpu_cache_level c;
2117
2118 #define _R(v) \
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07002119 if (do_read_u32(ff, &c.v))\
Jiri Olsa720e98b2016-02-16 16:01:43 +01002120 goto out_free_caches; \
Jiri Olsa720e98b2016-02-16 16:01:43 +01002121
2122 _R(level)
2123 _R(line_size)
2124 _R(sets)
2125 _R(ways)
2126 #undef _R
2127
David Carrillo-Cisneros1a222752017-07-17 21:25:41 -07002128 #define _R(v) \
David Carrillo-Cisneros48e5fce2017-07-17 21:25:43 -07002129 c.v = do_read_string(ff); \
David Carrillo-Cisneros1a222752017-07-17 21:25:41 -07002130 if (!c.v) \
Jiri Olsa720e98b2016-02-16 16:01:43 +01002131 goto out_free_caches;
2132
2133 _R(type)
2134 _R(size)
2135 _R(map)
2136 #undef _R
2137
2138 caches[i] = c;
2139 }
2140
David Carrillo-Cisneros1a222752017-07-17 21:25:41 -07002141 ff->ph->env.caches = caches;
2142 ff->ph->env.caches_cnt = cnt;
Jiri Olsa720e98b2016-02-16 16:01:43 +01002143 return 0;
2144out_free_caches:
2145 free(caches);
2146 return -1;
2147}
2148
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002149struct feature_ops {
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -07002150 int (*write)(struct feat_fd *ff, struct perf_evlist *evlist);
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07002151 void (*print)(struct feat_fd *ff, FILE *fp);
David Carrillo-Cisneros62552452017-07-17 21:25:42 -07002152 int (*process)(struct feat_fd *ff, void *data);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002153 const char *name;
2154 bool full_only;
David Carrillo-Cisnerosa4d8c982017-07-17 21:25:46 -07002155 bool synthesize;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002156};
2157
David Carrillo-Cisnerosa4d8c982017-07-17 21:25:46 -07002158#define FEAT_OPR(n, func, __full_only) \
2159 [HEADER_##n] = { \
2160 .name = __stringify(n), \
2161 .write = write_##func, \
2162 .print = print_##func, \
2163 .full_only = __full_only, \
2164 .process = process_##func, \
2165 .synthesize = true \
2166 }
2167
2168#define FEAT_OPN(n, func, __full_only) \
2169 [HEADER_##n] = { \
2170 .name = __stringify(n), \
2171 .write = write_##func, \
2172 .print = print_##func, \
2173 .full_only = __full_only, \
2174 .process = process_##func \
2175 }
Robert Richter8cdfa782011-12-07 10:02:56 +01002176
2177/* feature_ops not implemented: */
Stephane Eranian2eeaaa02012-05-15 13:28:13 +02002178#define print_tracing_data NULL
2179#define print_build_id NULL
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002180
David Carrillo-Cisnerosa4d8c982017-07-17 21:25:46 -07002181#define process_branch_stack NULL
2182#define process_stat NULL
2183
2184
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002185static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
David Carrillo-Cisnerosa4d8c982017-07-17 21:25:46 -07002186 FEAT_OPN(TRACING_DATA, tracing_data, false),
2187 FEAT_OPN(BUILD_ID, build_id, false),
2188 FEAT_OPR(HOSTNAME, hostname, false),
2189 FEAT_OPR(OSRELEASE, osrelease, false),
2190 FEAT_OPR(VERSION, version, false),
2191 FEAT_OPR(ARCH, arch, false),
2192 FEAT_OPR(NRCPUS, nrcpus, false),
2193 FEAT_OPR(CPUDESC, cpudesc, false),
2194 FEAT_OPR(CPUID, cpuid, false),
2195 FEAT_OPR(TOTAL_MEM, total_mem, false),
2196 FEAT_OPR(EVENT_DESC, event_desc, false),
2197 FEAT_OPR(CMDLINE, cmdline, false),
2198 FEAT_OPR(CPU_TOPOLOGY, cpu_topology, true),
2199 FEAT_OPR(NUMA_TOPOLOGY, numa_topology, true),
2200 FEAT_OPN(BRANCH_STACK, branch_stack, false),
2201 FEAT_OPR(PMU_MAPPINGS, pmu_mappings, false),
2202 FEAT_OPN(GROUP_DESC, group_desc, false),
2203 FEAT_OPN(AUXTRACE, auxtrace, false),
2204 FEAT_OPN(STAT, stat, false),
2205 FEAT_OPN(CACHE, cache, true),
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002206};
2207
2208struct header_print_data {
2209 FILE *fp;
2210 bool full; /* extended list of headers */
2211};
2212
2213static int perf_file_section__fprintf_info(struct perf_file_section *section,
2214 struct perf_header *ph,
2215 int feat, int fd, void *data)
2216{
2217 struct header_print_data *hd = data;
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07002218 struct feat_fd ff;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002219
2220 if (lseek(fd, section->offset, SEEK_SET) == (off_t)-1) {
2221 pr_debug("Failed to lseek to %" PRIu64 " offset for feature "
2222 "%d, continuing...\n", section->offset, feat);
2223 return 0;
2224 }
Robert Richterb1e5a9b2011-12-07 10:02:57 +01002225 if (feat >= HEADER_LAST_FEATURE) {
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002226 pr_warning("unknown feature %d\n", feat);
Robert Richterf7a8a132011-12-07 10:02:51 +01002227 return 0;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002228 }
2229 if (!feat_ops[feat].print)
2230 return 0;
2231
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07002232 ff = (struct feat_fd) {
2233 .fd = fd,
2234 .ph = ph,
2235 };
2236
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002237 if (!feat_ops[feat].full_only || hd->full)
David Carrillo-Cisneroscfc65422017-07-17 21:25:40 -07002238 feat_ops[feat].print(&ff, hd->fp);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002239 else
2240 fprintf(hd->fp, "# %s info available, use -I to display\n",
2241 feat_ops[feat].name);
2242
2243 return 0;
2244}
2245
2246int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full)
2247{
2248 struct header_print_data hd;
2249 struct perf_header *header = &session->header;
Jiri Olsa8ceb41d2017-01-23 22:07:59 +01002250 int fd = perf_data__fd(session->data);
Jiri Olsaf45f5612016-10-10 09:03:07 +02002251 struct stat st;
Jiri Olsaaabae162016-10-10 09:35:50 +02002252 int ret, bit;
Jiri Olsaf45f5612016-10-10 09:03:07 +02002253
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002254 hd.fp = fp;
2255 hd.full = full;
2256
Jiri Olsaf45f5612016-10-10 09:03:07 +02002257 ret = fstat(fd, &st);
2258 if (ret == -1)
2259 return -1;
2260
2261 fprintf(fp, "# captured on: %s", ctime(&st.st_ctime));
2262
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002263 perf_header__process_sections(header, fd, &hd,
2264 perf_file_section__fprintf_info);
Jiri Olsaaabae162016-10-10 09:35:50 +02002265
Jiri Olsa8ceb41d2017-01-23 22:07:59 +01002266 if (session->data->is_pipe)
David Carrillo-Cisnerosc9d1c932017-04-10 13:14:32 -07002267 return 0;
2268
Jiri Olsaaabae162016-10-10 09:35:50 +02002269 fprintf(fp, "# missing features: ");
2270 for_each_clear_bit(bit, header->adds_features, HEADER_LAST_FEATURE) {
2271 if (bit)
2272 fprintf(fp, "%s ", feat_ops[bit].name);
2273 }
2274
2275 fprintf(fp, "\n");
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002276 return 0;
2277}
2278
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -07002279static int do_write_feat(struct feat_fd *ff, int type,
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002280 struct perf_file_section **p,
2281 struct perf_evlist *evlist)
2282{
2283 int err;
2284 int ret = 0;
2285
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -07002286 if (perf_header__has_feat(ff->ph, type)) {
Robert Richterb1e5a9b2011-12-07 10:02:57 +01002287 if (!feat_ops[type].write)
2288 return -1;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002289
David Carrillo-Cisneros0b3d3412017-07-17 21:25:45 -07002290 if (WARN(ff->buf, "Error: calling %s in pipe-mode.\n", __func__))
2291 return -1;
2292
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -07002293 (*p)->offset = lseek(ff->fd, 0, SEEK_CUR);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002294
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -07002295 err = feat_ops[type].write(ff, evlist);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002296 if (err < 0) {
Jiri Olsa0c2aff42016-10-10 09:38:02 +02002297 pr_debug("failed to write feature %s\n", feat_ops[type].name);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002298
2299 /* undo anything written */
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -07002300 lseek(ff->fd, (*p)->offset, SEEK_SET);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002301
2302 return -1;
2303 }
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -07002304 (*p)->size = lseek(ff->fd, 0, SEEK_CUR) - (*p)->offset;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002305 (*p)++;
2306 }
2307 return ret;
2308}
2309
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002310static int perf_header__adds_write(struct perf_header *header,
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -02002311 struct perf_evlist *evlist, int fd)
Frederic Weisbecker2ba08252009-10-17 17:12:34 +02002312{
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002313 int nr_sections;
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -07002314 struct feat_fd ff;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002315 struct perf_file_section *feat_sec, *p;
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002316 int sec_size;
2317 u64 sec_start;
Robert Richterb1e5a9b2011-12-07 10:02:57 +01002318 int feat;
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002319 int err;
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002320
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -07002321 ff = (struct feat_fd){
2322 .fd = fd,
2323 .ph = header,
2324 };
2325
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002326 nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS);
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002327 if (!nr_sections)
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -02002328 return 0;
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002329
Paul Gortmaker91b98802013-01-30 20:05:49 -05002330 feat_sec = p = calloc(nr_sections, sizeof(*feat_sec));
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -02002331 if (feat_sec == NULL)
2332 return -ENOMEM;
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002333
2334 sec_size = sizeof(*feat_sec) * nr_sections;
2335
Jiri Olsa8d541e92013-07-17 19:49:44 +02002336 sec_start = header->feat_offset;
Xiao Guangrongf887f302010-02-04 16:46:42 +08002337 lseek(fd, sec_start + sec_size, SEEK_SET);
Frederic Weisbecker2ba08252009-10-17 17:12:34 +02002338
Robert Richterb1e5a9b2011-12-07 10:02:57 +01002339 for_each_set_bit(feat, header->adds_features, HEADER_FEAT_BITS) {
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -07002340 if (do_write_feat(&ff, feat, &p, evlist))
Robert Richterb1e5a9b2011-12-07 10:02:57 +01002341 perf_header__clear_feat(header, feat);
2342 }
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002343
Xiao Guangrongf887f302010-02-04 16:46:42 +08002344 lseek(fd, sec_start, SEEK_SET);
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002345 /*
2346 * may write more than needed due to dropped feature, but
2347 * this is okay, reader will skip the mising entries
2348 */
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -07002349 err = do_write(&ff, feat_sec, sec_size);
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -02002350 if (err < 0)
2351 pr_debug("failed to write feature section\n");
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002352 free(feat_sec);
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -02002353 return err;
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002354}
Frederic Weisbecker2ba08252009-10-17 17:12:34 +02002355
Tom Zanussi8dc58102010-04-01 23:59:15 -05002356int perf_header__write_pipe(int fd)
2357{
2358 struct perf_pipe_file_header f_header;
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -07002359 struct feat_fd ff;
Tom Zanussi8dc58102010-04-01 23:59:15 -05002360 int err;
2361
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -07002362 ff = (struct feat_fd){ .fd = fd };
2363
Tom Zanussi8dc58102010-04-01 23:59:15 -05002364 f_header = (struct perf_pipe_file_header){
2365 .magic = PERF_MAGIC,
2366 .size = sizeof(f_header),
2367 };
2368
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -07002369 err = do_write(&ff, &f_header, sizeof(f_header));
Tom Zanussi8dc58102010-04-01 23:59:15 -05002370 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;
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -07002386 struct feat_fd ff;
Jiri Olsa944d62b2013-07-17 19:49:43 +02002387 u64 attr_offset;
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002388 int err;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002389
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -07002390 ff = (struct feat_fd){ .fd = fd};
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002391 lseek(fd, sizeof(f_header), SEEK_SET);
2392
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -03002393 evlist__for_each_entry(session->evlist, evsel) {
Robert Richter6606f872012-08-16 21:10:19 +02002394 evsel->id_offset = lseek(fd, 0, SEEK_CUR);
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -07002395 err = do_write(&ff, evsel->id, evsel->ids * sizeof(u64));
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -02002396 if (err < 0) {
2397 pr_debug("failed to write perf header\n");
2398 return err;
2399 }
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002400 }
2401
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -07002402 attr_offset = lseek(ff.fd, 0, SEEK_CUR);
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002403
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -03002404 evlist__for_each_entry(evlist, evsel) {
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002405 f_attr = (struct perf_file_attr){
Robert Richter6606f872012-08-16 21:10:19 +02002406 .attr = evsel->attr,
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002407 .ids = {
Robert Richter6606f872012-08-16 21:10:19 +02002408 .offset = evsel->id_offset,
2409 .size = evsel->ids * sizeof(u64),
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002410 }
2411 };
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -07002412 err = do_write(&ff, &f_attr, sizeof(f_attr));
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -02002413 if (err < 0) {
2414 pr_debug("failed to write perf header attribute\n");
2415 return err;
2416 }
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002417 }
2418
Adrian Hunterd645c442013-12-11 14:36:28 +02002419 if (!header->data_offset)
2420 header->data_offset = lseek(fd, 0, SEEK_CUR);
Jiri Olsa8d541e92013-07-17 19:49:44 +02002421 header->feat_offset = header->data_offset + header->data_size;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002422
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -02002423 if (at_exit) {
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002424 err = perf_header__adds_write(header, evlist, fd);
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -02002425 if (err < 0)
2426 return err;
2427 }
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002428
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002429 f_header = (struct perf_file_header){
2430 .magic = PERF_MAGIC,
2431 .size = sizeof(f_header),
2432 .attr_size = sizeof(f_attr),
2433 .attrs = {
Jiri Olsa944d62b2013-07-17 19:49:43 +02002434 .offset = attr_offset,
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002435 .size = evlist->nr_entries * sizeof(f_attr),
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002436 },
2437 .data = {
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002438 .offset = header->data_offset,
2439 .size = header->data_size,
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002440 },
Jiri Olsa44b3c572013-07-11 17:28:31 +02002441 /* event_types is ignored, store zeros */
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002442 };
2443
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002444 memcpy(&f_header.adds_features, &header->adds_features, sizeof(header->adds_features));
Frederic Weisbecker2ba08252009-10-17 17:12:34 +02002445
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002446 lseek(fd, 0, SEEK_SET);
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -07002447 err = do_write(&ff, &f_header, sizeof(f_header));
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -02002448 if (err < 0) {
2449 pr_debug("failed to write perf header\n");
2450 return err;
2451 }
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002452 lseek(fd, header->data_offset + header->data_size, SEEK_SET);
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002453
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -02002454 return 0;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002455}
2456
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002457static int perf_header__getbuffer64(struct perf_header *header,
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -02002458 int fd, void *buf, size_t size)
2459{
Arnaldo Carvalho de Melo1e7972c2011-01-03 16:50:55 -02002460 if (readn(fd, buf, size) <= 0)
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -02002461 return -1;
2462
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002463 if (header->needs_swap)
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -02002464 mem_bswap_64(buf, size);
2465
2466 return 0;
2467}
2468
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002469int perf_header__process_sections(struct perf_header *header, int fd,
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002470 void *data,
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002471 int (*process)(struct perf_file_section *section,
Robert Richterb1e5a9b2011-12-07 10:02:57 +01002472 struct perf_header *ph,
2473 int feat, int fd, void *data))
Frederic Weisbecker2ba08252009-10-17 17:12:34 +02002474{
Robert Richterb1e5a9b2011-12-07 10:02:57 +01002475 struct perf_file_section *feat_sec, *sec;
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002476 int nr_sections;
2477 int sec_size;
Robert Richterb1e5a9b2011-12-07 10:02:57 +01002478 int feat;
2479 int err;
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002480
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002481 nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS);
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002482 if (!nr_sections)
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002483 return 0;
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002484
Paul Gortmaker91b98802013-01-30 20:05:49 -05002485 feat_sec = sec = calloc(nr_sections, sizeof(*feat_sec));
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002486 if (!feat_sec)
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002487 return -1;
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002488
2489 sec_size = sizeof(*feat_sec) * nr_sections;
2490
Jiri Olsa8d541e92013-07-17 19:49:44 +02002491 lseek(fd, header->feat_offset, SEEK_SET);
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002492
Robert Richterb1e5a9b2011-12-07 10:02:57 +01002493 err = perf_header__getbuffer64(header, fd, feat_sec, sec_size);
2494 if (err < 0)
Arnaldo Carvalho de Melo769885f2009-12-28 22:48:32 -02002495 goto out_free;
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002496
Robert Richterb1e5a9b2011-12-07 10:02:57 +01002497 for_each_set_bit(feat, header->adds_features, HEADER_LAST_FEATURE) {
2498 err = process(sec++, header, feat, fd, data);
2499 if (err < 0)
2500 goto out_free;
Frederic Weisbecker4778d2e2009-11-11 04:51:05 +01002501 }
Robert Richterb1e5a9b2011-12-07 10:02:57 +01002502 err = 0;
Arnaldo Carvalho de Melo769885f2009-12-28 22:48:32 -02002503out_free:
Frederic Weisbecker9e827dd2009-11-11 04:51:07 +01002504 free(feat_sec);
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002505 return err;
Arnaldo Carvalho de Melo769885f2009-12-28 22:48:32 -02002506}
Frederic Weisbecker2ba08252009-10-17 17:12:34 +02002507
Stephane Eranian114382a2012-02-09 23:21:08 +01002508static const int attr_file_abi_sizes[] = {
2509 [0] = PERF_ATTR_SIZE_VER0,
2510 [1] = PERF_ATTR_SIZE_VER1,
Jiri Olsa239cc472012-08-07 15:20:42 +02002511 [2] = PERF_ATTR_SIZE_VER2,
Jiri Olsa0f6a3012012-08-07 15:20:45 +02002512 [3] = PERF_ATTR_SIZE_VER3,
Stephane Eranian6a21c0b2014-09-24 13:48:39 +02002513 [4] = PERF_ATTR_SIZE_VER4,
Stephane Eranian114382a2012-02-09 23:21:08 +01002514 0,
2515};
2516
2517/*
2518 * In the legacy file format, the magic number is not used to encode endianness.
2519 * hdr_sz was used to encode endianness. But given that hdr_sz can vary based
2520 * on ABI revisions, we need to try all combinations for all endianness to
2521 * detect the endianness.
2522 */
2523static int try_all_file_abis(uint64_t hdr_sz, struct perf_header *ph)
2524{
2525 uint64_t ref_size, attr_size;
2526 int i;
2527
2528 for (i = 0 ; attr_file_abi_sizes[i]; i++) {
2529 ref_size = attr_file_abi_sizes[i]
2530 + sizeof(struct perf_file_section);
2531 if (hdr_sz != ref_size) {
2532 attr_size = bswap_64(hdr_sz);
2533 if (attr_size != ref_size)
2534 continue;
2535
2536 ph->needs_swap = true;
2537 }
2538 pr_debug("ABI%d perf.data file detected, need_swap=%d\n",
2539 i,
2540 ph->needs_swap);
2541 return 0;
2542 }
2543 /* could not determine endianness */
2544 return -1;
2545}
2546
2547#define PERF_PIPE_HDR_VER0 16
2548
2549static const size_t attr_pipe_abi_sizes[] = {
2550 [0] = PERF_PIPE_HDR_VER0,
2551 0,
2552};
2553
2554/*
2555 * In the legacy pipe format, there is an implicit assumption that endiannesss
2556 * between host recording the samples, and host parsing the samples is the
2557 * same. This is not always the case given that the pipe output may always be
2558 * redirected into a file and analyzed on a different machine with possibly a
2559 * different endianness and perf_event ABI revsions in the perf tool itself.
2560 */
2561static int try_all_pipe_abis(uint64_t hdr_sz, struct perf_header *ph)
2562{
2563 u64 attr_size;
2564 int i;
2565
2566 for (i = 0 ; attr_pipe_abi_sizes[i]; i++) {
2567 if (hdr_sz != attr_pipe_abi_sizes[i]) {
2568 attr_size = bswap_64(hdr_sz);
2569 if (attr_size != hdr_sz)
2570 continue;
2571
2572 ph->needs_swap = true;
2573 }
2574 pr_debug("Pipe ABI%d perf.data file detected\n", i);
2575 return 0;
2576 }
2577 return -1;
2578}
2579
Feng Tange84ba4e2012-10-30 11:56:07 +08002580bool is_perf_magic(u64 magic)
2581{
2582 if (!memcmp(&magic, __perf_magic1, sizeof(magic))
2583 || magic == __perf_magic2
2584 || magic == __perf_magic2_sw)
2585 return true;
2586
2587 return false;
2588}
2589
Stephane Eranian114382a2012-02-09 23:21:08 +01002590static int check_magic_endian(u64 magic, uint64_t hdr_sz,
2591 bool is_pipe, struct perf_header *ph)
Stephane Eranian73323f52012-02-02 13:54:44 +01002592{
2593 int ret;
2594
2595 /* check for legacy format */
Stephane Eranian114382a2012-02-09 23:21:08 +01002596 ret = memcmp(&magic, __perf_magic1, sizeof(magic));
Stephane Eranian73323f52012-02-02 13:54:44 +01002597 if (ret == 0) {
Jiri Olsa2a08c3e2013-07-17 19:49:47 +02002598 ph->version = PERF_HEADER_VERSION_1;
Stephane Eranian73323f52012-02-02 13:54:44 +01002599 pr_debug("legacy perf.data format\n");
Stephane Eranian114382a2012-02-09 23:21:08 +01002600 if (is_pipe)
2601 return try_all_pipe_abis(hdr_sz, ph);
Stephane Eranian73323f52012-02-02 13:54:44 +01002602
Stephane Eranian114382a2012-02-09 23:21:08 +01002603 return try_all_file_abis(hdr_sz, ph);
Stephane Eranian73323f52012-02-02 13:54:44 +01002604 }
Stephane Eranian114382a2012-02-09 23:21:08 +01002605 /*
2606 * the new magic number serves two purposes:
2607 * - unique number to identify actual perf.data files
2608 * - encode endianness of file
2609 */
Namhyung Kimf7913972015-01-29 17:06:45 +09002610 ph->version = PERF_HEADER_VERSION_2;
Stephane Eranian73323f52012-02-02 13:54:44 +01002611
Stephane Eranian114382a2012-02-09 23:21:08 +01002612 /* check magic number with one endianness */
2613 if (magic == __perf_magic2)
Stephane Eranian73323f52012-02-02 13:54:44 +01002614 return 0;
2615
Stephane Eranian114382a2012-02-09 23:21:08 +01002616 /* check magic number with opposite endianness */
2617 if (magic != __perf_magic2_sw)
Stephane Eranian73323f52012-02-02 13:54:44 +01002618 return -1;
2619
2620 ph->needs_swap = true;
2621
2622 return 0;
2623}
2624
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002625int perf_file_header__read(struct perf_file_header *header,
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002626 struct perf_header *ph, int fd)
2627{
Jiri Olsa727ebd52013-11-28 11:30:14 +01002628 ssize_t ret;
Stephane Eranian73323f52012-02-02 13:54:44 +01002629
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002630 lseek(fd, 0, SEEK_SET);
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002631
Stephane Eranian73323f52012-02-02 13:54:44 +01002632 ret = readn(fd, header, sizeof(*header));
2633 if (ret <= 0)
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002634 return -1;
2635
Stephane Eranian114382a2012-02-09 23:21:08 +01002636 if (check_magic_endian(header->magic,
2637 header->attr_size, false, ph) < 0) {
2638 pr_debug("magic/endian check failed\n");
Stephane Eranian73323f52012-02-02 13:54:44 +01002639 return -1;
Stephane Eranian114382a2012-02-09 23:21:08 +01002640 }
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -02002641
Stephane Eranian73323f52012-02-02 13:54:44 +01002642 if (ph->needs_swap) {
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002643 mem_bswap_64(header, offsetof(struct perf_file_header,
Stephane Eranian73323f52012-02-02 13:54:44 +01002644 adds_features));
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -02002645 }
2646
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002647 if (header->size != sizeof(*header)) {
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002648 /* Support the previous format */
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002649 if (header->size == offsetof(typeof(*header), adds_features))
2650 bitmap_zero(header->adds_features, HEADER_FEAT_BITS);
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002651 else
2652 return -1;
David Ahernd327fa42011-10-18 17:34:01 -06002653 } else if (ph->needs_swap) {
David Ahernd327fa42011-10-18 17:34:01 -06002654 /*
2655 * feature bitmap is declared as an array of unsigned longs --
2656 * not good since its size can differ between the host that
2657 * generated the data file and the host analyzing the file.
2658 *
2659 * We need to handle endianness, but we don't know the size of
2660 * the unsigned long where the file was generated. Take a best
2661 * guess at determining it: try 64-bit swap first (ie., file
2662 * created on a 64-bit host), and check if the hostname feature
2663 * bit is set (this feature bit is forced on as of fbe96f2).
2664 * If the bit is not, undo the 64-bit swap and try a 32-bit
2665 * swap. If the hostname bit is still not set (e.g., older data
2666 * file), punt and fallback to the original behavior --
2667 * clearing all feature bits and setting buildid.
2668 */
David Ahern80c01202012-06-08 11:47:51 -03002669 mem_bswap_64(&header->adds_features,
2670 BITS_TO_U64(HEADER_FEAT_BITS));
David Ahernd327fa42011-10-18 17:34:01 -06002671
2672 if (!test_bit(HEADER_HOSTNAME, header->adds_features)) {
David Ahern80c01202012-06-08 11:47:51 -03002673 /* unswap as u64 */
2674 mem_bswap_64(&header->adds_features,
2675 BITS_TO_U64(HEADER_FEAT_BITS));
2676
2677 /* unswap as u32 */
2678 mem_bswap_32(&header->adds_features,
2679 BITS_TO_U32(HEADER_FEAT_BITS));
David Ahernd327fa42011-10-18 17:34:01 -06002680 }
2681
2682 if (!test_bit(HEADER_HOSTNAME, header->adds_features)) {
2683 bitmap_zero(header->adds_features, HEADER_FEAT_BITS);
2684 set_bit(HEADER_BUILD_ID, header->adds_features);
2685 }
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002686 }
2687
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002688 memcpy(&ph->adds_features, &header->adds_features,
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -02002689 sizeof(ph->adds_features));
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002690
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002691 ph->data_offset = header->data.offset;
2692 ph->data_size = header->data.size;
Jiri Olsa8d541e92013-07-17 19:49:44 +02002693 ph->feat_offset = header->data.offset + header->data.size;
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002694 return 0;
2695}
2696
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002697static int perf_file_section__process(struct perf_file_section *section,
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -02002698 struct perf_header *ph,
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -03002699 int feat, int fd, void *data)
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002700{
David Carrillo-Cisneros62552452017-07-17 21:25:42 -07002701 struct feat_fd fdd = {
David Carrillo-Cisneros1a222752017-07-17 21:25:41 -07002702 .fd = fd,
2703 .ph = ph,
David Carrillo-Cisneros62552452017-07-17 21:25:42 -07002704 .size = section->size,
2705 .offset = section->offset,
David Carrillo-Cisneros1a222752017-07-17 21:25:41 -07002706 };
2707
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002708 if (lseek(fd, section->offset, SEEK_SET) == (off_t)-1) {
Arnaldo Carvalho de Melo9486aa32011-01-22 20:37:02 -02002709 pr_debug("Failed to lseek to %" PRIu64 " offset for feature "
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002710 "%d, continuing...\n", section->offset, feat);
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002711 return 0;
2712 }
2713
Robert Richterb1e5a9b2011-12-07 10:02:57 +01002714 if (feat >= HEADER_LAST_FEATURE) {
2715 pr_debug("unknown feature %d, continuing...\n", feat);
2716 return 0;
2717 }
2718
Robert Richterf1c67db2012-02-10 15:41:56 +01002719 if (!feat_ops[feat].process)
2720 return 0;
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002721
David Carrillo-Cisneros62552452017-07-17 21:25:42 -07002722 return feat_ops[feat].process(&fdd, data);
Arnaldo Carvalho de Melo37562ea2009-11-16 16:32:43 -02002723}
2724
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002725static int perf_file_header__read_pipe(struct perf_pipe_file_header *header,
Tom Zanussi454c4072010-05-01 01:41:20 -05002726 struct perf_header *ph, int fd,
2727 bool repipe)
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002728{
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -07002729 struct feat_fd ff = {
2730 .fd = STDOUT_FILENO,
2731 .ph = ph,
2732 };
Jiri Olsa727ebd52013-11-28 11:30:14 +01002733 ssize_t ret;
Stephane Eranian73323f52012-02-02 13:54:44 +01002734
2735 ret = readn(fd, header, sizeof(*header));
2736 if (ret <= 0)
2737 return -1;
2738
Stephane Eranian114382a2012-02-09 23:21:08 +01002739 if (check_magic_endian(header->magic, header->size, true, ph) < 0) {
2740 pr_debug("endian/magic failed\n");
Tom Zanussi8dc58102010-04-01 23:59:15 -05002741 return -1;
Stephane Eranian114382a2012-02-09 23:21:08 +01002742 }
2743
2744 if (ph->needs_swap)
2745 header->size = bswap_64(header->size);
Tom Zanussi8dc58102010-04-01 23:59:15 -05002746
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -07002747 if (repipe && do_write(&ff, header, sizeof(*header)) < 0)
Tom Zanussi454c4072010-05-01 01:41:20 -05002748 return -1;
2749
Tom Zanussi8dc58102010-04-01 23:59:15 -05002750 return 0;
2751}
2752
Jiri Olsad4339562013-07-17 19:49:41 +02002753static int perf_header__read_pipe(struct perf_session *session)
Tom Zanussi8dc58102010-04-01 23:59:15 -05002754{
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002755 struct perf_header *header = &session->header;
Tom Zanussi8dc58102010-04-01 23:59:15 -05002756 struct perf_pipe_file_header f_header;
2757
Jiri Olsacc9784bd2013-10-15 16:27:34 +02002758 if (perf_file_header__read_pipe(&f_header, header,
Jiri Olsa8ceb41d2017-01-23 22:07:59 +01002759 perf_data__fd(session->data),
Tom Zanussi454c4072010-05-01 01:41:20 -05002760 session->repipe) < 0) {
Tom Zanussi8dc58102010-04-01 23:59:15 -05002761 pr_debug("incompatible file format\n");
2762 return -EINVAL;
2763 }
2764
Tom Zanussi8dc58102010-04-01 23:59:15 -05002765 return 0;
2766}
2767
Stephane Eranian69996df2012-02-09 23:21:06 +01002768static int read_attr(int fd, struct perf_header *ph,
2769 struct perf_file_attr *f_attr)
2770{
2771 struct perf_event_attr *attr = &f_attr->attr;
2772 size_t sz, left;
2773 size_t our_sz = sizeof(f_attr->attr);
Jiri Olsa727ebd52013-11-28 11:30:14 +01002774 ssize_t ret;
Stephane Eranian69996df2012-02-09 23:21:06 +01002775
2776 memset(f_attr, 0, sizeof(*f_attr));
2777
2778 /* read minimal guaranteed structure */
2779 ret = readn(fd, attr, PERF_ATTR_SIZE_VER0);
2780 if (ret <= 0) {
2781 pr_debug("cannot read %d bytes of header attr\n",
2782 PERF_ATTR_SIZE_VER0);
2783 return -1;
2784 }
2785
2786 /* on file perf_event_attr size */
2787 sz = attr->size;
Stephane Eranian114382a2012-02-09 23:21:08 +01002788
Stephane Eranian69996df2012-02-09 23:21:06 +01002789 if (ph->needs_swap)
2790 sz = bswap_32(sz);
2791
2792 if (sz == 0) {
2793 /* assume ABI0 */
2794 sz = PERF_ATTR_SIZE_VER0;
2795 } else if (sz > our_sz) {
2796 pr_debug("file uses a more recent and unsupported ABI"
2797 " (%zu bytes extra)\n", sz - our_sz);
2798 return -1;
2799 }
2800 /* what we have not yet read and that we know about */
2801 left = sz - PERF_ATTR_SIZE_VER0;
2802 if (left) {
2803 void *ptr = attr;
2804 ptr += PERF_ATTR_SIZE_VER0;
2805
2806 ret = readn(fd, ptr, left);
2807 }
2808 /* read perf_file_section, ids are read in caller */
2809 ret = readn(fd, &f_attr->ids, sizeof(f_attr->ids));
2810
2811 return ret <= 0 ? -1 : 0;
2812}
2813
Namhyung Kim831394b2012-09-06 11:10:46 +09002814static int perf_evsel__prepare_tracepoint_event(struct perf_evsel *evsel,
2815 struct pevent *pevent)
Arnaldo Carvalho de Melocb9dd492012-06-11 19:03:32 -03002816{
Namhyung Kim831394b2012-09-06 11:10:46 +09002817 struct event_format *event;
Arnaldo Carvalho de Melocb9dd492012-06-11 19:03:32 -03002818 char bf[128];
2819
Namhyung Kim831394b2012-09-06 11:10:46 +09002820 /* already prepared */
2821 if (evsel->tp_format)
2822 return 0;
2823
Namhyung Kim3dce2ce2013-03-21 16:18:48 +09002824 if (pevent == NULL) {
2825 pr_debug("broken or missing trace data\n");
2826 return -1;
2827 }
2828
Namhyung Kim831394b2012-09-06 11:10:46 +09002829 event = pevent_find_event(pevent, evsel->attr.config);
Namhyung Kima7619ae2013-04-18 21:24:16 +09002830 if (event == NULL) {
2831 pr_debug("cannot find event format for %d\n", (int)evsel->attr.config);
Arnaldo Carvalho de Melocb9dd492012-06-11 19:03:32 -03002832 return -1;
Namhyung Kima7619ae2013-04-18 21:24:16 +09002833 }
Arnaldo Carvalho de Melocb9dd492012-06-11 19:03:32 -03002834
Namhyung Kim831394b2012-09-06 11:10:46 +09002835 if (!evsel->name) {
2836 snprintf(bf, sizeof(bf), "%s:%s", event->system, event->name);
2837 evsel->name = strdup(bf);
2838 if (evsel->name == NULL)
2839 return -1;
2840 }
Arnaldo Carvalho de Melocb9dd492012-06-11 19:03:32 -03002841
Arnaldo Carvalho de Melofcf65bf2012-08-07 09:58:03 -03002842 evsel->tp_format = event;
Arnaldo Carvalho de Melocb9dd492012-06-11 19:03:32 -03002843 return 0;
2844}
2845
Namhyung Kim831394b2012-09-06 11:10:46 +09002846static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist,
2847 struct pevent *pevent)
Arnaldo Carvalho de Melocb9dd492012-06-11 19:03:32 -03002848{
2849 struct perf_evsel *pos;
2850
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -03002851 evlist__for_each_entry(evlist, pos) {
Namhyung Kim831394b2012-09-06 11:10:46 +09002852 if (pos->attr.type == PERF_TYPE_TRACEPOINT &&
2853 perf_evsel__prepare_tracepoint_event(pos, pevent))
Arnaldo Carvalho de Melocb9dd492012-06-11 19:03:32 -03002854 return -1;
2855 }
2856
2857 return 0;
2858}
2859
Jiri Olsad4339562013-07-17 19:49:41 +02002860int perf_session__read_header(struct perf_session *session)
Tom Zanussi8dc58102010-04-01 23:59:15 -05002861{
Jiri Olsa8ceb41d2017-01-23 22:07:59 +01002862 struct perf_data *data = session->data;
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002863 struct perf_header *header = &session->header;
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -02002864 struct perf_file_header f_header;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002865 struct perf_file_attr f_attr;
2866 u64 f_id;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002867 int nr_attrs, nr_ids, i, j;
Jiri Olsa8ceb41d2017-01-23 22:07:59 +01002868 int fd = perf_data__fd(data);
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002869
Namhyung Kim334fe7a2013-03-11 16:43:12 +09002870 session->evlist = perf_evlist__new();
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002871 if (session->evlist == NULL)
2872 return -ENOMEM;
2873
Kan Liang2c071442015-08-28 05:48:05 -04002874 session->evlist->env = &header->env;
Arnaldo Carvalho de Melo4cde9982015-09-09 12:25:00 -03002875 session->machines.host.env = &header->env;
Jiri Olsa8ceb41d2017-01-23 22:07:59 +01002876 if (perf_data__is_pipe(data))
Jiri Olsad4339562013-07-17 19:49:41 +02002877 return perf_header__read_pipe(session);
Tom Zanussi8dc58102010-04-01 23:59:15 -05002878
Stephane Eranian69996df2012-02-09 23:21:06 +01002879 if (perf_file_header__read(&f_header, header, fd) < 0)
Arnaldo Carvalho de Melo4dc0a042009-11-19 14:55:55 -02002880 return -EINVAL;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002881
Namhyung Kimb314e5c2013-09-30 17:19:48 +09002882 /*
2883 * Sanity check that perf.data was written cleanly; data size is
2884 * initialized to 0 and updated only if the on_exit function is run.
2885 * If data size is still 0 then the file contains only partial
2886 * information. Just warn user and process it as much as it can.
2887 */
2888 if (f_header.data.size == 0) {
2889 pr_warning("WARNING: The %s file's data size field is 0 which is unexpected.\n"
2890 "Was the 'perf record' command properly terminated?\n",
Jiri Olsaeae8ad82017-01-23 22:25:41 +01002891 data->file.path);
Namhyung Kimb314e5c2013-09-30 17:19:48 +09002892 }
2893
Stephane Eranian69996df2012-02-09 23:21:06 +01002894 nr_attrs = f_header.attrs.size / f_header.attr_size;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002895 lseek(fd, f_header.attrs.offset, SEEK_SET);
2896
2897 for (i = 0; i < nr_attrs; i++) {
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002898 struct perf_evsel *evsel;
Peter Zijlstra1c222bc2009-08-06 20:57:41 +02002899 off_t tmp;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002900
Stephane Eranian69996df2012-02-09 23:21:06 +01002901 if (read_attr(fd, header, &f_attr) < 0)
Arnaldo Carvalho de Melo769885f2009-12-28 22:48:32 -02002902 goto out_errno;
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -02002903
David Ahern1060ab82015-04-09 16:15:46 -04002904 if (header->needs_swap) {
2905 f_attr.ids.size = bswap_64(f_attr.ids.size);
2906 f_attr.ids.offset = bswap_64(f_attr.ids.offset);
David Aherneda39132011-07-15 12:34:09 -06002907 perf_event__attr_swap(&f_attr.attr);
David Ahern1060ab82015-04-09 16:15:46 -04002908 }
David Aherneda39132011-07-15 12:34:09 -06002909
Peter Zijlstra1c222bc2009-08-06 20:57:41 +02002910 tmp = lseek(fd, 0, SEEK_CUR);
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -03002911 evsel = perf_evsel__new(&f_attr.attr);
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002912
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002913 if (evsel == NULL)
2914 goto out_delete_evlist;
Arnaldo Carvalho de Melo0807d2d2012-09-26 12:48:18 -03002915
2916 evsel->needs_swap = header->needs_swap;
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002917 /*
2918 * Do it before so that if perf_evsel__alloc_id fails, this
2919 * entry gets purged too at perf_evlist__delete().
2920 */
2921 perf_evlist__add(session->evlist, evsel);
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002922
2923 nr_ids = f_attr.ids.size / sizeof(u64);
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002924 /*
2925 * We don't have the cpu and thread maps on the header, so
2926 * for allocating the perf_sample_id table we fake 1 cpu and
2927 * hattr->ids threads.
2928 */
2929 if (perf_evsel__alloc_id(evsel, 1, nr_ids))
2930 goto out_delete_evlist;
2931
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002932 lseek(fd, f_attr.ids.offset, SEEK_SET);
2933
2934 for (j = 0; j < nr_ids; j++) {
Arnaldo Carvalho de Melo1c0b04d2011-03-09 08:13:19 -03002935 if (perf_header__getbuffer64(header, fd, &f_id, sizeof(f_id)))
Arnaldo Carvalho de Melo769885f2009-12-28 22:48:32 -02002936 goto out_errno;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002937
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002938 perf_evlist__id_add(session->evlist, evsel, 0, j, f_id);
Arnaldo Carvalho de Melo4dc0a042009-11-19 14:55:55 -02002939 }
Arnaldo Carvalho de Melo11deb1f2009-11-17 01:18:09 -02002940
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002941 lseek(fd, tmp, SEEK_SET);
2942 }
2943
Arnaldo Carvalho de Melod04b35f2011-11-11 22:17:32 -02002944 symbol_conf.nr_events = nr_attrs;
2945
Jiri Olsa29f5ffd2013-12-03 14:09:23 +01002946 perf_header__process_sections(header, fd, &session->tevent,
Stephane Eranianfbe96f22011-09-30 15:40:40 +02002947 perf_file_section__process);
Frederic Weisbecker4778d2e2009-11-11 04:51:05 +01002948
Namhyung Kim831394b2012-09-06 11:10:46 +09002949 if (perf_evlist__prepare_tracepoint_events(session->evlist,
Jiri Olsa29f5ffd2013-12-03 14:09:23 +01002950 session->tevent.pevent))
Arnaldo Carvalho de Melocb9dd492012-06-11 19:03:32 -03002951 goto out_delete_evlist;
2952
Arnaldo Carvalho de Melo4dc0a042009-11-19 14:55:55 -02002953 return 0;
Arnaldo Carvalho de Melo769885f2009-12-28 22:48:32 -02002954out_errno:
2955 return -errno;
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03002956
2957out_delete_evlist:
2958 perf_evlist__delete(session->evlist);
2959 session->evlist = NULL;
2960 return -ENOMEM;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +02002961}
Frederic Weisbecker0d3a5c82009-08-16 20:56:37 +02002962
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -02002963int perf_event__synthesize_attr(struct perf_tool *tool,
Robert Richterf4d83432012-08-16 21:10:17 +02002964 struct perf_event_attr *attr, u32 ids, u64 *id,
Arnaldo Carvalho de Melo743eb862011-11-28 07:56:39 -02002965 perf_event__handler_t process)
Frederic Weisbecker0d3a5c82009-08-16 20:56:37 +02002966{
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -02002967 union perf_event *ev;
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05002968 size_t size;
2969 int err;
2970
2971 size = sizeof(struct perf_event_attr);
Irina Tirdea9ac3e482012-09-11 01:15:01 +03002972 size = PERF_ALIGN(size, sizeof(u64));
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05002973 size += sizeof(struct perf_event_header);
2974 size += ids * sizeof(u64);
2975
2976 ev = malloc(size);
2977
Chris Samuelce47dc52010-11-13 13:35:06 +11002978 if (ev == NULL)
2979 return -ENOMEM;
2980
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05002981 ev->attr.attr = *attr;
2982 memcpy(ev->attr.id, id, ids * sizeof(u64));
2983
2984 ev->attr.header.type = PERF_RECORD_HEADER_ATTR;
Robert Richterf4d83432012-08-16 21:10:17 +02002985 ev->attr.header.size = (u16)size;
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05002986
Robert Richterf4d83432012-08-16 21:10:17 +02002987 if (ev->attr.header.size == size)
2988 err = process(tool, ev, NULL, NULL);
2989 else
2990 err = -E2BIG;
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05002991
2992 free(ev);
2993
2994 return err;
2995}
2996
David Carrillo-Cisnerose9def1b2017-07-17 21:25:48 -07002997int perf_event__synthesize_features(struct perf_tool *tool,
2998 struct perf_session *session,
2999 struct perf_evlist *evlist,
3000 perf_event__handler_t process)
3001{
3002 struct perf_header *header = &session->header;
3003 struct feat_fd ff;
3004 struct feature_event *fe;
3005 size_t sz, sz_hdr;
3006 int feat, ret;
3007
3008 sz_hdr = sizeof(fe->header);
3009 sz = sizeof(union perf_event);
3010 /* get a nice alignment */
3011 sz = PERF_ALIGN(sz, page_size);
3012
3013 memset(&ff, 0, sizeof(ff));
3014
3015 ff.buf = malloc(sz);
3016 if (!ff.buf)
3017 return -ENOMEM;
3018
3019 ff.size = sz - sz_hdr;
3020
3021 for_each_set_bit(feat, header->adds_features, HEADER_FEAT_BITS) {
3022 if (!feat_ops[feat].synthesize) {
3023 pr_debug("No record header feature for header :%d\n", feat);
3024 continue;
3025 }
3026
3027 ff.offset = sizeof(*fe);
3028
3029 ret = feat_ops[feat].write(&ff, evlist);
3030 if (ret || ff.offset <= (ssize_t)sizeof(*fe)) {
3031 pr_debug("Error writing feature\n");
3032 continue;
3033 }
3034 /* ff.buf may have changed due to realloc in do_write() */
3035 fe = ff.buf;
3036 memset(fe, 0, sizeof(*fe));
3037
3038 fe->feat_id = feat;
3039 fe->header.type = PERF_RECORD_HEADER_FEATURE;
3040 fe->header.size = ff.offset;
3041
3042 ret = process(tool, ff.buf, NULL, NULL);
3043 if (ret) {
3044 free(ff.buf);
3045 return ret;
3046 }
3047 }
3048 free(ff.buf);
3049 return 0;
3050}
3051
3052int perf_event__process_feature(struct perf_tool *tool,
3053 union perf_event *event,
3054 struct perf_session *session __maybe_unused)
3055{
3056 struct feat_fd ff = { .fd = 0 };
3057 struct feature_event *fe = (struct feature_event *)event;
3058 int type = fe->header.type;
3059 u64 feat = fe->feat_id;
3060
3061 if (type < 0 || type >= PERF_RECORD_HEADER_MAX) {
3062 pr_warning("invalid record type %d in pipe-mode\n", type);
3063 return 0;
3064 }
3065 if (feat == HEADER_RESERVED || feat > HEADER_LAST_FEATURE) {
3066 pr_warning("invalid record type %d in pipe-mode\n", type);
3067 return -1;
3068 }
3069
3070 if (!feat_ops[feat].process)
3071 return 0;
3072
3073 ff.buf = (void *)fe->data;
3074 ff.size = event->header.size - sizeof(event->header);
3075 ff.ph = &session->header;
3076
3077 if (feat_ops[feat].process(&ff, NULL))
3078 return -1;
3079
3080 if (!feat_ops[feat].print || !tool->show_feat_hdr)
3081 return 0;
3082
3083 if (!feat_ops[feat].full_only ||
3084 tool->show_feat_hdr >= SHOW_FEAT_HEADER_FULL_INFO) {
3085 feat_ops[feat].print(&ff, stdout);
3086 } else {
3087 fprintf(stdout, "# %s info available, use -I to display\n",
3088 feat_ops[feat].name);
3089 }
3090
3091 return 0;
3092}
3093
Jiri Olsaa6e52812015-10-25 15:51:37 +01003094static struct event_update_event *
3095event_update_event__new(size_t size, u64 type, u64 id)
3096{
3097 struct event_update_event *ev;
3098
3099 size += sizeof(*ev);
3100 size = PERF_ALIGN(size, sizeof(u64));
3101
3102 ev = zalloc(size);
3103 if (ev) {
3104 ev->header.type = PERF_RECORD_EVENT_UPDATE;
3105 ev->header.size = (u16)size;
3106 ev->type = type;
3107 ev->id = id;
3108 }
3109 return ev;
3110}
3111
3112int
3113perf_event__synthesize_event_update_unit(struct perf_tool *tool,
3114 struct perf_evsel *evsel,
3115 perf_event__handler_t process)
3116{
3117 struct event_update_event *ev;
3118 size_t size = strlen(evsel->unit);
3119 int err;
3120
3121 ev = event_update_event__new(size + 1, PERF_EVENT_UPDATE__UNIT, evsel->id[0]);
3122 if (ev == NULL)
3123 return -ENOMEM;
3124
3125 strncpy(ev->data, evsel->unit, size);
3126 err = process(tool, (union perf_event *)ev, NULL, NULL);
3127 free(ev);
3128 return err;
3129}
3130
Jiri Olsadaeecbc2015-10-25 15:51:38 +01003131int
3132perf_event__synthesize_event_update_scale(struct perf_tool *tool,
3133 struct perf_evsel *evsel,
3134 perf_event__handler_t process)
3135{
3136 struct event_update_event *ev;
3137 struct event_update_event_scale *ev_data;
3138 int err;
3139
3140 ev = event_update_event__new(sizeof(*ev_data), PERF_EVENT_UPDATE__SCALE, evsel->id[0]);
3141 if (ev == NULL)
3142 return -ENOMEM;
3143
3144 ev_data = (struct event_update_event_scale *) ev->data;
3145 ev_data->scale = evsel->scale;
3146 err = process(tool, (union perf_event*) ev, NULL, NULL);
3147 free(ev);
3148 return err;
3149}
3150
Jiri Olsa802c9042015-10-25 15:51:39 +01003151int
3152perf_event__synthesize_event_update_name(struct perf_tool *tool,
3153 struct perf_evsel *evsel,
3154 perf_event__handler_t process)
3155{
3156 struct event_update_event *ev;
3157 size_t len = strlen(evsel->name);
3158 int err;
3159
3160 ev = event_update_event__new(len + 1, PERF_EVENT_UPDATE__NAME, evsel->id[0]);
3161 if (ev == NULL)
3162 return -ENOMEM;
3163
3164 strncpy(ev->data, evsel->name, len);
3165 err = process(tool, (union perf_event*) ev, NULL, NULL);
3166 free(ev);
3167 return err;
3168}
Jiri Olsadaeecbc2015-10-25 15:51:38 +01003169
Jiri Olsa86ebb092015-10-25 15:51:40 +01003170int
3171perf_event__synthesize_event_update_cpus(struct perf_tool *tool,
3172 struct perf_evsel *evsel,
3173 perf_event__handler_t process)
3174{
3175 size_t size = sizeof(struct event_update_event);
3176 struct event_update_event *ev;
3177 int max, err;
3178 u16 type;
3179
3180 if (!evsel->own_cpus)
3181 return 0;
3182
3183 ev = cpu_map_data__alloc(evsel->own_cpus, &size, &type, &max);
3184 if (!ev)
3185 return -ENOMEM;
3186
3187 ev->header.type = PERF_RECORD_EVENT_UPDATE;
3188 ev->header.size = (u16)size;
3189 ev->type = PERF_EVENT_UPDATE__CPUS;
3190 ev->id = evsel->id[0];
3191
3192 cpu_map_data__synthesize((struct cpu_map_data *) ev->data,
3193 evsel->own_cpus,
3194 type, max);
3195
3196 err = process(tool, (union perf_event*) ev, NULL, NULL);
3197 free(ev);
3198 return err;
3199}
3200
Jiri Olsac853f932015-10-25 15:51:41 +01003201size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp)
3202{
3203 struct event_update_event *ev = &event->event_update;
3204 struct event_update_event_scale *ev_scale;
3205 struct event_update_event_cpus *ev_cpus;
3206 struct cpu_map *map;
3207 size_t ret;
3208
3209 ret = fprintf(fp, "\n... id: %" PRIu64 "\n", ev->id);
3210
3211 switch (ev->type) {
3212 case PERF_EVENT_UPDATE__SCALE:
3213 ev_scale = (struct event_update_event_scale *) ev->data;
3214 ret += fprintf(fp, "... scale: %f\n", ev_scale->scale);
3215 break;
3216 case PERF_EVENT_UPDATE__UNIT:
3217 ret += fprintf(fp, "... unit: %s\n", ev->data);
3218 break;
3219 case PERF_EVENT_UPDATE__NAME:
3220 ret += fprintf(fp, "... name: %s\n", ev->data);
3221 break;
3222 case PERF_EVENT_UPDATE__CPUS:
3223 ev_cpus = (struct event_update_event_cpus *) ev->data;
3224 ret += fprintf(fp, "... ");
3225
3226 map = cpu_map__new_data(&ev_cpus->cpus);
3227 if (map)
3228 ret += cpu_map__fprintf(map, fp);
3229 else
3230 ret += fprintf(fp, "failed to get cpus\n");
3231 break;
3232 default:
3233 ret += fprintf(fp, "... unknown type\n");
3234 break;
3235 }
3236
3237 return ret;
3238}
Jiri Olsa86ebb092015-10-25 15:51:40 +01003239
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -02003240int perf_event__synthesize_attrs(struct perf_tool *tool,
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -02003241 struct perf_session *session,
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03003242 perf_event__handler_t process)
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05003243{
Robert Richter6606f872012-08-16 21:10:19 +02003244 struct perf_evsel *evsel;
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03003245 int err = 0;
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05003246
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -03003247 evlist__for_each_entry(session->evlist, evsel) {
Robert Richter6606f872012-08-16 21:10:19 +02003248 err = perf_event__synthesize_attr(tool, &evsel->attr, evsel->ids,
3249 evsel->id, process);
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05003250 if (err) {
3251 pr_debug("failed to create perf header attribute\n");
3252 return err;
3253 }
3254 }
3255
3256 return err;
3257}
3258
Andi Kleenbfd8f722017-11-17 13:42:58 -08003259static bool has_unit(struct perf_evsel *counter)
3260{
3261 return counter->unit && *counter->unit;
3262}
3263
3264static bool has_scale(struct perf_evsel *counter)
3265{
3266 return counter->scale != 1;
3267}
3268
3269int perf_event__synthesize_extra_attr(struct perf_tool *tool,
3270 struct perf_evlist *evsel_list,
3271 perf_event__handler_t process,
3272 bool is_pipe)
3273{
3274 struct perf_evsel *counter;
3275 int err;
3276
3277 /*
3278 * Synthesize other events stuff not carried within
3279 * attr event - unit, scale, name
3280 */
3281 evlist__for_each_entry(evsel_list, counter) {
3282 if (!counter->supported)
3283 continue;
3284
3285 /*
3286 * Synthesize unit and scale only if it's defined.
3287 */
3288 if (has_unit(counter)) {
3289 err = perf_event__synthesize_event_update_unit(tool, counter, process);
3290 if (err < 0) {
3291 pr_err("Couldn't synthesize evsel unit.\n");
3292 return err;
3293 }
3294 }
3295
3296 if (has_scale(counter)) {
3297 err = perf_event__synthesize_event_update_scale(tool, counter, process);
3298 if (err < 0) {
3299 pr_err("Couldn't synthesize evsel counter.\n");
3300 return err;
3301 }
3302 }
3303
3304 if (counter->own_cpus) {
3305 err = perf_event__synthesize_event_update_cpus(tool, counter, process);
3306 if (err < 0) {
3307 pr_err("Couldn't synthesize evsel cpus.\n");
3308 return err;
3309 }
3310 }
3311
3312 /*
3313 * Name is needed only for pipe output,
3314 * perf.data carries event names.
3315 */
3316 if (is_pipe) {
3317 err = perf_event__synthesize_event_update_name(tool, counter, process);
3318 if (err < 0) {
3319 pr_err("Couldn't synthesize evsel name.\n");
3320 return err;
3321 }
3322 }
3323 }
3324 return 0;
3325}
3326
Adrian Hunter47c3d102013-07-04 16:20:21 +03003327int perf_event__process_attr(struct perf_tool *tool __maybe_unused,
3328 union perf_event *event,
Arnaldo Carvalho de Melo10d0f082011-11-11 22:45:41 -02003329 struct perf_evlist **pevlist)
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05003330{
Robert Richterf4d83432012-08-16 21:10:17 +02003331 u32 i, ids, n_ids;
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03003332 struct perf_evsel *evsel;
Arnaldo Carvalho de Melo10d0f082011-11-11 22:45:41 -02003333 struct perf_evlist *evlist = *pevlist;
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05003334
Arnaldo Carvalho de Melo10d0f082011-11-11 22:45:41 -02003335 if (evlist == NULL) {
Namhyung Kim334fe7a2013-03-11 16:43:12 +09003336 *pevlist = evlist = perf_evlist__new();
Arnaldo Carvalho de Melo10d0f082011-11-11 22:45:41 -02003337 if (evlist == NULL)
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05003338 return -ENOMEM;
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05003339 }
3340
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -03003341 evsel = perf_evsel__new(&event->attr.attr);
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03003342 if (evsel == NULL)
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05003343 return -ENOMEM;
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05003344
Arnaldo Carvalho de Melo10d0f082011-11-11 22:45:41 -02003345 perf_evlist__add(evlist, evsel);
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03003346
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -02003347 ids = event->header.size;
3348 ids -= (void *)&event->attr.id - (void *)event;
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05003349 n_ids = ids / sizeof(u64);
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -03003350 /*
3351 * We don't have the cpu and thread maps on the header, so
3352 * for allocating the perf_sample_id table we fake 1 cpu and
3353 * hattr->ids threads.
3354 */
3355 if (perf_evsel__alloc_id(evsel, 1, n_ids))
3356 return -ENOMEM;
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05003357
3358 for (i = 0; i < n_ids; i++) {
Arnaldo Carvalho de Melo10d0f082011-11-11 22:45:41 -02003359 perf_evlist__id_add(evlist, evsel, 0, i, event->attr.id[i]);
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05003360 }
3361
Adrian Hunter7e0d6fc2013-07-04 16:20:29 +03003362 symbol_conf.nr_events = evlist->nr_entries;
3363
Tom Zanussi2c46dbb2010-04-01 23:59:19 -05003364 return 0;
3365}
Tom Zanussicd19a032010-04-01 23:59:20 -05003366
Jiri Olsaffe777252015-10-25 15:51:36 +01003367int perf_event__process_event_update(struct perf_tool *tool __maybe_unused,
3368 union perf_event *event,
3369 struct perf_evlist **pevlist)
3370{
3371 struct event_update_event *ev = &event->event_update;
Jiri Olsadaeecbc2015-10-25 15:51:38 +01003372 struct event_update_event_scale *ev_scale;
Jiri Olsa86ebb092015-10-25 15:51:40 +01003373 struct event_update_event_cpus *ev_cpus;
Jiri Olsaffe777252015-10-25 15:51:36 +01003374 struct perf_evlist *evlist;
3375 struct perf_evsel *evsel;
Jiri Olsa86ebb092015-10-25 15:51:40 +01003376 struct cpu_map *map;
Jiri Olsaffe777252015-10-25 15:51:36 +01003377
3378 if (!pevlist || *pevlist == NULL)
3379 return -EINVAL;
3380
3381 evlist = *pevlist;
3382
3383 evsel = perf_evlist__id2evsel(evlist, ev->id);
3384 if (evsel == NULL)
3385 return -EINVAL;
3386
Jiri Olsaa6e52812015-10-25 15:51:37 +01003387 switch (ev->type) {
3388 case PERF_EVENT_UPDATE__UNIT:
3389 evsel->unit = strdup(ev->data);
Jiri Olsadaeecbc2015-10-25 15:51:38 +01003390 break;
Jiri Olsa802c9042015-10-25 15:51:39 +01003391 case PERF_EVENT_UPDATE__NAME:
3392 evsel->name = strdup(ev->data);
3393 break;
Jiri Olsadaeecbc2015-10-25 15:51:38 +01003394 case PERF_EVENT_UPDATE__SCALE:
3395 ev_scale = (struct event_update_event_scale *) ev->data;
3396 evsel->scale = ev_scale->scale;
Arnaldo Carvalho de Melo8434a2e2017-02-08 21:57:22 -03003397 break;
Jiri Olsa86ebb092015-10-25 15:51:40 +01003398 case PERF_EVENT_UPDATE__CPUS:
3399 ev_cpus = (struct event_update_event_cpus *) ev->data;
3400
3401 map = cpu_map__new_data(&ev_cpus->cpus);
3402 if (map)
3403 evsel->own_cpus = map;
3404 else
3405 pr_err("failed to get event_update cpus\n");
Jiri Olsaa6e52812015-10-25 15:51:37 +01003406 default:
3407 break;
3408 }
3409
Jiri Olsaffe777252015-10-25 15:51:36 +01003410 return 0;
3411}
3412
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -02003413int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -02003414 struct perf_evlist *evlist,
Arnaldo Carvalho de Melo743eb862011-11-28 07:56:39 -02003415 perf_event__handler_t process)
Tom Zanussi92155452010-04-01 23:59:21 -05003416{
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -02003417 union perf_event ev;
Jiri Olsa29208e52011-10-20 15:59:43 +02003418 struct tracing_data *tdata;
Tom Zanussi92155452010-04-01 23:59:21 -05003419 ssize_t size = 0, aligned_size = 0, padding;
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -07003420 struct feat_fd ff;
Irina Tirdea1d037ca2012-09-11 01:15:03 +03003421 int err __maybe_unused = 0;
Tom Zanussi92155452010-04-01 23:59:21 -05003422
Jiri Olsa29208e52011-10-20 15:59:43 +02003423 /*
3424 * We are going to store the size of the data followed
3425 * by the data contents. Since the fd descriptor is a pipe,
3426 * we cannot seek back to store the size of the data once
3427 * we know it. Instead we:
3428 *
3429 * - write the tracing data to the temp file
3430 * - get/write the data size to pipe
3431 * - write the tracing data from the temp file
3432 * to the pipe
3433 */
3434 tdata = tracing_data_get(&evlist->entries, fd, true);
3435 if (!tdata)
3436 return -1;
3437
Tom Zanussi92155452010-04-01 23:59:21 -05003438 memset(&ev, 0, sizeof(ev));
3439
3440 ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA;
Jiri Olsa29208e52011-10-20 15:59:43 +02003441 size = tdata->size;
Irina Tirdea9ac3e482012-09-11 01:15:01 +03003442 aligned_size = PERF_ALIGN(size, sizeof(u64));
Tom Zanussi92155452010-04-01 23:59:21 -05003443 padding = aligned_size - size;
3444 ev.tracing_data.header.size = sizeof(ev.tracing_data);
3445 ev.tracing_data.size = aligned_size;
3446
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -02003447 process(tool, &ev, NULL, NULL);
Tom Zanussi92155452010-04-01 23:59:21 -05003448
Jiri Olsa29208e52011-10-20 15:59:43 +02003449 /*
3450 * The put function will copy all the tracing data
3451 * stored in temp file to the pipe.
3452 */
3453 tracing_data_put(tdata);
3454
David Carrillo-Cisnerosccebbeb2017-07-17 21:25:39 -07003455 ff = (struct feat_fd){ .fd = fd };
3456 if (write_padded(&ff, NULL, 0, padding))
David Carrillo-Cisneros2ff53652017-07-17 21:25:36 -07003457 return -1;
Tom Zanussi92155452010-04-01 23:59:21 -05003458
3459 return aligned_size;
3460}
3461
Adrian Hunter47c3d102013-07-04 16:20:21 +03003462int perf_event__process_tracing_data(struct perf_tool *tool __maybe_unused,
3463 union perf_event *event,
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -02003464 struct perf_session *session)
Tom Zanussi92155452010-04-01 23:59:21 -05003465{
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -02003466 ssize_t size_read, padding, size = event->tracing_data.size;
Jiri Olsa8ceb41d2017-01-23 22:07:59 +01003467 int fd = perf_data__fd(session->data);
Jiri Olsacc9784bd2013-10-15 16:27:34 +02003468 off_t offset = lseek(fd, 0, SEEK_CUR);
Tom Zanussi92155452010-04-01 23:59:21 -05003469 char buf[BUFSIZ];
3470
3471 /* setup for reading amidst mmap */
Jiri Olsacc9784bd2013-10-15 16:27:34 +02003472 lseek(fd, offset + sizeof(struct tracing_data_event),
Tom Zanussi92155452010-04-01 23:59:21 -05003473 SEEK_SET);
3474
Jiri Olsa29f5ffd2013-12-03 14:09:23 +01003475 size_read = trace_report(fd, &session->tevent,
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -03003476 session->repipe);
Irina Tirdea9ac3e482012-09-11 01:15:01 +03003477 padding = PERF_ALIGN(size_read, sizeof(u64)) - size_read;
Tom Zanussi92155452010-04-01 23:59:21 -05003478
Jiri Olsacc9784bd2013-10-15 16:27:34 +02003479 if (readn(fd, buf, padding) < 0) {
Arnaldo Carvalho de Melo2caa48a2013-01-24 22:34:33 -03003480 pr_err("%s: reading input file", __func__);
3481 return -1;
3482 }
Tom Zanussi454c4072010-05-01 01:41:20 -05003483 if (session->repipe) {
3484 int retw = write(STDOUT_FILENO, buf, padding);
Arnaldo Carvalho de Melo2caa48a2013-01-24 22:34:33 -03003485 if (retw <= 0 || retw != padding) {
3486 pr_err("%s: repiping tracing data padding", __func__);
3487 return -1;
3488 }
Tom Zanussi454c4072010-05-01 01:41:20 -05003489 }
Tom Zanussi92155452010-04-01 23:59:21 -05003490
Arnaldo Carvalho de Melo2caa48a2013-01-24 22:34:33 -03003491 if (size_read + padding != size) {
3492 pr_err("%s: tracing data size mismatch", __func__);
3493 return -1;
3494 }
Tom Zanussi92155452010-04-01 23:59:21 -05003495
Namhyung Kim831394b2012-09-06 11:10:46 +09003496 perf_evlist__prepare_tracepoint_events(session->evlist,
Jiri Olsa29f5ffd2013-12-03 14:09:23 +01003497 session->tevent.pevent);
Arnaldo Carvalho de Melo8b6ee4c2012-08-07 23:36:16 -03003498
Tom Zanussi92155452010-04-01 23:59:21 -05003499 return size_read + padding;
3500}
Tom Zanussic7929e42010-04-01 23:59:22 -05003501
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -02003502int perf_event__synthesize_build_id(struct perf_tool *tool,
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -02003503 struct dso *pos, u16 misc,
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -02003504 perf_event__handler_t process,
Arnaldo Carvalho de Melo743eb862011-11-28 07:56:39 -02003505 struct machine *machine)
Tom Zanussic7929e42010-04-01 23:59:22 -05003506{
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -02003507 union perf_event ev;
Tom Zanussic7929e42010-04-01 23:59:22 -05003508 size_t len;
3509 int err = 0;
3510
3511 if (!pos->hit)
3512 return err;
3513
3514 memset(&ev, 0, sizeof(ev));
3515
3516 len = pos->long_name_len + 1;
Irina Tirdea9ac3e482012-09-11 01:15:01 +03003517 len = PERF_ALIGN(len, NAME_ALIGN);
Tom Zanussic7929e42010-04-01 23:59:22 -05003518 memcpy(&ev.build_id.build_id, pos->build_id, sizeof(pos->build_id));
3519 ev.build_id.header.type = PERF_RECORD_HEADER_BUILD_ID;
3520 ev.build_id.header.misc = misc;
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -03003521 ev.build_id.pid = machine->pid;
Tom Zanussic7929e42010-04-01 23:59:22 -05003522 ev.build_id.header.size = sizeof(ev.build_id) + len;
3523 memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len);
3524
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -02003525 err = process(tool, &ev, NULL, machine);
Tom Zanussic7929e42010-04-01 23:59:22 -05003526
3527 return err;
3528}
3529
Irina Tirdea1d037ca2012-09-11 01:15:03 +03003530int perf_event__process_build_id(struct perf_tool *tool __maybe_unused,
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -02003531 union perf_event *event,
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -02003532 struct perf_session *session)
Tom Zanussic7929e42010-04-01 23:59:22 -05003533{
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -02003534 __event_process_build_id(&event->build_id,
3535 event->build_id.filename,
Zhang, Yanmina1645ce2010-04-19 13:32:50 +08003536 session);
Tom Zanussic7929e42010-04-01 23:59:22 -05003537 return 0;
3538}