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