Re: [PATCH] perf script: Fix Python support when no libtraceevent

From: Arnaldo Carvalho de Melo
Date: Wed Mar 15 2023 - 09:27:41 EST


Em Wed, Mar 15, 2023 at 10:43:21AM +0200, Adrian Hunter escreveu:
> Python scripting can be used without libtraceevent. In particular,
> scripting for Intel PT does not use tracepoints, and so does not need
> libtraceevent support.
>
> Alter the build and employ conditional compilation to allow Python
> scripting without libtraceevent.
>
> Example:

Thanks, applied.

- Arnaldo


> Before:
>
> $ ldd `which perf` | grep -i python
> $ ldd `which perf` | grep -i libtraceevent
> $ perf record -e intel_pt//u uname
> Linux
> [ perf record: Woken up 1 times to write data ]
> [ perf record: Captured and wrote 0.031 MB perf.data ]
> $ perf script intel-pt-events.py |& head -3
> Error: Couldn't find script `intel-pt-events.py'
>
> See perf script -l for available scripts.
>
> After:
>
> $ ldd `which perf` | grep -i python
> libpython3.10.so.1.0 => /lib/x86_64-linux-gnu/libpython3.10.so.1.0 (0x00007f4bac400000)
> $ ldd `which perf` | grep -i libtraceevent
> $ perf script intel-pt-events.py | head
> Intel PT Branch Trace, Power Events, Event Trace and PTWRITE
> Switch In 8021/8021 [000] 11234.097713404 0/0
> perf-exec 8021/8021 [000] 11234.098041726 psb offset: 0x0 0 [unknown] ([unknown])
> perf-exec 8021/8021 [000] 11234.098041726 cbr 45 freq: 4505 MHz (161%) 0 [unknown] ([unknown])
> uname 8021/8021 [000] 11234.098082170 branches:uH tr strt 0 [unknown] ([unknown]) => 7f3a8b9422b0 _start+0x0 (/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2)
> uname 8021/8021 [000] 11234.098082379 branches:uH tr end 7f3a8b9422b0 _start+0x0 (/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2) => 0 [unknown] ([unknown])
> uname 8021/8021 [000] 11234.098083629 branches:uH tr strt 0 [unknown] ([unknown]) => 7f3a8b9422b0 _start+0x0 (/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2)
> uname 8021/8021 [000] 11234.098083629 branches:uH call 7f3a8b9422b3 _start+0x3 (/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2) => 7f3a8b943050 _dl_start+0x0 (/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2)
> uname 8021/8021 [000] 11234.098083837 branches:uH tr end 7f3a8b943060 _dl_start+0x10 (/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2) => 0 [unknown] ([unknown]) IPC: 0.01 (9/938)
> uname 8021/8021 [000] 11234.098084670 branches:uH tr strt 0 [unknown] ([unknown]) => 7f3a8b943060 _dl_start+0x10 (/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2)
>
> Fixes: 378ef0f5d9d7 ("perf build: Use libtraceevent from the system")
> Signed-off-by: Adrian Hunter <adrian.hunter@xxxxxxxxx>
> ---
> tools/perf/Build | 2 +-
> tools/perf/builtin-script.c | 2 +-
> tools/perf/scripts/Build | 4 +-
> .../perf/scripts/python/Perf-Trace-Util/Build | 2 +-
> .../scripts/python/Perf-Trace-Util/Context.c | 4 +
> tools/perf/util/Build | 2 +-
> tools/perf/util/scripting-engines/Build | 2 +-
> .../scripting-engines/trace-event-python.c | 75 +++++++++++++------
> tools/perf/util/trace-event-scripting.c | 9 ++-
> 9 files changed, 72 insertions(+), 30 deletions(-)
>
> diff --git a/tools/perf/Build b/tools/perf/Build
> index 6dd67e502295..aa7623622834 100644
> --- a/tools/perf/Build
> +++ b/tools/perf/Build
> @@ -56,6 +56,6 @@ CFLAGS_builtin-report.o += -DDOCDIR="BUILD_STR($(srcdir_SQ)/Documentation)"
> perf-y += util/
> perf-y += arch/
> perf-y += ui/
> -perf-$(CONFIG_LIBTRACEEVENT) += scripts/
> +perf-y += scripts/
>
> gtk-y += ui/gtk/
> diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
> index 522226114263..976f8bfe099c 100644
> --- a/tools/perf/builtin-script.c
> +++ b/tools/perf/builtin-script.c
> @@ -2313,8 +2313,8 @@ static void setup_scripting(void)
> {
> #ifdef HAVE_LIBTRACEEVENT
> setup_perl_scripting();
> - setup_python_scripting();
> #endif
> + setup_python_scripting();
> }
>
> static int flush_scripting(void)
> diff --git a/tools/perf/scripts/Build b/tools/perf/scripts/Build
> index 68d4b54574ad..7d8e2e57faac 100644
> --- a/tools/perf/scripts/Build
> +++ b/tools/perf/scripts/Build
> @@ -1,2 +1,4 @@
> -perf-$(CONFIG_LIBPERL) += perl/Perf-Trace-Util/
> +ifeq ($(CONFIG_LIBTRACEEVENT),y)
> + perf-$(CONFIG_LIBPERL) += perl/Perf-Trace-Util/
> +endif
> perf-$(CONFIG_LIBPYTHON) += python/Perf-Trace-Util/
> diff --git a/tools/perf/scripts/python/Perf-Trace-Util/Build b/tools/perf/scripts/python/Perf-Trace-Util/Build
> index d5fed4e42617..7d0e33ce6aba 100644
> --- a/tools/perf/scripts/python/Perf-Trace-Util/Build
> +++ b/tools/perf/scripts/python/Perf-Trace-Util/Build
> @@ -1,3 +1,3 @@
> -perf-$(CONFIG_LIBTRACEEVENT) += Context.o
> +perf-y += Context.o
>
> CFLAGS_Context.o += $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs
> diff --git a/tools/perf/scripts/python/Perf-Trace-Util/Context.c b/tools/perf/scripts/python/Perf-Trace-Util/Context.c
> index 895f5fc23965..b0d449f41650 100644
> --- a/tools/perf/scripts/python/Perf-Trace-Util/Context.c
> +++ b/tools/perf/scripts/python/Perf-Trace-Util/Context.c
> @@ -59,6 +59,7 @@ static struct scripting_context *get_scripting_context(PyObject *args)
> return get_args(args, "context", NULL);
> }
>
> +#ifdef HAVE_LIBTRACEEVENT
> static PyObject *perf_trace_context_common_pc(PyObject *obj, PyObject *args)
> {
> struct scripting_context *c = get_scripting_context(args);
> @@ -90,6 +91,7 @@ static PyObject *perf_trace_context_common_lock_depth(PyObject *obj,
>
> return Py_BuildValue("i", common_lock_depth(c));
> }
> +#endif
>
> static PyObject *perf_sample_insn(PyObject *obj, PyObject *args)
> {
> @@ -178,12 +180,14 @@ static PyObject *perf_sample_srccode(PyObject *obj, PyObject *args)
> }
>
> static PyMethodDef ContextMethods[] = {
> +#ifdef HAVE_LIBTRACEEVENT
> { "common_pc", perf_trace_context_common_pc, METH_VARARGS,
> "Get the common preempt count event field value."},
> { "common_flags", perf_trace_context_common_flags, METH_VARARGS,
> "Get the common flags event field value."},
> { "common_lock_depth", perf_trace_context_common_lock_depth,
> METH_VARARGS, "Get the common lock depth event field value."},
> +#endif
> { "perf_sample_insn", perf_sample_insn,
> METH_VARARGS, "Get the machine code instruction."},
> { "perf_set_itrace_options", perf_set_itrace_options,
> diff --git a/tools/perf/util/Build b/tools/perf/util/Build
> index 918b501f9bd8..4868e3bf7df9 100644
> --- a/tools/perf/util/Build
> +++ b/tools/perf/util/Build
> @@ -78,7 +78,7 @@ perf-y += pmu-bison.o
> perf-y += pmu-hybrid.o
> perf-y += svghelper.o
> perf-$(CONFIG_LIBTRACEEVENT) += trace-event-info.o
> -perf-$(CONFIG_LIBTRACEEVENT) += trace-event-scripting.o
> +perf-y += trace-event-scripting.o
> perf-$(CONFIG_LIBTRACEEVENT) += trace-event.o
> perf-$(CONFIG_LIBTRACEEVENT) += trace-event-parse.o
> perf-$(CONFIG_LIBTRACEEVENT) += trace-event-read.o
> diff --git a/tools/perf/util/scripting-engines/Build b/tools/perf/util/scripting-engines/Build
> index 2c96aa3cc1ec..c220fec97032 100644
> --- a/tools/perf/util/scripting-engines/Build
> +++ b/tools/perf/util/scripting-engines/Build
> @@ -1,7 +1,7 @@
> ifeq ($(CONFIG_LIBTRACEEVENT),y)
> perf-$(CONFIG_LIBPERL) += trace-event-perl.o
> - perf-$(CONFIG_LIBPYTHON) += trace-event-python.o
> endif
> +perf-$(CONFIG_LIBPYTHON) += trace-event-python.o
>
> CFLAGS_trace-event-perl.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-nested-externs -Wno-undef -Wno-switch-default -Wno-bad-function-cast -Wno-declaration-after-statement -Wno-switch-enum
>
> diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
> index 2c2697c5d025..0f4ef61f2ffa 100644
> --- a/tools/perf/util/scripting-engines/trace-event-python.c
> +++ b/tools/perf/util/scripting-engines/trace-event-python.c
> @@ -30,7 +30,9 @@
> #include <linux/bitmap.h>
> #include <linux/compiler.h>
> #include <linux/time64.h>
> +#ifdef HAVE_LIBTRACEEVENT
> #include <traceevent/event-parse.h>
> +#endif
>
> #include "../build-id.h"
> #include "../counts.h"
> @@ -87,18 +89,21 @@ PyMODINIT_FUNC initperf_trace_context(void);
> PyMODINIT_FUNC PyInit_perf_trace_context(void);
> #endif
>
> +#ifdef HAVE_LIBTRACEEVENT
> #define TRACE_EVENT_TYPE_MAX \
> ((1 << (sizeof(unsigned short) * 8)) - 1)
>
> static DECLARE_BITMAP(events_defined, TRACE_EVENT_TYPE_MAX);
>
> -#define MAX_FIELDS 64
> #define N_COMMON_FIELDS 7
>
> -extern struct scripting_context *scripting_context;
> -
> static char *cur_field_name;
> static int zero_flag_atom;
> +#endif
> +
> +#define MAX_FIELDS 64
> +
> +extern struct scripting_context *scripting_context;
>
> static PyObject *main_module, *main_dict;
>
> @@ -153,6 +158,26 @@ static PyObject *get_handler(const char *handler_name)
> return handler;
> }
>
> +static void call_object(PyObject *handler, PyObject *args, const char *die_msg)
> +{
> + PyObject *retval;
> +
> + retval = PyObject_CallObject(handler, args);
> + if (retval == NULL)
> + handler_call_die(die_msg);
> + Py_DECREF(retval);
> +}
> +
> +static void try_call_object(const char *handler_name, PyObject *args)
> +{
> + PyObject *handler;
> +
> + handler = get_handler(handler_name);
> + if (handler)
> + call_object(handler, args, handler_name);
> +}
> +
> +#ifdef HAVE_LIBTRACEEVENT
> static int get_argument_count(PyObject *handler)
> {
> int arg_count = 0;
> @@ -181,25 +206,6 @@ static int get_argument_count(PyObject *handler)
> return arg_count;
> }
>
> -static void call_object(PyObject *handler, PyObject *args, const char *die_msg)
> -{
> - PyObject *retval;
> -
> - retval = PyObject_CallObject(handler, args);
> - if (retval == NULL)
> - handler_call_die(die_msg);
> - Py_DECREF(retval);
> -}
> -
> -static void try_call_object(const char *handler_name, PyObject *args)
> -{
> - PyObject *handler;
> -
> - handler = get_handler(handler_name);
> - if (handler)
> - call_object(handler, args, handler_name);
> -}
> -
> static void define_value(enum tep_print_arg_type field_type,
> const char *ev_name,
> const char *field_name,
> @@ -379,6 +385,7 @@ static PyObject *get_field_numeric_entry(struct tep_event *event,
> obj = list;
> return obj;
> }
> +#endif
>
> static const char *get_dsoname(struct map *map)
> {
> @@ -906,6 +913,7 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample,
> return dict;
> }
>
> +#ifdef HAVE_LIBTRACEEVENT
> static void python_process_tracepoint(struct perf_sample *sample,
> struct evsel *evsel,
> struct addr_location *al,
> @@ -1035,6 +1043,16 @@ static void python_process_tracepoint(struct perf_sample *sample,
>
> Py_DECREF(t);
> }
> +#else
> +static void python_process_tracepoint(struct perf_sample *sample __maybe_unused,
> + struct evsel *evsel __maybe_unused,
> + struct addr_location *al __maybe_unused,
> + struct addr_location *addr_al __maybe_unused)
> +{
> + fprintf(stderr, "Tracepoint events are not supported because "
> + "perf is not linked with libtraceevent.\n");
> +}
> +#endif
>
> static PyObject *tuple_new(unsigned int sz)
> {
> @@ -1965,6 +1983,7 @@ static int python_stop_script(void)
> return 0;
> }
>
> +#ifdef HAVE_LIBTRACEEVENT
> static int python_generate_script(struct tep_handle *pevent, const char *outfile)
> {
> int i, not_first, count, nr_events;
> @@ -2155,6 +2174,18 @@ static int python_generate_script(struct tep_handle *pevent, const char *outfile
>
> return 0;
> }
> +#else
> +static int python_generate_script(struct tep_handle *pevent __maybe_unused,
> + const char *outfile __maybe_unused)
> +{
> + fprintf(stderr, "Generating Python perf-script is not supported."
> + " Install libtraceevent and rebuild perf to enable it.\n"
> + "For example:\n # apt install libtraceevent-dev (ubuntu)"
> + "\n # yum install libtraceevent-devel (Fedora)"
> + "\n etc.\n");
> + return -1;
> +}
> +#endif
>
> struct scripting_ops python_scripting_ops = {
> .name = "Python",
> diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
> index 56175c53f9af..bd0000300c77 100644
> --- a/tools/perf/util/trace-event-scripting.c
> +++ b/tools/perf/util/trace-event-scripting.c
> @@ -9,7 +9,9 @@
> #include <stdlib.h>
> #include <string.h>
> #include <errno.h>
> +#ifdef HAVE_LIBTRACEEVENT
> #include <traceevent/event-parse.h>
> +#endif
>
> #include "debug.h"
> #include "trace-event.h"
> @@ -27,10 +29,11 @@ void scripting_context__update(struct scripting_context *c,
> struct addr_location *addr_al)
> {
> c->event_data = sample->raw_data;
> + c->pevent = NULL;
> +#ifdef HAVE_LIBTRACEEVENT
> if (evsel->tp_format)
> c->pevent = evsel->tp_format->tep;
> - else
> - c->pevent = NULL;
> +#endif
> c->event = event;
> c->sample = sample;
> c->evsel = evsel;
> @@ -122,6 +125,7 @@ void setup_python_scripting(void)
> }
> #endif
>
> +#ifdef HAVE_LIBTRACEEVENT
> static void print_perl_unsupported_msg(void)
> {
> fprintf(stderr, "Perl scripting not supported."
> @@ -186,3 +190,4 @@ void setup_perl_scripting(void)
> register_perl_scripting(&perl_scripting_ops);
> }
> #endif
> +#endif
> --
> 2.34.1
>

--

- Arnaldo