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 fmt = re.sub("%(\d*)z(x|u|d)", "%\\1\\2", "".join(bits)) 82 return fmt 83 84def generate(events, backend, group): 85 out('/* This file is autogenerated by tracetool, do not edit. */', 86 '') 87 88 for event_id, e in enumerate(events): 89 if 'disable' in e.properties: 90 continue 91 92 out('probe %(probeprefix)s.log.%(name)s = %(probeprefix)s.%(name)s ?', 93 '{', 94 probeprefix=probeprefix(), 95 name=e.name) 96 97 # Get references to userspace strings 98 for type_, name in e.args: 99 name = stap_escape(name) 100 if is_string(type_): 101 out(' try {', 102 ' arg%(name)s_str = %(name)s ? ' + 103 'user_string_n(%(name)s, 512) : "<null>"', 104 ' } catch {}', 105 name=name) 106 107 # Determine systemtap's view of variable names 108 fields = ["pid()", "gettimeofday_ns()"] 109 for type_, name in e.args: 110 name = stap_escape(name) 111 if is_string(type_): 112 fields.append("arg" + name + "_str") 113 else: 114 fields.append(name) 115 116 # Emit the entire record in a single SystemTap printf() 117 arg_str = ', '.join(arg for arg in fields) 118 fmt_str = "%d@%d " + e.name + " " + c_fmt_to_stap(e.fmt) + "\\n" 119 out(' printf("%(fmt_str)s", %(arg_str)s)', 120 fmt_str=fmt_str, arg_str=arg_str) 121 122 out('}') 123 124 out() 125