|
From: <sv...@va...> - 2010-08-22 22:18:43
|
Author: sewardj
Date: 2010-08-22 23:18:31 +0100 (Sun, 22 Aug 2010)
New Revision: 11287
Log:
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.
Modified:
trunk/coregrind/m_syswrap/syswrap-main.c
Modified: trunk/coregrind/m_syswrap/syswrap-main.c
===================================================================
--- trunk/coregrind/m_syswrap/syswrap-main.c 2010-08-22 18:23:29 UTC (rev 11286)
+++ trunk/coregrind/m_syswrap/syswrap-main.c 2010-08-22 22:18:31 UTC (rev 11287)
@@ -1864,18 +1864,42 @@
}
#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)
|