Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
evsel.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <[email protected]>
3  *
4  * Parts came from builtin-{top,stat,record}.c, see those files for further
5  * copyright notes.
6  *
7  * Released under the GPL v2. (and only v2, not any later version)
8  */
9 
10 #include <byteswap.h>
11 #include <linux/bitops.h>
12 #include "asm/bug.h"
13 #include "debugfs.h"
14 #include "event-parse.h"
15 #include "evsel.h"
16 #include "evlist.h"
17 #include "util.h"
18 #include "cpumap.h"
19 #include "thread_map.h"
20 #include "target.h"
21 #include <linux/hw_breakpoint.h>
22 #include <linux/perf_event.h>
23 #include "perf_regs.h"
24 
25 #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
26 
27 static int __perf_evsel__sample_size(u64 sample_type)
28 {
29  u64 mask = sample_type & PERF_SAMPLE_MASK;
30  int size = 0;
31  int i;
32 
33  for (i = 0; i < 64; i++) {
34  if (mask & (1ULL << i))
35  size++;
36  }
37 
38  size *= sizeof(u64);
39 
40  return size;
41 }
42 
43 void hists__init(struct hists *hists)
44 {
45  memset(hists, 0, sizeof(*hists));
46  hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT;
47  hists->entries_in = &hists->entries_in_array[0];
48  hists->entries_collapsed = RB_ROOT;
49  hists->entries = RB_ROOT;
50  pthread_mutex_init(&hists->lock, NULL);
51 }
52 
53 void perf_evsel__init(struct perf_evsel *evsel,
54  struct perf_event_attr *attr, int idx)
55 {
56  evsel->idx = idx;
57  evsel->attr = *attr;
58  INIT_LIST_HEAD(&evsel->node);
59  hists__init(&evsel->hists);
60  evsel->sample_size = __perf_evsel__sample_size(attr->sample_type);
61 }
62 
64 {
65  struct perf_evsel *evsel = zalloc(sizeof(*evsel));
66 
67  if (evsel != NULL)
68  perf_evsel__init(evsel, attr, idx);
69 
70  return evsel;
71 }
72 
73 struct event_format *event_format__new(const char *sys, const char *name)
74 {
75  int fd, n;
76  char *filename;
77  void *bf = NULL, *nbf;
78  size_t size = 0, alloc_size = 0;
79  struct event_format *format = NULL;
80 
81  if (asprintf(&filename, "%s/%s/%s/format", tracing_events_path, sys, name) < 0)
82  goto out;
83 
84  fd = open(filename, O_RDONLY);
85  if (fd < 0)
86  goto out_free_filename;
87 
88  do {
89  if (size == alloc_size) {
90  alloc_size += BUFSIZ;
91  nbf = realloc(bf, alloc_size);
92  if (nbf == NULL)
93  goto out_free_bf;
94  bf = nbf;
95  }
96 
97  n = read(fd, bf + size, BUFSIZ);
98  if (n < 0)
99  goto out_free_bf;
100  size += n;
101  } while (n > 0);
102 
103  pevent_parse_format(&format, bf, size, sys);
104 
105 out_free_bf:
106  free(bf);
107  close(fd);
108 out_free_filename:
109  free(filename);
110 out:
111  return format;
112 }
113 
114 struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name, int idx)
115 {
116  struct perf_evsel *evsel = zalloc(sizeof(*evsel));
117 
118  if (evsel != NULL) {
119  struct perf_event_attr attr = {
121  .sample_type = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
123  };
124 
125  if (asprintf(&evsel->name, "%s:%s", sys, name) < 0)
126  goto out_free;
127 
128  evsel->tp_format = event_format__new(sys, name);
129  if (evsel->tp_format == NULL)
130  goto out_free;
131 
132  event_attr_init(&attr);
133  attr.config = evsel->tp_format->id;
134  attr.sample_period = 1;
135  perf_evsel__init(evsel, &attr, idx);
136  }
137 
138  return evsel;
139 
140 out_free:
141  free(evsel->name);
142  free(evsel);
143  return NULL;
144 }
145 
147  "cycles",
148  "instructions",
149  "cache-references",
150  "cache-misses",
151  "branches",
152  "branch-misses",
153  "bus-cycles",
154  "stalled-cycles-frontend",
155  "stalled-cycles-backend",
156  "ref-cycles",
157 };
158 
159 static const char *__perf_evsel__hw_name(u64 config)
160 {
161  if (config < PERF_COUNT_HW_MAX && perf_evsel__hw_names[config])
162  return perf_evsel__hw_names[config];
163 
164  return "unknown-hardware";
165 }
166 
167 static int perf_evsel__add_modifiers(struct perf_evsel *evsel, char *bf, size_t size)
168 {
169  int colon = 0, r = 0;
170  struct perf_event_attr *attr = &evsel->attr;
171  bool exclude_guest_default = false;
172 
173 #define MOD_PRINT(context, mod) do { \
174  if (!attr->exclude_##context) { \
175  if (!colon) colon = ++r; \
176  r += scnprintf(bf + r, size - r, "%c", mod); \
177  } } while(0)
178 
179  if (attr->exclude_kernel || attr->exclude_user || attr->exclude_hv) {
180  MOD_PRINT(kernel, 'k');
181  MOD_PRINT(user, 'u');
182  MOD_PRINT(hv, 'h');
183  exclude_guest_default = true;
184  }
185 
186  if (attr->precise_ip) {
187  if (!colon)
188  colon = ++r;
189  r += scnprintf(bf + r, size - r, "%.*s", attr->precise_ip, "ppp");
190  exclude_guest_default = true;
191  }
192 
193  if (attr->exclude_host || attr->exclude_guest == exclude_guest_default) {
194  MOD_PRINT(host, 'H');
195  MOD_PRINT(guest, 'G');
196  }
197 #undef MOD_PRINT
198  if (colon)
199  bf[colon - 1] = ':';
200  return r;
201 }
202 
203 static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size)
204 {
205  int r = scnprintf(bf, size, "%s", __perf_evsel__hw_name(evsel->attr.config));
206  return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
207 }
208 
210  "cpu-clock",
211  "task-clock",
212  "page-faults",
213  "context-switches",
214  "cpu-migrations",
215  "minor-faults",
216  "major-faults",
217  "alignment-faults",
218  "emulation-faults",
219 };
220 
221 static const char *__perf_evsel__sw_name(u64 config)
222 {
223  if (config < PERF_COUNT_SW_MAX && perf_evsel__sw_names[config])
224  return perf_evsel__sw_names[config];
225  return "unknown-software";
226 }
227 
228 static int perf_evsel__sw_name(struct perf_evsel *evsel, char *bf, size_t size)
229 {
230  int r = scnprintf(bf, size, "%s", __perf_evsel__sw_name(evsel->attr.config));
231  return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
232 }
233 
234 static int __perf_evsel__bp_name(char *bf, size_t size, u64 addr, u64 type)
235 {
236  int r;
237 
238  r = scnprintf(bf, size, "mem:0x%" PRIx64 ":", addr);
239 
240  if (type & HW_BREAKPOINT_R)
241  r += scnprintf(bf + r, size - r, "r");
242 
243  if (type & HW_BREAKPOINT_W)
244  r += scnprintf(bf + r, size - r, "w");
245 
246  if (type & HW_BREAKPOINT_X)
247  r += scnprintf(bf + r, size - r, "x");
248 
249  return r;
250 }
251 
252 static int perf_evsel__bp_name(struct perf_evsel *evsel, char *bf, size_t size)
253 {
254  struct perf_event_attr *attr = &evsel->attr;
255  int r = __perf_evsel__bp_name(bf, size, attr->bp_addr, attr->bp_type);
256  return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
257 }
258 
261  { "L1-dcache", "l1-d", "l1d", "L1-data", },
262  { "L1-icache", "l1-i", "l1i", "L1-instruction", },
263  { "LLC", "L2", },
264  { "dTLB", "d-tlb", "Data-TLB", },
265  { "iTLB", "i-tlb", "Instruction-TLB", },
266  { "branch", "branches", "bpu", "btb", "bpc", },
267  { "node", },
268 };
269 
272  { "load", "loads", "read", },
273  { "store", "stores", "write", },
274  { "prefetch", "prefetches", "speculative-read", "speculative-load", },
275 };
276 
279  { "refs", "Reference", "ops", "access", },
280  { "misses", "miss", },
281 };
282 
283 #define C(x) PERF_COUNT_HW_CACHE_##x
284 #define CACHE_READ (1 << C(OP_READ))
285 #define CACHE_WRITE (1 << C(OP_WRITE))
286 #define CACHE_PREFETCH (1 << C(OP_PREFETCH))
287 #define COP(x) (1 << x)
288 
289 /*
290  * cache operartion stat
291  * L1I : Read and prefetch only
292  * ITLB and BPU : Read-only
293  */
294 static unsigned long perf_evsel__hw_cache_stat[C(MAX)] = {
295  [C(L1D)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
296  [C(L1I)] = (CACHE_READ | CACHE_PREFETCH),
298  [C(DTLB)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
299  [C(ITLB)] = (CACHE_READ),
300  [C(BPU)] = (CACHE_READ),
301  [C(NODE)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
302 };
303 
305 {
306  if (perf_evsel__hw_cache_stat[type] & COP(op))
307  return true; /* valid */
308  else
309  return false; /* invalid */
310 }
311 
313  char *bf, size_t size)
314 {
315  if (result) {
316  return scnprintf(bf, size, "%s-%s-%s", perf_evsel__hw_cache[type][0],
318  perf_evsel__hw_cache_result[result][0]);
319  }
320 
321  return scnprintf(bf, size, "%s-%s", perf_evsel__hw_cache[type][0],
322  perf_evsel__hw_cache_op[op][1]);
323 }
324 
325 static int __perf_evsel__hw_cache_name(u64 config, char *bf, size_t size)
326 {
327  u8 op, result, type = (config >> 0) & 0xff;
328  const char *err = "unknown-ext-hardware-cache-type";
329 
330  if (type > PERF_COUNT_HW_CACHE_MAX)
331  goto out_err;
332 
333  op = (config >> 8) & 0xff;
334  err = "unknown-ext-hardware-cache-op";
336  goto out_err;
337 
338  result = (config >> 16) & 0xff;
339  err = "unknown-ext-hardware-cache-result";
340  if (result > PERF_COUNT_HW_CACHE_RESULT_MAX)
341  goto out_err;
342 
343  err = "invalid-cache";
344  if (!perf_evsel__is_cache_op_valid(type, op))
345  goto out_err;
346 
347  return __perf_evsel__hw_cache_type_op_res_name(type, op, result, bf, size);
348 out_err:
349  return scnprintf(bf, size, "%s", err);
350 }
351 
352 static int perf_evsel__hw_cache_name(struct perf_evsel *evsel, char *bf, size_t size)
353 {
354  int ret = __perf_evsel__hw_cache_name(evsel->attr.config, bf, size);
355  return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret);
356 }
357 
358 static int perf_evsel__raw_name(struct perf_evsel *evsel, char *bf, size_t size)
359 {
360  int ret = scnprintf(bf, size, "raw 0x%" PRIx64, evsel->attr.config);
361  return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret);
362 }
363 
364 const char *perf_evsel__name(struct perf_evsel *evsel)
365 {
366  char bf[128];
367 
368  if (evsel->name)
369  return evsel->name;
370 
371  switch (evsel->attr.type) {
372  case PERF_TYPE_RAW:
373  perf_evsel__raw_name(evsel, bf, sizeof(bf));
374  break;
375 
376  case PERF_TYPE_HARDWARE:
377  perf_evsel__hw_name(evsel, bf, sizeof(bf));
378  break;
379 
380  case PERF_TYPE_HW_CACHE:
381  perf_evsel__hw_cache_name(evsel, bf, sizeof(bf));
382  break;
383 
384  case PERF_TYPE_SOFTWARE:
385  perf_evsel__sw_name(evsel, bf, sizeof(bf));
386  break;
387 
389  scnprintf(bf, sizeof(bf), "%s", "unknown tracepoint");
390  break;
391 
393  perf_evsel__bp_name(evsel, bf, sizeof(bf));
394  break;
395 
396  default:
397  scnprintf(bf, sizeof(bf), "unknown attr type: %d",
398  evsel->attr.type);
399  break;
400  }
401 
402  evsel->name = strdup(bf);
403 
404  return evsel->name ?: "unknown";
405 }
406 
408  struct perf_evsel *first)
409 {
410  struct perf_event_attr *attr = &evsel->attr;
411  int track = !evsel->idx; /* only the first counter needs these */
412 
413  attr->disabled = 1;
414  attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1;
415  attr->inherit = !opts->no_inherit;
419 
421 
422  /*
423  * We default some events to a 1 default interval. But keep
424  * it a weak assumption overridable by the user.
425  */
426  if (!attr->sample_period || (opts->user_freq != UINT_MAX &&
427  opts->user_interval != ULLONG_MAX)) {
428  if (opts->freq) {
430  attr->freq = 1;
431  attr->sample_freq = opts->freq;
432  } else {
433  attr->sample_period = opts->default_interval;
434  }
435  }
436 
437  if (opts->no_samples)
438  attr->sample_freq = 0;
439 
440  if (opts->inherit_stat)
441  attr->inherit_stat = 1;
442 
443  if (opts->sample_address) {
444  attr->sample_type |= PERF_SAMPLE_ADDR;
445  attr->mmap_data = track;
446  }
447 
448  if (opts->call_graph) {
450 
451  if (opts->call_graph == CALLCHAIN_DWARF) {
455  attr->sample_stack_user = opts->stack_dump_size;
456  attr->exclude_callchain_user = 1;
457  }
458  }
459 
460  if (perf_target__has_cpu(&opts->target))
461  attr->sample_type |= PERF_SAMPLE_CPU;
462 
463  if (opts->period)
465 
466  if (!opts->sample_id_all_missing &&
467  (opts->sample_time || !opts->no_inherit ||
468  perf_target__has_cpu(&opts->target)))
469  attr->sample_type |= PERF_SAMPLE_TIME;
470 
471  if (opts->raw_samples) {
472  attr->sample_type |= PERF_SAMPLE_TIME;
473  attr->sample_type |= PERF_SAMPLE_RAW;
474  attr->sample_type |= PERF_SAMPLE_CPU;
475  }
476 
477  if (opts->no_delay) {
478  attr->watermark = 0;
479  attr->wakeup_events = 1;
480  }
481  if (opts->branch_stack) {
483  attr->branch_sample_type = opts->branch_stack;
484  }
485 
486  attr->mmap = track;
487  attr->comm = track;
488 
489  if (perf_target__none(&opts->target) &&
490  (!opts->group || evsel == first)) {
491  attr->enable_on_exec = 1;
492  }
493 }
494 
495 int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
496 {
497  int cpu, thread;
498  evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int));
499 
500  if (evsel->fd) {
501  for (cpu = 0; cpu < ncpus; cpu++) {
502  for (thread = 0; thread < nthreads; thread++) {
503  FD(evsel, cpu, thread) = -1;
504  }
505  }
506  }
507 
508  return evsel->fd != NULL ? 0 : -ENOMEM;
509 }
510 
511 int perf_evsel__set_filter(struct perf_evsel *evsel, int ncpus, int nthreads,
512  const char *filter)
513 {
514  int cpu, thread;
515 
516  for (cpu = 0; cpu < ncpus; cpu++) {
517  for (thread = 0; thread < nthreads; thread++) {
518  int fd = FD(evsel, cpu, thread),
519  err = ioctl(fd, PERF_EVENT_IOC_SET_FILTER, filter);
520 
521  if (err)
522  return err;
523  }
524  }
525 
526  return 0;
527 }
528 
529 int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)
530 {
531  evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id));
532  if (evsel->sample_id == NULL)
533  return -ENOMEM;
534 
535  evsel->id = zalloc(ncpus * nthreads * sizeof(u64));
536  if (evsel->id == NULL) {
537  xyarray__delete(evsel->sample_id);
538  evsel->sample_id = NULL;
539  return -ENOMEM;
540  }
541 
542  return 0;
543 }
544 
546 {
547  evsel->counts = zalloc((sizeof(*evsel->counts) +
548  (ncpus * sizeof(struct perf_counts_values))));
549  return evsel->counts != NULL ? 0 : -ENOMEM;
550 }
551 
552 void perf_evsel__free_fd(struct perf_evsel *evsel)
553 {
554  xyarray__delete(evsel->fd);
555  evsel->fd = NULL;
556 }
557 
558 void perf_evsel__free_id(struct perf_evsel *evsel)
559 {
560  xyarray__delete(evsel->sample_id);
561  evsel->sample_id = NULL;
562  free(evsel->id);
563  evsel->id = NULL;
564 }
565 
566 void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
567 {
568  int cpu, thread;
569 
570  for (cpu = 0; cpu < ncpus; cpu++)
571  for (thread = 0; thread < nthreads; ++thread) {
572  close(FD(evsel, cpu, thread));
573  FD(evsel, cpu, thread) = -1;
574  }
575 }
576 
577 void perf_evsel__exit(struct perf_evsel *evsel)
578 {
579  assert(list_empty(&evsel->node));
580  xyarray__delete(evsel->fd);
581  xyarray__delete(evsel->sample_id);
582  free(evsel->id);
583 }
584 
585 void perf_evsel__delete(struct perf_evsel *evsel)
586 {
587  perf_evsel__exit(evsel);
588  close_cgroup(evsel->cgrp);
589  free(evsel->group_name);
590  if (evsel->tp_format)
592  free(evsel->name);
593  free(evsel);
594 }
595 
597  int cpu, int thread, bool scale)
598 {
599  struct perf_counts_values count;
600  size_t nv = scale ? 3 : 1;
601 
602  if (FD(evsel, cpu, thread) < 0)
603  return -EINVAL;
604 
605  if (evsel->counts == NULL && perf_evsel__alloc_counts(evsel, cpu + 1) < 0)
606  return -ENOMEM;
607 
608  if (readn(FD(evsel, cpu, thread), &count, nv * sizeof(u64)) < 0)
609  return -errno;
610 
611  if (scale) {
612  if (count.run == 0)
613  count.val = 0;
614  else if (count.run < count.ena)
615  count.val = (u64)((double)count.val * count.ena / count.run + 0.5);
616  } else
617  count.ena = count.run = 0;
618 
619  evsel->counts->cpu[cpu] = count;
620  return 0;
621 }
622 
623 int __perf_evsel__read(struct perf_evsel *evsel,
624  int ncpus, int nthreads, bool scale)
625 {
626  size_t nv = scale ? 3 : 1;
627  int cpu, thread;
628  struct perf_counts_values *aggr = &evsel->counts->aggr, count;
629 
630  aggr->val = aggr->ena = aggr->run = 0;
631 
632  for (cpu = 0; cpu < ncpus; cpu++) {
633  for (thread = 0; thread < nthreads; thread++) {
634  if (FD(evsel, cpu, thread) < 0)
635  continue;
636 
637  if (readn(FD(evsel, cpu, thread),
638  &count, nv * sizeof(u64)) < 0)
639  return -errno;
640 
641  aggr->val += count.val;
642  if (scale) {
643  aggr->ena += count.ena;
644  aggr->run += count.run;
645  }
646  }
647  }
648 
649  evsel->counts->scaled = 0;
650  if (scale) {
651  if (aggr->run == 0) {
652  evsel->counts->scaled = -1;
653  aggr->val = 0;
654  return 0;
655  }
656 
657  if (aggr->run < aggr->ena) {
658  evsel->counts->scaled = 1;
659  aggr->val = (u64)((double)aggr->val * aggr->ena / aggr->run + 0.5);
660  }
661  } else
662  aggr->ena = aggr->run = 0;
663 
664  return 0;
665 }
666 
667 static int get_group_fd(struct perf_evsel *evsel, int cpu, int thread)
668 {
669  struct perf_evsel *leader = evsel->leader;
670  int fd;
671 
672  if (!leader)
673  return -1;
674 
675  /*
676  * Leader must be already processed/open,
677  * if not it's a bug.
678  */
679  BUG_ON(!leader->fd);
680 
681  fd = FD(leader, cpu, thread);
682  BUG_ON(fd == -1);
683 
684  return fd;
685 }
686 
687 static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
688  struct thread_map *threads)
689 {
690  int cpu, thread;
691  unsigned long flags = 0;
692  int pid = -1, err;
693 
694  if (evsel->fd == NULL &&
695  perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0)
696  return -ENOMEM;
697 
698  if (evsel->cgrp) {
699  flags = PERF_FLAG_PID_CGROUP;
700  pid = evsel->cgrp->fd;
701  }
702 
703  for (cpu = 0; cpu < cpus->nr; cpu++) {
704 
705  for (thread = 0; thread < threads->nr; thread++) {
706  int group_fd;
707 
708  if (!evsel->cgrp)
709  pid = threads->map[thread];
710 
711  group_fd = get_group_fd(evsel, cpu, thread);
712 
713  FD(evsel, cpu, thread) = sys_perf_event_open(&evsel->attr,
714  pid,
715  cpus->map[cpu],
716  group_fd, flags);
717  if (FD(evsel, cpu, thread) < 0) {
718  err = -errno;
719  goto out_close;
720  }
721  }
722  }
723 
724  return 0;
725 
726 out_close:
727  do {
728  while (--thread >= 0) {
729  close(FD(evsel, cpu, thread));
730  FD(evsel, cpu, thread) = -1;
731  }
732  thread = threads->nr;
733  } while (--cpu >= 0);
734  return err;
735 }
736 
737 void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads)
738 {
739  if (evsel->fd == NULL)
740  return;
741 
742  perf_evsel__close_fd(evsel, ncpus, nthreads);
743  perf_evsel__free_fd(evsel);
744  evsel->fd = NULL;
745 }
746 
747 static struct {
748  struct cpu_map map;
749  int cpus[1];
750 } empty_cpu_map = {
751  .map.nr = 1,
752  .cpus = { -1, },
753 };
754 
755 static struct {
756  struct thread_map map;
757  int threads[1];
758 } empty_thread_map = {
759  .map.nr = 1,
760  .threads = { -1, },
761 };
762 
763 int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
764  struct thread_map *threads)
765 {
766  if (cpus == NULL) {
767  /* Work around old compiler warnings about strict aliasing */
768  cpus = &empty_cpu_map.map;
769  }
770 
771  if (threads == NULL)
772  threads = &empty_thread_map.map;
773 
774  return __perf_evsel__open(evsel, cpus, threads);
775 }
776 
778  struct cpu_map *cpus)
779 {
780  return __perf_evsel__open(evsel, cpus, &empty_thread_map.map);
781 }
782 
784  struct thread_map *threads)
785 {
786  return __perf_evsel__open(evsel, &empty_cpu_map.map, threads);
787 }
788 
789 static int perf_evsel__parse_id_sample(const struct perf_evsel *evsel,
790  const union perf_event *event,
791  struct perf_sample *sample)
792 {
793  u64 type = evsel->attr.sample_type;
794  const u64 *array = event->sample.array;
795  bool swapped = evsel->needs_swap;
796  union u64_swap u;
797 
798  array += ((event->header.size -
799  sizeof(event->header)) / sizeof(u64)) - 1;
800 
801  if (type & PERF_SAMPLE_CPU) {
802  u.val64 = *array;
803  if (swapped) {
804  /* undo swap of u64, then swap on individual u32s */
805  u.val64 = bswap_64(u.val64);
806  u.val32[0] = bswap_32(u.val32[0]);
807  }
808 
809  sample->cpu = u.val32[0];
810  array--;
811  }
812 
813  if (type & PERF_SAMPLE_STREAM_ID) {
814  sample->stream_id = *array;
815  array--;
816  }
817 
818  if (type & PERF_SAMPLE_ID) {
819  sample->id = *array;
820  array--;
821  }
822 
823  if (type & PERF_SAMPLE_TIME) {
824  sample->time = *array;
825  array--;
826  }
827 
828  if (type & PERF_SAMPLE_TID) {
829  u.val64 = *array;
830  if (swapped) {
831  /* undo swap of u64, then swap on individual u32s */
832  u.val64 = bswap_64(u.val64);
833  u.val32[0] = bswap_32(u.val32[0]);
834  u.val32[1] = bswap_32(u.val32[1]);
835  }
836 
837  sample->pid = u.val32[0];
838  sample->tid = u.val32[1];
839  }
840 
841  return 0;
842 }
843 
844 static bool sample_overlap(const union perf_event *event,
845  const void *offset, u64 size)
846 {
847  const void *base = event;
848 
849  if (offset + size > base + event->header.size)
850  return true;
851 
852  return false;
853 }
854 
855 int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
856  struct perf_sample *data)
857 {
858  u64 type = evsel->attr.sample_type;
859  u64 regs_user = evsel->attr.sample_regs_user;
860  bool swapped = evsel->needs_swap;
861  const u64 *array;
862 
863  /*
864  * used for cross-endian analysis. See git commit 65014ab3
865  * for why this goofiness is needed.
866  */
867  union u64_swap u;
868 
869  memset(data, 0, sizeof(*data));
870  data->cpu = data->pid = data->tid = -1;
871  data->stream_id = data->id = data->time = -1ULL;
872  data->period = 1;
873 
874  if (event->header.type != PERF_RECORD_SAMPLE) {
875  if (!evsel->attr.sample_id_all)
876  return 0;
877  return perf_evsel__parse_id_sample(evsel, event, data);
878  }
879 
880  array = event->sample.array;
881 
882  if (evsel->sample_size + sizeof(event->header) > event->header.size)
883  return -EFAULT;
884 
885  if (type & PERF_SAMPLE_IP) {
886  data->ip = event->ip.ip;
887  array++;
888  }
889 
890  if (type & PERF_SAMPLE_TID) {
891  u.val64 = *array;
892  if (swapped) {
893  /* undo swap of u64, then swap on individual u32s */
894  u.val64 = bswap_64(u.val64);
895  u.val32[0] = bswap_32(u.val32[0]);
896  u.val32[1] = bswap_32(u.val32[1]);
897  }
898 
899  data->pid = u.val32[0];
900  data->tid = u.val32[1];
901  array++;
902  }
903 
904  if (type & PERF_SAMPLE_TIME) {
905  data->time = *array;
906  array++;
907  }
908 
909  data->addr = 0;
910  if (type & PERF_SAMPLE_ADDR) {
911  data->addr = *array;
912  array++;
913  }
914 
915  data->id = -1ULL;
916  if (type & PERF_SAMPLE_ID) {
917  data->id = *array;
918  array++;
919  }
920 
921  if (type & PERF_SAMPLE_STREAM_ID) {
922  data->stream_id = *array;
923  array++;
924  }
925 
926  if (type & PERF_SAMPLE_CPU) {
927 
928  u.val64 = *array;
929  if (swapped) {
930  /* undo swap of u64, then swap on individual u32s */
931  u.val64 = bswap_64(u.val64);
932  u.val32[0] = bswap_32(u.val32[0]);
933  }
934 
935  data->cpu = u.val32[0];
936  array++;
937  }
938 
939  if (type & PERF_SAMPLE_PERIOD) {
940  data->period = *array;
941  array++;
942  }
943 
944  if (type & PERF_SAMPLE_READ) {
945  fprintf(stderr, "PERF_SAMPLE_READ is unsupported for now\n");
946  return -1;
947  }
948 
949  if (type & PERF_SAMPLE_CALLCHAIN) {
950  if (sample_overlap(event, array, sizeof(data->callchain->nr)))
951  return -EFAULT;
952 
953  data->callchain = (struct ip_callchain *)array;
954 
955  if (sample_overlap(event, array, data->callchain->nr))
956  return -EFAULT;
957 
958  array += 1 + data->callchain->nr;
959  }
960 
961  if (type & PERF_SAMPLE_RAW) {
962  const u64 *pdata;
963 
964  u.val64 = *array;
965  if (WARN_ONCE(swapped,
966  "Endianness of raw data not corrected!\n")) {
967  /* undo swap of u64, then swap on individual u32s */
968  u.val64 = bswap_64(u.val64);
969  u.val32[0] = bswap_32(u.val32[0]);
970  u.val32[1] = bswap_32(u.val32[1]);
971  }
972 
973  if (sample_overlap(event, array, sizeof(u32)))
974  return -EFAULT;
975 
976  data->raw_size = u.val32[0];
977  pdata = (void *) array + sizeof(u32);
978 
979  if (sample_overlap(event, pdata, data->raw_size))
980  return -EFAULT;
981 
982  data->raw_data = (void *) pdata;
983 
984  array = (void *)array + data->raw_size + sizeof(u32);
985  }
986 
987  if (type & PERF_SAMPLE_BRANCH_STACK) {
988  u64 sz;
989 
990  data->branch_stack = (struct branch_stack *)array;
991  array++; /* nr */
992 
993  sz = data->branch_stack->nr * sizeof(struct branch_entry);
994  sz /= sizeof(u64);
995  array += sz;
996  }
997 
998  if (type & PERF_SAMPLE_REGS_USER) {
999  /* First u64 tells us if we have any regs in sample. */
1000  u64 avail = *array++;
1001 
1002  if (avail) {
1003  data->user_regs.regs = (u64 *)array;
1004  array += hweight_long(regs_user);
1005  }
1006  }
1007 
1008  if (type & PERF_SAMPLE_STACK_USER) {
1009  u64 size = *array++;
1010 
1011  data->user_stack.offset = ((char *)(array - 1)
1012  - (char *) event);
1013 
1014  if (!size) {
1015  data->user_stack.size = 0;
1016  } else {
1017  data->user_stack.data = (char *)array;
1018  array += size / sizeof(*array);
1019  data->user_stack.size = *array;
1020  }
1021  }
1022 
1023  return 0;
1024 }
1025 
1027  const struct perf_sample *sample,
1028  bool swapped)
1029 {
1030  u64 *array;
1031 
1032  /*
1033  * used for cross-endian analysis. See git commit 65014ab3
1034  * for why this goofiness is needed.
1035  */
1036  union u64_swap u;
1037 
1038  array = event->sample.array;
1039 
1040  if (type & PERF_SAMPLE_IP) {
1041  event->ip.ip = sample->ip;
1042  array++;
1043  }
1044 
1045  if (type & PERF_SAMPLE_TID) {
1046  u.val32[0] = sample->pid;
1047  u.val32[1] = sample->tid;
1048  if (swapped) {
1049  /*
1050  * Inverse of what is done in perf_evsel__parse_sample
1051  */
1052  u.val32[0] = bswap_32(u.val32[0]);
1053  u.val32[1] = bswap_32(u.val32[1]);
1054  u.val64 = bswap_64(u.val64);
1055  }
1056 
1057  *array = u.val64;
1058  array++;
1059  }
1060 
1061  if (type & PERF_SAMPLE_TIME) {
1062  *array = sample->time;
1063  array++;
1064  }
1065 
1066  if (type & PERF_SAMPLE_ADDR) {
1067  *array = sample->addr;
1068  array++;
1069  }
1070 
1071  if (type & PERF_SAMPLE_ID) {
1072  *array = sample->id;
1073  array++;
1074  }
1075 
1076  if (type & PERF_SAMPLE_STREAM_ID) {
1077  *array = sample->stream_id;
1078  array++;
1079  }
1080 
1081  if (type & PERF_SAMPLE_CPU) {
1082  u.val32[0] = sample->cpu;
1083  if (swapped) {
1084  /*
1085  * Inverse of what is done in perf_evsel__parse_sample
1086  */
1087  u.val32[0] = bswap_32(u.val32[0]);
1088  u.val64 = bswap_64(u.val64);
1089  }
1090  *array = u.val64;
1091  array++;
1092  }
1093 
1094  if (type & PERF_SAMPLE_PERIOD) {
1095  *array = sample->period;
1096  array++;
1097  }
1098 
1099  return 0;
1100 }
1101 
1102 struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name)
1103 {
1104  return pevent_find_field(evsel->tp_format, name);
1105 }
1106 
1107 void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample,
1108  const char *name)
1109 {
1110  struct format_field *field = perf_evsel__field(evsel, name);
1111  int offset;
1112 
1113  if (!field)
1114  return NULL;
1115 
1116  offset = field->offset;
1117 
1118  if (field->flags & FIELD_IS_DYNAMIC) {
1119  offset = *(int *)(sample->raw_data + field->offset);
1120  offset &= 0xffff;
1121  }
1122 
1123  return sample->raw_data + offset;
1124 }
1125 
1126 u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
1127  const char *name)
1128 {
1129  struct format_field *field = perf_evsel__field(evsel, name);
1130  void *ptr;
1131  u64 value;
1132 
1133  if (!field)
1134  return 0;
1135 
1136  ptr = sample->raw_data + field->offset;
1137 
1138  switch (field->size) {
1139  case 1:
1140  return *(u8 *)ptr;
1141  case 2:
1142  value = *(u16 *)ptr;
1143  break;
1144  case 4:
1145  value = *(u32 *)ptr;
1146  break;
1147  case 8:
1148  value = *(u64 *)ptr;
1149  break;
1150  default:
1151  return 0;
1152  }
1153 
1154  if (!evsel->needs_swap)
1155  return value;
1156 
1157  switch (field->size) {
1158  case 2:
1159  return bswap_16(value);
1160  case 4:
1161  return bswap_32(value);
1162  case 8:
1163  return bswap_64(value);
1164  default:
1165  return 0;
1166  }
1167 
1168  return 0;
1169 }