qemu-log.c 4.4 KB

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