aboutsummaryrefslogtreecommitdiff
path: root/scripts/tracetool
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/tracetool')
-rw-r--r--scripts/tracetool/__init__.py228
-rw-r--r--scripts/tracetool/backend/__init__.py43
-rw-r--r--scripts/tracetool/backend/dtrace.py2
-rw-r--r--scripts/tracetool/backend/ftrace.py30
-rw-r--r--scripts/tracetool/backend/log.py38
-rw-r--r--scripts/tracetool/backend/simple.py24
-rw-r--r--scripts/tracetool/backend/syslog.py25
-rw-r--r--scripts/tracetool/backend/ust.py2
-rw-r--r--scripts/tracetool/format/__init__.py4
-rw-r--r--scripts/tracetool/format/c.py5
-rw-r--r--scripts/tracetool/format/d.py5
-rw-r--r--scripts/tracetool/format/h.py37
-rw-r--r--scripts/tracetool/format/log_stap.py5
-rw-r--r--scripts/tracetool/format/rs.py64
-rw-r--r--scripts/tracetool/format/simpletrace_stap.py5
-rw-r--r--scripts/tracetool/format/stap.py3
-rw-r--r--scripts/tracetool/format/ust_events_c.py3
-rw-r--r--scripts/tracetool/format/ust_events_h.py3
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',