]>
git.proxmox.com Git - mirror_qemu.git/blob - scripts/tracetool/__init__.py
2 # -*- coding: utf-8 -*-
5 Machinery for generating tracing-related intermediate files.
8 __author__
= "Lluís Vilanova <vilanova@ac.upc.edu>"
9 __copyright__
= "Copyright 2012-2017, Lluís Vilanova <vilanova@ac.upc.edu>"
10 __license__
= "GPL version 2 or (at your option) any later version"
12 __maintainer__
= "Stefan Hajnoczi"
13 __email__
= "stefanha@linux.vnet.ibm.com"
20 import tracetool
.format
21 import tracetool
.backend
22 import tracetool
.transform
25 def error_write(*lines
):
26 """Write a set of error lines."""
27 sys
.stderr
.writelines("\n".join(lines
) + "\n")
30 """Write a set of error lines and exit."""
35 def out(*lines
, **kwargs
):
36 """Write a set of output lines.
38 You can use kwargs as a shorthand for mapping variables when formating all
41 lines
= [ l
% kwargs
for l
in lines
]
42 sys
.stdout
.writelines("\n".join(lines
) + "\n")
46 """Event arguments description."""
48 def __init__(self
, args
):
53 List of (type, name) tuples or Arguments objects.
57 if isinstance(arg
, Arguments
):
58 self
._args
.extend(arg
._args
)
60 self
._args
.append(arg
)
63 """Create a new copy."""
64 return Arguments(list(self
._args
))
68 """Build and Arguments instance from an argument string.
73 String describing the event arguments.
76 for arg
in arg_str
.split(","):
79 raise ValueError("Empty argument (did you forget to use 'void'?)")
84 arg_type
, identifier
= arg
.rsplit('*', 1)
86 identifier
= identifier
.strip()
88 arg_type
, identifier
= arg
.rsplit(None, 1)
90 res
.append((arg_type
, identifier
))
93 def __getitem__(self
, index
):
94 if isinstance(index
, slice):
95 return Arguments(self
._args
[index
])
97 return self
._args
[index
]
100 """Iterate over the (type, name) pairs."""
101 return iter(self
._args
)
104 """Number of arguments."""
105 return len(self
._args
)
108 """String suitable for declaring function arguments."""
109 if len(self
._args
) == 0:
112 return ", ".join([ " ".join([t
, n
]) for t
,n
in self
._args
])
115 """Evaluable string representation for this object."""
116 return "Arguments(\"%s\")" % str(self
)
119 """List of argument names."""
120 return [ name
for _
, name
in self
._args
]
123 """List of argument types."""
124 return [ type_
for type_
, _
in self
._args
]
127 """List of argument names casted to their type."""
128 return ["(%s)%s" % (type_
, name
) for type_
, name
in self
._args
]
130 def transform(self
, *trans
):
131 """Return a new Arguments instance with transformed types.
133 The types in the resulting Arguments instance are transformed according
134 to tracetool.transform.transform_type.
137 for type_
, name
in self
._args
:
138 res
.append((tracetool
.transform
.transform_type(type_
, *trans
),
140 return Arguments(res
)
144 """Event description.
151 The event format string.
152 properties : set(str)
153 Properties of the event.
159 _CRE
= re
.compile("((?P<props>[\w\s]+)\s+)?"
161 "\((?P<args>[^)]*)\)"
163 "(?:(?:(?P<fmt_trans>\".+),)?\s*(?P<fmt>\".+))?"
166 _VALID_PROPS
= set(["disable", "tcg", "tcg-trans", "tcg-exec", "vcpu"])
168 def __init__(self
, name
, props
, fmt
, args
, orig
=None,
169 event_trans
=None, event_exec
=None):
177 fmt : str, list of str
178 Event printing format string(s).
182 Original Event before transformation/generation.
183 event_trans : Event or None
184 Generated translation-time event ("tcg" property).
185 event_exec : Event or None
186 Generated execution-time event ("tcg" property).
190 self
.properties
= props
193 self
.event_trans
= event_trans
194 self
.event_exec
= event_exec
197 raise ValueError("Event '%s' has more than maximum permitted "
198 "argument count" % name
)
201 self
.original
= weakref
.ref(self
)
205 unknown_props
= set(self
.properties
) - self
._VALID
_PROPS
206 if len(unknown_props
) > 0:
207 raise ValueError("Unknown properties: %s"
208 % ", ".join(unknown_props
))
209 assert isinstance(self
.fmt
, str) or len(self
.fmt
) == 2
212 """Create a new copy."""
213 return Event(self
.name
, list(self
.properties
), self
.fmt
,
214 self
.args
.copy(), self
, self
.event_trans
, self
.event_exec
)
218 """Build an Event instance from a string.
223 Line describing the event.
225 m
= Event
._CRE
.match(line_str
)
227 groups
= m
.groupdict('')
229 name
= groups
["name"]
230 props
= groups
["props"].split()
232 fmt_trans
= groups
["fmt_trans"]
233 if len(fmt_trans
) > 0:
234 fmt
= [fmt_trans
, fmt
]
235 args
= Arguments
.build(groups
["args"])
237 if "tcg-trans" in props
:
238 raise ValueError("Invalid property 'tcg-trans'")
239 if "tcg-exec" in props
:
240 raise ValueError("Invalid property 'tcg-exec'")
241 if "tcg" not in props
and not isinstance(fmt
, str):
242 raise ValueError("Only events with 'tcg' property can have two format strings")
243 if "tcg" in props
and isinstance(fmt
, str):
244 raise ValueError("Events with 'tcg' property must have two format strings")
246 event
= Event(name
, props
, fmt
, args
)
248 # add implicit arguments when using the 'vcpu' property
249 import tracetool
.vcpu
250 event
= tracetool
.vcpu
.transform_event(event
)
255 """Evaluable string representation for this object."""
256 if isinstance(self
.fmt
, str):
259 fmt
= "%s, %s" % (self
.fmt
[0], self
.fmt
[1])
260 return "Event('%s %s(%s) %s')" % (" ".join(self
.properties
),
265 _FMT
= re
.compile("(%[\d\.]*\w+|%.*PRI\S+)")
268 """List conversion specifiers in the argument print format string."""
269 assert not isinstance(self
.fmt
, list)
270 return self
._FMT
.findall(self
.fmt
)
272 QEMU_TRACE
= "trace_%(name)s"
273 QEMU_TRACE_NOCHECK
= "_nocheck__" + QEMU_TRACE
274 QEMU_TRACE_TCG
= QEMU_TRACE
+ "_tcg"
275 QEMU_DSTATE
= "_TRACE_%(NAME)s_DSTATE"
276 QEMU_BACKEND_DSTATE
= "TRACE_%(NAME)s_BACKEND_DSTATE"
277 QEMU_EVENT
= "_TRACE_%(NAME)s_EVENT"
279 def api(self
, fmt
=None):
281 fmt
= Event
.QEMU_TRACE
282 return fmt
% {"name": self
.name
, "NAME": self
.name
.upper()}
284 def transform(self
, *trans
):
285 """Return a new Event with transformed Arguments."""
286 return Event(self
.name
,
287 list(self
.properties
),
289 self
.args
.transform(*trans
),
293 def read_events(fobj
):
294 """Generate the output for the given (format, backends) pair.
299 Event description file.
301 Returns a list of Event objects
305 for lineno
, line
in enumerate(fobj
, 1):
308 if line
.lstrip().startswith('#'):
312 event
= Event
.build(line
)
313 except ValueError as e
:
314 arg0
= 'Error on line %d: %s' % (lineno
, e
.args
[0])
315 e
.args
= (arg0
,) + e
.args
[1:]
318 # transform TCG-enabled events
319 if "tcg" not in event
.properties
:
322 event_trans
= event
.copy()
323 event_trans
.name
+= "_trans"
324 event_trans
.properties
+= ["tcg-trans"]
325 event_trans
.fmt
= event
.fmt
[0]
326 # ignore TCG arguments
328 for atrans
, aorig
in zip(
329 event_trans
.transform(tracetool
.transform
.TCG_2_HOST
).args
,
332 args_trans
.append(atrans
)
333 event_trans
.args
= Arguments(args_trans
)
335 event_exec
= event
.copy()
336 event_exec
.name
+= "_exec"
337 event_exec
.properties
+= ["tcg-exec"]
338 event_exec
.fmt
= event
.fmt
[1]
339 event_exec
.args
= event_exec
.args
.transform(tracetool
.transform
.TCG_2_HOST
)
341 new_event
= [event_trans
, event_exec
]
342 event
.event_trans
, event
.event_exec
= new_event
344 events
.extend(new_event
)
349 class TracetoolError (Exception):
350 """Exception for calls to generate."""
354 def try_import(mod_name
, attr_name
=None, attr_default
=None):
355 """Try to import a module and get an attribute from it.
361 attr_name : str, optional
362 Name of an attribute in the module.
363 attr_default : optional
364 Default value if the attribute does not exist in the module.
368 A pair indicating whether the module could be imported and the module or
369 object or attribute value.
372 module
= __import__(mod_name
, globals(), locals(), ["__package__"])
373 if attr_name
is None:
375 return True, getattr(module
, str(attr_name
), attr_default
)
380 def generate(events
, group
, format
, backends
,
381 binary
=None, probe_prefix
=None):
382 """Generate the output for the given (format, backends) pair.
387 list of Event objects to generate for
389 Name of the tracing group
393 Output backend names.
395 See tracetool.backend.dtrace.BINARY.
396 probe_prefix : str or None
397 See tracetool.backend.dtrace.PROBEPREFIX.
399 # fix strange python error (UnboundLocalError tracetool)
404 raise TracetoolError("format not set")
405 if not tracetool
.format
.exists(format
):
406 raise TracetoolError("unknown format: %s" % format
)
408 if len(backends
) is 0:
409 raise TracetoolError("no backends specified")
410 for backend
in backends
:
411 if not tracetool
.backend
.exists(backend
):
412 raise TracetoolError("unknown backend: %s" % backend
)
413 backend
= tracetool
.backend
.Wrapper(backends
, format
)
415 import tracetool
.backend
.dtrace
416 tracetool
.backend
.dtrace
.BINARY
= binary
417 tracetool
.backend
.dtrace
.PROBEPREFIX
= probe_prefix
419 tracetool
.format
.generate(events
, format
, backend
, group
)