Hi list, I'm experiencing a strange emulation bug with the op-code below. The instruction raises a segfault in the application (running on the guest), however, if I enable KVM to run the exact same application, no segfault is raised.
0x0080023b: 8b 04 65 11 22 33 44 mov regEAX, [0x44332211] where "11 22 33 44" is just some address. According to gdb (on a 32bit little- endian machine), this instruction can be disassembled as a "mov address to reg-eax". I have added some debugging code to the disas_insn function in translate.c to find out that the code is disassembled to the following blocks: (NOTE: this debugging comes from an old qemu version where the old TB-style code was still used. HOWEVER, the same bug is still happening when used on the 0.11.0 source branch). 0x0080023b: disassemble 7 bytes (to 0x00800242) 0x001: movl_A0_im 0x44332211 0x002: addl_A0_ESP_s1 0x003: ldl_user_T0_A0 0x004: movl_EAX_T0 So, as you can see, everything seems correct, but there is an additional (second) TB that messes everything up. In fact, the segfault happens because whatever is in ESP (shifted by one) is added to the address (which might then not be a valid address). As I said, the code might crash in old versions of Qemu just like in the 0.11.0 source branch and works fine if I use KVM (because the user code is not emulated of course). Since this is such a fundamental problem, I don't quite understand how this could stay hidden so long... or maybe there is an error on my side :-/ Any help on this is greatly appreciated!! --Clemens --- some additional debugging information: I have traced down the problem to the following call in translate.c: static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr) { ... if (s->aflag) { /// !!!!!!!!!! we take this path !!!!!!!!!!!!!! ... if (base == 4) { /// !!!!!!!!!! we take this path !!!!!!!!!!!!!! havesib = 1; code = ldub_code(s->pc++); scale = (code >> 6) & 3; index = ((code >> 3) & 7) | REX_X(s); base = (code & 7); } base |= REX_B(s); switch (mod) { ... default: case 2: /// !!!!!!!!!! 4byte load: we take this path !!!!!!!!!!!!!! disp = ldl_code(s->pc); s->pc += 4; break; } if (base >= 0) { /* for correct popl handling with esp */ ... } else { #ifdef TARGET_X86_64 if (s->aflag == 2) { gen_op_movq_A0_im(disp); } else #endif { /// !!!!!!!!!! this is still ok, we need the address !!!!!!! gen_op_movl_A0_im(disp); } } /* XXX: index == 4 is always invalid */ if (havesib && (index != 4 || scale != 0)) { #ifdef TARGET_X86_64 if (s->aflag == 2) { gen_op_addq_A0_reg_sN(scale, index); } else #endif { /// !!!!!!!!!! this does the evil !!!!!!!!!!!!!! gen_op_addl_A0_reg_sN(scale, index); } }