aboutsummaryrefslogtreecommitdiff
path: root/scripts/tracetool/format/log_stap.py
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/tracetool/format/log_stap.py')
-rw-r--r--scripts/tracetool/format/log_stap.py129
1 files changed, 129 insertions, 0 deletions
diff --git a/scripts/tracetool/format/log_stap.py b/scripts/tracetool/format/log_stap.py
new file mode 100644
index 0000000000..b49afababd
--- /dev/null
+++ b/scripts/tracetool/format/log_stap.py
@@ -0,0 +1,129 @@
+# -*- coding: utf-8 -*-
+
+"""
+Generate .stp file that printfs log messages (DTrace with SystemTAP only).
+"""
+
+__author__ = "Daniel P. Berrange <berrange@redhat.com>"
+__copyright__ = "Copyright (C) 2014-2019, Red Hat, Inc."
+__license__ = "GPL version 2 or (at your option) any later version"
+
+__maintainer__ = "Daniel Berrange"
+__email__ = "berrange@redhat.com"
+
+import re
+
+from tracetool import out
+from tracetool.backend.dtrace import binary, probeprefix
+from tracetool.backend.simple import is_string
+from tracetool.format.stap import stap_escape
+
+def global_var_name(name):
+ return probeprefix().replace(".", "_") + "_" + name
+
+STATE_SKIP = 0
+STATE_LITERAL = 1
+STATE_MACRO = 2
+
+def c_macro_to_format(macro):
+ if macro.startswith("PRI"):
+ return macro[3]
+
+ raise Exception("Unhandled macro '%s'" % macro)
+
+def c_fmt_to_stap(fmt):
+ state = 0
+ bits = []
+ literal = ""
+ macro = ""
+ escape = 0;
+ for i in range(len(fmt)):
+ if fmt[i] == '\\':
+ if escape:
+ escape = 0
+ else:
+ escape = 1
+ if state != STATE_LITERAL:
+ raise Exception("Unexpected escape outside string literal")
+ literal = literal + fmt[i]
+ elif fmt[i] == '"' and not escape:
+ if state == STATE_LITERAL:
+ state = STATE_SKIP
+ bits.append(literal)
+ literal = ""
+ else:
+ if state == STATE_MACRO:
+ bits.append(c_macro_to_format(macro))
+ macro = ""
+ state = STATE_LITERAL
+ elif fmt[i] == ' ' or fmt[i] == '\t':
+ if state == STATE_MACRO:
+ bits.append(c_macro_to_format(macro))
+ macro = ""
+ state = STATE_SKIP
+ elif state == STATE_LITERAL:
+ literal = literal + fmt[i]
+ else:
+ escape = 0
+ if state == STATE_SKIP:
+ state = STATE_MACRO
+
+ if state == STATE_LITERAL:
+ literal = literal + fmt[i]
+ else:
+ macro = macro + fmt[i]
+
+ if state == STATE_MACRO:
+ bits.append(c_macro_to_format(macro))
+ elif state == STATE_LITERAL:
+ bits.append(literal)
+
+ # All variables in systemtap are 64-bit in size
+ # The "%l" integer size qualifier is thus redundant
+ # and "%ll" is not valid at all. Similarly the size_t
+ # based "%z" size qualifier is not valid. We just
+ # strip all size qualifiers for sanity.
+ fmt = re.sub(r"%(\d*)(l+|z)(x|u|d)", r"%\1\3", "".join(bits))
+ return fmt
+
+def generate(events, backend, group):
+ out('/* This file is autogenerated by tracetool, do not edit. */',
+ '')
+
+ for event_id, e in enumerate(events):
+ if 'disable' in e.properties:
+ continue
+
+ out('probe %(probeprefix)s.log.%(name)s = %(probeprefix)s.%(name)s ?',
+ '{',
+ probeprefix=probeprefix(),
+ name=e.name)
+
+ # Get references to userspace strings
+ for type_, name in e.args:
+ name = stap_escape(name)
+ if is_string(type_):
+ out(' try {',
+ ' arg%(name)s_str = %(name)s ? ' +
+ 'user_string_n(%(name)s, 512) : "<null>"',
+ ' } catch {}',
+ name=name)
+
+ # Determine systemtap's view of variable names
+ fields = ["pid()", "gettimeofday_ns()"]
+ for type_, name in e.args:
+ name = stap_escape(name)
+ if is_string(type_):
+ fields.append("arg" + name + "_str")
+ else:
+ fields.append(name)
+
+ # Emit the entire record in a single SystemTap printf()
+ arg_str = ', '.join(arg for arg in fields)
+ fmt_str = "%d@%d " + e.name + " " + c_fmt_to_stap(e.fmt) + "\\n"
+ out(' printf("%(fmt_str)s", %(arg_str)s)',
+ fmt_str=fmt_str, arg_str=arg_str)
+
+ out('}')
+
+ out()