-----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
					
				
							
								
								
									
										35
									
								
								include/qemu/log-for-trace.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								include/qemu/log-for-trace.h
									
									
									
									
									
										Normal file
									
								
							| @ -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 | ||||
| #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 int qemu_loglevel; | ||||
| 
 | ||||
| /* 
 | ||||
|  * The new API: | ||||
| @ -41,16 +42,9 @@ static inline bool qemu_log_separate(void) | ||||
| #define CPU_LOG_MMU        (1 << 12) | ||||
| #define CPU_LOG_TB_NOCHAIN (1 << 13) | ||||
| #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) | ||||
| 
 | ||||
| /* 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
 | ||||
|  * 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 | ||||
| @ -69,10 +63,6 @@ static inline void qemu_log_unlock(void) | ||||
| 
 | ||||
| /* Logging functions: */ | ||||
| 
 | ||||
| /* main logging function
 | ||||
|  */ | ||||
| int GCC_FMT_ATTR(1, 2) qemu_log(const char *fmt, ...); | ||||
| 
 | ||||
| /* vfprintf-like logging function
 | ||||
|  */ | ||||
| static inline void GCC_FMT_ATTR(1, 0) | ||||
|  | ||||
| @ -168,7 +168,7 @@ class Analyzer(object): | ||||
| def process(events, log, analyzer, read_header=True): | ||||
|     """Invoke an analyzer on each event in a log.""" | ||||
|     if isinstance(events, str): | ||||
|         events = read_events(open(events, 'r')) | ||||
|         events = read_events(open(events, 'r'), events) | ||||
|     if isinstance(log, str): | ||||
|         log = open(log, 'rb') | ||||
| 
 | ||||
| @ -199,7 +199,7 @@ def process(events, log, analyzer, read_header=True): | ||||
|         fn_argcount = len(inspect.getargspec(fn)[0]) - 1 | ||||
|         if fn_argcount == event_argcount + 1: | ||||
|             # 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: | ||||
|             # Include timestamp and pid | ||||
|             return lambda _, rec: fn(*rec[1:3 + event_argcount]) | ||||
| @ -233,7 +233,7 @@ def run(analyzer): | ||||
|                          '<trace-file>\n' % sys.argv[0]) | ||||
|         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) | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|  | ||||
| @ -142,7 +142,7 @@ def main(args): | ||||
|     events = [] | ||||
|     for arg in args: | ||||
|         with open(arg, "r") as fh: | ||||
|             events.extend(tracetool.read_events(fh)) | ||||
|             events.extend(tracetool.read_events(fh, arg)) | ||||
| 
 | ||||
|     try: | ||||
|         tracetool.generate(events, arg_group, arg_format, arg_backends, | ||||
|  | ||||
| @ -41,6 +41,51 @@ def out(*lines, **kwargs): | ||||
|     lines = [ l % kwargs for l in lines ] | ||||
|     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: | ||||
|     """Event arguments description.""" | ||||
| @ -87,6 +132,7 @@ class Arguments: | ||||
|             else: | ||||
|                 arg_type, identifier = arg.rsplit(None, 1) | ||||
| 
 | ||||
|             validate_type(arg_type) | ||||
|             res.append((arg_type, identifier)) | ||||
|         return Arguments(res) | ||||
| 
 | ||||
| @ -291,13 +337,15 @@ class Event(object): | ||||
|                      self) | ||||
| 
 | ||||
| 
 | ||||
| def read_events(fobj): | ||||
| def read_events(fobj, fname): | ||||
|     """Generate the output for the given (format, backends) pair. | ||||
| 
 | ||||
|     Parameters | ||||
|     ---------- | ||||
|     fobj : file | ||||
|         Event description file. | ||||
|     fname : str | ||||
|         Name of event file | ||||
| 
 | ||||
|     Returns a list of Event objects | ||||
|     """ | ||||
| @ -312,7 +360,7 @@ def read_events(fobj): | ||||
|         try: | ||||
|             event = Event.build(line) | ||||
|         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:] | ||||
|             raise | ||||
| 
 | ||||
|  | ||||
| @ -20,7 +20,7 @@ PUBLIC = True | ||||
| 
 | ||||
| 
 | ||||
| def generate_h_begin(events, group): | ||||
|     out('#include "qemu/log.h"', | ||||
|     out('#include "qemu/log-for-trace.h"', | ||||
|         '') | ||||
| 
 | ||||
| 
 | ||||
| @ -35,14 +35,13 @@ def generate_h(event, group): | ||||
|     else: | ||||
|         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;', | ||||
|         '        gettimeofday(&_now, NULL);', | ||||
|         '        qemu_log_mask(LOG_TRACE,', | ||||
|         '                      "%%d@%%zd.%%06zd:%(name)s " %(fmt)s "\\n",', | ||||
|         '                      getpid(),', | ||||
|         '                      (size_t)_now.tv_sec, (size_t)_now.tv_usec', | ||||
|         '                      %(argnames)s);', | ||||
|         '        qemu_log("%%d@%%zd.%%06zd:%(name)s " %(fmt)s "\\n",', | ||||
|         '                 getpid(),', | ||||
|         '                 (size_t)_now.tv_sec, (size_t)_now.tv_usec', | ||||
|         '                 %(argnames)s);', | ||||
|         '    }', | ||||
|         cond=cond, | ||||
|         name=event.name, | ||||
|  | ||||
| @ -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_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" | ||||
| flatview_new(FlatView *view, MemoryRegion *root) "%p (root %p)" | ||||
| flatview_destroy(FlatView *view, MemoryRegion *root) "%p (root %p)" | ||||
| flatview_destroy_rcu(FlatView *view, MemoryRegion *root) "%p (root %p)" | ||||
| flatview_new(void *view, void *root) "%p (root %p)" | ||||
| flatview_destroy(void *view, void *root) "%p (root %p)" | ||||
| flatview_destroy_rcu(void *view, void *root) "%p (root %p)" | ||||
| 
 | ||||
| # gdbstub.c | ||||
| gdbstub_op_start(const char *device) "Starting gdbstub using device %s" | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Peter Maydell
						Peter Maydell