control.c 4.2 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;
}

P
Paolo Bonzini 已提交
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
void trace_enable_events(const char *line_buf)
{
    const bool enable = ('-' != line_buf[0]);
    const 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);
            }
        }
    } else {
        TraceEvent *ev = trace_event_name(line_ptr);
        if (ev == NULL) {
            error_report("WARNING: trace event '%s' does not exist",
                         line_ptr);
        } else if (!trace_event_get_state_static(ev)) {
            error_report("WARNING: trace event '%s' is not traceable",
                         line_ptr);
        } else {
            trace_event_set_state_dynamic(ev, enable);
        }
    }
}

117
void trace_init_events(const char *fname)
118
{
119 120 121 122 123
    Location loc;
    FILE *fp;
    char line_buf[1024];
    size_t line_idx = 0;

124 125 126 127
    if (fname == NULL) {
        return;
    }

128 129 130
    loc_push_none(&loc);
    loc_set_file(fname, 0);
    fp = fopen(fname, "r");
131
    if (!fp) {
132
        error_report("%s", strerror(errno));
133 134 135
        exit(1);
    }
    while (fgets(line_buf, sizeof(line_buf), fp)) {
136
        loc_set_file(fname, ++line_idx);
137 138 139
        size_t len = strlen(line_buf);
        if (len > 1) {              /* skip empty lines */
            line_buf[len - 1] = '\0';
140 141 142
            if ('#' == line_buf[0]) { /* skip commented lines */
                continue;
            }
P
Paolo Bonzini 已提交
143
            trace_enable_events(line_buf);
144 145 146
        }
    }
    if (fclose(fp) != 0) {
147 148
        loc_set_file(fname, 0);
        error_report("%s", strerror(errno));
149 150
        exit(1);
    }
151
    loc_pop(&loc);
152
}
L
Lluís Vilanova 已提交
153

154
void trace_init_file(const char *file)
L
Lluís Vilanova 已提交
155 156
{
#ifdef CONFIG_TRACE_SIMPLE
157
    st_set_trace_file(file);
L
Lluís Vilanova 已提交
158 159 160 161
#else
    if (file) {
        fprintf(stderr, "error: -trace file=...: "
                "option not supported by the selected tracing backends\n");
162 163 164 165 166 167 168 169 170 171
        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 已提交
172 173 174 175 176 177 178 179 180 181 182 183 184
        return false;
    }
#endif

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

    return true;
}