Signed-off-by: Mikhail Abakumov <mikhail.abaku...@ispras.ru> Signed-off-by: Pavel Dovgalyuk <dovga...@ispras.ru> --- target/i386/windbgstub.c | 374 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 372 insertions(+), 2 deletions(-)
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);