[libvirt] [PATCH v5 08/23] src: rewrite systemtap probe generator in Python

Daniel P. Berrangé posted 23 patches 5 years ago
There is a newer version of this series
[libvirt] [PATCH v5 08/23] src: rewrite systemtap probe generator in Python
Posted by Daniel P. Berrangé 5 years ago
As part of an goal to eliminate Perl from libvirt build tools,
rewrite the dtrace2systemtap.pl tool in Python.

This was a straight conversion, manually going line-by-line to
change the syntax from Perl to Python. Thus the overall structure
of the file and approach is the same.

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 Makefile.am                 |   1 +
 scripts/dtrace2systemtap.py | 143 ++++++++++++++++++++++++++++++++++++
 src/Makefile.am             |  10 +--
 src/dtrace2systemtap.pl     | 130 --------------------------------
 4 files changed, 147 insertions(+), 137 deletions(-)
 create mode 100755 scripts/dtrace2systemtap.py
 delete mode 100755 src/dtrace2systemtap.pl

diff --git a/Makefile.am b/Makefile.am
index 1c7b8045c2..e50a29635b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -50,6 +50,7 @@ EXTRA_DIST = \
   scripts/check-spacing.py \
   scripts/check-symfile.py \
   scripts/check-symsorting.py \
+  scripts/dtrace2systemtap.py \
   scripts/header-ifdef.py \
   scripts/minimize-po.py \
   scripts/mock-noinline.py \
diff --git a/scripts/dtrace2systemtap.py b/scripts/dtrace2systemtap.py
new file mode 100755
index 0000000000..922713e599
--- /dev/null
+++ b/scripts/dtrace2systemtap.py
@@ -0,0 +1,143 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2011-2019 Red Hat, Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library.  If not, see
+# <http://www.gnu.org/licenses/>.
+#
+#
+# Generate a set of systemtap probe definitions corresponding to
+# DTrace probe markers in libvirt.so
+#
+#  python dtrace2systemtap.py probes.d > libvirt_probes.stp
+#
+
+from __future__ import print_function
+
+import re
+import sys
+
+file = None
+filelist = []
+files = {}
+
+bindir = sys.argv[1]
+sbindir = sys.argv[2]
+libdir = sys.argv[3]
+dtrace = sys.argv[4]
+
+probe = None
+args = None
+
+# Read the DTraceprobes definition
+
+with open(dtrace, "r") as fh:
+    lineno = 0
+    for line in fh:
+        lineno = lineno + 1
+        line = line.strip()
+        if line == "":
+            continue
+        if line.find("provider ") != -1 and line.find("{") != -1:
+            continue
+        if line.find("};") != -1:
+            continue
+
+        if line.startswith("#"):
+            m = re.search(r'''^\#\s*file:\s*(\S+)$''', line)
+            if m is not None:
+                file = m.group(1)
+                filelist.append(file)
+                files[file] = {"prefix": None, "probes": []}
+                continue
+
+            m = re.search(r'''^\#\s*prefix:\s*(\S+)$''', line)
+            if m is not None:
+                files[file]["prefix"] = m.group(1)
+                continue
+
+            m = re.search(r'''^\#\s*binary:\s*(\S+)$''', line)
+            if m is not None:
+                files[file]["binary"] = m.group(1)
+                continue
+
+            m = re.search(r'''^\#\s*module:\s*(\S+)$''', line)
+            if m is not None:
+                files[file]["module"] = m.group(1)
+
+            # ignore unknown comments
+        else:
+            m = re.search(r'''probe\s+([a-zA-Z0-9_]+)\((.*?)(\);)?$''', line)
+            if m is not None:
+                probe = m.group(1)
+                args = m.group(2)
+                if m.group(3) is not None:
+                    files[file]["probes"].append([probe, args])
+                    probe = None
+                    args = None
+            elif probe is not None:
+                m = re.search(r'''^(.*?)(\);)?$''', line)
+                if m is not None:
+                    args = args + m.group(1)
+                    if m.group(2) is not None:
+                        files[file]["probes"].append([probe, args])
+                        probe = None
+                        args = None
+                else:
+                    raise Exception("unexpected data %s on line %d" %
+                                    (line, lineno))
+            else:
+                raise Exception("unexpected data %s on line %d" %
+                                (line, lineno))
+
+# Write out the SystemTap probes
+for file in filelist:
+    prefix = files[file]["prefix"]
+    probes = files[file]["probes"]
+
+    print("# %s\n" % file)
+    for probe in probes:
+        name = probe[0]
+        args = probe[1]
+
+        pname = name.replace(prefix + "_", "libvirt." + prefix + ".")
+
+        binary = libdir + "/libvirt.so"
+        if "binary" in files[file]:
+            binary = sbindir + "/" + files[file]["binary"]
+        if "module" in files[file]:
+            binary = libdir + "/" + files[file]["module"]
+
+        print("probe %s = process(\"%s\").mark(\"%s\") {" %
+              (pname, binary, name))
+
+        argbits = args.split(",")
+        for idx in range(len(argbits)):
+            arg = argbits[idx]
+            isstr = False
+            if arg.find("char *") != -1:
+                isstr = True
+
+            m = re.search(r'''^.*\s\*?(\S+)$''', arg)
+            if m is not None:
+                arg = m.group(1)
+            else:
+                raise Exception("Malformed arg %s" % arg)
+
+            if isstr:
+                print("  %s = user_string($arg%d);" % (arg, idx + 1))
+            else:
+                print("  %s = $arg%d;" % (arg, idx + 1))
+        print("}\n")
+    print("")
diff --git a/src/Makefile.am b/src/Makefile.am
index 929eef784c..085c193013 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -530,7 +530,6 @@ if WITH_DTRACE_PROBES
 libvirt_la_BUILT_LIBADD += libvirt_probes.lo
 libvirt_la_DEPENDENCIES += libvirt_probes.lo libvirt_probes.o
 nodist_libvirt_la_SOURCES = libvirt_probes.h
