control.c 4.3 KB
Newer Older
1 2 3
/*
 * Interface for configuring and controlling the state of tracing events.
 *
L
Lluís Vilanova 已提交
4
 * Copyright (C) 2011-2014 Lluís Vilanova <vilanova@ac.upc.edu>
5
 *
6 7
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 * See the COPYING file in the top-level directory.
8 9 10
 */

#include "trace/control.h"
L
Lluís Vilanova 已提交
11 12 13 14 15 16
#ifdef CONFIG_TRACE_SIMPLE
#include "trace/simple.h"
#endif
#ifdef CONFIG_TRACE_FTRACE
#include "trace/ftrace.h"
#endif
17
#include "qemu/error-report.h"
18

19
int trace_events_enabled_count;
20
bool trace_events_dstate[TRACE_EVENT_COUNT];
21

22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
TraceEvent *trace_event_name(const char *name)
{
    assert(name != NULL);

    TraceEventID i;
    for (i = 0; i < trace_event_count(); i++) {
        TraceEvent *ev = trace_event_id(i);
        if (strcmp(trace_event_get_name(ev), name) == 0) {
            return ev;
        }
    }
    return NULL;
}

static bool pattern_glob(const char *pat, const char *ev)
{
    while (*pat != '\0' && *ev != '\0') {
        if (*pat == *ev) {
            pat++;
            ev++;
        }
        else if (*pat == '*') {
            if (pattern_glob(pat, ev+1)) {
                return true;
            } else if (pattern_glob(pat+1, ev)) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    while (*pat == '*') {
        pat++;
    }

    if (*pat == '\0' && *ev == '\0') {
        return true;
    } else {
        return false;
    }
}

TraceEvent *trace_event_pattern(const char *pat, TraceEvent *ev)
68
{
69
    assert(pat != NULL);
70

71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
    TraceEventID i;

    if (ev == NULL) {
        i = -1;
    } else {
        i = trace_event_get_id(ev);
    }
    i++;

    while (i < trace_event_count()) {
        TraceEvent *res = trace_event_id(i);
        if (pattern_glob(pat, trace_event_get_name(res))) {
            return res;
        }
        i++;
    }

    return NULL;
}

91
void trace_init_events(const char *fname)
92
{
93 94 95 96 97
    Location loc;
    FILE *fp;
    char line_buf[1024];
    size_t line_idx = 0;

98 99 100 101
    if (fname == NULL) {
        return;
    }

102 103 104
    loc_push_none(&loc);
    loc_set_file(fname, 0);
    fp = fopen(fname, "r");
105
    if (!fp) {
106
        error_report("%s", strerror(errno));
107 108 109
        exit(1);
    }
    while (fgets(line_buf, sizeof(line_buf), fp)) {
110
        loc_set_file(fname, ++line_idx);
111 112 113
        size_t len = strlen(line_buf);
        if (len > 1) {              /* skip empty lines */
            line_buf[len - 1] = '\0';
114 115 116
            if ('#' == line_buf[0]) { /* skip commented lines */
                continue;
            }
117 118 119 120 121 122 123 124 125
            const bool enable = ('-' != line_buf[0]);
            char *line_ptr = enable ? line_buf : line_buf + 1;
            if (trace_event_is_pattern(line_ptr)) {
                TraceEvent *ev = NULL;
                while ((ev = trace_event_pattern(line_ptr, ev)) != NULL) {
                    if (trace_event_get_state_static(ev)) {
                        trace_event_set_state_dynamic(ev, enable);
                    }
                }
126
            } else {
127 128
                TraceEvent *ev = trace_event_name(line_ptr);
                if (ev == NULL) {
129 130
                    error_report("WARNING: trace event '%s' does not exist",
                                 line_ptr);
131
                } else if (!trace_event_get_state_static(ev)) {
132
                    error_report("WARNING: trace event '%s' is not traceable",
133
                                 line_ptr);
134 135
                } else {
                    trace_event_set_state_dynamic(ev, enable);
136
                }
137 138 139 140
            }
        }
    }
    if (fclose(fp) != 0) {
141 142
        loc_set_file(fname, 0);
        error_report("%s", strerror(errno));
143 144
        exit(1);
    }
145
    loc_pop(&loc);
146
}
L
Lluís Vilanova 已提交
147

148
void trace_init_file(const char *file)
L
Lluís Vilanova 已提交
149 150
{
#ifdef CONFIG_TRACE_SIMPLE
151
    st_set_trace_file(file);
L
Lluís Vilanova 已提交
152 153 154 155
#else
    if (file) {
        fprintf(stderr, "error: -trace file=...: "
                "option not supported by the selected tracing backends\n");
156 157 158 159 160 161 162 163 164 165
        exit(1);
    }
#endif
}

bool trace_init_backends(void)
{
#ifdef CONFIG_TRACE_SIMPLE
    if (!st_init()) {
        fprintf(stderr, "failed to initialize simple tracing backend.\n");
L
Lluís Vilanova 已提交
166 167 168 169 170 171 172 173 174 175 176 177 178
        return false;
    }
#endif

#ifdef CONFIG_TRACE_FTRACE
    if (!ftrace_init()) {
        fprintf(stderr, "failed to initialize ftrace backend.\n");
        return false;
    }
#endif

    return true;
}