#include "qemu/osdep.h"
#include "trace/control.h"
#include "qemu/help_option.h"
+#include "qemu/option.h"
#ifdef CONFIG_TRACE_SIMPLE
#include "trace/simple.h"
#endif
#include "qemu/error-report.h"
#include "qemu/config-file.h"
#include "monitor/monitor.h"
-#include "trace-root.h"
+#include "trace/trace-root.h"
int trace_events_enabled_count;
static size_t nevent_groups;
static uint32_t next_id;
static uint32_t next_vcpu_id;
+static bool init_trace_on_startup;
QemuOptsList qemu_trace_opts = {
.name = "trace",
if (likely(next_vcpu_id < CPU_TRACE_DSTATE_MAX_EVENTS)) {
events[i]->vcpu_id = next_vcpu_id++;
} else {
- error_report("WARNING: too many vcpu trace events; dropping '%s'",
- events[i]->name);
+ warn_report("too many vcpu trace events; dropping '%s'",
+ events[i]->name);
}
}
event_groups = g_renew(TraceEventGroup, event_groups, nevent_groups + 1);
return NULL;
}
-static bool pattern_glob(const char *pat, const char *ev)
-{
- while (*pat != '\0' && *ev != '\0') {
- if (*pat == *ev) {
- pat++;
- ev++;
- }
- else if (*pat == '*') {
- if (pattern_glob(pat, ev+1)) {
- return true;
- } else if (pattern_glob(pat+1, ev)) {
- return true;
- } else {
- return false;
- }
- } else {
- return false;
- }
- }
-
- while (*pat == '*') {
- pat++;
- }
-
- if (*pat == '\0' && *ev == '\0') {
- return true;
- } else {
- return false;
- }
-}
-
-
void trace_event_iter_init(TraceEventIter *iter, const char *pattern)
{
iter->event = 0;
iter->group++;
}
if (!iter->pattern ||
- pattern_glob(iter->pattern,
- trace_event_get_name(ev))) {
+ g_pattern_match_simple(iter->pattern, trace_event_get_name(ev))) {
return ev;
}
}
return NULL;
}
-void trace_list_events(void)
+void trace_list_events(FILE *f)
{
TraceEventIter iter;
TraceEvent *ev;
trace_event_iter_init(&iter, NULL);
while ((ev = trace_event_iter_next(&iter)) != NULL) {
- fprintf(stderr, "%s\n", trace_event_get_name(ev));
+ fprintf(f, "%s\n", trace_event_get_name(ev));
}
+#ifdef CONFIG_TRACE_DTRACE
+ fprintf(f, "This list of names of trace points may be incomplete "
+ "when using the DTrace/SystemTap backends.\n"
+ "Run 'qemu-trace-stap list %s' to print the full list.\n",
+ error_get_progname());
+#endif
}
static void do_trace_enable_events(const char *line_buf)
void trace_enable_events(const char *line_buf)
{
if (is_help_option(line_buf)) {
- trace_list_events();
- if (cur_mon == NULL) {
+ trace_list_events(stdout);
+ if (monitor_cur() == NULL) {
exit(0);
}
} else {
loc_pop(&loc);
}
-void trace_init_file(const char *file)
+void trace_init_file(void)
{
+ QemuOpts *opts = qemu_find_opts_singleton("trace");
+ const char *file = qemu_opt_get(opts, "file");
#ifdef CONFIG_TRACE_SIMPLE
st_set_trace_file(file);
+ if (init_trace_on_startup) {
+ st_set_trace_file_enabled(true);
+ }
#elif defined CONFIG_TRACE_LOG
- /* If both the simple and the log backends are enabled, "-trace file"
- * only applies to the simple backend; use "-D" for the log backend.
+ /*
+ * If both the simple and the log backends are enabled, "--trace file"
+ * only applies to the simple backend; use "-D" for the log
+ * backend. However we should only override -D if we actually have
+ * something to override it with.
*/
if (file) {
qemu_set_log_filename(file, &error_fatal);
}
#else
if (file) {
- fprintf(stderr, "error: -trace file=...: "
+ fprintf(stderr, "error: --trace file=...: "
"option not supported by the selected tracing backends\n");
exit(1);
}
return true;
}
-char *trace_opt_parse(const char *optarg)
+void trace_opt_parse(const char *optarg)
{
- char *trace_file;
QemuOpts *opts = qemu_opts_parse_noisily(qemu_find_opts("trace"),
optarg, true);
if (!opts) {
trace_enable_events(qemu_opt_get(opts, "enable"));
}
trace_init_events(qemu_opt_get(opts, "events"));
- trace_file = g_strdup(qemu_opt_get(opts, "file"));
+ init_trace_on_startup = true;
qemu_opts_del(opts);
-
- return trace_file;
}
uint32_t trace_get_vcpu_event_count(void)