qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

log_stap.py (4025B)


      1 # -*- coding: utf-8 -*-
      2 
      3 """
      4 Generate .stp file that printfs log messages (DTrace with SystemTAP only).
      5 """
      6 
      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"
     10 
     11 __maintainer__ = "Daniel Berrange"
     12 __email__      = "berrange@redhat.com"
     13 
     14 import re
     15 
     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
     20 
     21 def global_var_name(name):
     22     return probeprefix().replace(".", "_") + "_" + name
     23 
     24 STATE_SKIP = 0
     25 STATE_LITERAL = 1
     26 STATE_MACRO = 2
     27 
     28 def c_macro_to_format(macro):
     29     if macro.startswith("PRI"):
     30         return macro[3]
     31 
     32     raise Exception("Unhandled macro '%s'" % macro)
     33 
     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
     70 
     71             if state == STATE_LITERAL:
     72                 literal = literal + fmt[i]
     73             else:
     74                 macro = macro + fmt[i]
     75 
     76     if state == STATE_MACRO:
     77         bits.append(c_macro_to_format(macro))
     78     elif state == STATE_LITERAL:
     79         bits.append(literal)
     80 
     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
     88 
     89 def generate(events, backend, group):
     90     out('/* This file is autogenerated by tracetool, do not edit. */',
     91         '')
     92 
     93     for event_id, e in enumerate(events):
     94         if 'disable' in e.properties:
     95             continue
     96 
     97         out('probe %(probeprefix)s.log.%(name)s = %(probeprefix)s.%(name)s ?',
     98             '{',
     99             probeprefix=probeprefix(),
    100             name=e.name)
    101 
    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)
    111 
    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)
    120 
    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)
    126 
    127         out('}')
    128 
    129     out()