summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--Makefile.objs2
-rw-r--r--docs/tracing.txt4
-rw-r--r--qemu-config.c3
-rw-r--r--qemu-options.hx26
-rw-r--r--trace/control.c42
-rw-r--r--trace/control.h14
-rw-r--r--trace/default.c7
-rw-r--r--trace/simple.c3
-rw-r--r--vl.c4
9 files changed, 92 insertions, 13 deletions
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=<file>" command line argument can be used to enable the
+events listed in <file> 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>][,file=<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 <vilanova@ac.upc.edu>
+ *
+ * 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);
     }