Statistics
| Branch: | Revision:

root / qemu-log.c @ 1de7afc9

History | View | Annotate | Download (4.6 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 qemu_set_log(int log_flags, bool use_own_buffers)
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
        /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
65
        if (use_own_buffers) {
66
            static char logfile_buf[4096];
67

    
68
            setvbuf(qemu_logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
69
        } else {
70
#if 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
    }
79
    if (!qemu_loglevel && qemu_logfile) {
80
        fclose(qemu_logfile);
81
        qemu_logfile = NULL;
82
    }
83
}
84

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

    
95
const CPULogItem cpu_log_items[] = {
96
    { CPU_LOG_TB_OUT_ASM, "out_asm",
97
      "show generated host assembly code for each compiled TB" },
98
    { CPU_LOG_TB_IN_ASM, "in_asm",
99
      "show target assembly code for each compiled TB" },
100
    { CPU_LOG_TB_OP, "op",
101
      "show micro ops for each compiled TB" },
102
    { CPU_LOG_TB_OP_OPT, "op_opt",
103
      "show micro ops (x86 only: before eflags optimization) and\n"
104
      "after liveness analysis" },
105
    { CPU_LOG_INT, "int",
106
      "show interrupts/exceptions in short format" },
107
    { CPU_LOG_EXEC, "exec",
108
      "show trace before each executed TB (lots of logs)" },
109
    { CPU_LOG_TB_CPU, "cpu",
110
      "show CPU state before block translation" },
111
    { CPU_LOG_PCALL, "pcall",
112
      "x86 only: show protected mode far calls/returns/exceptions" },
113
    { CPU_LOG_RESET, "cpu_reset",
114
      "x86 only: show CPU state before CPU resets" },
115
    { CPU_LOG_IOPORT, "ioport",
116
      "show all i/o ports accesses" },
117
    { LOG_UNIMP, "unimp",
118
      "log unimplemented functionality" },
119
    { LOG_GUEST_ERROR, "guest_errors",
120
      "log when the guest OS does something invalid (eg accessing a\n"
121
      "non-existent register)" },
122
    { 0, NULL, NULL },
123
};
124

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

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

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