xref: /openbmc/qemu/trace/control.c (revision 14a650ec)
1 /*
2  * Interface for configuring and controlling the state of tracing events.
3  *
4  * Copyright (C) 2011-2012 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 "trace/control.h"
11 
12 
13 TraceEvent *trace_event_name(const char *name)
14 {
15     assert(name != NULL);
16 
17     TraceEventID i;
18     for (i = 0; i < trace_event_count(); i++) {
19         TraceEvent *ev = trace_event_id(i);
20         if (strcmp(trace_event_get_name(ev), name) == 0) {
21             return ev;
22         }
23     }
24     return NULL;
25 }
26 
27 static bool pattern_glob(const char *pat, const char *ev)
28 {
29     while (*pat != '\0' && *ev != '\0') {
30         if (*pat == *ev) {
31             pat++;
32             ev++;
33         }
34         else if (*pat == '*') {
35             if (pattern_glob(pat, ev+1)) {
36                 return true;
37             } else if (pattern_glob(pat+1, ev)) {
38                 return true;
39             } else {
40                 return false;
41             }
42         } else {
43             return false;
44         }
45     }
46 
47     while (*pat == '*') {
48         pat++;
49     }
50 
51     if (*pat == '\0' && *ev == '\0') {
52         return true;
53     } else {
54         return false;
55     }
56 }
57 
58 TraceEvent *trace_event_pattern(const char *pat, TraceEvent *ev)
59 {
60     assert(pat != NULL);
61 
62     TraceEventID i;
63 
64     if (ev == NULL) {
65         i = -1;
66     } else {
67         i = trace_event_get_id(ev);
68     }
69     i++;
70 
71     while (i < trace_event_count()) {
72         TraceEvent *res = trace_event_id(i);
73         if (pattern_glob(pat, trace_event_get_name(res))) {
74             return res;
75         }
76         i++;
77     }
78 
79     return NULL;
80 }
81 
82 void trace_backend_init_events(const char *fname)
83 {
84     if (fname == NULL) {
85         return;
86     }
87 
88     FILE *fp = fopen(fname, "r");
89     if (!fp) {
90         fprintf(stderr, "error: could not open trace events file '%s': %s\n",
91                 fname, strerror(errno));
92         exit(1);
93     }
94     char line_buf[1024];
95     while (fgets(line_buf, sizeof(line_buf), fp)) {
96         size_t len = strlen(line_buf);
97         if (len > 1) {              /* skip empty lines */
98             line_buf[len - 1] = '\0';
99             if ('#' == line_buf[0]) { /* skip commented lines */
100                 continue;
101             }
102             const bool enable = ('-' != line_buf[0]);
103             char *line_ptr = enable ? line_buf : line_buf + 1;
104             if (trace_event_is_pattern(line_ptr)) {
105                 TraceEvent *ev = NULL;
106                 while ((ev = trace_event_pattern(line_ptr, ev)) != NULL) {
107                     if (trace_event_get_state_static(ev)) {
108                         trace_event_set_state_dynamic(ev, enable);
109                     }
110                 }
111             } else {
112                 TraceEvent *ev = trace_event_name(line_ptr);
113                 if (ev == NULL) {
114                     fprintf(stderr,
115                             "error: trace event '%s' does not exist\n", line_ptr);
116                     exit(1);
117                 }
118                 if (!trace_event_get_state_static(ev)) {
119                     fprintf(stderr,
120                             "error: trace event '%s' is not traceable\n", line_ptr);
121                     exit(1);
122                 }
123                 trace_event_set_state_dynamic(ev, enable);
124             }
125         }
126     }
127     if (fclose(fp) != 0) {
128         fprintf(stderr, "error: closing file '%s': %s\n",
129                 fname, strerror(errno));
130         exit(1);
131     }
132 }
133