Statistics
| Branch: | Revision:

root / qemu-log.c @ eeacee4d

History | View | Annotate | Download (4.4 kB)

1
/*
2
 * Logging support
3
 *
4
 *  Copyright (c) 2003 Fabrice Bellard
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18
 */
19

    
20
#include "qemu-common.h"
21
#include "qemu-log.h"
22

    
23
#ifdef WIN32
24
static const char *logfilename = "qemu.log";
25
#else
26
static const char *logfilename = "/tmp/qemu.log";
27
#endif
28
FILE *qemu_logfile;
29
int qemu_loglevel;
30
static int log_append = 0;
31

    
32
void qemu_log(const char *fmt, ...)
33
{
34
    va_list ap;
35

    
36
    va_start(ap, fmt);
37
    if (qemu_logfile) {
38
        vfprintf(qemu_logfile, fmt, ap);
39
    }
40
    va_end(ap);
41
}
42

    
43
void qemu_log_mask(int mask, const char *fmt, ...)
44
{
45
    va_list ap;
46

    
47
    va_start(ap, fmt);
48
    if ((qemu_loglevel & mask) && qemu_logfile) {
49
        vfprintf(qemu_logfile, fmt, ap);
50
    }
51
    va_end(ap);
52
}
53

    
54
/* enable or disable low levels log */
55
void cpu_set_log(int log_flags)
56
{
57
    qemu_loglevel = log_flags;
58
    if (qemu_loglevel && !qemu_logfile) {
59
        qemu_logfile = fopen(logfilename, log_append ? "a" : "w");
60
        if (!qemu_logfile) {
61
            perror(logfilename);
62
            _exit(1);
63
        }
64
#if !defined(CONFIG_SOFTMMU)
65
        /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
66
        {
67
            static char logfile_buf[4096];
68
            setvbuf(qemu_logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
69
        }
70
#elif defined(_WIN32)
71
        /* Win32 doesn't support line-buffering, so use unbuffered output. */
72
        setvbuf(qemu_logfile, NULL, _IONBF, 0);
73
#else
74
        setvbuf(qemu_logfile, NULL, _IOLBF, 0);
75
#endif
76
        log_append = 1;
77
    }
78
    if (!qemu_loglevel && qemu_logfile) {
79
        fclose(qemu_logfile);
80
        qemu_logfile = NULL;
81
    }
82
}
83

    
84
void cpu_set_log_filename(const char *filename)
85
{
86
    logfilename = strdup(filename);
87
    if (qemu_logfile) {
88
        fclose(qemu_logfile);
89
        qemu_logfile = NULL;
90
    }
91
    cpu_set_log(qemu_loglevel);
92
}
93

    
94
const CPULogItem cpu_log_items[] = {
95
    { CPU_LOG_TB_OUT_ASM, "out_asm",
96
      "show generated host assembly code for each compiled TB" },
97
    { CPU_LOG_TB_IN_ASM, "in_asm",
98
      "show target assembly code for each compiled TB" },
99
    { CPU_LOG_TB_OP, "op",
100
      "show micro ops for each compiled TB" },
101
    { CPU_LOG_TB_OP_OPT, "op_opt",
102
      "show micro ops "
103
#ifdef TARGET_I386
104
      "before eflags optimization and "
105
#endif
106
      "after liveness analysis" },
107
    { CPU_LOG_INT, "int",
108
      "show interrupts/exceptions in short format" },
109
    { CPU_LOG_EXEC, "exec",
110
      "show trace before each executed TB (lots of logs)" },
111
    { CPU_LOG_TB_CPU, "cpu",
112
      "show CPU state before block translation" },
113
#ifdef TARGET_I386
114
    { CPU_LOG_PCALL, "pcall",
115
      "show protected mode far calls/returns/exceptions" },
116
    { CPU_LOG_RESET, "cpu_reset",
117
      "show CPU state before CPU resets" },
118
#endif
119
#ifdef DEBUG_IOPORT
120
    { CPU_LOG_IOPORT, "ioport",
121
      "show all i/o ports accesses" },
122
#endif
123
    { 0, NULL, NULL },
124
};
125

    
126
static int cmp1(const char *s1, int n, const char *s2)
127
{
128
    if (strlen(s2) != n) {
129
        return 0;
130
    }
131
    return memcmp(s1, s2, n) == 0;
132
}
133

    
134
/* takes a comma separated list of log masks. Return 0 if error. */
135
int cpu_str_to_log_mask(const char *str)
136
{
137
    const CPULogItem *item;
138
    int mask;
139
    const char *p, *p1;
140

    
141
    p = str;
142
    mask = 0;
143
    for (;;) {
144
        p1 = strchr(p, ',');
145
        if (!p1) {
146
            p1 = p + strlen(p);
147
        }
148
        if (cmp1(p,p1-p,"all")) {
149
            for (item = cpu_log_items; item->mask != 0; item++) {
150
                mask |= item->mask;
151
            }
152
        } else {
153
            for (item = cpu_log_items; item->mask != 0; item++) {
154
                if (cmp1(p, p1 - p, item->name)) {
155
                    goto found;
156
                }
157
            }
158
            return 0;
159
        }
160
    found:
161
        mask |= item->mask;
162
        if (*p1 != ',') {
163
            break;
164
        }
165
        p = p1 + 1;
166
    }
167
    return mask;
168
}