libvirt/scripts/dtrace2systemtap.py
Daniel P. Berrangé 952c018efe src: rewrite systemtap probe generator in Python
As part of a 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.

The "--with-modules" flag was dropped because this functionality
is not implicitly always enabled.

Tested-by: Cole Robinson <crobinso@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
2019-11-20 14:45:25 +00:00

144 lines
4.4 KiB
Python
Executable File

#!/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("")