arm64-linux: make restarting of syscalls interrupted by signals work


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@13823 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/m_syswrap/syswrap-main.c b/coregrind/m_syswrap/syswrap-main.c
index 292723c..d63504e 100644
--- a/coregrind/m_syswrap/syswrap-main.c
+++ b/coregrind/m_syswrap/syswrap-main.c
@@ -2046,8 +2046,25 @@
    }
 
 #elif defined(VGP_arm64_linux)
-   // probably simplest to copy the ppc version
-   I_die_here;
+   arch->vex.guest_PC -= 4;             // sizeof(arm64 instr)
+
+   /* Make sure our caller is actually sane, and we're really backing
+      back over a syscall.
+
+      svc #0 == d4 00 00 01
+   */
+   {
+      UChar *p = (UChar *)arch->vex.guest_PC;
+
+      if (p[0] != 0x01 || p[1] != 0x00 || p[2] != 0x00 || p[3] != 0xD4)
+         VG_(message)(
+            Vg_DebugMsg,
+            "?! restarting over syscall at %#llx %02x %02x %02x %02x\n",
+            arch->vex.guest_PC + 0ULL, p[0], p[1], p[2], p[3]
+          );
+
+      vg_assert(p[0] == 0x01 && p[1] == 0x00 && p[2] == 0x00 && p[3] == 0xD4);
+   }
 
 #elif defined(VGP_x86_darwin)
    arch->vex.guest_EIP = arch->vex.guest_IP_AT_SYSCALL; 
diff --git a/include/vki/vki-arm64-linux.h b/include/vki/vki-arm64-linux.h
index 277e632..9eb0c20 100644
--- a/include/vki/vki-arm64-linux.h
+++ b/include/vki/vki-arm64-linux.h
@@ -515,15 +515,18 @@
 typedef struct vki_user_fpsimd_state vki_elf_fpregset_t;
 
 //----------------------------------------------------------------------
-// From linux-3.10.5/include/uapi/asm-generic/ucontext.h
+// From linux-3.10.5/arch/arm64/include/asm/ucontext.h
 //----------------------------------------------------------------------
 
 struct vki_ucontext {
-	unsigned long		uc_flags;
-	struct vki_ucontext    *uc_link;
-	vki_stack_t		uc_stack;
-	struct vki_sigcontext	uc_mcontext;
-	vki_sigset_t		uc_sigmask;
+        unsigned long           uc_flags;
+        struct vki_ucontext    *uc_link;
+        vki_stack_t             uc_stack;
+        vki_sigset_t            uc_sigmask;
+        /* glibc uses a 1024-bit sigset_t */
+        __vki_u8                __unused[1024 / 8 - sizeof(vki_sigset_t)];
+        /* last for future expansion */
+        struct vki_sigcontext   uc_mcontext;
 };
 
 //ZZ //----------------------------------------------------------------------