diff --git a/Makefile.objs b/Makefile.objs index 57a80e6130..036a4eb6ab 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -384,6 +384,8 @@ trace-nested-$(CONFIG_TRACE_DEFAULT) += default.o trace-nested-$(CONFIG_TRACE_SIMPLE) += simple.o trace-obj-$(CONFIG_TRACE_SIMPLE) += qemu-timer-common.o +trace-nested-y += control.o + trace-obj-y += $(addprefix trace/, $(trace-nested-y)) ###################################################################### diff --git a/docs/tracing.txt b/docs/tracing.txt index 41eb8e6fec..455da37969 100644 --- a/docs/tracing.txt +++ b/docs/tracing.txt @@ -138,6 +138,10 @@ This functionality is also provided through monitor commands: * trace-event NAME on|off Enable/disable a given trace event. +The "-trace events=" command line argument can be used to enable the +events listed in from the very beginning of the program. This file must +contain one event name per line. + == Trace backends == The "tracetool" script automates tedious trace event code generation and also diff --git a/qemu-config.c b/qemu-config.c index 4f3465d384..7a7854fd06 100644 --- a/qemu-config.c +++ b/qemu-config.c @@ -309,6 +309,9 @@ static QemuOptsList qemu_trace_opts = { .head = QTAILQ_HEAD_INITIALIZER(qemu_trace_opts.head), .desc = { { + .name = "events", + .type = QEMU_OPT_STRING, + },{ .name = "file", .type = QEMU_OPT_STRING, }, diff --git a/qemu-options.hx b/qemu-options.hx index 2d29933ab1..edd181bb8e 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2437,17 +2437,29 @@ Normally QEMU loads a configuration file from @var{sysconfdir}/qemu.conf and option will prevent QEMU from loading these configuration files at startup. ETEXI DEF("trace", HAS_ARG, QEMU_OPTION_trace, - "-trace\n" - " Specify a trace file to log traces to\n", + "-trace [events=][,file=]\n" + " specify tracing options\n", QEMU_ARCH_ALL) STEXI -HXCOMM This line is not accurate, as the option is backend-specific but HX does -HXCOMM not support conditional compilation of text. -@item -trace +HXCOMM This line is not accurate, as some sub-options are backend-specific but +HXCOMM HX does not support conditional compilation of text. +@item -trace [events=@var{file}][,file=@var{file}] @findex -trace -Specify a trace file to log output traces to. -This option is available only when using the @var{simple} tracing backend. +Specify tracing options. + +@table @option +@item events=@var{file} +Immediately enable events listed in @var{file}. +The file must contain one event name (as listed in the @var{trace-events} file) +per line. + +This option is only available when using the @var{simple} tracing backend. +@item file=@var{file} +Log output traces to @var{file}. + +This option is only available when using the @var{simple} tracing backend. +@end table ETEXI HXCOMM This is the last statement. Insert new options before this line! diff --git a/trace/control.c b/trace/control.c new file mode 100644 index 0000000000..4c5527d20a --- /dev/null +++ b/trace/control.c @@ -0,0 +1,42 @@ +/* + * Interface for configuring and controlling the state of tracing events. + * + * Copyright (C) 2011 LluĂ­s Vilanova + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + */ + +#include "trace/control.h" + + +void trace_backend_init_events(const char *fname) +{ + if (fname == NULL) { + return; + } + + FILE *fp = fopen(fname, "r"); + if (!fp) { + fprintf(stderr, "error: could not open trace events file '%s': %s\n", + fname, strerror(errno)); + exit(1); + } + char line_buf[1024]; + while (fgets(line_buf, sizeof(line_buf), fp)) { + size_t len = strlen(line_buf); + if (len > 1) { /* skip empty lines */ + line_buf[len - 1] = '\0'; + if (!trace_event_set_state(line_buf, true)) { + fprintf(stderr, + "error: trace event '%s' does not exist\n", line_buf); + exit(1); + } + } + } + if (fclose(fp) != 0) { + fprintf(stderr, "error: closing file '%s': %s\n", + fname, strerror(errno)); + exit(1); + } +} diff --git a/trace/control.h b/trace/control.h index c99b4d50a8..2acaa4290e 100644 --- a/trace/control.h +++ b/trace/control.h @@ -24,10 +24,18 @@ bool trace_event_set_state(const char *name, bool state); /** Initialize the tracing backend. * - * @file Name of trace output file; may be NULL. - * Corresponds to commandline option "-trace file=...". + * @events Name of file with events to be enabled at startup; may be NULL. + * Corresponds to commandline option "-trace events=...". + * @file Name of trace output file; may be NULL. + * Corresponds to commandline option "-trace file=...". * @return Whether the backend could be successfully initialized. */ -bool trace_backend_init(const char *file); +bool trace_backend_init(const char *events, const char *file); + +/** Generic function to initialize the state of events. + * + * @fname Name of file with events to enable; may be NULL. + */ +void trace_backend_init_events(const char *fname); #endif /* TRACE_CONTROL_H */ diff --git a/trace/default.c b/trace/default.c index 3573d5b296..c9b27a289b 100644 --- a/trace/default.c +++ b/trace/default.c @@ -25,8 +25,13 @@ bool trace_event_set_state(const char *name, bool state) return false; } -bool trace_backend_init(const char *file) +bool trace_backend_init(const char *events, const char *file) { + if (events) { + fprintf(stderr, "error: -trace events=...: " + "option not supported by the selected tracing backend\n"); + return false; + } if (file) { fprintf(stderr, "error: -trace file=...: " "option not supported by the selected tracing backend\n"); diff --git a/trace/simple.c b/trace/simple.c index 70689e9484..a6093682dd 100644 --- a/trace/simple.c +++ b/trace/simple.c @@ -331,7 +331,7 @@ bool trace_event_set_state(const char *name, bool state) return false; } -bool trace_backend_init(const char *file) +bool trace_backend_init(const char *events, const char *file) { pthread_t thread; pthread_attr_t attr; @@ -350,6 +350,7 @@ bool trace_backend_init(const char *file) fprintf(stderr, "warning: unable to initialize simple trace backend\n"); } else { atexit(st_flush_trace_buffer); + trace_backend_init_events(events); st_set_trace_file(file); } diff --git a/vl.c b/vl.c index 60322b62a4..c6dc6895b4 100644 --- a/vl.c +++ b/vl.c @@ -2137,6 +2137,7 @@ int main(int argc, char **argv, char **envp) .realloc = realloc_and_trace, .free = free_and_trace, }; + const char *trace_events = NULL; const char *trace_file = NULL; atexit(qemu_run_exit_notifiers); @@ -2934,6 +2935,7 @@ int main(int argc, char **argv, char **envp) if (!opts) { exit(1); } + trace_events = qemu_opt_get(opts, "events"); trace_file = qemu_opt_get(opts, "file"); break; } @@ -2994,7 +2996,7 @@ int main(int argc, char **argv, char **envp) set_cpu_log(log_mask); } - if (!trace_backend_init(trace_file)) { + if (!trace_backend_init(trace_events, trace_file)) { exit(1); }