Add AArch64 support to strace

AArch64 has been included in linux from 3.7 onwards.
Add support for AArch64 in strace, tested on linux in a simulator.

* configure.ac: Support AArch64.
* defs.h [AARCH64]: Include <sys/ptrace.h>, define TCB_WAITEXECVE.
* ipc.c (indirect_ipccall): Support AArch64.
* process.c (struct_user_offsets): Likewise.
* syscall.c [AARCH64]: Include <asm/ptrace.h>,  <sys/uio.h>, and
<elf.h>.  Define struct user_pt_regs regs.
(get_scno, get_syscall_result): Support AArch64 using PTRACE_GETREGSET.
(get_syscall_args, get_error): Support AArch64.
* linux/aarch64/ioctlent.h.in: New file.
* linux/aarch64/syscallent.h: New file, based on linux 3.7 version of
asm-generic/unistd.h.

Signed-off-by: Steve McIntyre <steve.mcintyre@linaro.org>
diff --git a/syscall.c b/syscall.c
index 37936ad..680cbc3 100644
--- a/syscall.c
+++ b/syscall.c
@@ -65,6 +65,12 @@
 # include <asm/rse.h>
 #endif
 
+#if defined(AARCH64)
+# include <asm/ptrace.h>
+# include <sys/uio.h>
+# include <elf.h>
+#endif
+
 #ifndef ERESTARTSYS
 # define ERESTARTSYS	512
 #endif
@@ -657,6 +663,8 @@
 static long r0;
 #elif defined(ARM)
 static struct pt_regs regs;
+#elif defined(AARCH64)
+static struct user_pt_regs regs;
 #elif defined(ALPHA)
 static long r0;
 static long a3;
@@ -967,6 +975,13 @@
 		fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
 		tcp->flags |= TCB_INSYSCALL;
 	}
+#elif defined(AARCH64)
+	struct iovec io;
+	io.iov_base = &regs;
+	io.iov_len = sizeof(regs);
+	if (ptrace(PTRACE_GETREGSET, tcp->pid, NT_PRSTATUS, (void *)&io) == -1)
+		return -1;
+	scno = regs.regs[8];
 #elif defined(M68K)
 	if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
 		return -1;
@@ -1403,6 +1418,9 @@
 #elif defined(ARM)
 	for (i = 0; i < nargs; ++i)
 		tcp->u_arg[i] = regs.uregs[i];
+#elif defined(AARCH64)
+	for (i = 0; i < nargs; ++i)
+		tcp->u_arg[i] = regs.regs[i];
 #elif defined(AVR32)
 	(void)i;
 	(void)nargs;
@@ -1641,6 +1659,12 @@
 	/* Read complete register set in one go. */
 	if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
 		return -1;
+#elif defined(AARCH64)
+	struct iovec io;
+	io.iov_base = &regs;
+	io.iov_len = sizeof(regs);
+	if (ptrace(PTRACE_GETREGSET, tcp->pid, NT_PRSTATUS, (void *)&io) == -1)
+		return -1;
 #elif defined(M68K)
 	if (upeek(tcp, 4*PT_D0, &d0) < 0)
 		return -1;
@@ -1823,6 +1847,14 @@
 	else {
 		tcp->u_rval = regs.ARM_r0;
 	}
+#elif defined(AARCH64)
+	if (check_errno && is_negated_errno(regs.regs[0])) {
+		tcp->u_rval = -1;
+		u_error = -regs.regs[0];
+	}
+	else {
+		tcp->u_rval = regs.regs[0];
+	}
 #elif defined(AVR32)
 	if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
 		tcp->u_rval = -1;