diff options
Diffstat (limited to 'scripts/tracetool')
-rw-r--r-- | scripts/tracetool/__init__.py | 228 | ||||
-rw-r--r-- | scripts/tracetool/backend/__init__.py | 43 | ||||
-rw-r--r-- | scripts/tracetool/backend/dtrace.py | 2 | ||||
-rw-r--r-- | scripts/tracetool/backend/ftrace.py | 30 | ||||
-rw-r--r-- | scripts/tracetool/backend/log.py | 38 | ||||
-rw-r--r-- | scripts/tracetool/backend/simple.py | 24 | ||||
-rw-r--r-- | scripts/tracetool/backend/syslog.py | 25 | ||||
-rw-r--r-- | scripts/tracetool/backend/ust.py | 2 | ||||
-rw-r--r-- | scripts/tracetool/format/__init__.py | 4 | ||||
-rw-r--r-- | scripts/tracetool/format/c.py | 5 | ||||
-rw-r--r-- | scripts/tracetool/format/d.py | 5 | ||||
-rw-r--r-- | scripts/tracetool/format/h.py | 37 | ||||
-rw-r--r-- | scripts/tracetool/format/log_stap.py | 5 | ||||
-rw-r--r-- | scripts/tracetool/format/rs.py | 64 | ||||
-rw-r--r-- | scripts/tracetool/format/simpletrace_stap.py | 5 | ||||
-rw-r--r-- | scripts/tracetool/format/stap.py | 3 | ||||
-rw-r--r-- | scripts/tracetool/format/ust_events_c.py | 3 | ||||
-rw-r--r-- | scripts/tracetool/format/ust_events_h.py | 3 |
18 files changed, 352 insertions, 174 deletions
diff --git a/scripts/tracetool/__init__.py b/scripts/tracetool/__init__.py index bc03238..74062d2 100644 --- a/scripts/tracetool/__init__.py +++ b/scripts/tracetool/__init__.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# SPDX-License-Identifier: GPL-2.0-or-later """ Machinery for generating tracing-related intermediate files. @@ -12,12 +12,13 @@ __maintainer__ = "Stefan Hajnoczi" __email__ = "stefanha@redhat.com" +import os import re import sys -import weakref +from pathlib import PurePath -import tracetool.format import tracetool.backend +import tracetool.format def error_write(*lines): @@ -29,6 +30,49 @@ def error(*lines): error_write(*lines) sys.exit(1) +FMT_TOKEN = re.compile(r'''(?: + " ( (?: [^"\\] | \\[\\"abfnrt] | # a string literal + \\x[0-9a-fA-F][0-9a-fA-F]) *? ) " + | ( PRI [duixX] (?:8|16|32|64|PTR|MAX) ) # a PRIxxx macro + | \s+ # spaces (ignored) + )''', re.X) + +PRI_SIZE_MAP = { + '8': 'hh', + '16': 'h', + '32': '', + '64': 'll', + 'PTR': 't', + 'MAX': 'j', +} + +def expand_format_string(c_fmt, prefix=""): + def pri_macro_to_fmt(pri_macro): + assert pri_macro.startswith("PRI") + fmt_type = pri_macro[3] # 'd', 'i', 'u', or 'x' + fmt_size = pri_macro[4:] # '8', '16', '32', '64', 'PTR', 'MAX' + + size = PRI_SIZE_MAP.get(fmt_size, None) + if size is None: + raise Exception(f"unknown macro {pri_macro}") + return size + fmt_type + + result = prefix + pos = 0 + while pos < len(c_fmt): + m = FMT_TOKEN.match(c_fmt, pos) + if not m: + print("No match at position", pos, ":", repr(c_fmt[pos:]), file=sys.stderr) + raise Exception("syntax error in trace file") + if m[1]: + substr = m[1] + elif m[2]: + substr = pri_macro_to_fmt(m[2]) + else: + substr = "" + result += substr + pos = m.end() + return result out_lineno = 1 out_filename = '<none>' @@ -36,7 +80,7 @@ out_fobj = sys.stdout def out_open(filename): global out_filename, out_fobj - out_filename = filename + out_filename = posix_relpath(filename) out_fobj = open(filename, 'wt') def out(*lines, **kwargs): @@ -88,6 +132,49 @@ ALLOWED_TYPES = [ "ptrdiff_t", ] +C_TYPE_KEYWORDS = {"char", "int", "void", "short", "long", "signed", "unsigned"} + +C_TO_RUST_TYPE_MAP = { + "int": "std::ffi::c_int", + "long": "std::ffi::c_long", + "long long": "std::ffi::c_longlong", + "short": "std::ffi::c_short", + "char": "std::ffi::c_char", + "bool": "bool", + "unsigned": "std::ffi::c_uint", + # multiple keywords, keep them sorted + "long unsigned": "std::ffi::c_long", + "long long unsigned": "std::ffi::c_ulonglong", + "short unsigned": "std::ffi::c_ushort", + "char unsigned": "u8", + "int8_t": "i8", + "uint8_t": "u8", + "int16_t": "i16", + "uint16_t": "u16", + "int32_t": "i32", + "uint32_t": "u32", + "int64_t": "i64", + "uint64_t": "u64", + "void": "()", + "size_t": "usize", + "ssize_t": "isize", + "uintptr_t": "usize", + "ptrdiff_t": "isize", +} + +# Rust requires manual casting of <32-bit types when passing them to +# variable-argument functions. +RUST_VARARGS_SMALL_TYPES = { + "std::ffi::c_short", + "std::ffi::c_ushort", + "std::ffi::c_char", + "i8", + "u8", + "i16", + "u16", + "bool", +} + def validate_type(name): bits = name.split(" ") for bit in bits: @@ -103,6 +190,38 @@ def validate_type(name): "other complex pointer types should be " "declared as 'void *'" % name) +def c_type_to_rust(name): + ptr = False + const = False + name = name.rstrip() + if name[-1] == '*': + name = name[:-1].rstrip() + ptr = True + if name[-1] == '*': + # pointers to pointers are the same as void* + name = "void" + + bits = name.split() + if "const" in bits: + const = True + bits.remove("const") + if bits[0] in C_TYPE_KEYWORDS: + if "signed" in bits: + bits.remove("signed") + if len(bits) > 1 and "int" in bits: + bits.remove("int") + bits.sort() + name = ' '.join(bits) + else: + if len(bits) > 1: + raise ValueError("Invalid type '%s'." % name) + name = bits[0] + + ty = C_TO_RUST_TYPE_MAP[name.strip()] + if ptr: + ty = f'*{"const" if const else "mut"} {ty}' + return ty + class Arguments: """Event arguments description.""" @@ -120,10 +239,6 @@ class Arguments: else: self._args.append(arg) - def copy(self): - """Create a new copy.""" - return Arguments(list(self._args)) - @staticmethod def build(arg_str): """Build and Arguments instance from an argument string. @@ -168,10 +283,16 @@ class Arguments: def __str__(self): """String suitable for declaring function arguments.""" + def onearg(t, n): + if t[-1] == '*': + return "".join([t, n]) + else: + return " ".join([t, n]) + if len(self._args) == 0: return "void" else: - return ", ".join([ " ".join([t, n]) for t,n in self._args ]) + return ", ".join([ onearg(t, n) for t,n in self._args ]) def __repr__(self): """Evaluable string representation for this object.""" @@ -189,6 +310,43 @@ class Arguments: """List of argument names casted to their type.""" return ["(%s)%s" % (type_, name) for type_, name in self._args] + def rust_decl_extern(self): + """Return a Rust argument list for an extern "C" function""" + return ", ".join((f"_{name}: {c_type_to_rust(type_)}" + for type_, name in self._args)) + + def rust_decl(self): + """Return a Rust argument list for a tracepoint function""" + def decl_type(type_): + if type_ == "const char *": + return "&std::ffi::CStr" + return c_type_to_rust(type_) + + return ", ".join((f"_{name}: {decl_type(type_)}" + for type_, name in self._args)) + + def rust_call_extern(self): + """Return a Rust argument list for a call to an extern "C" function""" + def rust_cast(name, type_): + if type_ == "const char *": + return f"_{name}.as_ptr()" + return f"_{name}" + + return ", ".join((rust_cast(name, type_) for type_, name in self._args)) + + def rust_call_varargs(self): + """Return a Rust argument list for a call to a C varargs function""" + def rust_cast(name, type_): + if type_ == "const char *": + return f"_{name}.as_ptr()" + + type_ = c_type_to_rust(type_) + if type_ in RUST_VARARGS_SMALL_TYPES: + return f"_{name} as std::ffi::c_int" + return f"_{name} /* as {type_} */" + + return ", ".join((rust_cast(name, type_) for type_, name in self._args)) + class Event(object): """Event description. @@ -214,13 +372,12 @@ class Event(object): r"(?P<name>\w+)" r"\((?P<args>[^)]*)\)" r"\s*" - r"(?:(?:(?P<fmt_trans>\".+),)?\s*(?P<fmt>\".+))?" + r"(?P<fmt>\".+)?" r"\s*") - _VALID_PROPS = set(["disable", "vcpu"]) + _VALID_PROPS = set(["disable"]) - def __init__(self, name, props, fmt, args, lineno, filename, orig=None, - event_trans=None, event_exec=None): + def __init__(self, name, props, fmt, args, lineno, filename): """ Parameters ---------- @@ -228,20 +385,14 @@ class Event(object): Event name. props : list of str Property names. - fmt : str, list of str - Event printing format string(s). + fmt : str + Event printing format string. args : Arguments Event arguments. lineno : int The line number in the input file. filename : str The path to the input file. - orig : Event or None - Original Event before transformation/generation. - event_trans : Event or None - Generated translation-time event ("tcg" property). - event_exec : Event or None - Generated execution-time event ("tcg" property). """ self.name = name @@ -250,29 +401,16 @@ class Event(object): self.args = args self.lineno = int(lineno) self.filename = str(filename) - self.event_trans = event_trans - self.event_exec = event_exec if len(args) > 10: raise ValueError("Event '%s' has more than maximum permitted " "argument count" % name) - if orig is None: - self.original = weakref.ref(self) - else: - self.original = orig - unknown_props = set(self.properties) - self._VALID_PROPS if len(unknown_props) > 0: raise ValueError("Unknown properties: %s" % ", ".join(unknown_props)) - assert isinstance(self.fmt, str) or len(self.fmt) == 2 - def copy(self): - """Create a new copy.""" - return Event(self.name, list(self.properties), self.fmt, - self.args.copy(), self.lineno, self.filename, - self, self.event_trans, self.event_exec) @staticmethod def build(line_str, lineno, filename): @@ -294,8 +432,7 @@ class Event(object): name = groups["name"] props = groups["props"].split() fmt = groups["fmt"] - fmt_trans = groups["fmt_trans"] - if fmt.find("%m") != -1 or fmt_trans.find("%m") != -1: + if fmt.find("%m") != -1: raise ValueError("Event format '%m' is forbidden, pass the error " "as an explicit trace argument") if fmt.endswith(r'\n"'): @@ -304,33 +441,25 @@ class Event(object): if '\\n' in fmt: raise ValueError("Event format must not use new line character") - if len(fmt_trans) > 0: - fmt = [fmt_trans, fmt] args = Arguments.build(groups["args"]) - return Event(name, props, fmt, args, lineno, filename) + return Event(name, props, fmt, args, lineno, posix_relpath(filename)) def __repr__(self): """Evaluable string representation for this object.""" - if isinstance(self.fmt, str): - fmt = self.fmt - else: - fmt = "%s, %s" % (self.fmt[0], self.fmt[1]) return "Event('%s %s(%s) %s')" % (" ".join(self.properties), self.name, self.args, - fmt) + self.fmt) # Star matching on PRI is dangerous as one might have multiple # arguments with that format, hence the non-greedy version of it. _FMT = re.compile(r"(%[\d\.]*\w+|%.*?PRI\S+)") def formats(self): """List conversion specifiers in the argument print format string.""" - assert not isinstance(self.fmt, list) return self._FMT.findall(self.fmt) QEMU_TRACE = "trace_%(name)s" - QEMU_TRACE_NOCHECK = "_nocheck__" + QEMU_TRACE QEMU_TRACE_TCG = QEMU_TRACE + "_tcg" QEMU_DSTATE = "_TRACE_%(NAME)s_DSTATE" QEMU_BACKEND_DSTATE = "TRACE_%(NAME)s_BACKEND_DSTATE" @@ -447,3 +576,10 @@ def generate(events, group, format, backends, tracetool.backend.dtrace.PROBEPREFIX = probe_prefix tracetool.format.generate(events, format, backend, group) + +def posix_relpath(path, start=None): + try: + path = os.path.relpath(path, start) + except ValueError: + pass + return PurePath(path).as_posix() diff --git a/scripts/tracetool/backend/__init__.py b/scripts/tracetool/backend/__init__.py index 7bfcc86..9109a78 100644 --- a/scripts/tracetool/backend/__init__.py +++ b/scripts/tracetool/backend/__init__.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# SPDX-License-Identifier: GPL-2.0-or-later """ Backend management. @@ -19,11 +19,15 @@ All backends must generate their contents through the 'tracetool.out' routine. Backend attributes ------------------ -========= ==================================================================== -Attribute Description -========= ==================================================================== -PUBLIC If exists and is set to 'True', the backend is considered "public". -========= ==================================================================== +=========================== ==================================================== +Attribute Description +=========================== ==================================================== +PUBLIC If exists and is set to 'True', the backend is + considered "public". +CHECK_TRACE_EVENT_GET_STATE If exists and is set to 'True', the backend-specific + code inside the tracepoint is emitted within an + ``if trace_event_get_state()`` conditional. +=========================== ==================================================== Backend functions @@ -94,29 +98,40 @@ def exists(name): if name == "nop": return True name = name.replace("-", "_") - return tracetool.try_import("tracetool.backend." + name)[1] + return tracetool.try_import("tracetool.backend." + name)[0] class Wrapper: def __init__(self, backends, format): self._backends = [backend.replace("-", "_") for backend in backends] self._format = format.replace("-", "_") + self.check_trace_event_get_state = False for backend in self._backends: assert exists(backend) assert tracetool.format.exists(self._format) + for backend in self.backend_modules(): + check_trace_event_get_state = getattr(backend, "CHECK_TRACE_EVENT_GET_STATE", False) + self.check_trace_event_get_state = self.check_trace_event_get_state or check_trace_event_get_state - def _run_function(self, name, *args, **kwargs): + def backend_modules(self): for backend in self._backends: - func = tracetool.try_import("tracetool.backend." + backend, - name % self._format, None)[1] - if func is not None: - func(*args, **kwargs) + module = tracetool.try_import("tracetool.backend." + backend)[1] + if module is not None: + yield module + + def _run_function(self, name, *args, check_trace_event_get_state=None, **kwargs): + for backend in self.backend_modules(): + func = getattr(backend, name % self._format, None) + if func is not None and \ + (check_trace_event_get_state is None or + check_trace_event_get_state == getattr(backend, 'CHECK_TRACE_EVENT_GET_STATE', False)): + func(*args, **kwargs) def generate_begin(self, events, group): self._run_function("generate_%s_begin", events, group) - def generate(self, event, group): - self._run_function("generate_%s", event, group) + def generate(self, event, group, check_trace_event_get_state=None): + self._run_function("generate_%s", event, group, check_trace_event_get_state=check_trace_event_get_state) def generate_backend_dstate(self, event, group): self._run_function("generate_%s_backend_dstate", event, group) diff --git a/scripts/tracetool/backend/dtrace.py b/scripts/tracetool/backend/dtrace.py index e17edc9..b4af403 100644 --- a/scripts/tracetool/backend/dtrace.py +++ b/scripts/tracetool/backend/dtrace.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# SPDX-License-Identifier: GPL-2.0-or-later """ DTrace/SystemTAP backend. diff --git a/scripts/tracetool/backend/ftrace.py b/scripts/tracetool/backend/ftrace.py index baed2ae..e03698a 100644 --- a/scripts/tracetool/backend/ftrace.py +++ b/scripts/tracetool/backend/ftrace.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# SPDX-License-Identifier: GPL-2.0-or-later """ Ftrace built-in backend. @@ -12,12 +12,11 @@ __maintainer__ = "Stefan Hajnoczi" __email__ = "stefanha@redhat.com" -import os.path - -from tracetool import out +from tracetool import out, expand_format_string PUBLIC = True +CHECK_TRACE_EVENT_GET_STATE = True def generate_h_begin(events, group): @@ -30,24 +29,13 @@ def generate_h(event, group): if len(event.args) > 0: argnames = ", " + argnames - out(' {', - ' char ftrace_buf[MAX_TRACE_STRLEN];', - ' int unused __attribute__ ((unused));', - ' int trlen;', - ' if (trace_event_get_state(%(event_id)s)) {', - '#line %(event_lineno)d "%(event_filename)s"', - ' trlen = snprintf(ftrace_buf, MAX_TRACE_STRLEN,', - ' "%(name)s " %(fmt)s "\\n" %(argnames)s);', + out('#line %(event_lineno)d "%(event_filename)s"', + ' ftrace_write("%(name)s " %(fmt)s "\\n" %(argnames)s);', '#line %(out_next_lineno)d "%(out_filename)s"', - ' trlen = MIN(trlen, MAX_TRACE_STRLEN - 1);', - ' unused = write(trace_marker_fd, ftrace_buf, trlen);', - ' }', - ' }', name=event.name, args=event.args, - event_id="TRACE_" + event.name.upper(), event_lineno=event.lineno, - event_filename=os.path.relpath(event.filename), + event_filename=event.filename, fmt=event.fmt.rstrip("\n"), argnames=argnames) @@ -55,3 +43,9 @@ def generate_h(event, group): def generate_h_backend_dstate(event, group): out(' trace_event_get_state_dynamic_by_id(%(event_id)s) || \\', event_id="TRACE_" + event.name.upper()) + +def generate_rs(event, group): + out(' let format_string = c"%(fmt)s";', + ' unsafe {bindings::ftrace_write(format_string.as_ptr() as *const c_char, %(args)s);}', + fmt=expand_format_string(event.fmt), + args=event.args.rust_call_varargs()) diff --git a/scripts/tracetool/backend/log.py b/scripts/tracetool/backend/log.py index de27b7e..9e3e504 100644 --- a/scripts/tracetool/backend/log.py +++ b/scripts/tracetool/backend/log.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# SPDX-License-Identifier: GPL-2.0-or-later """ Stderr built-in backend. @@ -12,17 +12,15 @@ __maintainer__ = "Stefan Hajnoczi" __email__ = "stefanha@redhat.com" -import os.path - -from tracetool import out +from tracetool import out, expand_format_string PUBLIC = True +CHECK_TRACE_EVENT_GET_STATE = True def generate_h_begin(events, group): out('#include "qemu/log-for-trace.h"', - '#include "qemu/error-report.h"', '') @@ -31,31 +29,13 @@ def generate_h(event, group): if len(event.args) > 0: argnames = ", " + argnames - if "vcpu" in event.properties: - # already checked on the generic format code - cond = "true" - else: - cond = "trace_event_get_state(%s)" % ("TRACE_" + event.name.upper()) - - out(' if (%(cond)s && qemu_loglevel_mask(LOG_TRACE)) {', - ' if (message_with_timestamp) {', - ' struct timeval _now;', - ' gettimeofday(&_now, NULL);', - '#line %(event_lineno)d "%(event_filename)s"', - ' qemu_log("%%d@%%zu.%%06zu:%(name)s " %(fmt)s "\\n",', - ' qemu_get_thread_id(),', - ' (size_t)_now.tv_sec, (size_t)_now.tv_usec', - ' %(argnames)s);', - '#line %(out_next_lineno)d "%(out_filename)s"', - ' } else {', + out(' if (qemu_loglevel_mask(LOG_TRACE)) {', '#line %(event_lineno)d "%(event_filename)s"', ' qemu_log("%(name)s " %(fmt)s "\\n"%(argnames)s);', '#line %(out_next_lineno)d "%(out_filename)s"', ' }', - ' }', - cond=cond, event_lineno=event.lineno, - event_filename=os.path.relpath(event.filename), + event_filename=event.filename, name=event.name, fmt=event.fmt.rstrip("\n"), argnames=argnames) @@ -64,3 +44,11 @@ def generate_h(event, group): def generate_h_backend_dstate(event, group): out(' trace_event_get_state_dynamic_by_id(%(event_id)s) || \\', event_id="TRACE_" + event.name.upper()) + +def generate_rs(event, group): + out(' let format_string = c"%(fmt)s\\n";', + ' if (unsafe { bindings::qemu_loglevel } & bindings::LOG_TRACE) != 0 {', + ' unsafe { bindings::qemu_log(format_string.as_ptr() as *const c_char, %(args)s);}', + ' }', + fmt=expand_format_string(event.fmt, event.name + " "), + args=event.args.rust_call_varargs()) diff --git a/scripts/tracetool/backend/simple.py b/scripts/tracetool/backend/simple.py index a74d61f..b131e4f 100644 --- a/scripts/tracetool/backend/simple.py +++ b/scripts/tracetool/backend/simple.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# SPDX-License-Identifier: GPL-2.0-or-later """ Simple built-in backend. @@ -16,6 +16,7 @@ from tracetool import out PUBLIC = True +CHECK_TRACE_EVENT_GET_STATE = True def is_string(arg): @@ -36,7 +37,7 @@ def generate_h_begin(events, group): def generate_h(event, group): - out(' _simple_%(api)s(%(args)s);', + out(' _simple_%(api)s(%(args)s);', api=event.api(), args=", ".join(event.args.names())) @@ -72,22 +73,10 @@ def generate_c(event, group): if len(event.args) == 0: sizestr = '0' - event_id = 'TRACE_' + event.name.upper() - if "vcpu" in event.properties: - # already checked on the generic format code - cond = "true" - else: - cond = "trace_event_get_state(%s)" % event_id - out('', - ' if (!%(cond)s) {', - ' return;', - ' }', - '', ' if (trace_record_start(&rec, %(event_obj)s.id, %(size_str)s)) {', ' return; /* Trace Buffer Full, Event Dropped ! */', ' }', - cond=cond, event_obj=event.api(event.QEMU_EVENT), size_str=sizestr) @@ -109,3 +98,10 @@ def generate_c(event, group): out(' trace_record_finish(&rec);', '}', '') + +def generate_rs(event, group): + out(' extern "C" { fn _simple_%(api)s(%(rust_args)s); }', + ' unsafe { _simple_%(api)s(%(args)s); }', + api=event.api(), + rust_args=event.args.rust_decl_extern(), + args=event.args.rust_call_extern()) diff --git a/scripts/tracetool/backend/syslog.py b/scripts/tracetool/backend/syslog.py index 012970f..12b8265 100644 --- a/scripts/tracetool/backend/syslog.py +++ b/scripts/tracetool/backend/syslog.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# SPDX-License-Identifier: GPL-2.0-or-later """ Syslog built-in backend. @@ -12,12 +12,11 @@ __maintainer__ = "Stefan Hajnoczi" __email__ = "stefanha@redhat.com" -import os.path - -from tracetool import out +from tracetool import out, expand_format_string PUBLIC = True +CHECK_TRACE_EVENT_GET_STATE = True def generate_h_begin(events, group): @@ -30,24 +29,20 @@ def generate_h(event, group): if len(event.args) > 0: argnames = ", " + argnames - if "vcpu" in event.properties: - # already checked on the generic format code - cond = "true" - else: - cond = "trace_event_get_state(%s)" % ("TRACE_" + event.name.upper()) - - out(' if (%(cond)s) {', - '#line %(event_lineno)d "%(event_filename)s"', + out('#line %(event_lineno)d "%(event_filename)s"', ' syslog(LOG_INFO, "%(name)s " %(fmt)s %(argnames)s);', '#line %(out_next_lineno)d "%(out_filename)s"', - ' }', - cond=cond, event_lineno=event.lineno, - event_filename=os.path.relpath(event.filename), + event_filename=event.filename, name=event.name, fmt=event.fmt.rstrip("\n"), argnames=argnames) +def generate_rs(event, group): + out(' let format_string = c"%(fmt)s";', + ' unsafe {::trace::syslog(::trace::LOG_INFO, format_string.as_ptr() as *const c_char, %(args)s);}', + fmt=expand_format_string(event.fmt), + args=event.args.rust_call_varargs()) def generate_h_backend_dstate(event, group): out(' trace_event_get_state_dynamic_by_id(%(event_id)s) || \\', diff --git a/scripts/tracetool/backend/ust.py b/scripts/tracetool/backend/ust.py index c857516..3aa9bb1 100644 --- a/scripts/tracetool/backend/ust.py +++ b/scripts/tracetool/backend/ust.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# SPDX-License-Identifier: GPL-2.0-or-later """ LTTng User Space Tracing backend. diff --git a/scripts/tracetool/format/__init__.py b/scripts/tracetool/format/__init__.py index 2dc46f3..7b9d1b5 100644 --- a/scripts/tracetool/format/__init__.py +++ b/scripts/tracetool/format/__init__.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# SPDX-License-Identifier: GPL-2.0-or-later """ Format management. @@ -70,7 +70,7 @@ def exists(name): if len(name) == 0: return False name = name.replace("-", "_") - return tracetool.try_import("tracetool.format." + name)[1] + return tracetool.try_import("tracetool.format." + name)[0] def generate(events, format, backend, group): diff --git a/scripts/tracetool/format/c.py b/scripts/tracetool/format/c.py index 69edf0d..50e0331 100644 --- a/scripts/tracetool/format/c.py +++ b/scripts/tracetool/format/c.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# SPDX-License-Identifier: GPL-2.0-or-later """ trace/generated-tracers.c @@ -22,6 +22,7 @@ def generate(events, backend, group): header = "trace-" + group + ".h" out('/* This file is autogenerated by tracetool, do not edit. */', + '/* SPDX-License-Identifier: GPL-2.0-or-later */', '', '#include "qemu/osdep.h"', '#include "qemu/module.h"', @@ -36,7 +37,7 @@ def generate(events, backend, group): ' .id = 0,', ' .name = \"%(name)s\",', ' .sstate = %(sstate)s,', - ' .dstate = &%(dstate)s ', + ' .dstate = &%(dstate)s', '};', event = e.api(e.QEMU_EVENT), name = e.name, diff --git a/scripts/tracetool/format/d.py b/scripts/tracetool/format/d.py index ebfb714..e9e33df 100644 --- a/scripts/tracetool/format/d.py +++ b/scripts/tracetool/format/d.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# SPDX-License-Identifier: GPL-2.0-or-later """ trace/generated-tracers.dtrace (DTrace only). @@ -39,7 +39,8 @@ def generate(events, backend, group): if not events and platform != "darwin": return - out('/* This file is autogenerated by tracetool, do not edit. */' + out('/* This file is autogenerated by tracetool, do not edit. */', + '/* SPDX-License-Identifier: GPL-2.0-or-later */', '', 'provider qemu {') diff --git a/scripts/tracetool/format/h.py b/scripts/tracetool/format/h.py index ea126b0..dd58713 100644 --- a/scripts/tracetool/format/h.py +++ b/scripts/tracetool/format/h.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# SPDX-License-Identifier: GPL-2.0-or-later """ trace/generated-tracers.h @@ -19,6 +19,7 @@ def generate(events, backend, group): header = "trace/control.h" out('/* This file is autogenerated by tracetool, do not edit. */', + '/* SPDX-License-Identifier: GPL-2.0-or-later */', '', '#ifndef TRACE_%s_GENERATED_TRACERS_H' % group.upper(), '#define TRACE_%s_GENERATED_TRACERS_H' % group.upper(), @@ -39,11 +40,6 @@ def generate(events, backend, group): enabled = 0 else: enabled = 1 - if "tcg-exec" in e.properties: - # a single define for the two "sub-events" - out('#define TRACE_%(name)s_ENABLED %(enabled)d', - name=e.original.name.upper(), - enabled=enabled) out('#define TRACE_%s_ENABLED %d' % (e.name.upper(), enabled)) backend.generate_begin(events, group) @@ -59,33 +55,24 @@ def generate(events, backend, group): out(' false)') - # tracer without checks out('', 'static inline void %(api)s(%(args)s)', '{', - api=e.api(e.QEMU_TRACE_NOCHECK), + api=e.api(), args=e.args) if "disable" not in e.properties: - backend.generate(e, group) - + backend.generate(e, group, check_trace_event_get_state=False) + + if backend.check_trace_event_get_state: + event_id = 'TRACE_' + e.name.upper() + cond = "trace_event_get_state(%s)" % event_id + out(' if (%(cond)s) {', + cond=cond) + backend.generate(e, group, check_trace_event_get_state=True) + out(' }') out('}') - cond = "true" - - out('', - 'static inline void %(api)s(%(args)s)', - '{', - ' if (%(cond)s) {', - ' %(api_nocheck)s(%(names)s);', - ' }', - '}', - api=e.api(), - api_nocheck=e.api(e.QEMU_TRACE_NOCHECK), - args=e.args, - names=", ".join(e.args.names()), - cond=cond) - backend.generate_end(events, group) out('#endif /* TRACE_%s_GENERATED_TRACERS_H */' % group.upper()) diff --git a/scripts/tracetool/format/log_stap.py b/scripts/tracetool/format/log_stap.py index b49afab..259303a 100644 --- a/scripts/tracetool/format/log_stap.py +++ b/scripts/tracetool/format/log_stap.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# SPDX-License-Identifier: GPL-2.0-or-later """ Generate .stp file that printfs log messages (DTrace with SystemTAP only). @@ -18,8 +18,6 @@ from tracetool.backend.dtrace import binary, probeprefix from tracetool.backend.simple import is_string from tracetool.format.stap import stap_escape -def global_var_name(name): - return probeprefix().replace(".", "_") + "_" + name STATE_SKIP = 0 STATE_LITERAL = 1 @@ -88,6 +86,7 @@ def c_fmt_to_stap(fmt): def generate(events, backend, group): out('/* This file is autogenerated by tracetool, do not edit. */', + '/* SPDX-License-Identifier: GPL-2.0-or-later */', '') for event_id, e in enumerate(events): diff --git a/scripts/tracetool/format/rs.py b/scripts/tracetool/format/rs.py new file mode 100644 index 0000000..32ac4e5 --- /dev/null +++ b/scripts/tracetool/format/rs.py @@ -0,0 +1,64 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +""" +trace-DIR.rs +""" + +__author__ = "Tanish Desai <tanishdesai37@gmail.com>" +__copyright__ = "Copyright 2025, Tanish Desai <tanishdesai37@gmail.com>" +__license__ = "GPL version 2 or (at your option) any later version" + +__maintainer__ = "Stefan Hajnoczi" +__email__ = "stefanha@redhat.com" + + +from tracetool import out + + +def generate(events, backend, group): + out('// SPDX-License-Identifier: GPL-2.0-or-later', + '// This file is @generated by tracetool, do not edit.', + '', + '#[allow(unused_imports)]', + 'use std::ffi::c_char;', + '#[allow(unused_imports)]', + 'use util::bindings;', + '', + '#[inline(always)]', + 'fn trace_event_state_is_enabled(dstate: u16) -> bool {', + ' (unsafe { trace_events_enabled_count }) != 0 && dstate != 0', + '}', + '', + 'extern "C" {', + ' static mut trace_events_enabled_count: u32;', + '}',) + + out('extern "C" {') + + for e in events: + out(' static mut %s: u16;' % e.api(e.QEMU_DSTATE)) + out('}') + + backend.generate_begin(events, group) + + for e in events: + out('', + '#[inline(always)]', + '#[allow(dead_code)]', + 'pub fn %(api)s(%(args)s)', + '{', + api=e.api(e.QEMU_TRACE), + args=e.args.rust_decl()) + + if "disable" not in e.properties: + backend.generate(e, group, check_trace_event_get_state=False) + if backend.check_trace_event_get_state: + event_id = 'TRACE_' + e.name.upper() + out(' if trace_event_state_is_enabled(unsafe { _%(event_id)s_DSTATE}) {', + event_id = event_id, + api=e.api()) + backend.generate(e, group, check_trace_event_get_state=True) + out(' }') + out('}') + + backend.generate_end(events, group) diff --git a/scripts/tracetool/format/simpletrace_stap.py b/scripts/tracetool/format/simpletrace_stap.py index 4f4633b..c7bde97 100644 --- a/scripts/tracetool/format/simpletrace_stap.py +++ b/scripts/tracetool/format/simpletrace_stap.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# SPDX-License-Identifier: GPL-2.0-or-later """ Generate .stp file that outputs simpletrace binary traces (DTrace with SystemTAP only). @@ -17,11 +17,10 @@ from tracetool.backend.dtrace import probeprefix from tracetool.backend.simple import is_string from tracetool.format.stap import stap_escape -def global_var_name(name): - return probeprefix().replace(".", "_") + "_" + name def generate(events, backend, group): out('/* This file is autogenerated by tracetool, do not edit. */', + '/* SPDX-License-Identifier: GPL-2.0-or-later */', '') for event_id, e in enumerate(events): diff --git a/scripts/tracetool/format/stap.py b/scripts/tracetool/format/stap.py index a218b04..285c920 100644 --- a/scripts/tracetool/format/stap.py +++ b/scripts/tracetool/format/stap.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# SPDX-License-Identifier: GPL-2.0-or-later """ Generate .stp file (DTrace with SystemTAP only). @@ -38,6 +38,7 @@ def generate(events, backend, group): if "disable" not in e.properties] out('/* This file is autogenerated by tracetool, do not edit. */', + '/* SPDX-License-Identifier: GPL-2.0-or-later */', '') for e in events: diff --git a/scripts/tracetool/format/ust_events_c.py b/scripts/tracetool/format/ust_events_c.py index deced95..074226b 100644 --- a/scripts/tracetool/format/ust_events_c.py +++ b/scripts/tracetool/format/ust_events_c.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# SPDX-License-Identifier: GPL-2.0-or-later """ trace/generated-ust.c @@ -20,6 +20,7 @@ def generate(events, backend, group): if "disabled" not in e.properties] out('/* This file is autogenerated by tracetool, do not edit. */', + '/* SPDX-License-Identifier: GPL-2.0-or-later */', '', '#include "qemu/osdep.h"', '', diff --git a/scripts/tracetool/format/ust_events_h.py b/scripts/tracetool/format/ust_events_h.py index b99fe68..cee7970 100644 --- a/scripts/tracetool/format/ust_events_h.py +++ b/scripts/tracetool/format/ust_events_h.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# SPDX-License-Identifier: GPL-2.0-or-later """ trace/generated-ust-provider.h @@ -25,6 +25,7 @@ def generate(events, backend, group): include = "trace-ust.h" out('/* This file is autogenerated by tracetool, do not edit. */', + '/* SPDX-License-Identifier: GPL-2.0-or-later */', '', '#undef TRACEPOINT_PROVIDER', '#define TRACEPOINT_PROVIDER qemu', |