-DTRACE2SYSTEMTAP_FLAGS = --with-modules
 
 BUILT_SOURCES += libvirt_probes.h libvirt_probes.stp libvirt_functions.stp
 
@@ -565,10 +564,10 @@ RPC_PROBE_FILES += $(srcdir)/rpc/virnetprotocol.x \
 libvirt_functions.stp: $(RPC_PROBE_FILES) $(srcdir)/rpc/gensystemtap.pl
 	$(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gensystemtap.pl $(RPC_PROBE_FILES) > $@
 
-%_probes.stp: %_probes.d $(srcdir)/dtrace2systemtap.pl \
+%_probes.stp: %_probes.d $(top_srcdir)/scripts/dtrace2systemtap.py \
 		$(top_builddir)/config.status
-	$(AM_V_GEN)$(PERL) -w $(srcdir)/dtrace2systemtap.pl \
-	  $(DTRACE2SYSTEMTAP_FLAGS) $(bindir) $(sbindir) $(libdir) $< > $@
+	$(AM_V_GEN)$(RUNUTF8) $(PYTHON) $(top_srcdir)/scripts/dtrace2systemtap.py \
+	  $(bindir) $(sbindir) $(libdir) $< > $@
 
 CLEANFILES += libvirt_probes.h libvirt_probes.o libvirt_probes.lo \
               libvirt_functions.stp libvirt_probes.stp
@@ -689,9 +688,6 @@ endif LIBVIRT_INIT_SCRIPT_SYSTEMD
 endif WITH_LIBVIRTD
 
 
-EXTRA_DIST += dtrace2systemtap.pl
-
-
 if WITH_LIBVIRTD
 libexec_PROGRAMS += libvirt_iohelper
 libvirt_iohelper_SOURCES = $(UTIL_IO_HELPER_SOURCES)
diff --git a/src/dtrace2systemtap.pl b/src/dtrace2systemtap.pl
deleted file mode 100755
index c5fce248b4..0000000000
--- a/src/dtrace2systemtap.pl
+++ /dev/null
@@ -1,130 +0,0 @@
-#!/usr/bin/env perl
-#
-# Copyright (C) 2011-2012 Red Hat, Inc.
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library.  If not, see
-# <http://www.gnu.org/licenses/>.
-#
-#
-# Generate a set of systemtap probe definitions corresponding to
-# DTrace probe markers in libvirt.so
-#
-#  perl dtrace2systemtap.pl probes.d > libvirt_probes.stp
-#
-
-use strict;
-use warnings;
-
-my $file;
-my @files;
-my %files;
-
-my $with_modules = 0;
-if ($ARGV[0] eq "--with-modules") {
-    # set if we want to honor the "module" setting in the .d file
-    $with_modules = 1;
-    shift @ARGV;
-}
-
-my $bindir = shift @ARGV;
-my $sbindir = shift @ARGV;
-my $libdir = shift @ARGV;
-
-my $probe;
-my $args;
-
-# Read the DTraceprobes definition
-while (<>) {
-    next if m,^\s*$,;
-
-    next if /^\s*provider\s+\w+\s*{\s*$/;
-    next if /^\s*};\s*$/;
-
-    if (m,^\s*\#,) {
-        if (m,^\s*\#\s*file:\s*(\S+)\s*$,) {
-            $file = $1;
-            push @files, $file;
-            $files{$file} = { prefix => undef, probes => [] };
-        } elsif (m,^\s*\#\s*prefix:\s*(\S+)\s*$,) {
-            $files{$file}->{prefix} = $1;
-        } elsif (m,^\s*\#\s*binary:\s*(\S+)\s*$,) {
-            $files{$file}->{binary} = $1;
-        } elsif (m,^\s*\#\s*module:\s*(\S+)\s*$,) {
-            $files{$file}->{module} = $1;
-        } else {
-            # ignore unknown comments
-        }
-    } else {
-        if (m,\s*probe\s+([a-zA-Z0-9_]+)\((.*?)(\);)?$,) {
-            $probe = $1;
-            $args = $2;
-            if ($3) {
-                push @{$files{$file}->{probes}}, [$probe, $args];
-                $probe = $args = undef;
-            }
-        } elsif ($probe) {
-            if (m,^(.*?)(\);)?$,) {
-                $args .= $1;
-                if ($2) {
-                    push @{$files{$file}->{probes}}, [$probe, $args];
-                    $probe = $args = undef;
-                }
-            } else {
-                die "unexpected data $_ on line $.";
-            }
-        } else {
-            die "unexpected data $_ on line $.";
-        }
-    }
-}
-
-# Write out the SystemTap probes
-foreach my $file (@files) {
-    my $prefix = $files{$file}->{prefix};
-    my @probes = @{$files{$file}->{probes}};
-
-    print "# $file\n\n";
-    foreach my $probe (@probes) {
-        my $name = $probe->[0];
-        my $args = $probe->[1];
-
-        my $pname = $name;
-        $pname =~ s/${prefix}_/libvirt.$prefix./;
-
-        my $binary = "$libdir/libvirt.so";
-        if (exists $files{$file}->{binary}) {
-            $binary = $sbindir . "/" . $files{$file}->{binary};
-        }
-        if ($with_modules && exists $files{$file}->{module}) {
-            $binary = $libdir . "/" . $files{$file}->{module};
-        }
-
-        print "probe $pname = process(\"$binary\").mark(\"$name\") {\n";
-
-        my @args = split /,/, $args;
-        for (my $i = 0 ; $i <= $#args ; $i++) {
-            my $arg = $args[$i];
-            my $isstr = $arg =~ /char\s+\*/;
-            $arg =~ s/^.*\s\*?(\S+)$/$1/;
-
-            if ($isstr) {
-                print "  $arg = user_string(\$arg", $i + 1, ");\n";
-            } else {
-                print "  $arg = \$arg", $i + 1, ";\n";
-            }
-        }
-        print "}\n\n";
-    }
-    print "\n";
-}
-- 
2.21.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v5 08/23] src: rewrite systemtap probe generator in Python
Posted by Cole Robinson 5 years ago
On 11/11/19 9:38 AM, Daniel P. Berrangé wrote:
> As part of an goal to eliminate Perl from libvirt build tools,
> rewrite the dtrace2systemtap.pl tool in Python.
> 
> This was a straight conversion, manually going line-by-line to
> change the syntax from Perl to Python. Thus the overall structure
> of the file and approach is the same.
> 
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>

