You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
perf trace: Add Perl scripting support
Implement trace_scripting_ops to make Perl a supported perf trace scripting language. Additionally adds code that allows Perl trace scripts to access the 'flag' and 'symbolic' (__print_flags(), __print_symbolic()) field information parsed from the trace format files. Also adds the Perl implementation of the generate_script() trace_scripting_op, which creates a ready-to-run perf trace Perl script based on existing trace data. Scripts generated by this implementation print out all the fields for each event mentioned in perf.data (and will detect and generate the proper scripting code for 'flag' and 'symbolic' fields), and will additionally generate handlers for the special 'trace_unhandled', 'trace_begin' and 'trace_end' handlers. Script authors can simply remove the printing code to implement their own custom event handling. Signed-off-by: Tom Zanussi <tzanussi@gmail.com> Cc: fweisbec@gmail.com Cc: rostedt@goodmis.org Cc: anton@samba.org Cc: hch@infradead.org LKML-Reference: <1259133352-23685-4-git-send-email-tzanussi@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
@@ -407,6 +407,7 @@ LIB_OBJS += util/thread.o
|
||||
LIB_OBJS += util/trace-event-parse.o
|
||||
LIB_OBJS += util/trace-event-read.o
|
||||
LIB_OBJS += util/trace-event-info.o
|
||||
LIB_OBJS += util/trace-event-perl.o
|
||||
LIB_OBJS += util/svghelper.o
|
||||
LIB_OBJS += util/sort.o
|
||||
LIB_OBJS += util/hist.o
|
||||
@@ -489,6 +490,15 @@ else
|
||||
LIB_OBJS += util/probe-finder.o
|
||||
endif
|
||||
|
||||
PERL_EMBED_LDOPTS = `perl -MExtUtils::Embed -e ldopts`
|
||||
PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts`
|
||||
|
||||
ifneq ($(shell sh -c "(echo '\#include <EXTERN.h>'; echo '\#include <perl.h>'; echo 'int main(void) { perl_alloc(); return 0; }') | $(CC) -x c - $(PERL_EMBED_CCOPTS) -o /dev/null $(PERL_EMBED_LDOPTS) > /dev/null 2>&1 && echo y"), y)
|
||||
BASIC_CFLAGS += -DNO_LIBPERL
|
||||
else
|
||||
ALL_LDFLAGS += $(PERL_EMBED_LDOPTS)
|
||||
endif
|
||||
|
||||
ifdef NO_DEMANGLE
|
||||
BASIC_CFLAGS += -DNO_DEMANGLE
|
||||
else
|
||||
@@ -860,6 +870,9 @@ util/hweight.o: ../../lib/hweight.c PERF-CFLAGS
|
||||
util/find_next_bit.o: ../../lib/find_next_bit.c PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o util/find_next_bit.o -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
|
||||
|
||||
util/trace-event-perl.o: util/trace-event-perl.c PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o util/trace-event-perl.o -c $(ALL_CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter $<
|
||||
|
||||
perf-%$X: %.o $(PERFLIBS)
|
||||
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
|
||||
|
||||
|
||||
@@ -38,6 +38,8 @@ static void setup_scripting(void)
|
||||
/* make sure PERF_EXEC_PATH is set for scripts */
|
||||
perf_set_argv_exec_path(perf_exec_path());
|
||||
|
||||
setup_perl_scripting();
|
||||
|
||||
scripting_ops = &default_scripting_ops;
|
||||
}
|
||||
|
||||
|
||||
@@ -1888,7 +1888,7 @@ find_any_field(struct event *event, const char *name)
|
||||
return find_field(event, name);
|
||||
}
|
||||
|
||||
static unsigned long long read_size(void *ptr, int size)
|
||||
unsigned long long read_size(void *ptr, int size)
|
||||
{
|
||||
switch (size) {
|
||||
case 1:
|
||||
@@ -1973,7 +1973,7 @@ int trace_parse_common_type(void *data)
|
||||
"common_type");
|
||||
}
|
||||
|
||||
static int parse_common_pid(void *data)
|
||||
int trace_parse_common_pid(void *data)
|
||||
{
|
||||
static int pid_offset;
|
||||
static int pid_size;
|
||||
@@ -2025,6 +2025,14 @@ struct event *trace_find_event(int id)
|
||||
return event;
|
||||
}
|
||||
|
||||
struct event *trace_find_next_event(struct event *event)
|
||||
{
|
||||
if (!event)
|
||||
return event_list;
|
||||
|
||||
return event->next;
|
||||
}
|
||||
|
||||
static unsigned long long eval_num_arg(void *data, int size,
|
||||
struct event *event, struct print_arg *arg)
|
||||
{
|
||||
@@ -2164,7 +2172,7 @@ static const struct flag flags[] = {
|
||||
{ "HRTIMER_RESTART", 1 },
|
||||
};
|
||||
|
||||
static unsigned long long eval_flag(const char *flag)
|
||||
unsigned long long eval_flag(const char *flag)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -2694,7 +2702,7 @@ get_return_for_leaf(int cpu, int cur_pid, unsigned long long cur_func,
|
||||
if (!(event->flags & EVENT_FL_ISFUNCRET))
|
||||
return NULL;
|
||||
|
||||
pid = parse_common_pid(next->data);
|
||||
pid = trace_parse_common_pid(next->data);
|
||||
field = find_field(event, "func");
|
||||
if (!field)
|
||||
die("function return does not have field func");
|
||||
@@ -2980,7 +2988,7 @@ void print_event(int cpu, void *data, int size, unsigned long long nsecs,
|
||||
return;
|
||||
}
|
||||
|
||||
pid = parse_common_pid(data);
|
||||
pid = trace_parse_common_pid(data);
|
||||
|
||||
if (event->flags & (EVENT_FL_ISFUNCENT | EVENT_FL_ISFUNCRET))
|
||||
return pretty_print_func_graph(data, size, event, cpu,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,42 @@
|
||||
#ifndef __PERF_TRACE_EVENT_PERL_H
|
||||
#define __PERF_TRACE_EVENT_PERL_H
|
||||
#ifdef NO_LIBPERL
|
||||
typedef int INTERP;
|
||||
#define dSP
|
||||
#define ENTER
|
||||
#define SAVETMPS
|
||||
#define PUTBACK
|
||||
#define SPAGAIN
|
||||
#define FREETMPS
|
||||
#define LEAVE
|
||||
#define SP
|
||||
#define ERRSV
|
||||
#define G_SCALAR (0)
|
||||
#define G_DISCARD (0)
|
||||
#define G_NOARGS (0)
|
||||
#define PUSHMARK(a)
|
||||
#define SvTRUE(a) (0)
|
||||
#define XPUSHs(s)
|
||||
#define sv_2mortal(a)
|
||||
#define newSVpv(a,b)
|
||||
#define newSVuv(a)
|
||||
#define newSViv(a)
|
||||
#define get_cv(a,b) (0)
|
||||
#define call_pv(a,b) (0)
|
||||
#define perl_alloc() (0)
|
||||
#define perl_construct(a) (0)
|
||||
#define perl_parse(a,b,c,d,e) (0)
|
||||
#define perl_run(a) (0)
|
||||
#define perl_destruct(a) (0)
|
||||
#define perl_free(a) (0)
|
||||
#else
|
||||
#include <EXTERN.h>
|
||||
#include <perl.h>
|
||||
typedef PerlInterpreter * INTERP;
|
||||
#endif
|
||||
|
||||
struct scripting_context {
|
||||
void *event_data;
|
||||
};
|
||||
|
||||
#endif /* __PERF_TRACE_EVENT_PERL_H */
|
||||
@@ -245,10 +245,14 @@ extern int latency_format;
|
||||
|
||||
int parse_header_page(char *buf, unsigned long size);
|
||||
int trace_parse_common_type(void *data);
|
||||
int trace_parse_common_pid(void *data);
|
||||
struct event *trace_find_event(int id);
|
||||
struct event *trace_find_next_event(struct event *event);
|
||||
unsigned long long read_size(void *ptr, int size);
|
||||
unsigned long long
|
||||
raw_field_value(struct event *event, const char *name, void *data);
|
||||
void *raw_field_ptr(struct event *event, const char *name, void *data);
|
||||
unsigned long long eval_flag(const char *flag);
|
||||
|
||||
int read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events);
|
||||
|
||||
@@ -272,4 +276,7 @@ struct scripting_ops {
|
||||
|
||||
int script_spec_register(const char *spec, struct scripting_ops *ops);
|
||||
|
||||
extern struct scripting_ops perl_scripting_ops;
|
||||
void setup_perl_scripting(void);
|
||||
|
||||
#endif /* __PERF_TRACE_EVENTS_H */
|
||||
|
||||
Reference in New Issue
Block a user