]>
Commit | Line | Data |
---|---|---|
23d15e86 LV |
1 | /* |
2 | * Interface for configuring and controlling the state of tracing events. | |
3 | * | |
5b808275 | 4 | * Copyright (C) 2011-2014 Lluís Vilanova <vilanova@ac.upc.edu> |
23d15e86 | 5 | * |
b1bae816 LV |
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. | |
23d15e86 LV |
8 | */ |
9 | ||
10 | #include "trace/control.h" | |
5b808275 LV |
11 | #ifdef CONFIG_TRACE_SIMPLE |
12 | #include "trace/simple.h" | |
13 | #endif | |
14 | #ifdef CONFIG_TRACE_FTRACE | |
15 | #include "trace/ftrace.h" | |
16 | #endif | |
a35d9be6 | 17 | #include "qemu/error-report.h" |
23d15e86 | 18 | |
43b48cfc | 19 | int trace_events_enabled_count; |
585ec727 | 20 | bool trace_events_dstate[TRACE_EVENT_COUNT]; |
43b48cfc | 21 | |
b1bae816 LV |
22 | TraceEvent *trace_event_name(const char *name) |
23 | { | |
24 | assert(name != NULL); | |
25 | ||
26 | TraceEventID i; | |
27 | for (i = 0; i < trace_event_count(); i++) { | |
28 | TraceEvent *ev = trace_event_id(i); | |
29 | if (strcmp(trace_event_get_name(ev), name) == 0) { | |
30 | return ev; | |
31 | } | |
32 | } | |
33 | return NULL; | |
34 | } | |
35 | ||
36 | static bool pattern_glob(const char *pat, const char *ev) | |
37 | { | |
38 | while (*pat != '\0' && *ev != '\0') { | |
39 | if (*pat == *ev) { | |
40 | pat++; | |
41 | ev++; | |
42 | } | |
43 | else if (*pat == '*') { | |
44 | if (pattern_glob(pat, ev+1)) { | |
45 | return true; | |
46 | } else if (pattern_glob(pat+1, ev)) { | |
47 | return true; | |
48 | } else { | |
49 | return false; | |
50 | } | |
51 | } else { | |
52 | return false; | |
53 | } | |
54 | } | |
55 | ||
56 | while (*pat == '*') { | |
57 | pat++; | |
58 | } | |
59 | ||
60 | if (*pat == '\0' && *ev == '\0') { | |
61 | return true; | |
62 | } else { | |
63 | return false; | |
64 | } | |
65 | } | |
66 | ||
67 | TraceEvent *trace_event_pattern(const char *pat, TraceEvent *ev) | |
23d15e86 | 68 | { |
b1bae816 | 69 | assert(pat != NULL); |
ddde8acc | 70 | |
b1bae816 LV |
71 | TraceEventID i; |
72 | ||
73 | if (ev == NULL) { | |
74 | i = -1; | |
75 | } else { | |
76 | i = trace_event_get_id(ev); | |
77 | } | |
78 | i++; | |
79 | ||
80 | while (i < trace_event_count()) { | |
81 | TraceEvent *res = trace_event_id(i); | |
82 | if (pattern_glob(pat, trace_event_get_name(res))) { | |
83 | return res; | |
84 | } | |
85 | i++; | |
86 | } | |
87 | ||
88 | return NULL; | |
89 | } | |
90 | ||
45bd0b41 | 91 | void trace_init_events(const char *fname) |
b1bae816 | 92 | { |
a35d9be6 AK |
93 | Location loc; |
94 | FILE *fp; | |
95 | char line_buf[1024]; | |
96 | size_t line_idx = 0; | |
97 | ||
23d15e86 LV |
98 | if (fname == NULL) { |
99 | return; | |
100 | } | |
101 | ||
a35d9be6 AK |
102 | loc_push_none(&loc); |
103 | loc_set_file(fname, 0); | |
104 | fp = fopen(fname, "r"); | |
23d15e86 | 105 | if (!fp) { |
a35d9be6 | 106 | error_report("%s", strerror(errno)); |
23d15e86 LV |
107 | exit(1); |
108 | } | |
23d15e86 | 109 | while (fgets(line_buf, sizeof(line_buf), fp)) { |
a35d9be6 | 110 | loc_set_file(fname, ++line_idx); |
23d15e86 LV |
111 | size_t len = strlen(line_buf); |
112 | if (len > 1) { /* skip empty lines */ | |
113 | line_buf[len - 1] = '\0'; | |
794b1f96 AK |
114 | if ('#' == line_buf[0]) { /* skip commented lines */ |
115 | continue; | |
116 | } | |
b1bae816 LV |
117 | const bool enable = ('-' != line_buf[0]); |
118 | char *line_ptr = enable ? line_buf : line_buf + 1; | |
119 | if (trace_event_is_pattern(line_ptr)) { | |
120 | TraceEvent *ev = NULL; | |
121 | while ((ev = trace_event_pattern(line_ptr, ev)) != NULL) { | |
122 | if (trace_event_get_state_static(ev)) { | |
123 | trace_event_set_state_dynamic(ev, enable); | |
124 | } | |
125 | } | |
ddde8acc | 126 | } else { |
b1bae816 LV |
127 | TraceEvent *ev = trace_event_name(line_ptr); |
128 | if (ev == NULL) { | |
a35d9be6 AK |
129 | error_report("WARNING: trace event '%s' does not exist", |
130 | line_ptr); | |
82432638 | 131 | } else if (!trace_event_get_state_static(ev)) { |
81b07353 | 132 | error_report("WARNING: trace event '%s' is not traceable", |
a35d9be6 | 133 | line_ptr); |
82432638 AK |
134 | } else { |
135 | trace_event_set_state_dynamic(ev, enable); | |
b1bae816 | 136 | } |
23d15e86 LV |
137 | } |
138 | } | |
139 | } | |
140 | if (fclose(fp) != 0) { | |
a35d9be6 AK |
141 | loc_set_file(fname, 0); |
142 | error_report("%s", strerror(errno)); | |
23d15e86 LV |
143 | exit(1); |
144 | } | |
a35d9be6 | 145 | loc_pop(&loc); |
23d15e86 | 146 | } |
5b808275 | 147 | |
41fc57e4 | 148 | void trace_init_file(const char *file) |
5b808275 LV |
149 | { |
150 | #ifdef CONFIG_TRACE_SIMPLE | |
41fc57e4 | 151 | st_set_trace_file(file); |
5b808275 LV |
152 | #else |
153 | if (file) { | |
154 | fprintf(stderr, "error: -trace file=...: " | |
155 | "option not supported by the selected tracing backends\n"); | |
41fc57e4 PB |
156 | exit(1); |
157 | } | |
158 | #endif | |
159 | } | |
160 | ||
161 | bool trace_init_backends(void) | |
162 | { | |
163 | #ifdef CONFIG_TRACE_SIMPLE | |
164 | if (!st_init()) { | |
165 | fprintf(stderr, "failed to initialize simple tracing backend.\n"); | |
5b808275 LV |
166 | return false; |
167 | } | |
168 | #endif | |
169 | ||
170 | #ifdef CONFIG_TRACE_FTRACE | |
171 | if (!ftrace_init()) { | |
172 | fprintf(stderr, "failed to initialize ftrace backend.\n"); | |
173 | return false; | |
174 | } | |
175 | #endif | |
176 | ||
5b808275 LV |
177 | return true; |
178 | } |