Linux Perf
trace-event-perl.c
Go to the documentation of this file.
1 /*
2  * trace-event-perl. Feed perf script events to an embedded Perl interpreter.
3  *
4  * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21 
22 #include <inttypes.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <errno.h>
28 #include <linux/bitmap.h>
29 #include <linux/time64.h>
30 
31 #include <stdbool.h>
32 /* perl needs the following define, right after including stdbool.h */
33 #define HAS_BOOL
34 #include <EXTERN.h>
35 #include <perl.h>
36 
37 #include "../../perf.h"
38 #include "../callchain.h"
39 #include "../machine.h"
40 #include "../thread.h"
41 #include "../event.h"
42 #include "../trace-event.h"
43 #include "../evsel.h"
44 #include "../debug.h"
45 
46 void boot_Perf__Trace__Context(pTHX_ CV *cv);
47 void boot_DynaLoader(pTHX_ CV *cv);
48 typedef PerlInterpreter * INTERP;
49 
50 void xs_init(pTHX);
51 
52 void xs_init(pTHX)
53 {
54  const char *file = __FILE__;
55  dXSUB_SYS;
56 
57  newXS("Perf::Trace::Context::bootstrap", boot_Perf__Trace__Context,
58  file);
59  newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
60 }
61 
63 
64 #define TRACE_EVENT_TYPE_MAX \
65  ((1 << (sizeof(unsigned short) * 8)) - 1)
66 
67 static DECLARE_BITMAP(events_defined, TRACE_EVENT_TYPE_MAX);
68 
70 
71 static char *cur_field_name;
72 static int zero_flag_atom;
73 
74 static void define_symbolic_value(const char *ev_name,
75  const char *field_name,
76  const char *field_value,
77  const char *field_str)
78 {
79  unsigned long long value;
80  dSP;
81 
82  value = eval_flag(field_value);
83 
84  ENTER;
85  SAVETMPS;
86  PUSHMARK(SP);
87 
88  XPUSHs(sv_2mortal(newSVpv(ev_name, 0)));
89  XPUSHs(sv_2mortal(newSVpv(field_name, 0)));
90  XPUSHs(sv_2mortal(newSVuv(value)));
91  XPUSHs(sv_2mortal(newSVpv(field_str, 0)));
92 
93  PUTBACK;
94  if (get_cv("main::define_symbolic_value", 0))
95  call_pv("main::define_symbolic_value", G_SCALAR);
96  SPAGAIN;
97  PUTBACK;
98  FREETMPS;
99  LEAVE;
100 }
101 
102 static void define_symbolic_values(struct print_flag_sym *field,
103  const char *ev_name,
104  const char *field_name)
105 {
106  define_symbolic_value(ev_name, field_name, field->value, field->str);
107  if (field->next)
108  define_symbolic_values(field->next, ev_name, field_name);
109 }
110 
111 static void define_symbolic_field(const char *ev_name,
112  const char *field_name)
113 {
114  dSP;
115 
116  ENTER;
117  SAVETMPS;
118  PUSHMARK(SP);
119 
120  XPUSHs(sv_2mortal(newSVpv(ev_name, 0)));
121  XPUSHs(sv_2mortal(newSVpv(field_name, 0)));
122 
123  PUTBACK;
124  if (get_cv("main::define_symbolic_field", 0))
125  call_pv("main::define_symbolic_field", G_SCALAR);
126  SPAGAIN;
127  PUTBACK;
128  FREETMPS;
129  LEAVE;
130 }
131 
132 static void define_flag_value(const char *ev_name,
133  const char *field_name,
134  const char *field_value,
135  const char *field_str)
136 {
137  unsigned long long value;
138  dSP;
139 
140  value = eval_flag(field_value);
141 
142  ENTER;
143  SAVETMPS;
144  PUSHMARK(SP);
145 
146  XPUSHs(sv_2mortal(newSVpv(ev_name, 0)));
147  XPUSHs(sv_2mortal(newSVpv(field_name, 0)));
148  XPUSHs(sv_2mortal(newSVuv(value)));
149  XPUSHs(sv_2mortal(newSVpv(field_str, 0)));
150 
151  PUTBACK;
152  if (get_cv("main::define_flag_value", 0))
153  call_pv("main::define_flag_value", G_SCALAR);
154  SPAGAIN;
155  PUTBACK;
156  FREETMPS;
157  LEAVE;
158 }
159 
160 static void define_flag_values(struct print_flag_sym *field,
161  const char *ev_name,
162  const char *field_name)
163 {
164  define_flag_value(ev_name, field_name, field->value, field->str);
165  if (field->next)
166  define_flag_values(field->next, ev_name, field_name);
167 }
168 
169 static void define_flag_field(const char *ev_name,
170  const char *field_name,
171  const char *delim)
172 {
173  dSP;
174 
175  ENTER;
176  SAVETMPS;
177  PUSHMARK(SP);
178 
179  XPUSHs(sv_2mortal(newSVpv(ev_name, 0)));
180  XPUSHs(sv_2mortal(newSVpv(field_name, 0)));
181  XPUSHs(sv_2mortal(newSVpv(delim, 0)));
182 
183  PUTBACK;
184  if (get_cv("main::define_flag_field", 0))
185  call_pv("main::define_flag_field", G_SCALAR);
186  SPAGAIN;
187  PUTBACK;
188  FREETMPS;
189  LEAVE;
190 }
191 
192 static void define_event_symbols(struct event_format *event,
193  const char *ev_name,
194  struct print_arg *args)
195 {
196  if (args == NULL)
197  return;
198 
199  switch (args->type) {
200  case PRINT_NULL:
201  break;
202  case PRINT_ATOM:
203  define_flag_value(ev_name, cur_field_name, "0",
204  args->atom.atom);
205  zero_flag_atom = 0;
206  break;
207  case PRINT_FIELD:
209  cur_field_name = strdup(args->field.name);
210  break;
211  case PRINT_FLAGS:
212  define_event_symbols(event, ev_name, args->flags.field);
213  define_flag_field(ev_name, cur_field_name, args->flags.delim);
214  define_flag_values(args->flags.flags, ev_name, cur_field_name);
215  break;
216  case PRINT_SYMBOL:
217  define_event_symbols(event, ev_name, args->symbol.field);
219  define_symbolic_values(args->symbol.symbols, ev_name,
221  break;
222  case PRINT_HEX:
223  case PRINT_HEX_STR:
224  define_event_symbols(event, ev_name, args->hex.field);
225  define_event_symbols(event, ev_name, args->hex.size);
226  break;
227  case PRINT_INT_ARRAY:
228  define_event_symbols(event, ev_name, args->int_array.field);
229  define_event_symbols(event, ev_name, args->int_array.count);
230  define_event_symbols(event, ev_name, args->int_array.el_size);
231  break;
232  case PRINT_BSTRING:
233  case PRINT_DYNAMIC_ARRAY:
234  case PRINT_DYNAMIC_ARRAY_LEN:
235  case PRINT_STRING:
236  case PRINT_BITMASK:
237  break;
238  case PRINT_TYPE:
239  define_event_symbols(event, ev_name, args->typecast.item);
240  break;
241  case PRINT_OP:
242  if (strcmp(args->op.op, ":") == 0)
243  zero_flag_atom = 1;
244  define_event_symbols(event, ev_name, args->op.left);
245  define_event_symbols(event, ev_name, args->op.right);
246  break;
247  case PRINT_FUNC:
248  default:
249  pr_err("Unsupported print arg type\n");
250  /* we should warn... */
251  return;
252  }
253 
254  if (args->next)
255  define_event_symbols(event, ev_name, args->next);
256 }
257 
259  struct perf_evsel *evsel,
260  struct addr_location *al)
261 {
262  AV *list;
263 
264  list = newAV();
265  if (!list)
266  goto exit;
267 
268  if (!symbol_conf.use_callchain || !sample->callchain)
269  goto exit;
270 
272  sample, NULL, NULL, scripting_max_stack) != 0) {
273  pr_err("Failed to resolve callchain. Skipping\n");
274  goto exit;
275  }
277 
278 
279  while (1) {
280  HV *elem;
281  struct callchain_cursor_node *node;
283  if (!node)
284  break;
285 
286  elem = newHV();
287  if (!elem)
288  goto exit;
289 
290  if (!hv_stores(elem, "ip", newSVuv(node->ip))) {
291  hv_undef(elem);
292  goto exit;
293  }
294 
295  if (node->sym) {
296  HV *sym = newHV();
297  if (!sym) {
298  hv_undef(elem);
299  goto exit;
300  }
301  if (!hv_stores(sym, "start", newSVuv(node->sym->start)) ||
302  !hv_stores(sym, "end", newSVuv(node->sym->end)) ||
303  !hv_stores(sym, "binding", newSVuv(node->sym->binding)) ||
304  !hv_stores(sym, "name", newSVpvn(node->sym->name,
305  node->sym->namelen)) ||
306  !hv_stores(elem, "sym", newRV_noinc((SV*)sym))) {
307  hv_undef(sym);
308  hv_undef(elem);
309  goto exit;
310  }
311  }
312 
313  if (node->map) {
314  struct map *map = node->map;
315  const char *dsoname = "[unknown]";
316  if (map && map->dso) {
318  dsoname = map->dso->long_name;
319  else
320  dsoname = map->dso->name;
321  }
322  if (!hv_stores(elem, "dso", newSVpv(dsoname,0))) {
323  hv_undef(elem);
324  goto exit;
325  }
326  }
327 
329  av_push(list, newRV_noinc((SV*)elem));
330  }
331 
332 exit:
333  return newRV_noinc((SV*)list);
334 }
335 
337  struct perf_evsel *evsel,
338  struct addr_location *al)
339 {
340  struct thread *thread = al->thread;
341  struct event_format *event = evsel->tp_format;
342  struct format_field *field;
343  static char handler[256];
344  unsigned long long val;
345  unsigned long s, ns;
346  int pid;
347  int cpu = sample->cpu;
348  void *data = sample->raw_data;
349  unsigned long long nsecs = sample->time;
350  const char *comm = thread__comm_str(thread);
351 
352  dSP;
353 
354  if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
355  return;
356 
357  if (!event) {
358  pr_debug("ug! no event found for type %" PRIu64, (u64)evsel->attr.config);
359  return;
360  }
361 
362  pid = raw_field_value(event, "common_pid", data);
363 
364  sprintf(handler, "%s::%s", event->system, event->name);
365 
366  if (!test_and_set_bit(event->id, events_defined))
367  define_event_symbols(event, handler, event->print_fmt.args);
368 
369  s = nsecs / NSEC_PER_SEC;
370  ns = nsecs - s * NSEC_PER_SEC;
371 
372  scripting_context->event_data = data;
373  scripting_context->pevent = evsel->tp_format->pevent;
374 
375  ENTER;
376  SAVETMPS;
377  PUSHMARK(SP);
378 
379  XPUSHs(sv_2mortal(newSVpv(handler, 0)));
380  XPUSHs(sv_2mortal(newSViv(PTR2IV(scripting_context))));
381  XPUSHs(sv_2mortal(newSVuv(cpu)));
382  XPUSHs(sv_2mortal(newSVuv(s)));
383  XPUSHs(sv_2mortal(newSVuv(ns)));
384  XPUSHs(sv_2mortal(newSViv(pid)));
385  XPUSHs(sv_2mortal(newSVpv(comm, 0)));
386  XPUSHs(sv_2mortal(perl_process_callchain(sample, evsel, al)));
387 
388  /* common fields other than pid can be accessed via xsub fns */
389 
390  for (field = event->format.fields; field; field = field->next) {
391  if (field->flags & FIELD_IS_STRING) {
392  int offset;
393  if (field->flags & FIELD_IS_DYNAMIC) {
394  offset = *(int *)(data + field->offset);
395  offset &= 0xffff;
396  } else
397  offset = field->offset;
398  XPUSHs(sv_2mortal(newSVpv((char *)data + offset, 0)));
399  } else { /* FIELD_IS_NUMERIC */
400  val = read_size(event, data + field->offset,
401  field->size);
402  if (field->flags & FIELD_IS_SIGNED) {
403  XPUSHs(sv_2mortal(newSViv(val)));
404  } else {
405  XPUSHs(sv_2mortal(newSVuv(val)));
406  }
407  }
408  }
409 
410  PUTBACK;
411 
412  if (get_cv(handler, 0))
413  call_pv(handler, G_SCALAR);
414  else if (get_cv("main::trace_unhandled", 0)) {
415  XPUSHs(sv_2mortal(newSVpv(handler, 0)));
416  XPUSHs(sv_2mortal(newSViv(PTR2IV(scripting_context))));
417  XPUSHs(sv_2mortal(newSVuv(cpu)));
418  XPUSHs(sv_2mortal(newSVuv(nsecs)));
419  XPUSHs(sv_2mortal(newSViv(pid)));
420  XPUSHs(sv_2mortal(newSVpv(comm, 0)));
421  XPUSHs(sv_2mortal(perl_process_callchain(sample, evsel, al)));
422  call_pv("main::trace_unhandled", G_SCALAR);
423  }
424  SPAGAIN;
425  PUTBACK;
426  FREETMPS;
427  LEAVE;
428 }
429 
431  struct perf_sample *sample,
432  struct perf_evsel *evsel)
433 {
434  dSP;
435 
436  if (!get_cv("process_event", 0))
437  return;
438 
439  ENTER;
440  SAVETMPS;
441  PUSHMARK(SP);
442  XPUSHs(sv_2mortal(newSVpvn((const char *)event, event->header.size)));
443  XPUSHs(sv_2mortal(newSVpvn((const char *)&evsel->attr, sizeof(evsel->attr))));
444  XPUSHs(sv_2mortal(newSVpvn((const char *)sample, sizeof(*sample))));
445  XPUSHs(sv_2mortal(newSVpvn((const char *)sample->raw_data, sample->raw_size)));
446  PUTBACK;
447  call_pv("process_event", G_SCALAR);
448  SPAGAIN;
449  PUTBACK;
450  FREETMPS;
451  LEAVE;
452 }
453 
455  struct perf_sample *sample,
456  struct perf_evsel *evsel,
457  struct addr_location *al)
458 {
459  perl_process_tracepoint(sample, evsel, al);
460  perl_process_event_generic(event, sample, evsel);
461 }
462 
463 static void run_start_sub(void)
464 {
465  dSP; /* access to Perl stack */
466  PUSHMARK(SP);
467 
468  if (get_cv("main::trace_begin", 0))
469  call_pv("main::trace_begin", G_DISCARD | G_NOARGS);
470 }
471 
472 /*
473  * Start trace script
474  */
475 static int perl_start_script(const char *script, int argc, const char **argv)
476 {
477  const char **command_line;
478  int i, err = 0;
479 
480  command_line = malloc((argc + 2) * sizeof(const char *));
481  command_line[0] = "";
482  command_line[1] = script;
483  for (i = 2; i < argc + 2; i++)
484  command_line[i] = argv[i - 2];
485 
486  my_perl = perl_alloc();
487  perl_construct(my_perl);
488 
489  if (perl_parse(my_perl, xs_init, argc + 2, (char **)command_line,
490  (char **)NULL)) {
491  err = -1;
492  goto error;
493  }
494 
495  if (perl_run(my_perl)) {
496  err = -1;
497  goto error;
498  }
499 
500  if (SvTRUE(ERRSV)) {
501  err = -1;
502  goto error;
503  }
504 
505  run_start_sub();
506 
507  free(command_line);
508  return 0;
509 error:
510  perl_free(my_perl);
511  free(command_line);
512 
513  return err;
514 }
515 
516 static int perl_flush_script(void)
517 {
518  return 0;
519 }
520 
521 /*
522  * Stop trace script
523  */
524 static int perl_stop_script(void)
525 {
526  dSP; /* access to Perl stack */
527  PUSHMARK(SP);
528 
529  if (get_cv("main::trace_end", 0))
530  call_pv("main::trace_end", G_DISCARD | G_NOARGS);
531 
532  perl_destruct(my_perl);
533  perl_free(my_perl);
534 
535  return 0;
536 }
537 
538 static int perl_generate_script(struct pevent *pevent, const char *outfile)
539 {
540  struct event_format *event = NULL;
541  struct format_field *f;
542  char fname[PATH_MAX];
543  int not_first, count;
544  FILE *ofp;
545 
546  sprintf(fname, "%s.pl", outfile);
547  ofp = fopen(fname, "w");
548  if (ofp == NULL) {
549  fprintf(stderr, "couldn't open %s\n", fname);
550  return -1;
551  }
552 
553  fprintf(ofp, "# perf script event handlers, "
554  "generated by perf script -g perl\n");
555 
556  fprintf(ofp, "# Licensed under the terms of the GNU GPL"
557  " License version 2\n\n");
558 
559  fprintf(ofp, "# The common_* event handler fields are the most useful "
560  "fields common to\n");
561 
562  fprintf(ofp, "# all events. They don't necessarily correspond to "
563  "the 'common_*' fields\n");
564 
565  fprintf(ofp, "# in the format files. Those fields not available as "
566  "handler params can\n");
567 
568  fprintf(ofp, "# be retrieved using Perl functions of the form "
569  "common_*($context).\n");
570 
571  fprintf(ofp, "# See Context.pm for the list of available "
572  "functions.\n\n");
573 
574  fprintf(ofp, "use lib \"$ENV{'PERF_EXEC_PATH'}/scripts/perl/"
575  "Perf-Trace-Util/lib\";\n");
576 
577  fprintf(ofp, "use lib \"./Perf-Trace-Util/lib\";\n");
578  fprintf(ofp, "use Perf::Trace::Core;\n");
579  fprintf(ofp, "use Perf::Trace::Context;\n");
580  fprintf(ofp, "use Perf::Trace::Util;\n\n");
581 
582  fprintf(ofp, "sub trace_begin\n{\n\t# optional\n}\n\n");
583  fprintf(ofp, "sub trace_end\n{\n\t# optional\n}\n");
584 
585 
586  fprintf(ofp, "\n\
587 sub print_backtrace\n\
588 {\n\
589  my $callchain = shift;\n\
590  for my $node (@$callchain)\n\
591  {\n\
592  if(exists $node->{sym})\n\
593  {\n\
594  printf( \"\\t[\\%%x] \\%%s\\n\", $node->{ip}, $node->{sym}{name});\n\
595  }\n\
596  else\n\
597  {\n\
598  printf( \"\\t[\\%%x]\\n\", $node{ip});\n\
599  }\n\
600  }\n\
601 }\n\n\
602 ");
603 
604 
605  while ((event = trace_find_next_event(pevent, event))) {
606  fprintf(ofp, "sub %s::%s\n{\n", event->system, event->name);
607  fprintf(ofp, "\tmy (");
608 
609  fprintf(ofp, "$event_name, ");
610  fprintf(ofp, "$context, ");
611  fprintf(ofp, "$common_cpu, ");
612  fprintf(ofp, "$common_secs, ");
613  fprintf(ofp, "$common_nsecs,\n");
614  fprintf(ofp, "\t $common_pid, ");
615  fprintf(ofp, "$common_comm, ");
616  fprintf(ofp, "$common_callchain,\n\t ");
617 
618  not_first = 0;
619  count = 0;
620 
621  for (f = event->format.fields; f; f = f->next) {
622  if (not_first++)
623  fprintf(ofp, ", ");
624  if (++count % 5 == 0)
625  fprintf(ofp, "\n\t ");
626 
627  fprintf(ofp, "$%s", f->name);
628  }
629  fprintf(ofp, ") = @_;\n\n");
630 
631  fprintf(ofp, "\tprint_header($event_name, $common_cpu, "
632  "$common_secs, $common_nsecs,\n\t "
633  "$common_pid, $common_comm, $common_callchain);\n\n");
634 
635  fprintf(ofp, "\tprintf(\"");
636 
637  not_first = 0;
638  count = 0;
639 
640  for (f = event->format.fields; f; f = f->next) {
641  if (not_first++)
642  fprintf(ofp, ", ");
643  if (count && count % 4 == 0) {
644  fprintf(ofp, "\".\n\t \"");
645  }
646  count++;
647 
648  fprintf(ofp, "%s=", f->name);
649  if (f->flags & FIELD_IS_STRING ||
650  f->flags & FIELD_IS_FLAG ||
651  f->flags & FIELD_IS_SYMBOLIC)
652  fprintf(ofp, "%%s");
653  else if (f->flags & FIELD_IS_SIGNED)
654  fprintf(ofp, "%%d");
655  else
656  fprintf(ofp, "%%u");
657  }
658 
659  fprintf(ofp, "\\n\",\n\t ");
660 
661  not_first = 0;
662  count = 0;
663 
664  for (f = event->format.fields; f; f = f->next) {
665  if (not_first++)
666  fprintf(ofp, ", ");
667 
668  if (++count % 5 == 0)
669  fprintf(ofp, "\n\t ");
670 
671  if (f->flags & FIELD_IS_FLAG) {
672  if ((count - 1) % 5 != 0) {
673  fprintf(ofp, "\n\t ");
674  count = 4;
675  }
676  fprintf(ofp, "flag_str(\"");
677  fprintf(ofp, "%s::%s\", ", event->system,
678  event->name);
679  fprintf(ofp, "\"%s\", $%s)", f->name,
680  f->name);
681  } else if (f->flags & FIELD_IS_SYMBOLIC) {
682  if ((count - 1) % 5 != 0) {
683  fprintf(ofp, "\n\t ");
684  count = 4;
685  }
686  fprintf(ofp, "symbol_str(\"");
687  fprintf(ofp, "%s::%s\", ", event->system,
688  event->name);
689  fprintf(ofp, "\"%s\", $%s)", f->name,
690  f->name);
691  } else
692  fprintf(ofp, "$%s", f->name);
693  }
694 
695  fprintf(ofp, ");\n\n");
696 
697  fprintf(ofp, "\tprint_backtrace($common_callchain);\n");
698 
699  fprintf(ofp, "}\n\n");
700  }
701 
702  fprintf(ofp, "sub trace_unhandled\n{\n\tmy ($event_name, $context, "
703  "$common_cpu, $common_secs, $common_nsecs,\n\t "
704  "$common_pid, $common_comm, $common_callchain) = @_;\n\n");
705 
706  fprintf(ofp, "\tprint_header($event_name, $common_cpu, "
707  "$common_secs, $common_nsecs,\n\t $common_pid, "
708  "$common_comm, $common_callchain);\n");
709  fprintf(ofp, "\tprint_backtrace($common_callchain);\n");
710  fprintf(ofp, "}\n\n");
711 
712  fprintf(ofp, "sub print_header\n{\n"
713  "\tmy ($event_name, $cpu, $secs, $nsecs, $pid, $comm) = @_;\n\n"
714  "\tprintf(\"%%-20s %%5u %%05u.%%09u %%8u %%-20s \",\n\t "
715  "$event_name, $cpu, $secs, $nsecs, $pid, $comm);\n}\n");
716 
717  fprintf(ofp,
718  "\n# Packed byte string args of process_event():\n"
719  "#\n"
720  "# $event:\tunion perf_event\tutil/event.h\n"
721  "# $attr:\tstruct perf_event_attr\tlinux/perf_event.h\n"
722  "# $sample:\tstruct perf_sample\tutil/event.h\n"
723  "# $raw_data:\tperf_sample->raw_data\tutil/event.h\n"
724  "\n"
725  "sub process_event\n"
726  "{\n"
727  "\tmy ($event, $attr, $sample, $raw_data) = @_;\n"
728  "\n"
729  "\tmy @event\t= unpack(\"LSS\", $event);\n"
730  "\tmy @attr\t= unpack(\"LLQQQQQLLQQ\", $attr);\n"
731  "\tmy @sample\t= unpack(\"QLLQQQQQLL\", $sample);\n"
732  "\tmy @raw_data\t= unpack(\"C*\", $raw_data);\n"
733  "\n"
734  "\tuse Data::Dumper;\n"
735  "\tprint Dumper \\@event, \\@attr, \\@sample, \\@raw_data;\n"
736  "}\n");
737 
738  fclose(ofp);
739 
740  fprintf(stderr, "generated Perl script: %s\n", fname);
741 
742  return 0;
743 }
744 
746  .name = "Perl",
747  .start_script = perl_start_script,
748  .flush_script = perl_flush_script,
749  .stop_script = perl_stop_script,
750  .process_event = perl_process_event,
751  .generate_script = perl_generate_script,
752 };
#define TRACE_EVENT_TYPE_MAX
Definition: mem2node.c:7
int value
Definition: python.c:1143
static void define_symbolic_field(const char *ev_name, const char *field_name)
static void define_event_symbols(struct event_format *event, const char *ev_name, struct print_arg *args)
struct event_format * trace_find_next_event(struct pevent *pevent, struct event_format *event)
struct scripting_ops perl_scripting_ops
void boot_Perf__Trace__Context(pTHX_ CV *cv)
static int perl_generate_script(struct pevent *pevent, const char *outfile)
dictionary data
Definition: stat-cpi.py:4
struct ip_callchain * callchain
Definition: event.h:211
int int err
Definition: 5sec.c:44
struct symbol * sym
Definition: callchain.h:140
static void define_symbolic_values(struct print_flag_sym *field, const char *ev_name, const char *field_name)
void boot_DynaLoader(pTHX_ CV *cv)
bool show_kernel_path
Definition: symbol.h:93
static char * cur_field_name
static void perl_process_event_generic(union perf_event *event, struct perf_sample *sample, struct perf_evsel *evsel)
const char * long_name
Definition: dso.h:173
PerlInterpreter * INTERP
u64 end
Definition: symbol.h:58
struct scripting_context * scripting_context
static void callchain_cursor_commit(struct callchain_cursor *cursor)
Definition: callchain.h:212
#define pr_err(fmt,...)
Definition: json.h:21
Definition: comm.h:11
def ns(sec, nsec)
void * malloc(YYSIZE_T)
static void define_flag_values(struct print_flag_sym *field, const char *ev_name, const char *field_name)
unsigned long long eval_flag(const char *flag)
unsigned int scripting_max_stack
u8 binding
Definition: symbol.h:61
Definition: thread.h:18
static void define_flag_field(const char *ev_name, const char *field_name, const char *delim)
static int perl_stop_script(void)
const char * thread__comm_str(const struct thread *thread)
Definition: thread.c:258
char name[0]
Definition: dso.h:197
#define pr_debug(fmt,...)
Definition: json.h:27
u64 start
Definition: symbol.h:57
const char * name
Definition: trace-event.h:75
unsigned long long read_size(struct event_format *event, void *ptr, int size)
static void perl_process_event(union perf_event *event, struct perf_sample *sample, struct perf_evsel *evsel, struct addr_location *al)
static void callchain_cursor_advance(struct callchain_cursor *cursor)
Definition: callchain.h:228
static int zero_flag_atom
void xs_init(pTHX)
INTERP my_perl
struct dso * dso
Definition: map.h:45
struct event_format * tp_format
Definition: evsel.h:105
#define PATH_MAX
Definition: jevents.c:1042
Definition: jevents.c:169
char name[0]
Definition: symbol.h:66
static int perl_flush_script(void)
#define event
struct map * map
Definition: callchain.h:139
u32 cpu
Definition: event.h:201
static int perl_start_script(const char *script, int argc, const char **argv)
struct thread * thread
Definition: symbol.h:209
#define NSEC_PER_SEC
Definition: jvmti_agent.c:101
struct pevent * pevent
Definition: trace-event.h:97
static SV * perl_process_callchain(struct perf_sample *sample, struct perf_evsel *evsel, struct addr_location *al)
void * raw_data
Definition: event.h:210
#define PRINT_FIELD(x)
struct perf_event_header header
Definition: event.h:624
u32 pid
Definition: hists_common.c:15
static void define_flag_value(const char *ev_name, const char *field_name, const char *field_value, const char *field_str)
static void run_start_sub(void)
Definition: jevents.c:228
bool use_callchain
Definition: symbol.h:93
static int sym(yyscan_t scanner, int type, int config)
u64 time
Definition: event.h:194
static unsigned int nsecs
Definition: futex-hash.c:32
static void define_symbolic_value(const char *ev_name, const char *field_name, const char *field_value, const char *field_str)
void free(void *)
static FILE * f
Definition: intel-pt-log.c:30
static DECLARE_BITMAP(events_defined, TRACE_EVENT_TYPE_MAX)
int thread__resolve_callchain(struct thread *thread, struct callchain_cursor *cursor, struct perf_evsel *evsel, struct perf_sample *sample, struct symbol **parent, struct addr_location *root_al, int max_stack)
Definition: machine.c:2308
static void perl_process_tracepoint(struct perf_sample *sample, struct perf_evsel *evsel, struct addr_location *al)
u16 namelen
Definition: symbol.h:59
struct perf_event_attr attr
Definition: evsel.h:93
unsigned long long raw_field_value(struct event_format *event, const char *name, void *data)
static struct callchain_cursor_node * callchain_cursor_current(struct callchain_cursor *cursor)
Definition: callchain.h:220