cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

log_stap.py (4025B)


      1# -*- coding: utf-8 -*-
      2
      3"""
      4Generate .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
     14import re
     15
     16from tracetool import out
     17from tracetool.backend.dtrace import binary, probeprefix
     18from tracetool.backend.simple import is_string
     19from tracetool.format.stap import stap_escape
     20
     21def global_var_name(name):
     22    return probeprefix().replace(".", "_") + "_" + name
     23
     24STATE_SKIP = 0
     25STATE_LITERAL = 1
     26STATE_MACRO = 2
     27
     28def c_macro_to_format(macro):
     29    if macro.startswith("PRI"):
     30        return macro[3]
     31
     32    raise Exception("Unhandled macro '%s'" % macro)
     33
     34def 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
     89def 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()