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