mirror of https://gitee.com/openkylin/qemu.git
-----BEGIN PGP SIGNATURE-----
iQEcBAABAgAGBQJapqP6AAoJEJykq7OBq3PIZasIAL+NKBQGa/e0FD28PYdLU/JE sKZZ0O6+eVTCejGXap4bzbKOy+qZyOXvaRk5KNREc5A9R8HFBt5GotMfE80Cw9Nt rryX+qVdf4w27u2jMqY4215jD5jy/nPijRQ0a8UBsi6z2PXVPPNeS3lMB8RSFEZS IZu+l3j1op1wUlM4GfZvLCjmgHC+73lk6a5xZLJ2UvH9UoqJepgVZnSs2YvOctzG LVGMhk6/yAy4hh3NWx/M2h2B2ASMJJya8XrLgelAVnr6CxKBeBII0bSPur+1YIH7 OkJhNsk6QKSWNFKtzXE6N+y1ryWLnbE8vzKSZt+xSzUDjhnqTm5iFpZQ+Ed16qA= =nCAn -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/stefanha/tags/tracing-pull-request' into staging # gpg: Signature made Mon 12 Mar 2018 15:59:54 GMT # gpg: using RSA key 9CA4ABB381AB73C8 # gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>" # gpg: aka "Stefan Hajnoczi <stefanha@gmail.com>" # Primary key fingerprint: 8695 A8BF D3F9 7CDA AC35 775A 9CA4 ABB3 81AB 73C8 * remotes/stefanha/tags/tracing-pull-request: trace: only permit standard C types and fixed size integer types trace: remove use of QEMU specific types from trace probes trace: include filename when printing parser error messages simpletrace: fix timestamp argument type log-for-trace.h: Split out parts of log.h used by trace.h Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
73988d529e
|
@ -0,0 +1,35 @@
|
||||||
|
/* log-for-trace.h: logging basics required by the trace.h generated
|
||||||
|
* by the log trace backend.
|
||||||
|
*
|
||||||
|
* This should not be included directly by any .c file: if you
|
||||||
|
* need to use the logging functions include "qemu/log.h".
|
||||||
|
*
|
||||||
|
* The purpose of splitting these parts out into their own header
|
||||||
|
* is to catch the easy mistake where a .c file includes trace.h
|
||||||
|
* but forgets to include qemu/log.h. Without this split, that
|
||||||
|
* would result in the .c file compiling fine when the default
|
||||||
|
* trace backend is in use but failing to compile with any other
|
||||||
|
* backend.
|
||||||
|
*
|
||||||
|
* This code is licensed under the GNU General Public License,
|
||||||
|
* version 2 or (at your option) any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef QEMU_LOG_FOR_TRACE_H
|
||||||
|
#define QEMU_LOG_FOR_TRACE_H
|
||||||
|
|
||||||
|
/* Private global variable, don't use */
|
||||||
|
extern int qemu_loglevel;
|
||||||
|
|
||||||
|
#define LOG_TRACE (1 << 15)
|
||||||
|
|
||||||
|
/* Returns true if a bit is set in the current loglevel mask */
|
||||||
|
static inline bool qemu_loglevel_mask(int mask)
|
||||||
|
{
|
||||||
|
return (qemu_loglevel & mask) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* main logging function */
|
||||||
|
int GCC_FMT_ATTR(1, 2) qemu_log(const char *fmt, ...);
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,10 +1,11 @@
|
||||||
#ifndef QEMU_LOG_H
|
#ifndef QEMU_LOG_H
|
||||||
#define QEMU_LOG_H
|
#define QEMU_LOG_H
|
||||||
|
|
||||||
|
/* A small part of this API is split into its own header */
|
||||||
|
#include "qemu/log-for-trace.h"
|
||||||
|
|
||||||
/* Private global variables, don't use */
|
/* Private global variable, don't use */
|
||||||
extern FILE *qemu_logfile;
|
extern FILE *qemu_logfile;
|
||||||
extern int qemu_loglevel;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The new API:
|
* The new API:
|
||||||
|
@ -41,16 +42,9 @@ static inline bool qemu_log_separate(void)
|
||||||
#define CPU_LOG_MMU (1 << 12)
|
#define CPU_LOG_MMU (1 << 12)
|
||||||
#define CPU_LOG_TB_NOCHAIN (1 << 13)
|
#define CPU_LOG_TB_NOCHAIN (1 << 13)
|
||||||
#define CPU_LOG_PAGE (1 << 14)
|
#define CPU_LOG_PAGE (1 << 14)
|
||||||
#define LOG_TRACE (1 << 15)
|
/* LOG_TRACE (1 << 15) is defined in log-for-trace.h */
|
||||||
#define CPU_LOG_TB_OP_IND (1 << 16)
|
#define CPU_LOG_TB_OP_IND (1 << 16)
|
||||||
|
|
||||||
/* Returns true if a bit is set in the current loglevel mask
|
|
||||||
*/
|
|
||||||
static inline bool qemu_loglevel_mask(int mask)
|
|
||||||
{
|
|
||||||
return (qemu_loglevel & mask) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Lock output for a series of related logs. Since this is not needed
|
/* Lock output for a series of related logs. Since this is not needed
|
||||||
* for a single qemu_log / qemu_log_mask / qemu_log_mask_and_addr, we
|
* for a single qemu_log / qemu_log_mask / qemu_log_mask_and_addr, we
|
||||||
* assume that qemu_loglevel_mask has already been tested, and that
|
* assume that qemu_loglevel_mask has already been tested, and that
|
||||||
|
@ -69,10 +63,6 @@ static inline void qemu_log_unlock(void)
|
||||||
|
|
||||||
/* Logging functions: */
|
/* Logging functions: */
|
||||||
|
|
||||||
/* main logging function
|
|
||||||
*/
|
|
||||||
int GCC_FMT_ATTR(1, 2) qemu_log(const char *fmt, ...);
|
|
||||||
|
|
||||||
/* vfprintf-like logging function
|
/* vfprintf-like logging function
|
||||||
*/
|
*/
|
||||||
static inline void GCC_FMT_ATTR(1, 0)
|
static inline void GCC_FMT_ATTR(1, 0)
|
||||||
|
|
|
@ -168,7 +168,7 @@ def end(self):
|
||||||
def process(events, log, analyzer, read_header=True):
|
def process(events, log, analyzer, read_header=True):
|
||||||
"""Invoke an analyzer on each event in a log."""
|
"""Invoke an analyzer on each event in a log."""
|
||||||
if isinstance(events, str):
|
if isinstance(events, str):
|
||||||
events = read_events(open(events, 'r'))
|
events = read_events(open(events, 'r'), events)
|
||||||
if isinstance(log, str):
|
if isinstance(log, str):
|
||||||
log = open(log, 'rb')
|
log = open(log, 'rb')
|
||||||
|
|
||||||
|
@ -199,7 +199,7 @@ def build_fn(analyzer, event):
|
||||||
fn_argcount = len(inspect.getargspec(fn)[0]) - 1
|
fn_argcount = len(inspect.getargspec(fn)[0]) - 1
|
||||||
if fn_argcount == event_argcount + 1:
|
if fn_argcount == event_argcount + 1:
|
||||||
# Include timestamp as first argument
|
# Include timestamp as first argument
|
||||||
return lambda _, rec: fn(*((rec[1:2],) + rec[3:3 + event_argcount]))
|
return lambda _, rec: fn(*(rec[1:2] + rec[3:3 + event_argcount]))
|
||||||
elif fn_argcount == event_argcount + 2:
|
elif fn_argcount == event_argcount + 2:
|
||||||
# Include timestamp and pid
|
# Include timestamp and pid
|
||||||
return lambda _, rec: fn(*rec[1:3 + event_argcount])
|
return lambda _, rec: fn(*rec[1:3 + event_argcount])
|
||||||
|
@ -233,7 +233,7 @@ def run(analyzer):
|
||||||
'<trace-file>\n' % sys.argv[0])
|
'<trace-file>\n' % sys.argv[0])
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
events = read_events(open(sys.argv[1], 'r'))
|
events = read_events(open(sys.argv[1], 'r'), sys.argv[1])
|
||||||
process(events, sys.argv[2], analyzer, read_header=read_header)
|
process(events, sys.argv[2], analyzer, read_header=read_header)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -142,7 +142,7 @@ def main(args):
|
||||||
events = []
|
events = []
|
||||||
for arg in args:
|
for arg in args:
|
||||||
with open(arg, "r") as fh:
|
with open(arg, "r") as fh:
|
||||||
events.extend(tracetool.read_events(fh))
|
events.extend(tracetool.read_events(fh, arg))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
tracetool.generate(events, arg_group, arg_format, arg_backends,
|
tracetool.generate(events, arg_group, arg_format, arg_backends,
|
||||||
|
|
|
@ -41,6 +41,51 @@ def out(*lines, **kwargs):
|
||||||
lines = [ l % kwargs for l in lines ]
|
lines = [ l % kwargs for l in lines ]
|
||||||
sys.stdout.writelines("\n".join(lines) + "\n")
|
sys.stdout.writelines("\n".join(lines) + "\n")
|
||||||
|
|
||||||
|
# We only want to allow standard C types or fixed sized
|
||||||
|
# integer types. We don't want QEMU specific types
|
||||||
|
# as we can't assume trace backends can resolve all the
|
||||||
|
# typedefs
|
||||||
|
ALLOWED_TYPES = [
|
||||||
|
"int",
|
||||||
|
"long",
|
||||||
|
"short",
|
||||||
|
"char",
|
||||||
|
"bool",
|
||||||
|
"unsigned",
|
||||||
|
"signed",
|
||||||
|
"float",
|
||||||
|
"double",
|
||||||
|
"int8_t",
|
||||||
|
"uint8_t",
|
||||||
|
"int16_t",
|
||||||
|
"uint16_t",
|
||||||
|
"int32_t",
|
||||||
|
"uint32_t",
|
||||||
|
"int64_t",
|
||||||
|
"uint64_t",
|
||||||
|
"void",
|
||||||
|
"size_t",
|
||||||
|
"ssize_t",
|
||||||
|
"uintptr_t",
|
||||||
|
"ptrdiff_t",
|
||||||
|
# Magic substitution is done by tracetool
|
||||||
|
"TCGv",
|
||||||
|
]
|
||||||
|
|
||||||
|
def validate_type(name):
|
||||||
|
bits = name.split(" ")
|
||||||
|
for bit in bits:
|
||||||
|
bit = re.sub("\*", "", bit)
|
||||||
|
if bit == "":
|
||||||
|
continue
|
||||||
|
if bit == "const":
|
||||||
|
continue
|
||||||
|
if bit not in ALLOWED_TYPES:
|
||||||
|
raise ValueError("Argument type '%s' is not in whitelist. "
|
||||||
|
"Only standard C types and fixed size integer "
|
||||||
|
"types should be used. struct, union, and "
|
||||||
|
"other complex pointer types should be "
|
||||||
|
"declared as 'void *'" % name)
|
||||||
|
|
||||||
class Arguments:
|
class Arguments:
|
||||||
"""Event arguments description."""
|
"""Event arguments description."""
|
||||||
|
@ -87,6 +132,7 @@ def build(arg_str):
|
||||||
else:
|
else:
|
||||||
arg_type, identifier = arg.rsplit(None, 1)
|
arg_type, identifier = arg.rsplit(None, 1)
|
||||||
|
|
||||||
|
validate_type(arg_type)
|
||||||
res.append((arg_type, identifier))
|
res.append((arg_type, identifier))
|
||||||
return Arguments(res)
|
return Arguments(res)
|
||||||
|
|
||||||
|
@ -291,13 +337,15 @@ def transform(self, *trans):
|
||||||
self)
|
self)
|
||||||
|
|
||||||
|
|
||||||
def read_events(fobj):
|
def read_events(fobj, fname):
|
||||||
"""Generate the output for the given (format, backends) pair.
|
"""Generate the output for the given (format, backends) pair.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
fobj : file
|
fobj : file
|
||||||
Event description file.
|
Event description file.
|
||||||
|
fname : str
|
||||||
|
Name of event file
|
||||||
|
|
||||||
Returns a list of Event objects
|
Returns a list of Event objects
|
||||||
"""
|
"""
|
||||||
|
@ -312,7 +360,7 @@ def read_events(fobj):
|
||||||
try:
|
try:
|
||||||
event = Event.build(line)
|
event = Event.build(line)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
arg0 = 'Error on line %d: %s' % (lineno, e.args[0])
|
arg0 = 'Error at %s:%d: %s' % (fname, lineno, e.args[0])
|
||||||
e.args = (arg0,) + e.args[1:]
|
e.args = (arg0,) + e.args[1:]
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
|
|
||||||
def generate_h_begin(events, group):
|
def generate_h_begin(events, group):
|
||||||
out('#include "qemu/log.h"',
|
out('#include "qemu/log-for-trace.h"',
|
||||||
'')
|
'')
|
||||||
|
|
||||||
|
|
||||||
|
@ -35,11 +35,10 @@ def generate_h(event, group):
|
||||||
else:
|
else:
|
||||||
cond = "trace_event_get_state(%s)" % ("TRACE_" + event.name.upper())
|
cond = "trace_event_get_state(%s)" % ("TRACE_" + event.name.upper())
|
||||||
|
|
||||||
out(' if (%(cond)s) {',
|
out(' if (%(cond)s && qemu_loglevel_mask(LOG_TRACE)) {',
|
||||||
' struct timeval _now;',
|
' struct timeval _now;',
|
||||||
' gettimeofday(&_now, NULL);',
|
' gettimeofday(&_now, NULL);',
|
||||||
' qemu_log_mask(LOG_TRACE,',
|
' qemu_log("%%d@%%zd.%%06zd:%(name)s " %(fmt)s "\\n",',
|
||||||
' "%%d@%%zd.%%06zd:%(name)s " %(fmt)s "\\n",',
|
|
||||||
' getpid(),',
|
' getpid(),',
|
||||||
' (size_t)_now.tv_sec, (size_t)_now.tv_usec',
|
' (size_t)_now.tv_sec, (size_t)_now.tv_usec',
|
||||||
' %(argnames)s);',
|
' %(argnames)s);',
|
||||||
|
|
|
@ -68,9 +68,9 @@ memory_region_tb_read(int cpu_index, uint64_t addr, uint64_t value, unsigned siz
|
||||||
memory_region_tb_write(int cpu_index, uint64_t addr, uint64_t value, unsigned size) "cpu %d addr 0x%"PRIx64" value 0x%"PRIx64" size %u"
|
memory_region_tb_write(int cpu_index, uint64_t addr, uint64_t value, unsigned size) "cpu %d addr 0x%"PRIx64" value 0x%"PRIx64" size %u"
|
||||||
memory_region_ram_device_read(int cpu_index, void *mr, uint64_t addr, uint64_t value, unsigned size) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u"
|
memory_region_ram_device_read(int cpu_index, void *mr, uint64_t addr, uint64_t value, unsigned size) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u"
|
||||||
memory_region_ram_device_write(int cpu_index, void *mr, uint64_t addr, uint64_t value, unsigned size) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u"
|
memory_region_ram_device_write(int cpu_index, void *mr, uint64_t addr, uint64_t value, unsigned size) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u"
|
||||||
flatview_new(FlatView *view, MemoryRegion *root) "%p (root %p)"
|
flatview_new(void *view, void *root) "%p (root %p)"
|
||||||
flatview_destroy(FlatView *view, MemoryRegion *root) "%p (root %p)"
|
flatview_destroy(void *view, void *root) "%p (root %p)"
|
||||||
flatview_destroy_rcu(FlatView *view, MemoryRegion *root) "%p (root %p)"
|
flatview_destroy_rcu(void *view, void *root) "%p (root %p)"
|
||||||
|
|
||||||
# gdbstub.c
|
# gdbstub.c
|
||||||
gdbstub_op_start(const char *device) "Starting gdbstub using device %s"
|
gdbstub_op_start(const char *device) "Starting gdbstub using device %s"
|
||||||
|
|
Loading…
Reference in New Issue