Patchwork [v3,24/39] windbg: [de]serialization cpu context

login
register
mail settings
Submitter Mihail Abakumov
Date Dec. 6, 2018, noon
Message ID <154409765298.5432.10926034197214598884.stgit@Misha-PC.lan02.inno>
Download mbox | patch
Permalink /patch/673977/
State New
Headers show

Comments

Mihail Abakumov - Dec. 6, 2018, noon
Signed-off-by: Mikhail Abakumov <mikhail.abakumov@ispras.ru>
Signed-off-by: Pavel Dovgalyuk <dovgaluk@ispras.ru>
---
 target/i386/windbgstub.c |  374 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 372 insertions(+), 2 deletions(-)

Patch

diff --git a/target/i386/windbgstub.c b/target/i386/windbgstub.c
index e2ed2b3105..7a091e1dee 100644
--- a/target/i386/windbgstub.c
+++ b/target/i386/windbgstub.c
@@ -280,7 +280,6 @@  static InitedAddr kdDebuggerDataBlock;
 static InitedAddr kdVersion;
 #endif /* TARGET_I386 */
 
-__attribute__ ((unused)) /* unused yet */
 static void windbg_set_dr(CPUState *cs, int index, target_ulong value)
 {
     X86CPU *cpu = X86_CPU(cs);
@@ -300,7 +299,6 @@  static void windbg_set_dr(CPUState *cs, int index, target_ulong value)
 }
 
 /* copy from gdbstub.c */