I verified *.stp generated output is the same across old and new versions

Tested-by: Cole Robinson <crobinso@redhat.com>

- Cole

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v5 08/23] src: rewrite systemtap probe generator in Python
Posted by Ján Tomko 5 years ago
On Mon, Nov 11, 2019 at 02:38:11PM +0000, Daniel P. Berrangé wrote:
>As part of an goal to eliminate Perl from libvirt build tools,
>rewrite the dtrace2systemtap.pl tool in Python.
>
>This was a straight conversion, manually going line-by-line to
>change the syntax from Perl to Python. Thus the overall structure
>of the file and approach is the same.
>
>Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
>---
> Makefile.am                 |   1 +
> scripts/dtrace2systemtap.py | 143 ++++++++++++++++++++++++++++++++++++
> src/Makefile.am             |  10 +--
> src/dtrace2systemtap.pl     | 130 --------------------------------
> 4 files changed, 147 insertions(+), 137 deletions(-)
> create mode 100755 scripts/dtrace2systemtap.py
> delete mode 100755 src/dtrace2systemtap.pl
>
>diff --git a/src/Makefile.am b/src/Makefile.am
>index 929eef784c..085c193013 100644
>--- a/src/Makefile.am
>+++ b/src/Makefile.am
>@@ -530,7 +530,6 @@ if WITH_DTRACE_PROBES
> libvirt_la_BUILT_LIBADD += libvirt_probes.lo
> libvirt_la_DEPENDENCIES += libvirt_probes.lo libvirt_probes.o
> nodist_libvirt_la_SOURCES = libvirt_probes.h
>-DTRACE2SYSTEMTAP_FLAGS = --with-modules

Dropping the (now implied) --with-modules flag deserves a mention in the
commit message.

>
> BUILT_SOURCES += libvirt_probes.h libvirt_probes.stp libvirt_functions.stp
>

Reviewed-by: Ján Tomko <jtomko@redhat.com>

Jano
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list