Merge remote-tracking branch 'remotes/jasowang/tags/net-pull-request' into staging
[qemu/ar7.git] / scripts / tracetool / format / log_stap.py
blob0b6549d534a2d5aaa76c6e6f6b901bd2352497a2
1 # -*- coding: utf-8 -*-
3 """
4 Generate .stp file that printfs log messages (DTrace with SystemTAP only).
5 """
7 __author__ = "Daniel P. Berrange <berrange@redhat.com>"
8 __copyright__ = "Copyright (C) 2014-2019, Red Hat, Inc."
9 __license__ = "GPL version 2 or (at your option) any later version"
11 __maintainer__ = "Daniel Berrange"
12 __email__ = "berrange@redhat.com"
14 import re
16 from tracetool import out
17 from tracetool.backend.dtrace import binary, probeprefix
18 from tracetool.backend.simple import is_string
19 from tracetool.format.stap import stap_escape
21 def global_var_name(name):
22 return probeprefix().replace(".", "_") + "_" + name
24 STATE_SKIP = 0
25 STATE_LITERAL = 1
26 STATE_MACRO = 2
28 def c_macro_to_format(macro):
29 if macro.startswith("PRI"):
30 return macro[3]
32 raise Exception("Unhandled macro '%s'" % macro)
34 def c_fmt_to_stap(fmt):
35 state = 0
36 bits = []
37 literal = ""
38 macro = ""
39 escape = 0;
40 for i in range(len(fmt)):
41 if fmt[i] == '\\':
42 if escape:
43 escape = 0
44 else:
45 escape = 1
46 if state != STATE_LITERAL:
47 raise Exception("Unexpected escape outside string literal")
48 literal = literal + fmt[i]
49 elif fmt[i] == '"' and not escape:
50 if state == STATE_LITERAL:
51 state = STATE_SKIP
52 bits.append(literal)
53 literal = ""
54 else:
55 if state == STATE_MACRO:
56 bits.append(c_macro_to_format(macro))
57 macro = ""
58 state = STATE_LITERAL
59 elif fmt[i] == ' ' or fmt[i] == '\t':
60 if state == STATE_MACRO:
61 bits.append(c_macro_to_format(macro))
62 macro = ""
63 state = STATE_SKIP
64 elif state == STATE_LITERAL:
65 literal = literal + fmt[i]
66 else:
67 escape = 0
68 if state == STATE_SKIP:
69 state = STATE_MACRO
71 if state == STATE_LITERAL:
72 literal = literal + fmt[i]
73 else:
74 macro = macro + fmt[i]
76 if state == STATE_MACRO:
77 bits.append(c_macro_to_format(macro))
78 elif state == STATE_LITERAL:
79 bits.append(literal)
81 # All variables in systemtap are 64-bit in size
82 # The "%l" integer size qualifier is thus redundant
83 # and "%ll" is not valid at all. Similarly the size_t
84 # based "%z" size qualifier is not valid. We just
85 # strip all size qualifiers for sanity.
86 fmt = re.sub("%(\d*)(l+|z)(x|u|d)", "%\\1\\3", "".join(bits))
87 return fmt
89 def generate(events, backend, group):
90 out('/* This file is autogenerated by tracetool, do not edit. */',
91 '')
93 for event_id, e in enumerate(events):
94 if 'disable' in e.properties:
95 continue
97 out('probe %(probeprefix)s.log.%(name)s = %(probeprefix)s.%(name)s ?',
98 '{',
99 probeprefix=probeprefix(),
100 name=e.name)
102 # Get references to userspace strings
103 for type_, name in e.args:
104 name = stap_escape(name)
105 if is_string(type_):
106 out(' try {',
107 ' arg%(name)s_str = %(name)s ? ' +
108 'user_string_n(%(name)s, 512) : "<null>"',
109 ' } catch {}',
110 name=name)
112 # Determine systemtap's view of variable names
113 fields = ["pid()", "gettimeofday_ns()"]
114 for type_, name in e.args:
115 name = stap_escape(name)
116 if is_string(type_):
117 fields.append("arg" + name + "_str")
118 else:
119 fields.append(name)
121 # Emit the entire record in a single SystemTap printf()
122 arg_str = ', '.join(arg for arg in fields)
123 fmt_str = "%d@%d " + e.name + " " + c_fmt_to_stap(e.fmt) + "\\n"
124 out(' printf("%(fmt_str)s", %(arg_str)s)',
125 fmt_str=fmt_str, arg_str=arg_str)
127 out('}')
129 out()