qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH] log disasm insns when nochain + in_asm enabled


From: Sergey Smolov
Subject: [Qemu-devel] [PATCH] log disasm insns when nochain + in_asm enabled
Date: Tue, 3 Nov 2015 16:13:43 +0400

When 'nochain' and 'in_asm' debug options are enabled,
disassembled forms of all executed translation blocks (TB)
 are printed to log. For this task a mapping between
disassembled instructions and executed TBs is created
and used.

Signed-off-by: Sergey Smolov <address@hidden>
---
 cpu-exec.c            |   20 ++++++++++++++++++++
 disas.c               |   18 +++++++++++++++++-
 include/disas/disas.h |   14 ++++++++++++++
 qemu-log.c            |    2 +-
 4 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/cpu-exec.c b/cpu-exec.c
index 7eef083..b9385f9 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -345,6 +345,9 @@ int cpu_exec(CPUState *cpu)
     uintptr_t next_tb;
     SyncClocks sc;
 
+    hwaddr pc_prev;
+    bool pc_prev_valid = false;
+
     if (cpu->halted) {
 #if defined(TARGET_I386) && !defined(CONFIG_USER_ONLY)
         if (cpu->interrupt_request & CPU_INTERRUPT_POLL) {
@@ -474,6 +477,23 @@ int cpu_exec(CPUState *cpu)
                     qemu_log("Trace %p [" TARGET_FMT_lx "] %s\n",
                              tb->tc_ptr, tb->pc, lookup_symbol(tb->pc));
                 }
+                if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
+                    && qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) {
+                    struct insninfo *s;
+                    for (s = insninfos; s != NULL; s = s->next) {
+                        if (s->insn_addr == tb->pc
+                                && pc_prev_valid
+                                && s->insn_addr != pc_prev) {
+                            qemu_log("%s\n", s->insn);
+                            pc_prev = s->insn_addr;
+                            if (!pc_prev_valid) {
+                                pc_prev_valid = true;
+                            }
+                        } else if (s->insn_addr == pc_prev) {
+                            pc_prev_valid = false;
+                        }
+                    }
+                }
                 /* see if we can patch the calling TB. When the TB
                    spans two pages, we cannot safely do a direct
                    jump. */
diff --git a/disas.c b/disas.c
index 4e11944..51bf68f 100644
--- a/disas.c
+++ b/disas.c
@@ -16,6 +16,9 @@ typedef struct CPUDebug {
 /* Filled in by elfload.c.  Simplistic, but will do for now. */
 struct syminfo *syminfos = NULL;
 
+/* Filled in here. */
+struct insninfo *insninfos;
+
 /* Get LENGTH bytes from info's buffer, at target address memaddr.
    Transfer them to myaddr.  */
 int
@@ -236,7 +239,20 @@ void target_disas(FILE *out, CPUState *cpu, target_ulong 
code,
     }
 
     for (pc = code; size > 0; pc += count, size -= count) {
-       fprintf(out, "0x" TARGET_FMT_lx ":  ", pc);
+
+        if (qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)
+            && qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
+            struct insninfo *s =
+                (struct insninfo *)malloc(
+                        sizeof(struct insninfo));
+            s->insn_addr = pc;
+
+            sprintf(s->insn, " " TARGET_FMT_lx " ", pc);
+            s->next = insninfos;
+            insninfos = s;
+        } else {
+            fprintf(out, "0x" TARGET_FMT_lx ":  ", pc);
+        }
        count = s.info.print_insn(pc, &s.info);
 #if 0
         {
diff --git a/include/disas/disas.h b/include/disas/disas.h
index 2b9293b..75a4c73 100644
--- a/include/disas/disas.h
+++ b/include/disas/disas.h
@@ -2,6 +2,7 @@
 #define _QEMU_DISAS_H
 
 #include "qemu-common.h"
+#include "exec/hwaddr.h"
 
 #ifdef NEED_CPU_H
 /* Disassemble this for me please... (debugging). */
@@ -40,4 +41,17 @@ struct syminfo {
 /* Filled in by elfload.c.  Simplistic, but will do for now. */
 extern struct syminfo *syminfos;
 
+struct insninfo {
+
+    /* Instruction address. */
+    hwaddr insn_addr;
+
+    /* Instruction string representation. */
+    char insn[256];
+    struct insninfo *next;
+};
+
+/* Filled in by disas.c - Information about instructions. */
+extern struct insninfo *insninfos;
+
 #endif /* _QEMU_DISAS_H */
diff --git a/qemu-log.c b/qemu-log.c
index efd07c8..bbc10e3 100644
--- a/qemu-log.c
+++ b/qemu-log.c
@@ -120,7 +120,7 @@ const QEMULogItem qemu_log_items[] = {
       "log when the guest OS does something invalid (eg accessing a\n"
       "non-existent register)" },
     { CPU_LOG_TB_NOCHAIN, "nochain",
-      "do not chain compiled TBs so that \"exec\" and \"cpu\" show\n"
+      "do not chain compiled TBs so that \"exec\", \"in_asm\" and \"cpu\" 
show\n"
       "complete traces" },
     { 0, NULL, NULL },
 };
-- 
1.7.10.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]