From: Julian Seward Date: Sun, 22 Aug 2010 22:18:31 +0000 (+0000) Subject: arm-linux: make restarting interrupted syscalls work in Thumb mode. X-Git-Tag: svn/VALGRIND_3_6_0~170 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f3a7b3a8b9ddab5eec3e802a90ae9184781cc4cd;p=thirdparty%2Fvalgrind.git arm-linux: make restarting interrupted syscalls work in Thumb mode. This isn't exactly right, in the sense that the if the SVC instruction was conditional, then it will be restarted with the condition for the following instruction. IOW we should back up ITSTATE too, but don't. This doesn't happen in glibc, though, afaics. Also tighten up the checks for restarting in ARM mode. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@11287 --- diff --git a/coregrind/m_syswrap/syswrap-main.c b/coregrind/m_syswrap/syswrap-main.c index 562ed58b71..142695e0ae 100644 --- a/coregrind/m_syswrap/syswrap-main.c +++ b/coregrind/m_syswrap/syswrap-main.c @@ -1864,18 +1864,42 @@ void ML_(fixup_guest_state_to_restart_syscall) ( ThreadArchState* arch ) } #elif defined(VGP_arm_linux) - // INTERWORKING FIXME. This is certainly wrong. Need to look at - // R15T to determine current mode, then back up accordingly. - arch->vex.guest_R15T -= 4; // sizeof(arm instr) - { - UChar *p = (UChar*)arch->vex.guest_R15T; - - if ((p[3] & 0xF) != 0xF) + if (arch->vex.guest_R15T & 1) { + // Thumb mode. SVC is a encoded as + // 1101 1111 imm8 + // where imm8 is the SVC number, and we only accept 0. + arch->vex.guest_R15T -= 2; // sizeof(thumb 16 bit insn) + UChar* p = (UChar*)(arch->vex.guest_R15T - 1); + Bool valid = p[0] == 0 && p[1] == 0xDF; + if (!valid) { VG_(message)(Vg_DebugMsg, - "?! restarting over syscall that is not syscall at %#llx %02x %02x %02x %02x\n", + "?! restarting over (Thumb) syscall that is not syscall " + "at %#llx %02x %02x\n", + arch->vex.guest_R15T - 1ULL, p[0], p[1]); + } + vg_assert(valid); + // FIXME: NOTE, this really isn't right. We need to back up + // ITSTATE to what it was before the SVC instruction, but we + // don't know what it was. At least assert that it is now + // zero, because if it is nonzero then it must also have + // been nonzero for the SVC itself, which means it was + // conditional. Urk. + vg_assert(arch->vex.guest_ITSTATE == 0); + } else { + // ARM mode. SVC is encoded as + // cond 1111 imm24 + // where imm24 is the SVC number, and we only accept 0. + arch->vex.guest_R15T -= 4; // sizeof(arm instr) + UChar* p = (UChar*)arch->vex.guest_R15T; + Bool valid = p[0] == 0 && p[1] == 0 && p[2] == 0 + && (p[3] & 0xF) == 0xF; + if (!valid) { + VG_(message)(Vg_DebugMsg, + "?! restarting over (ARM) syscall that is not syscall " + "at %#llx %02x %02x %02x %02x\n", arch->vex.guest_R15T + 0ULL, p[0], p[1], p[2], p[3]); - - vg_assert((p[3] & 0xF) == 0xF); + } + vg_assert(valid); } #elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)