qemu-log.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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. #include "qemu-common.h"
  20. #include "qemu/log.h"
  21. static char *logfilename;
  22. FILE *qemu_logfile;
  23. int qemu_loglevel;
  24. static int log_append = 0;
  25. void qemu_log(const char *fmt, ...)
  26. {
  27. va_list ap;
  28. va_start(ap, fmt);
  29. if (qemu_logfile) {
  30. vfprintf(qemu_logfile, fmt, ap);
  31. }
  32. va_end(ap);
  33. }
  34. void qemu_log_mask(int mask, const char *fmt, ...)
  35. {
  36. va_list ap;
  37. va_start(ap, fmt);
  38. if ((qemu_loglevel & mask) && qemu_logfile) {
  39. vfprintf(qemu_logfile, fmt, ap);
  40. }
  41. va_end(ap);
  42. }
  43. /* enable or disable low levels log */
  44. void do_qemu_set_log(int log_flags, bool use_own_buffers)
  45. {
  46. qemu_loglevel = log_flags;
  47. if (qemu_loglevel && !qemu_logfile) {
  48. if (logfilename) {
  49. qemu_logfile = fopen(logfilename, log_append ? "a" : "w");
  50. if (!qemu_logfile) {
  51. perror(logfilename);
  52. _exit(1);
  53. }
  54. } else {
  55. /* Default to stderr if no log file specified */
  56. qemu_logfile = stderr;
  57. }
  58. /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
  59. if (use_own_buffers) {
  60. static char logfile_buf[4096];
  61. setvbuf(qemu_logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
  62. } else {
  63. #if defined(_WIN32)
  64. /* Win32 doesn't support line-buffering, so use unbuffered output. */
  65. setvbuf(qemu_logfile, NULL, _IONBF, 0);
  66. #else
  67. setvbuf(qemu_logfile, NULL, _IOLBF, 0);
  68. #endif
  69. log_append = 1;
  70. }
  71. }
  72. if (!qemu_loglevel && qemu_logfile) {
  73. qemu_log_close();
  74. }
  75. }
  76. void qemu_set_log_filename(const char *filename)
  77. {
  78. g_free(logfilename);
  79. logfilename = g_strdup(filename);
  80. qemu_log_close();
  81. qemu_set_log(qemu_loglevel);
  82. }
  83. const QEMULogItem qemu_log_items[] = {
  84. { CPU_LOG_TB_OUT_ASM, "out_asm",
  85. "show generated host assembly code for each compiled TB" },
  86. { CPU_LOG_TB_IN_ASM, "in_asm",
  87. "show target assembly code for each compiled TB" },
  88. { CPU_LOG_TB_OP, "op",
  89. "show micro ops for each compiled TB" },
  90. { CPU_LOG_TB_OP_OPT, "op_opt",
  91. "show micro ops (x86 only: before eflags optimization) and\n"
  92. "after liveness analysis" },
  93. { CPU_LOG_INT, "int",
  94. "show interrupts/exceptions in short format" },
  95. { CPU_LOG_EXEC, "exec",
  96. "show trace before each executed TB (lots of logs)" },
  97. { CPU_LOG_TB_CPU, "cpu",
  98. "show CPU state before block translation" },
  99. { CPU_LOG_MMU, "mmu",
  100. "log MMU-related activities" },
  101. { CPU_LOG_PCALL, "pcall",
  102. "x86 only: show protected mode far calls/returns/exceptions" },
  103. { CPU_LOG_RESET, "cpu_reset",
  104. "show CPU state before CPU resets" },
  105. { CPU_LOG_IOPORT, "ioport",
  106. "show all i/o ports accesses" },
  107. { LOG_UNIMP, "unimp",
  108. "log unimplemented functionality" },
  109. { LOG_GUEST_ERROR, "guest_errors",
  110. "log when the guest OS does something invalid (eg accessing a\n"
  111. "non-existent register)" },
  112. { 0, NULL, NULL },
  113. };
  114. static int cmp1(const char *s1, int n, const char *s2)
  115. {
  116. if (strlen(s2) != n) {
  117. return 0;
  118. }
  119. return memcmp(s1, s2, n) == 0;
  120. }
  121. /* takes a comma separated list of log masks. Return 0 if error. */
  122. int qemu_str_to_log_mask(const char *str)
  123. {
  124. const QEMULogItem *item;
  125. int mask;
  126. const char *p, *p1;
  127. p = str;
  128. mask = 0;
  129. for (;;) {
  130. p1 = strchr(p, ',');
  131. if (!p1) {
  132. p1 = p + strlen(p);
  133. }
  134. if (cmp1(p,p1-p,"all")) {
  135. for (item = qemu_log_items; item->mask != 0; item++) {
  136. mask |= item->mask;
  137. }
  138. } else {
  139. for (item = qemu_log_items; item->mask != 0; item++) {
  140. if (cmp1(p, p1 - p, item->name)) {
  141. goto found;
  142. }
  143. }
  144. return 0;
  145. }
  146. found:
  147. mask |= item->mask;
  148. if (*p1 != ',') {
  149. break;
  150. }
  151. p = p1 + 1;
  152. }
  153. return mask;
  154. }
  155. void qemu_print_log_usage(FILE *f)
  156. {
  157. const QEMULogItem *item;
  158. fprintf(f, "Log items (comma separated):\n");
  159. for (item = qemu_log_items; item->mask != 0; item++) {
  160. fprintf(f, "%-10s %s\n", item->name, item->help);
  161. }
  162. }