]> git.proxmox.com Git - mirror_qemu.git/blob - trace/control.c
smbios: Move table build tools into an include file.
[mirror_qemu.git] / trace / control.c
1 /*
2 * Interface for configuring and controlling the state of tracing events.
3 *
4 * Copyright (C) 2011-2014 LluĂ­s Vilanova <vilanova@ac.upc.edu>
5 *
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 */
9
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"
25
26 int trace_events_enabled_count;
27 bool trace_events_dstate[TRACE_EVENT_COUNT];
28
29 TraceEvent *trace_event_name(const char *name)
30 {
31 assert(name != NULL);
32
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;
38 }
39 }
40 return NULL;
41 }
42
43 static bool pattern_glob(const char *pat, const char *ev)
44 {
45 while (*pat != '\0' && *ev != '\0') {
46 if (*pat == *ev) {
47 pat++;
48 ev++;
49 }
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;
57 }
58 } else {
59 return false;
60 }
61 }
62
63 while (*pat == '*') {
64 pat++;
65 }
66
67 if (*pat == '\0' && *ev == '\0') {
68 return true;
69 } else {
70 return false;
71 }
72 }
73
74 TraceEvent *trace_event_pattern(const char *pat, TraceEvent *ev)
75 {
76 assert(pat != NULL);
77
78 TraceEventID i;
79
80 if (ev == NULL) {
81 i = -1;
82 } else {
83 i = trace_event_get_id(ev);
84 }
85 i++;
86
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;
91 }
92 i++;
93 }
94
95 return NULL;
96 }
97
98 void trace_list_events(void)
99 {
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));
104 }
105 }
106
107 static void do_trace_enable_events(const char *line_buf)
108 {
109 const bool enable = ('-' != line_buf[0]);
110 const char *line_ptr = enable ? line_buf : line_buf + 1;
111
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);
117 }
118 }
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);
129 }
130 }
131 }
132
133 void trace_enable_events(const char *line_buf)
134 {
135 if (is_help_option(line_buf)) {
136 trace_list_events();
137 if (cur_mon == NULL) {
138 exit(0);
139 }
140 } else {
141 do_trace_enable_events(line_buf);
142 }
143 }
144
145 void trace_init_events(const char *fname)
146 {
147 Location loc;
148 FILE *fp;
149 char line_buf[1024];
150 size_t line_idx = 0;
151
152 if (fname == NULL) {
153 return;
154 }
155
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);
162 }
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;
170 }
171 trace_enable_events(line_buf);
172 }
173 }
174 if (fclose(fp) != 0) {
175 loc_set_file(fname, 0);
176 error_report("%s", strerror(errno));
177 exit(1);
178 }
179 loc_pop(&loc);
180 }
181
182 void trace_init_file(const char *file)
183 {
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.
189 */
190 if (file) {
191 qemu_set_log_filename(file, &error_fatal);
192 }
193 #else
194 if (file) {
195 fprintf(stderr, "error: -trace file=...: "
196 "option not supported by the selected tracing backends\n");
197 exit(1);
198 }
199 #endif
200 }
201
202 bool trace_init_backends(void)
203 {
204 #ifdef CONFIG_TRACE_SIMPLE
205 if (!st_init()) {
206 fprintf(stderr, "failed to initialize simple tracing backend.\n");
207 return false;
208 }
209 #endif
210
211 #ifdef CONFIG_TRACE_FTRACE
212 if (!ftrace_init()) {
213 fprintf(stderr, "failed to initialize ftrace backend.\n");
214 return false;
215 }
216 #endif
217
218 return true;
219 }