-__attribute__ ((unused)) /* unused yet */
 static void windbg_set_sr(CPUState *cs, int sreg, uint16_t selector)
 {
     X86CPU *cpu = X86_CPU(cs);
@@ -403,6 +401,378 @@  static void windbg_set_sr(CPUState *cs, int sreg, uint16_t selector)
     CASE_FIELD(stct, field, field_size, block)
 #endif /* TARGET_I386 */
 
+#define GEN_WINDBG_CONTEXT_RW(fun_name, is_read)                               \
+static int fun_name(CPUState *cs, uint8_t *buf, int buf_size,                  \
+                    int offset, int len)                                       \
+{                                                                              \
+    X86CPU *cpu = X86_CPU(cs);                                                 \
+    CPUX86State *env = &cpu->env;                                              \
+    uint32_t ctx_flags = CPU_CONTEXT_ALL;                                      \
+    uint32_t tmp32, i;                                                         \
+    uint32_t f_size = 0;                                                       \
+                                                                               \
+    if (len < 0 || len > buf_size) {                                           \
+        WINDBG_ERROR("" #fun_name ": incorrect length %d", len);               \
+        return 1;                                                              \
+    }                                                                          \
+                                                                               \
+    if (offset < 0 || offset + len > sizeof(CPU_CONTEXT)) {                    \
+        WINDBG_ERROR("" #fun_name ": incorrect offset %d", offset);            \
+        return 2;                                                              \
+    }                                                                          \
+                                                                               \
+    len = MIN(len, sizeof(CPU_CONTEXT) - offset);                              \
+                                                                               \
+    while (offset < len) {                                                     \
+        switch (offset) {                                                      \
+        CASE_FIELD(CPU_CONTEXT, ContextFlags, f_size, {                        \
+            rwl_p(buf, ctx_flags, is_read);                                    \
+        });                                                                    \
+        /* DEBUG REGISTERS */                                                  \
+        CASE_FIELD(CPU_CONTEXT, Dr0, f_size, {                                 \
+            if (ctx_flags & CPU_CONTEXT_DEBUG_REGISTERS) {                     \
+                RW_DR(buf, cs, 0, is_read);                                    \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD(CPU_CONTEXT, Dr1, f_size, {                                 \
+            if (ctx_flags & CPU_CONTEXT_DEBUG_REGISTERS) {                     \
+                RW_DR(buf, cs, 1, is_read);                                    \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD(CPU_CONTEXT, Dr2, f_size, {                                 \
+            if (ctx_flags & CPU_CONTEXT_DEBUG_REGISTERS) {                     \
+                RW_DR(buf, cs, 2, is_read);                                    \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD(CPU_CONTEXT, Dr3, f_size, {                                 \
+            if (ctx_flags & CPU_CONTEXT_DEBUG_REGISTERS) {                     \
+                RW_DR(buf, cs, 3, is_read);                                    \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD(CPU_CONTEXT, Dr6, f_size, {                                 \
+            if (ctx_flags & CPU_CONTEXT_DEBUG_REGISTERS) {                     \
+                RW_DR(buf, cs, 6, is_read);                                    \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD(CPU_CONTEXT, Dr7, f_size, {                                 \
+            if (ctx_flags & CPU_CONTEXT_DEBUG_REGISTERS) {                     \
+                RW_DR(buf, cs, 7, is_read);                                    \
+            }                                                                  \
+        });                                                                    \
+        /* SEGMENT REGISTERS */                                                \
+        CASE_FIELD(CPU_CONTEXT, SegCs, f_size, {                               \
+            if (ctx_flags & CPU_CONTEXT_SEGMENTS) {                            \
+                RW_SR(buf, cs, R_CS, is_read);                                 \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD(CPU_CONTEXT, SegDs, f_size, {                               \
+            if (ctx_flags & CPU_CONTEXT_SEGMENTS) {                            \
+                RW_SR(buf, cs, R_DS, is_read);                                 \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD(CPU_CONTEXT, SegEs, f_size, {                               \
+            if (ctx_flags & CPU_CONTEXT_SEGMENTS) {                            \
+                RW_SR(buf, cs, R_ES, is_read);                                 \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD(CPU_CONTEXT, SegFs, f_size, {                               \
+            if (ctx_flags & CPU_CONTEXT_SEGMENTS) {                            \
+                RW_SR(buf, cs, R_FS, is_read);                                 \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD(CPU_CONTEXT, SegGs, f_size, {                               \
+            if (ctx_flags & CPU_CONTEXT_SEGMENTS) {                            \
+                RW_SR(buf, cs, R_GS, is_read);                                 \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD(CPU_CONTEXT, SegSs, f_size, {                               \
+            if (ctx_flags & CPU_CONTEXT_SEGMENTS) {                            \
+                RW_SR(buf, cs, R_SS, is_read);                                 \
+            }                                                                  \
+        });                                                                    \
+        /* INTEGER REGISTERS */                                                \
+        CASE_FIELD_X32_64(CPU_CONTEXT, Eax, Rax, f_size, {                     \
+            if (ctx_flags & CPU_CONTEXT_INTEGER) {                             \
+                rwtul_p(buf, env->regs[R_EAX], is_read);                       \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD_X32_64(CPU_CONTEXT, Ecx, Rcx, f_size, {                     \
+            if (ctx_flags & CPU_CONTEXT_INTEGER) {                             \
+                rwtul_p(buf, env->regs[R_ECX], is_read);                       \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD_X32_64(CPU_CONTEXT, Edx, Rdx, f_size, {                     \
+            if (ctx_flags & CPU_CONTEXT_INTEGER) {                             \
+                rwtul_p(buf, env->regs[R_EDX], is_read);                       \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD_X32_64(CPU_CONTEXT, Ebx, Rbx, f_size, {                     \
+            if (ctx_flags & CPU_CONTEXT_INTEGER) {                             \
+                rwtul_p(buf, env->regs[R_EBX], is_read);                       \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD_X32_64(CPU_CONTEXT, Esi, Rsi, f_size, {                     \
+            if (ctx_flags & CPU_CONTEXT_INTEGER) {                             \
+                rwtul_p(buf, env->regs[R_ESI], is_read);                       \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD_X32_64(CPU_CONTEXT, Edi, Rdi, f_size, {                     \
+            if (ctx_flags & CPU_CONTEXT_INTEGER) {                             \
+                rwtul_p(buf, env->regs[R_EDI], is_read);                       \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD_X64(CPU_CONTEXT, R8, f_size, {                              \
+            if (ctx_flags & CPU_CONTEXT_INTEGER) {                             \
+                rwtul_p(buf, env->regs[8], is_read);                           \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD_X64(CPU_CONTEXT, R9, f_size, {                              \
+            if (ctx_flags & CPU_CONTEXT_INTEGER) {                             \
+                rwtul_p(buf, env->regs[9], is_read);                           \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD_X64(CPU_CONTEXT, R10, f_size, {                             \
+            if (ctx_flags & CPU_CONTEXT_INTEGER) {                             \
+                rwtul_p(buf, env->regs[10], is_read);                          \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD_X64(CPU_CONTEXT, R11, f_size, {                             \
+            if (ctx_flags & CPU_CONTEXT_INTEGER) {                             \
+                rwtul_p(buf, env->regs[11], is_read);                          \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD_X64(CPU_CONTEXT, R12, f_size, {                             \
+            if (ctx_flags & CPU_CONTEXT_INTEGER) {                             \
+                rwtul_p(buf, env->regs[12], is_read);                          \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD_X64(CPU_CONTEXT, R13, f_size, {                             \
+            if (ctx_flags & CPU_CONTEXT_INTEGER) {                             \
+                rwtul_p(buf, env->regs[13], is_read);                          \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD_X64(CPU_CONTEXT, R14, f_size, {                             \
+            if (ctx_flags & CPU_CONTEXT_INTEGER) {                             \
+                rwtul_p(buf, env->regs[14], is_read);                          \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD_X64(CPU_CONTEXT, R15, f_size, {                             \
+            if (ctx_flags & CPU_CONTEXT_INTEGER) {                             \
+                rwtul_p(buf, env->regs[15], is_read);                          \
+            }                                                                  \
+        });                                                                    \
+        /* CONTROL REGISTERS */                                                \
+        CASE_FIELD_X32_64(CPU_CONTEXT, Esp, Rsp, f_size, {                     \
+            if (ctx_flags & CPU_CONTEXT_CONTROL) {                             \
+                rwtul_p(buf, env->regs[R_ESP], is_read);                       \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD_X32_64(CPU_CONTEXT, Ebp, Rbp, f_size, {                     \
+            if (ctx_flags & CPU_CONTEXT_CONTROL) {                             \
+                rwtul_p(buf, env->regs[R_EBP], is_read);                       \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD_X32_64(CPU_CONTEXT, Eip, Rip, f_size, {                     \
+            if (ctx_flags & CPU_CONTEXT_CONTROL) {                             \
+                rwtul_p(buf, env->eip, is_read);                               \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD(CPU_CONTEXT, EFlags, f_size, {                              \
+            if (ctx_flags & CPU_CONTEXT_CONTROL) {                             \
+                rwl_p(buf, env->eflags, is_read);                              \
+            }                                                                  \
+        });                                                                    \
+        /* FLOAT REGISTERS */                                                  \
+        CASE_FIELD(CPU_CONTEXT, FloatSave.ControlWord, f_size, {               \
+            if (ctx_flags & CPU_CONTEXT_FLOATING_POINT) {                      \
+                if (is_read) {                                                 \
+                    cpu_set_fpuc(env, TARGET_SAFE(ldl_p, lduw_p)(buf));        \
+                } else {                                                       \
+                    TARGET_SAFE(stl_p, stw_p)(buf, env->fpuc);                 \
+                }                                                              \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD(CPU_CONTEXT, FloatSave.StatusWord, f_size, {                \
+            if (ctx_flags & CPU_CONTEXT_FLOATING_POINT) {                      \
+                if (is_read) {                                                 \
+                    tmp32 = TARGET_SAFE(ldl_p, lduw_p)(buf);                   \
+                    env->fpstt = (tmp32 >> 11) & 7;                            \
+                    env->fpus = tmp32 & ~0x3800;                               \
+                } else {                                                       \
+                    tmp32 = env->fpus & ~(7 << 11);                            \
+                    tmp32 |= (env->fpstt & 7) << 11;                           \
+                    TARGET_SAFE(stl_p, stw_p)(buf, tmp32);                     \
+                }                                                              \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD(CPU_CONTEXT, FloatSave.TagWord, f_size, {                   \
+            if (ctx_flags & CPU_CONTEXT_FLOATING_POINT) {                      \
+                if (is_read) {                                                 \
+                    tmp32 = TARGET_SAFE(ldl_p(buf), buf[0]);                   \
+                    for (i = 0; i < 8; ++i) {                                  \
+                        env->fptags[i] = !((tmp32 >> i) & 1);                  \
+                    }                                                          \
+                } else {                                                       \
+                    tmp32 = 0;                                                 \
+                    for (i = 0; i < 8; ++i) {                                  \
+                        tmp32 |= (!env->fptags[i]) << i;                       \
+                    }                                                          \
+                    TARGET_SAFE(stl_p, stb_p)(buf, tmp32);                     \
+                }                                                              \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD_X64(CPU_CONTEXT, FloatSave.Reserved1, f_size, {});          \
+        CASE_FIELD_X64(CPU_CONTEXT, FloatSave.ErrorOpcode, f_size, {           \
+            if (ctx_flags & CPU_CONTEXT_FLOATING_POINT) {                      \
+                rwuw_p(buf, env->fpop, is_read);                               \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD(CPU_CONTEXT, FloatSave.ErrorOffset, f_size, {               \
+            if (ctx_flags & CPU_CONTEXT_FLOATING_POINT) {                      \
+                if (is_read) {                                                 \
+                    env->fpip &= ~0xffffffffL;                                 \
+                    env->fpip |= ldl_p(buf);                                   \
+                } else {                                                       \
+                    stl_p(buf, env->fpip & 0xffffffff);                        \
+                }                                                              \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD(CPU_CONTEXT, FloatSave.ErrorSelector, f_size, {             \
+            if (ctx_flags & CPU_CONTEXT_FLOATING_POINT) {                      \
+                if (is_read) {                                                 \
+                    env->fpip &= 0xffffffffL;                                  \
+                    env->fpip |= ((uint64_t) ldl_p(buf)) << 32;                \
+                } else {                                                       \
+                    stl_p(buf, (env->fpip >> 32) & 0xffffffff);                \
+                }                                                              \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD_X64(CPU_CONTEXT, FloatSave.Reserved2, f_size, {});          \
+        CASE_FIELD(CPU_CONTEXT, FloatSave.DataOffset, f_size, {                \
+            if (ctx_flags & CPU_CONTEXT_FLOATING_POINT) {                      \
+                if (is_read) {                                                 \
+                    env->fpdp &= ~0xffffffffL;                                 \
+                    env->fpdp |= ldl_p(buf);                                   \
+                } else {                                                       \
+                    stl_p(buf, env->fpdp & 0xffffffff);                        \
+                }                                                              \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD(CPU_CONTEXT, FloatSave.DataSelector, f_size, {              \
+            if (ctx_flags & CPU_CONTEXT_FLOATING_POINT) {                      \
+                if (is_read) {                                                 \
+                    env->fpdp &= 0xffffffffL;                                  \
+                    env->fpdp |= ((uint64_t) ldl_p(buf)) << 32;                \
+                } else {                                                       \
+                    stl_p(buf, (env->fpdp >> 32) & 0xffffffff);                \
+                }                                                              \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD_X64(CPU_CONTEXT, FloatSave.Reserved3, f_size, {});          \
+        CASE_FIELD_X32(CPU_CONTEXT, FloatSave.Cr0NpxState, f_size, {           \
+            if (ctx_flags & CPU_CONTEXT_FLOATING_POINT) {                      \
+                rwl_p(buf, env->xcr0, is_read);                                \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD_X64(CPU_CONTEXT, FloatSave.MxCsr, f_size, {                 \
+            if (ctx_flags & CPU_CONTEXT_FLOATING_POINT) {                      \
+                rwl_p(buf, env->mxcsr, is_read);                               \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD_X64(CPU_CONTEXT, FloatSave.MxCsr_Mask, f_size, {            \
+            if (ctx_flags & CPU_CONTEXT_FLOATING_POINT) {                      \
+                /* FIXME: this is unimplemented in qemu? */                    \
+                /* rwl_p(buf, env->mxcsr_mask, is_read); */                    \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD_X32_64(CPU_CONTEXT, FloatSave.RegisterArea,                 \
+                                       FloatSave.FloatRegisters, f_size, {     \
+            if (ctx_flags & CPU_CONTEXT_FLOATING_POINT) {                      \
+                uint8_t *mem = buf;                                            \
+                for (i = 0; i < 8; ++i, mem += TARGET_SAFE(10, 16)) {          \
+                    floatx80 fl = env->fpregs[i].d;                            \
+                    if (is_read) {                                             \
+                        fl.low = ldq_p(mem);                                   \
+                        fl.high = TARGET_SAFE(lduw_p, ldq_p)(mem + 8);         \
+                    } else {                                                   \
+                        stq_p(mem, fl.low);                                    \
+                        TARGET_SAFE(stw_p, stq_p)(mem + 8, fl.high);           \
+                    }                                                          \
+                }                                                              \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD_X64(CPU_CONTEXT, FloatSave.XmmRegisters, f_size, {          \
+            if (ctx_flags & CPU_CONTEXT_FLOATING_POINT) {                      \
+                uint8_t *mem = buf;                                            \
+                if (is_read) {                                                 \
+                    for (i = 0; i < CPU_NB_REGS; ++i, mem += 16) {             \
+                        env->xmm_regs[i].ZMM_Q(0) = ldl_p(mem);                \
+                        env->xmm_regs[i].ZMM_Q(1) = ldl_p(mem + 8);            \
+                    }                                                          \
+                } else {                                                       \
+                    for (i = 0; i < CPU_NB_REGS; ++i, mem += 16) {             \
+                        stq_p(mem, env->xmm_regs[i].ZMM_Q(0));                 \
+                        stq_p(mem + 8, env->xmm_regs[i].ZMM_Q(1));             \
+                    }                                                          \
+                }                                                              \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD_X64(CPU_CONTEXT, FloatSave.Reserved4, f_size, {});          \
+        /* EXTENDED REGISTERS I386 */                                          \
+        CASE_FIELD_X32(CPU_CONTEXT, ExtendedRegisters, f_size, {               \
+            if (ctx_flags & CPU_CONTEXT_EXTENDED_REGISTERS) {                  \
+                uint8_t *mem = buf + 160;                                      \
+                if (is_read) {                                                 \
+                    for (i = 0; i < CPU_NB_REGS; ++i, mem += 16) {             \
+                        env->xmm_regs[i].ZMM_Q(0) = ldl_p(mem);                \
+                        env->xmm_regs[i].ZMM_Q(1) = ldl_p(mem + 8);            \
+                    }                                                          \
+                    cpu_set_mxcsr(env, ldl_p(mem + 24));                       \
+                } else {                                                       \
+                    for (i = 0; i < CPU_NB_REGS; ++i, mem += 16) {             \
+                        stq_p(mem, env->xmm_regs[i].ZMM_Q(0));                 \
+                        stq_p(mem + 8, env->xmm_regs[i].ZMM_Q(1));             \
+                    }                                                          \
+                    stl_p(mem + 24, env->mxcsr);                               \
+                }                                                              \
+            }                                                                  \
+        });                                                                    \
+        /* UNKNOWN REGISTERS */                                                \
+        CASE_FIELD_X64(CPU_CONTEXT, P1Home, f_size, {});                       \
+        CASE_FIELD_X64(CPU_CONTEXT, P2Home, f_size, {});                       \
+        CASE_FIELD_X64(CPU_CONTEXT, P3Home, f_size, {});                       \
+        CASE_FIELD_X64(CPU_CONTEXT, P4Home, f_size, {});                       \
+        CASE_FIELD_X64(CPU_CONTEXT, P5Home, f_size, {});                       \
+        CASE_FIELD_X64(CPU_CONTEXT, P6Home, f_size, {});                       \
+        CASE_FIELD_X64(CPU_CONTEXT, MxCsr, f_size, {                           \
+            if (is_read) {                                                     \
+                cpu_set_mxcsr(env, ldl_p(buf));                                \
+            } else {                                                           \
+                stl_p(buf, env->mxcsr);                                        \
+            }                                                                  \
+        });                                                                    \
+        CASE_FIELD_X64(CPU_CONTEXT, VectorRegister, f_size, {});               \
+        CASE_FIELD_X64(CPU_CONTEXT, VectorControl, f_size, {});                \
+        CASE_FIELD_X64(CPU_CONTEXT, DebugControl, f_size, {});                 \
+        CASE_FIELD_X64(CPU_CONTEXT, LastBranchToRip, f_size, {});              \
+        CASE_FIELD_X64(CPU_CONTEXT, LastBranchFromRip, f_size, {});            \
+        CASE_FIELD_X64(CPU_CONTEXT, LastExceptionToRip, f_size, {});           \
+        CASE_FIELD_X64(CPU_CONTEXT, LastExceptionFromRip, f_size, {});         \
+        default:                                                               \
+            f_size = 1;                                                        \
+        }                                                                      \
+        offset += f_size;                                                      \
+        buf += f_size;                                                         \
+    }                                                                          \
+    return 0;                                                                  \
+}
+
+__attribute__ ((unused)) /* unused yet */
+GEN_WINDBG_CONTEXT_RW(windbg_read_context, false)
+
+__attribute__ ((unused)) /* unused yet */
+GEN_WINDBG_CONTEXT_RW(windbg_write_context, true)
+
 static bool find_KPCR(CPUState *cs)
 {
     X86CPU *cpu = X86_CPU(cs);