qemu-log.c 4.7 KB

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