target-ppc: ppce500_spin.c uses SPR_PIR, should use SPR_BOOKE_PIR
[qemu.git] / trace / control.c
blobe1556a35704ee81d6dc0437777cbed7c782fb8c2
1 /*
2 * Interface for configuring and controlling the state of tracing events.
4 * Copyright (C) 2011-2014 LluĂ­s Vilanova <vilanova@ac.upc.edu>
6 * This work is licensed under the terms of the GNU GPL, version 2 or later.
7 * See the COPYING file in the top-level directory.
8 */
10 #include "qemu/osdep.h"
11 #include "trace/control.h"
12 #include "qemu/help_option.h"
13 #ifdef CONFIG_TRACE_SIMPLE
14 #include "trace/simple.h"
15 #endif
16 #ifdef CONFIG_TRACE_FTRACE
17 #include "trace/ftrace.h"
18 #endif
19 #ifdef CONFIG_TRACE_LOG
20 #include "qemu/log.h"
21 #endif
22 #include "qapi/error.h"
23 #include "qemu/error-report.h"
24 #include "monitor/monitor.h"
26 int trace_events_enabled_count;
27 bool trace_events_dstate[TRACE_EVENT_COUNT];
29 TraceEvent *trace_event_name(const char *name)
31 assert(name != NULL);
33 TraceEventID i;
34 for (i = 0; i < trace_event_count(); i++) {
35 TraceEvent *ev = trace_event_id(i);
36 if (strcmp(trace_event_get_name(ev), name) == 0) {
37 return ev;
40 return NULL;
43 static bool pattern_glob(const char *pat, const char *ev)
45 while (*pat != '\0' && *ev != '\0') {
46 if (*pat == *ev) {
47 pat++;
48 ev++;
50 else if (*pat == '*') {
51 if (pattern_glob(pat, ev+1)) {
52 return true;
53 } else if (pattern_glob(pat+1, ev)) {
54 return true;
55 } else {
56 return false;
58 } else {
59 return false;
63 while (*pat == '*') {
64 pat++;
67 if (*pat == '\0' && *ev == '\0') {
68 return true;
69 } else {
70 return false;
74 TraceEvent *trace_event_pattern(const char *pat, TraceEvent *ev)
76 assert(pat != NULL);
78 TraceEventID i;
80 if (ev == NULL) {
81 i = -1;
82 } else {
83 i = trace_event_get_id(ev);
85 i++;
87 while (i < trace_event_count()) {
88 TraceEvent *res = trace_event_id(i);
89 if (pattern_glob(pat, trace_event_get_name(res))) {
90 return res;
92 i++;
95 return NULL;
98 void trace_list_events(void)
100 int i;
101 for (i = 0; i < trace_event_count(); i++) {
102 TraceEvent *res = trace_event_id(i);
103 fprintf(stderr, "%s\n", trace_event_get_name(res));
107 static void do_trace_enable_events(const char *line_buf)
109 const bool enable = ('-' != line_buf[0]);
110 const char *line_ptr = enable ? line_buf : line_buf + 1;
112 if (trace_event_is_pattern(line_ptr)) {
113 TraceEvent *ev = NULL;
114 while ((ev = trace_event_pattern(line_ptr, ev)) != NULL) {
115 if (trace_event_get_state_static(ev)) {
116 trace_event_set_state_dynamic(ev, enable);
119 } else {
120 TraceEvent *ev = trace_event_name(line_ptr);
121 if (ev == NULL) {
122 error_report("WARNING: trace event '%s' does not exist",
123 line_ptr);
124 } else if (!trace_event_get_state_static(ev)) {
125 error_report("WARNING: trace event '%s' is not traceable",
126 line_ptr);
127 } else {
128 trace_event_set_state_dynamic(ev, enable);
133 void trace_enable_events(const char *line_buf)
135 if (is_help_option(line_buf)) {
136 trace_list_events();
137 if (cur_mon == NULL) {
138 exit(0);
140 } else {
141 do_trace_enable_events(line_buf);
145 void trace_init_events(const char *fname)
147 Location loc;
148 FILE *fp;
149 char line_buf[1024];
150 size_t line_idx = 0;
152 if (fname == NULL) {
153 return;
156 loc_push_none(&loc);
157 loc_set_file(fname, 0);
158 fp = fopen(fname, "r");
159 if (!fp) {
160 error_report("%s", strerror(errno));
161 exit(1);
163 while (fgets(line_buf, sizeof(line_buf), fp)) {
164 loc_set_file(fname, ++line_idx);
165 size_t len = strlen(line_buf);
166 if (len > 1) { /* skip empty lines */
167 line_buf[len - 1] = '\0';
168 if ('#' == line_buf[0]) { /* skip commented lines */
169 continue;
171 trace_enable_events(line_buf);
174 if (fclose(fp) != 0) {
175 loc_set_file(fname, 0);
176 error_report("%s", strerror(errno));
177 exit(1);
179 loc_pop(&loc);
182 void trace_init_file(const char *file)
184 #ifdef CONFIG_TRACE_SIMPLE
185 st_set_trace_file(file);
186 #elif defined CONFIG_TRACE_LOG
187 /* If both the simple and the log backends are enabled, "-trace file"
188 * only applies to the simple backend; use "-D" for the log backend.
190 if (file) {
191 qemu_set_log_filename(file, &error_fatal);
193 #else
194 if (file) {
195 fprintf(stderr, "error: -trace file=...: "
196 "option not supported by the selected tracing backends\n");
197 exit(1);
199 #endif
202 bool trace_init_backends(void)
204 #ifdef CONFIG_TRACE_SIMPLE
205 if (!st_init()) {
206 fprintf(stderr, "failed to initialize simple tracing backend.\n");
207 return false;
209 #endif
211 #ifdef CONFIG_TRACE_FTRACE
212 if (!ftrace_init()) {
213 fprintf(stderr, "failed to initialize ftrace backend.\n");
214 return false;
216 #endif
218 return true;