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