Message ID | 1454514465-11856-11-git-send-email-stefanha@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Wed, Feb 03, 2016 at 03:47:42PM +0000, Stefan Hajnoczi wrote: > From: "Denis V. Lunev" <den@openvz.org> > > log will become common facility with tracepoints support in next step. > > Signed-off-by: Denis V. Lunev <den@openvz.org> > Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> > Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> > Message-id: 1452174932-28657-9-git-send-email-den@openvz.org > Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> > --- > Makefile.objs | 1 - > qemu-log.c | 179 ----------------------------------------------------- > util/Makefile.objs | 1 + > util/log.c | 179 +++++++++++++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 180 insertions(+), 180 deletions(-) > delete mode 100644 qemu-log.c > create mode 100644 util/log.c Note we don't have a MAINTAINERS entry for the log code currently. Need some unlucky volunteer.... ? Regards, Daniel
On 02/03/2016 07:03 PM, Daniel P. Berrange wrote: > On Wed, Feb 03, 2016 at 03:47:42PM +0000, Stefan Hajnoczi wrote: >> From: "Denis V. Lunev" <den@openvz.org> >> >> log will become common facility with tracepoints support in next step. >> >> Signed-off-by: Denis V. Lunev <den@openvz.org> >> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> >> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> >> Message-id: 1452174932-28657-9-git-send-email-den@openvz.org >> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> >> --- >> Makefile.objs | 1 - >> qemu-log.c | 179 ----------------------------------------------------- >> util/Makefile.objs | 1 + >> util/log.c | 179 +++++++++++++++++++++++++++++++++++++++++++++++++++++ >> 4 files changed, 180 insertions(+), 180 deletions(-) >> delete mode 100644 qemu-log.c >> create mode 100644 util/log.c > Note we don't have a MAINTAINERS entry for the log code currently. > Need some unlucky volunteer.... ? > > Regards, > Daniel why unlucky? :) Actually we can manage this as a part of tracing or sign me if there is no other willing person at the moment if this will be good to all other parties. Den
On 02/03/2016 09:03 AM, Daniel P. Berrange wrote: > On Wed, Feb 03, 2016 at 03:47:42PM +0000, Stefan Hajnoczi wrote: >> From: "Denis V. Lunev" <den@openvz.org> >> >> log will become common facility with tracepoints support in next step. >> >> Signed-off-by: Denis V. Lunev <den@openvz.org> >> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> >> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> >> Message-id: 1452174932-28657-9-git-send-email-den@openvz.org >> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> >> --- >> Makefile.objs | 1 - >> qemu-log.c | 179 ----------------------------------------------------- >> util/Makefile.objs | 1 + >> util/log.c | 179 +++++++++++++++++++++++++++++++++++++++++++++++++++++ >> 4 files changed, 180 insertions(+), 180 deletions(-) >> delete mode 100644 qemu-log.c >> create mode 100644 util/log.c > > Note we don't have a MAINTAINERS entry for the log code currently. > Need some unlucky volunteer.... ? A while ago, we mentioned the idea of tweaking checkpatch.pl to prevent the addition of any new files without coverage in MAINTAINERS. Is anyone up to the task of hacking that in? (My perl is too weak, or I might volunteer)
Hi all, A while ago me and Alex [cc'ed] submitted a trivial patch related to logging [1]. Since this patch set here moves the qemu-log.c under util/, our patch will not apply any more. Should we rebase it and resend it against current master? Thanks a lot, dimara [1] https://lists.gnu.org/archive/html/qemu-devel/2015-12/msg02687.html * Stefan Hajnoczi <stefanha@redhat.com> [2016-02-03 15:47:42 +0000]: > From: "Denis V. Lunev" <den@openvz.org> > > log will become common facility with tracepoints support in next step. > > Signed-off-by: Denis V. Lunev <den@openvz.org> > Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> > Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> > Message-id: 1452174932-28657-9-git-send-email-den@openvz.org > Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> > --- > Makefile.objs | 1 - > qemu-log.c | 179 ----------------------------------------------------- > util/Makefile.objs | 1 + > util/log.c | 179 +++++++++++++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 180 insertions(+), 180 deletions(-) > delete mode 100644 qemu-log.c > create mode 100644 util/log.c > > diff --git a/Makefile.objs b/Makefile.objs > index 06b95c7..fbcaa74 100644 > --- a/Makefile.objs > +++ b/Makefile.objs > @@ -89,7 +89,6 @@ endif > > ####################################################################### > # Target-independent parts used in system and user emulation > -common-obj-y += qemu-log.o > common-obj-y += tcg-runtime.o > common-obj-y += hw/ > common-obj-y += qom/ > diff --git a/qemu-log.c b/qemu-log.c > deleted file mode 100644 > index 901b930..0000000 > --- a/qemu-log.c > +++ /dev/null > @@ -1,179 +0,0 @@ > -/* > - * Logging support > - * > - * Copyright (c) 2003 Fabrice Bellard > - * > - * This library is free software; you can redistribute it and/or > - * modify it under the terms of the GNU Lesser General Public > - * License as published by the Free Software Foundation; either > - * version 2 of the License, or (at your option) any later version. > - * > - * This library is distributed in the hope that it will be useful, > - * but WITHOUT ANY WARRANTY; without even the implied warranty of > - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > - * Lesser General Public License for more details. > - * > - * You should have received a copy of the GNU Lesser General Public > - * License along with this library; if not, see <http://www.gnu.org/licenses/>. > - */ > - > -#include "qemu-common.h" > -#include "qemu/log.h" > - > -static char *logfilename; > -FILE *qemu_logfile; > -int qemu_loglevel; > -static int log_append = 0; > - > -void qemu_log(const char *fmt, ...) > -{ > - va_list ap; > - > - va_start(ap, fmt); > - if (qemu_logfile) { > - vfprintf(qemu_logfile, fmt, ap); > - } > - va_end(ap); > -} > - > -void qemu_log_mask(int mask, const char *fmt, ...) > -{ > - va_list ap; > - > - va_start(ap, fmt); > - if ((qemu_loglevel & mask) && qemu_logfile) { > - vfprintf(qemu_logfile, fmt, ap); > - } > - va_end(ap); > -} > - > -/* enable or disable low levels log */ > -void do_qemu_set_log(int log_flags, bool use_own_buffers) > -{ > - qemu_loglevel = log_flags; > - if (qemu_loglevel && !qemu_logfile) { > - if (logfilename) { > - qemu_logfile = fopen(logfilename, log_append ? "a" : "w"); > - if (!qemu_logfile) { > - perror(logfilename); > - _exit(1); > - } > - } else { > - /* Default to stderr if no log file specified */ > - qemu_logfile = stderr; > - } > - /* must avoid mmap() usage of glibc by setting a buffer "by hand" */ > - if (use_own_buffers) { > - static char logfile_buf[4096]; > - > - setvbuf(qemu_logfile, logfile_buf, _IOLBF, sizeof(logfile_buf)); > - } else { > -#if defined(_WIN32) > - /* Win32 doesn't support line-buffering, so use unbuffered output. */ > - setvbuf(qemu_logfile, NULL, _IONBF, 0); > -#else > - setvbuf(qemu_logfile, NULL, _IOLBF, 0); > -#endif > - log_append = 1; > - } > - } > - if (!qemu_loglevel && qemu_logfile) { > - qemu_log_close(); > - } > -} > - > -void qemu_set_log_filename(const char *filename) > -{ > - g_free(logfilename); > - logfilename = g_strdup(filename); > - qemu_log_close(); > - qemu_set_log(qemu_loglevel); > -} > - > -const QEMULogItem qemu_log_items[] = { > - { CPU_LOG_TB_OUT_ASM, "out_asm", > - "show generated host assembly code for each compiled TB" }, > - { CPU_LOG_TB_IN_ASM, "in_asm", > - "show target assembly code for each compiled TB" }, > - { CPU_LOG_TB_OP, "op", > - "show micro ops for each compiled TB" }, > - { CPU_LOG_TB_OP_OPT, "op_opt", > - "show micro ops (x86 only: before eflags optimization) and\n" > - "after liveness analysis" }, > - { CPU_LOG_INT, "int", > - "show interrupts/exceptions in short format" }, > - { CPU_LOG_EXEC, "exec", > - "show trace before each executed TB (lots of logs)" }, > - { CPU_LOG_TB_CPU, "cpu", > - "show CPU state before block translation" }, > - { CPU_LOG_MMU, "mmu", > - "log MMU-related activities" }, > - { CPU_LOG_PCALL, "pcall", > - "x86 only: show protected mode far calls/returns/exceptions" }, > - { CPU_LOG_RESET, "cpu_reset", > - "show CPU state before CPU resets" }, > - { LOG_UNIMP, "unimp", > - "log unimplemented functionality" }, > - { LOG_GUEST_ERROR, "guest_errors", > - "log when the guest OS does something invalid (eg accessing a\n" > - "non-existent register)" }, > - { CPU_LOG_PAGE, "page", > - "dump pages at beginning of user mode emulation" }, > - { CPU_LOG_TB_NOCHAIN, "nochain", > - "do not chain compiled TBs so that \"exec\" and \"cpu\" show\n" > - "complete traces" }, > - { 0, NULL, NULL }, > -}; > - > -static int cmp1(const char *s1, int n, const char *s2) > -{ > - if (strlen(s2) != n) { > - return 0; > - } > - return memcmp(s1, s2, n) == 0; > -} > - > -/* takes a comma separated list of log masks. Return 0 if error. */ > -int qemu_str_to_log_mask(const char *str) > -{ > - const QEMULogItem *item; > - int mask; > - const char *p, *p1; > - > - p = str; > - mask = 0; > - for (;;) { > - p1 = strchr(p, ','); > - if (!p1) { > - p1 = p + strlen(p); > - } > - if (cmp1(p,p1-p,"all")) { > - for (item = qemu_log_items; item->mask != 0; item++) { > - mask |= item->mask; > - } > - } else { > - for (item = qemu_log_items; item->mask != 0; item++) { > - if (cmp1(p, p1 - p, item->name)) { > - goto found; > - } > - } > - return 0; > - } > - found: > - mask |= item->mask; > - if (*p1 != ',') { > - break; > - } > - p = p1 + 1; > - } > - return mask; > -} > - > -void qemu_print_log_usage(FILE *f) > -{ > - const QEMULogItem *item; > - fprintf(f, "Log items (comma separated):\n"); > - for (item = qemu_log_items; item->mask != 0; item++) { > - fprintf(f, "%-10s %s\n", item->name, item->help); > - } > -} > diff --git a/util/Makefile.objs b/util/Makefile.objs > index 8620a80..a8a777e 100644 > --- a/util/Makefile.objs > +++ b/util/Makefile.objs > @@ -31,3 +31,4 @@ util-obj-y += coroutine-$(CONFIG_COROUTINE_BACKEND).o > util-obj-y += buffer.o > util-obj-y += timed-average.o > util-obj-y += base64.o > +util-obj-y += log.o > diff --git a/util/log.c b/util/log.c > new file mode 100644 > index 0000000..901b930 > --- /dev/null > +++ b/util/log.c > @@ -0,0 +1,179 @@ > +/* > + * Logging support > + * > + * Copyright (c) 2003 Fabrice Bellard > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2 of the License, or (at your option) any later version. > + * > + * This library is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library; if not, see <http://www.gnu.org/licenses/>. > + */ > + > +#include "qemu-common.h" > +#include "qemu/log.h" > + > +static char *logfilename; > +FILE *qemu_logfile; > +int qemu_loglevel; > +static int log_append = 0; > + > +void qemu_log(const char *fmt, ...) > +{ > + va_list ap; > + > + va_start(ap, fmt); > + if (qemu_logfile) { > + vfprintf(qemu_logfile, fmt, ap); > + } > + va_end(ap); > +} > + > +void qemu_log_mask(int mask, const char *fmt, ...) > +{ > + va_list ap; > + > + va_start(ap, fmt); > + if ((qemu_loglevel & mask) && qemu_logfile) { > + vfprintf(qemu_logfile, fmt, ap); > + } > + va_end(ap); > +} > + > +/* enable or disable low levels log */ > +void do_qemu_set_log(int log_flags, bool use_own_buffers) > +{ > + qemu_loglevel = log_flags; > + if (qemu_loglevel && !qemu_logfile) { > + if (logfilename) { > + qemu_logfile = fopen(logfilename, log_append ? "a" : "w"); > + if (!qemu_logfile) { > + perror(logfilename); > + _exit(1); > + } > + } else { > + /* Default to stderr if no log file specified */ > + qemu_logfile = stderr; > + } > + /* must avoid mmap() usage of glibc by setting a buffer "by hand" */ > + if (use_own_buffers) { > + static char logfile_buf[4096]; > + > + setvbuf(qemu_logfile, logfile_buf, _IOLBF, sizeof(logfile_buf)); > + } else { > +#if defined(_WIN32) > + /* Win32 doesn't support line-buffering, so use unbuffered output. */ > + setvbuf(qemu_logfile, NULL, _IONBF, 0); > +#else > + setvbuf(qemu_logfile, NULL, _IOLBF, 0); > +#endif > + log_append = 1; > + } > + } > + if (!qemu_loglevel && qemu_logfile) { > + qemu_log_close(); > + } > +} > + > +void qemu_set_log_filename(const char *filename) > +{ > + g_free(logfilename); > + logfilename = g_strdup(filename); > + qemu_log_close(); > + qemu_set_log(qemu_loglevel); > +} > + > +const QEMULogItem qemu_log_items[] = { > + { CPU_LOG_TB_OUT_ASM, "out_asm", > + "show generated host assembly code for each compiled TB" }, > + { CPU_LOG_TB_IN_ASM, "in_asm", > + "show target assembly code for each compiled TB" }, > + { CPU_LOG_TB_OP, "op", > + "show micro ops for each compiled TB" }, > + { CPU_LOG_TB_OP_OPT, "op_opt", > + "show micro ops (x86 only: before eflags optimization) and\n" > + "after liveness analysis" }, > + { CPU_LOG_INT, "int", > + "show interrupts/exceptions in short format" }, > + { CPU_LOG_EXEC, "exec", > + "show trace before each executed TB (lots of logs)" }, > + { CPU_LOG_TB_CPU, "cpu", > + "show CPU state before block translation" }, > + { CPU_LOG_MMU, "mmu", > + "log MMU-related activities" }, > + { CPU_LOG_PCALL, "pcall", > + "x86 only: show protected mode far calls/returns/exceptions" }, > + { CPU_LOG_RESET, "cpu_reset", > + "show CPU state before CPU resets" }, > + { LOG_UNIMP, "unimp", > + "log unimplemented functionality" }, > + { LOG_GUEST_ERROR, "guest_errors", > + "log when the guest OS does something invalid (eg accessing a\n" > + "non-existent register)" }, > + { CPU_LOG_PAGE, "page", > + "dump pages at beginning of user mode emulation" }, > + { CPU_LOG_TB_NOCHAIN, "nochain", > + "do not chain compiled TBs so that \"exec\" and \"cpu\" show\n" > + "complete traces" }, > + { 0, NULL, NULL }, > +}; > + > +static int cmp1(const char *s1, int n, const char *s2) > +{ > + if (strlen(s2) != n) { > + return 0; > + } > + return memcmp(s1, s2, n) == 0; > +} > + > +/* takes a comma separated list of log masks. Return 0 if error. */ > +int qemu_str_to_log_mask(const char *str) > +{ > + const QEMULogItem *item; > + int mask; > + const char *p, *p1; > + > + p = str; > + mask = 0; > + for (;;) { > + p1 = strchr(p, ','); > + if (!p1) { > + p1 = p + strlen(p); > + } > + if (cmp1(p,p1-p,"all")) { > + for (item = qemu_log_items; item->mask != 0; item++) { > + mask |= item->mask; > + } > + } else { > + for (item = qemu_log_items; item->mask != 0; item++) { > + if (cmp1(p, p1 - p, item->name)) { > + goto found; > + } > + } > + return 0; > + } > + found: > + mask |= item->mask; > + if (*p1 != ',') { > + break; > + } > + p = p1 + 1; > + } > + return mask; > +} > + > +void qemu_print_log_usage(FILE *f) > +{ > + const QEMULogItem *item; > + fprintf(f, "Log items (comma separated):\n"); > + for (item = qemu_log_items; item->mask != 0; item++) { > + fprintf(f, "%-10s %s\n", item->name, item->help); > + } > +} > -- > 2.5.0 >
On 03/02/2016 18:38, Dimitris Aragiorgis wrote: > Hi all, > > A while ago me and Alex [cc'ed] submitted a trivial patch related > to logging [1]. Since this patch set here moves the qemu-log.c > under util/, our patch will not apply any more. Should we rebase it > and resend it against current master? git can handle it, it will apply. I'll look at the patch tomorrow, it's a good idea (though -daemonize isn't a good idea :)). Paolo
diff --git a/Makefile.objs b/Makefile.objs index 06b95c7..fbcaa74 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -89,7 +89,6 @@ endif ####################################################################### # Target-independent parts used in system and user emulation -common-obj-y += qemu-log.o common-obj-y += tcg-runtime.o common-obj-y += hw/ common-obj-y += qom/ diff --git a/qemu-log.c b/qemu-log.c deleted file mode 100644 index 901b930..0000000 --- a/qemu-log.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Logging support - * - * Copyright (c) 2003 Fabrice Bellard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see <http://www.gnu.org/licenses/>. - */ - -#include "qemu-common.h" -#include "qemu/log.h" - -static char *logfilename; -FILE *qemu_logfile; -int qemu_loglevel; -static int log_append = 0; - -void qemu_log(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - if (qemu_logfile) { - vfprintf(qemu_logfile, fmt, ap); - } - va_end(ap); -} - -void qemu_log_mask(int mask, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - if ((qemu_loglevel & mask) && qemu_logfile) { - vfprintf(qemu_logfile, fmt, ap); - } - va_end(ap); -} - -/* enable or disable low levels log */ -void do_qemu_set_log(int log_flags, bool use_own_buffers) -{ - qemu_loglevel = log_flags; - if (qemu_loglevel && !qemu_logfile) { - if (logfilename) { - qemu_logfile = fopen(logfilename, log_append ? "a" : "w"); - if (!qemu_logfile) { - perror(logfilename); - _exit(1); - } - } else { - /* Default to stderr if no log file specified */ - qemu_logfile = stderr; - } - /* must avoid mmap() usage of glibc by setting a buffer "by hand" */ - if (use_own_buffers) { - static char logfile_buf[4096]; - - setvbuf(qemu_logfile, logfile_buf, _IOLBF, sizeof(logfile_buf)); - } else { -#if defined(_WIN32) - /* Win32 doesn't support line-buffering, so use unbuffered output. */ - setvbuf(qemu_logfile, NULL, _IONBF, 0); -#else - setvbuf(qemu_logfile, NULL, _IOLBF, 0); -#endif - log_append = 1; - } - } - if (!qemu_loglevel && qemu_logfile) { - qemu_log_close(); - } -} - -void qemu_set_log_filename(const char *filename) -{ - g_free(logfilename); - logfilename = g_strdup(filename); - qemu_log_close(); - qemu_set_log(qemu_loglevel); -} - -const QEMULogItem qemu_log_items[] = { - { CPU_LOG_TB_OUT_ASM, "out_asm", - "show generated host assembly code for each compiled TB" }, - { CPU_LOG_TB_IN_ASM, "in_asm", - "show target assembly code for each compiled TB" }, - { CPU_LOG_TB_OP, "op", - "show micro ops for each compiled TB" }, - { CPU_LOG_TB_OP_OPT, "op_opt", - "show micro ops (x86 only: before eflags optimization) and\n" - "after liveness analysis" }, - { CPU_LOG_INT, "int", - "show interrupts/exceptions in short format" }, - { CPU_LOG_EXEC, "exec", - "show trace before each executed TB (lots of logs)" }, - { CPU_LOG_TB_CPU, "cpu", - "show CPU state before block translation" }, - { CPU_LOG_MMU, "mmu", - "log MMU-related activities" }, - { CPU_LOG_PCALL, "pcall", - "x86 only: show protected mode far calls/returns/exceptions" }, - { CPU_LOG_RESET, "cpu_reset", - "show CPU state before CPU resets" }, - { LOG_UNIMP, "unimp", - "log unimplemented functionality" }, - { LOG_GUEST_ERROR, "guest_errors", - "log when the guest OS does something invalid (eg accessing a\n" - "non-existent register)" }, - { CPU_LOG_PAGE, "page", - "dump pages at beginning of user mode emulation" }, - { CPU_LOG_TB_NOCHAIN, "nochain", - "do not chain compiled TBs so that \"exec\" and \"cpu\" show\n" - "complete traces" }, - { 0, NULL, NULL }, -}; - -static int cmp1(const char *s1, int n, const char *s2) -{ - if (strlen(s2) != n) { - return 0; - } - return memcmp(s1, s2, n) == 0; -} - -/* takes a comma separated list of log masks. Return 0 if error. */ -int qemu_str_to_log_mask(const char *str) -{ - const QEMULogItem *item; - int mask; - const char *p, *p1; - - p = str; - mask = 0; - for (;;) { - p1 = strchr(p, ','); - if (!p1) { - p1 = p + strlen(p); - } - if (cmp1(p,p1-p,"all")) { - for (item = qemu_log_items; item->mask != 0; item++) { - mask |= item->mask; - } - } else { - for (item = qemu_log_items; item->mask != 0; item++) { - if (cmp1(p, p1 - p, item->name)) { - goto found; - } - } - return 0; - } - found: - mask |= item->mask; - if (*p1 != ',') { - break; - } - p = p1 + 1; - } - return mask; -} - -void qemu_print_log_usage(FILE *f) -{ - const QEMULogItem *item; - fprintf(f, "Log items (comma separated):\n"); - for (item = qemu_log_items; item->mask != 0; item++) { - fprintf(f, "%-10s %s\n", item->name, item->help); - } -} diff --git a/util/Makefile.objs b/util/Makefile.objs index 8620a80..a8a777e 100644 --- a/util/Makefile.objs +++ b/util/Makefile.objs @@ -31,3 +31,4 @@ util-obj-y += coroutine-$(CONFIG_COROUTINE_BACKEND).o util-obj-y += buffer.o util-obj-y += timed-average.o util-obj-y += base64.o +util-obj-y += log.o diff --git a/util/log.c b/util/log.c new file mode 100644 index 0000000..901b930 --- /dev/null +++ b/util/log.c @@ -0,0 +1,179 @@ +/* + * Logging support + * + * Copyright (c) 2003 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "qemu-common.h" +#include "qemu/log.h" + +static char *logfilename; +FILE *qemu_logfile; +int qemu_loglevel; +static int log_append = 0; + +void qemu_log(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + if (qemu_logfile) { + vfprintf(qemu_logfile, fmt, ap); + } + va_end(ap); +} + +void qemu_log_mask(int mask, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + if ((qemu_loglevel & mask) && qemu_logfile) { + vfprintf(qemu_logfile, fmt, ap); + } + va_end(ap); +} + +/* enable or disable low levels log */ +void do_qemu_set_log(int log_flags, bool use_own_buffers) +{ + qemu_loglevel = log_flags; + if (qemu_loglevel && !qemu_logfile) { + if (logfilename) { + qemu_logfile = fopen(logfilename, log_append ? "a" : "w"); + if (!qemu_logfile) { + perror(logfilename); + _exit(1); + } + } else { + /* Default to stderr if no log file specified */ + qemu_logfile = stderr; + } + /* must avoid mmap() usage of glibc by setting a buffer "by hand" */ + if (use_own_buffers) { + static char logfile_buf[4096]; + + setvbuf(qemu_logfile, logfile_buf, _IOLBF, sizeof(logfile_buf)); + } else { +#if defined(_WIN32) + /* Win32 doesn't support line-buffering, so use unbuffered output. */ + setvbuf(qemu_logfile, NULL, _IONBF, 0); +#else + setvbuf(qemu_logfile, NULL, _IOLBF, 0); +#endif + log_append = 1; + } + } + if (!qemu_loglevel && qemu_logfile) { + qemu_log_close(); + } +} + +void qemu_set_log_filename(const char *filename) +{ + g_free(logfilename); + logfilename = g_strdup(filename); + qemu_log_close(); + qemu_set_log(qemu_loglevel); +} + +const QEMULogItem qemu_log_items[] = { + { CPU_LOG_TB_OUT_ASM, "out_asm", + "show generated host assembly code for each compiled TB" }, + { CPU_LOG_TB_IN_ASM, "in_asm", + "show target assembly code for each compiled TB" }, + { CPU_LOG_TB_OP, "op", + "show micro ops for each compiled TB" }, + { CPU_LOG_TB_OP_OPT, "op_opt", + "show micro ops (x86 only: before eflags optimization) and\n" + "after liveness analysis" }, + { CPU_LOG_INT, "int", + "show interrupts/exceptions in short format" }, + { CPU_LOG_EXEC, "exec", + "show trace before each executed TB (lots of logs)" }, + { CPU_LOG_TB_CPU, "cpu", + "show CPU state before block translation" }, + { CPU_LOG_MMU, "mmu", + "log MMU-related activities" }, + { CPU_LOG_PCALL, "pcall", + "x86 only: show protected mode far calls/returns/exceptions" }, + { CPU_LOG_RESET, "cpu_reset", + "show CPU state before CPU resets" }, + { LOG_UNIMP, "unimp", + "log unimplemented functionality" }, + { LOG_GUEST_ERROR, "guest_errors", + "log when the guest OS does something invalid (eg accessing a\n" + "non-existent register)" }, + { CPU_LOG_PAGE, "page", + "dump pages at beginning of user mode emulation" }, + { CPU_LOG_TB_NOCHAIN, "nochain", + "do not chain compiled TBs so that \"exec\" and \"cpu\" show\n" + "complete traces" }, + { 0, NULL, NULL }, +}; + +static int cmp1(const char *s1, int n, const char *s2) +{ + if (strlen(s2) != n) { + return 0; + } + return memcmp(s1, s2, n) == 0; +} + +/* takes a comma separated list of log masks. Return 0 if error. */ +int qemu_str_to_log_mask(const char *str) +{ + const QEMULogItem *item; + int mask; + const char *p, *p1; + + p = str; + mask = 0; + for (;;) { + p1 = strchr(p, ','); + if (!p1) { + p1 = p + strlen(p); + } + if (cmp1(p,p1-p,"all")) { + for (item = qemu_log_items; item->mask != 0; item++) { + mask |= item->mask; + } + } else { + for (item = qemu_log_items; item->mask != 0; item++) { + if (cmp1(p, p1 - p, item->name)) { + goto found; + } + } + return 0; + } + found: + mask |= item->mask; + if (*p1 != ',') { + break; + } + p = p1 + 1; + } + return mask; +} + +void qemu_print_log_usage(FILE *f) +{ + const QEMULogItem *item; + fprintf(f, "Log items (comma separated):\n"); + for (item = qemu_log_items; item->mask != 0; item++) { + fprintf(f, "%-10s %s\n", item->name, item->help); + } +}