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